Starting your career as a software developer

A couple of years ago I was asked to give a talk to programming undergraduates at Kings College, London. I wrote up the session as a blog post and added it to my personal website, where it has received thousands one or two hits since.

Reading it back this week I was pleasantly surprised how relevant and useful it still is, and as we are currently hiring engineers at the start of their career it is worth resharing here.

Getting that first job

Whilst I can still remember the interview for my first job, I have greater insight these days from interviewing developers, and I have personally recruited, managed and mentored a number of junior engineers at the beginning of their careers. The next sections talk about our hiring process at OpenTable and within this framework here’s how you’d get us to give you a job.

The CV

The CV is not as crucial as you might think. Get the basics right – no typos and a neat layout – but don’t cram it full of everything you’ve ever done, just enough to whet our appetite. A single page is usually best (no more than two).

The most important thing for a job as a developer is to show that you love writing code. Nothing conveys this passion better than sites/plugins/projects/online courses that you have worked on, particularly outside of your employment. Even better, provide links to repositories, websites, blogs or Q&A sites to show your work and genuine interest.

Dare I say it, but your exams results do not really matter to us. Passion, backed up with examples of work will grab our attention, with that hard-earned first or 2:1 counting only as a tie-breaker.

The code test

If we like your CV we’ll ring you for a quick chat, and then ask you to complete a test - either at our office or in your own time. The coding test will vary from role-to-role but will need skills that will be required in the job. If you can’t do the test at all then this isn’t the right role for you, but if you can do part of it then give it a go as it will give us things to talk about in the next stage of the interview.

[Read More]

Monads explained by a imperative programmer - with examples

A monad is any type construct that follows a specific pattern; it works in the same way as other design patterns. The .NET ApplicationContext is a singleton in the same way that Array is a Monad. Something being a monad does not define its purpose; in the same way that a class can implement many interfaces, a monadic type can also conform to many patterns to increase its usefulness.

Monads are hard to get our heads around because they are very generic. They are defined by having two methods: the bind method (also commonly called fmap), and the unit method (also commonly known as pure or from).

A bind/fmap method.

The fmap method follows this signature:

1
2
3
4
5
6
// Given a monadic type TMonad with value type V1,
// and a method that takes a value of type V1 and
// returns the same monadic type TMonad but with
// a value type of V2, produce a monadic type
// TMonad with value V2.
function (TMonad<V1> m, Func<V1, TMonad<V2>> f) => TMonad<V2>

A quick breakdown of the method signature in plain english: given a monadic type TMonad with value type V1, followed by a method that takes a value of type V1 and returns the same monadic type TMonad but with a value type of V2, produce a monadic type TMonad with value V2.

From the signature, it appears that we should give the value V1 from the first monad to the function f and simply return the TMonad from that call. The ability to control the usage of that function and the ability to intercept the return value is where it gets interesting.

The resulting monad will usually be a composition of the original monad, and the new monad produced by f. That means the “state” held by the two monads are merged and the specifics of how is up to the developer.

The monadic type TMonad cannot change after a call to f; a Maybe monad cannot change to a State monad, but this also means that a Maybe monad can never read the value of a State monad by being bound to it. This is something I understood later when I started to question how to use different monads together.

The value type V1 is free to change as a result of calling f. This is why we denote the final result as TMonad<V2>; this doesn’t prevent the value staying the same, in the same way that in a program, x can equal 1 and y can also equal 1, V1 could represent a boolean and V2 could also represent a boolean.

A unit/pure/from method

[Read More]

Circuit Breakers and Application Resilience

For most people circuit breakers are a concept that belongs in the world of electricity. They are usually a box of fuses under the stairs that prevents the tangle of extension cords from turning into an unexpected open fireplace behind the TV. But the concept of a circuit breaker is something that we can apply to software and software services.

Martin Fowler described a software circuit breaker as follows:

“… a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all”

Background

OpenTable runs on many microservices that depend on one another to deliver the OpenTable site. These services can have dependencies on data stores such as MongoDB and Elastic Search as well as services such as RabbitMQ and Redis. Sometimes these dependencies can have performance or availability issues; such as when somebody accidentally drops an index on a collection in Mongo.

This actually happened, your author accidentally dropped a critical index while working with a DB synchronization tool which resulted in downtime. Hence this article.

When this happens calls to dependencies may fail or take a long time to complete which then causes the dependent service to behave in the same way. Other upstream services can also suffer the same problem. This can be described as a cascading failure.

Ideally what we would like to happen at this point is for our service to recognize what is happening, fail gracefully, and stop calling the service that already can’t keep up with the load placed upon it. (As well as alerting us to the problem). This is where a software circuit breaker can help us.

Polly to the rescue

[Read More]

Hosting external events

This June, OpenTable hosted the London Machine Learning Study Group to great success. We provided the food, drinks, and space for an extremely talented speaker and over 100 RSVPs. It was also my first experience hosting an external meetup at OpenTable - and I learned a lot!

My Experience

OpenTable has frequently hosted meetups in our office such as Web Platform London and WEBdeLDN. However, acting as an event host was a complete unknown for me, so leading up to the machine learning event, I made a point of sitting down with someone who had organised one before.

We documented the key steps in setting up an external event, and then published what we’d discussed on our internal wiki so as to avoid siloing useful information for future use. Following the steps documented in the wiki proved invaluable in reducing my stress on the day.

After our last event we also looked back on how we’d done the last few events.

Retrospective

Following our last meetup, we held a retrospective as, along with the London Machine Learning Study Group, we have had a recent spate of meetups at OpenTable. This was extremely useful to underline our shared experiences as well as the considerations we want to make for our next external event. Here are a few areas we will look to improve.

Push social media more

We want the largest number of people to know about these events ahead of time, which means not just relying on one platform. Instead we aim to advertise our meetups on all channels available to us to get as diverse an audience as possible. We will tweet about our events more via @OpenTableTechUK and we will use this blog to advertise upcoming events.

A lot of people don’t turn up

[Read More]

Pragmatic Testing with GraphQL

We’ve been using GraphQL at OpenTable for a little over half a year now. I won’t go into detail as to why we started using it, but suffice to say, we really enjoyed creating our very first GraphQL endpoint. It eased a lot of the inconsistencies that we were experiencing with some of our REST-ful services.

This post assumes you have some experience building a GraphQL endpoint. For those of who you aren’t familiar with it, it feels a lot like having a querying language via an HTTP endpoint. If you want to try it for yourself, I recommend GitHub’s endpoint. To get started with GraphQL, the official documentation is a perfect place.

The Problem

Now, let’s get back to writing tests for an endpoint. When we were creating our first endpoint, we started facing regression testing problems while expanding our schema. It seemed our existing testing methods were ill-equipped to handle it.

Finding a good solution to this is important because I’ve had such a love–hate affair with testing. All tests are not created equal and a naive developer would say, “write a test in case something changes”. This certainly isn’t a good measure. I’ve also found that just attempting to write tests immediately without forethought can be a costly distraction if you grow your codebase.

The Approach

So we took a step back and looked at the code we were writing. Most of the connectors we wrote were fairly anemic. We didn’t have much logic for our API nor did we want any. We could have written unit tests for each parts of the schema but mocking portions of the system seemed more work than it was worth.

So where did we start? I personally enjoy the outside-in approach and started writing a few acceptance tests. So, we wrote a test for each query in the schema that we had. It would fire an HTTP request and expect a 200 status code and have no errors in the resulting JSON body. Thanks to GraphQL most errors are handily reported using this mechanism so we would be able to make a decent impact using little work.

As you can see, we found that this would be good enough at the time but eventually found that it would not scale very well. If you forget to update one of these queries, you could leave out a major section out accidentally. Being a big fan of automation, we wondered how we could scale this out.

[Read More]

OpenTable's Global Hackathon 2017

Last week we were excited to kick-off our first OpenTable Global Hackathon, underway simultaneously in San Francisco, Los Angeles, Mumbai, Melbourne, and right here in London. Having personally never attended a hackathon before let alone helped organise one I was initially daunted, but with some careful planning, good suggestions from the team and a fair amount of making it up as we went along, the end result was quite a success.

This post discusses what format our hackathon took, what challenges we faced in coordinating across countries, the experience in the London office and what we learned.

The basic format

The hackathon was conceived in our San Francisco headquarters and could easily have been confined to that one office, but I was delighted to learn is was intended to be a global event from the outset. The basic format, described below, was however optimised for our SF office.

In the weeks leading up to the hackathon, individuals were asked to submit their hack proposals. Idea prompts were circulated such as “engages and delights diners” or “socially connected”, as well as the judging criteria; Originality, Feasibility, Likely to adopt, Fidelity of prototype, Business impact and Captivating presentation.

One week before the hackathon, our San Francisco office held a ‘happy-hour’ in which everyone taking part mingled and discussed ideas. This social event encouraged the developers, designers and product owners to self-organise into teams and submit their proposals in advance.

The hackathon itself was devised as a 2½ day event, running from Tuesday morning to Thursday lunchtime during normal working hours, with OpenTable providing breakfast and lunch. Live incidents or outages still had to be fixed, but otherwise the teams would be uninterrupted for the duration.

The hackathon concluded with each team having up to five minutes to present their hack to their colleagues and the judges. The awards were for the top three hacks, special CEO and CTO’s prizes, and an open vote - and generous cash prizes and gifts were up for grabs.

Tweaks for the London version and building enthusiasm

The big headache in London that we always have to live with is the eight hour time difference between London and San Francisco - and the same constraint obviously existed for the hackathon. Each team concluded that it wouldn’t be feasible to form teams across the offices so all our build-up and actual hacking remained independent. However we submitted our recorded presentations for the final judging along with the rest of the company.

[Read More]

The goal driven organisation

Quarterly team goals are an effective way to establish organisational purpose, direction and alignment while supporting team agility. But be vigilant - they can be used inappropriately.

Overview

Due to factors such as growth, acquisition, changing markets amongst others, organisations can find themselves in new environments to which they struggle to adapt.

Scaling Agile in these new environments is hard. The practices and tools that are frequently used to solve this problem can give the appearance of acting against team autonomy and agility. Teams and individuals naturally try to protect the engineering culture that they have worked hard to establish but by allowing new organisational needs to go unmet they put their autonomy and agility at risk.

In this post I will show how quarterly goal setting, using Agile principles and with one eye on the dysfunctions that can arise, is an effective way to meet organisational needs while protecting team agility and engineering culture.

What needs are we trying to meet?

Senior leaders in an organisation need confidence that the creativity, intelligence, skills and knowledge of their employees are directed most effectively towards delivering long term business objectives. Ensuring that teams are aligned around those business objectives is traditionally called governance.

The top-down command-and-control connotations of that term do not sit comfortably in modern software development and rightly so. The responsibility for organisational alignment should rest with teams and individuals.

A bottom-up approach to organisational alignment relies on transparency. Everyone in the business needs to know the business objectives and what all teams are doing to meet the objectives. Arguably the primary output of all product development and engineering teams is a statement of intent and a narrative of their progress.

Put another way, the first output of all knowledge work is shared, actionable knowledge - we can then decide how best to utilise that knowledge. Teams need to know that the decisions that they are making right now are the right decisions for the business. Without full transparency this is not possible.

[Read More]