Doing things the wrong way to get the right result
There are many different routes you can take on your journey to becoming a developer. Mine ended up including a formal Computer Science degree, which meant learning a lot about software development philosophies. Regardless of whether you took this route or not, you probably found people telling you what is right or wrong.
Keep it simple.
Don’t repeat yourself.
Never use your prototypes in production.
All of these are helpful guiding principles to inform your decisions. But being a good developer is not only about following rules, it’s also about knowing when to ignore them (luckily, unlike an accountant, your creativity will rarely end up being considered embezzlement).
On one of our recent projects, we got way further by doing something “the dirty way” and ignoring our inner good developers. Before I share the specifics of that project, I’ll tell you a story of a side-project to illustrate why you should play against the rules sometimes . The fact that it includes a severed finger (just a prop!) only makes it easier to remember.
I know I’m using developers as a reference point here, but that’s only because of my experience. I’m sure that the same thing applies to other roles as well.
Don't redesign the finger
Just like any other project, this one started with a problem — albeit not a very profound one. The door entry system to our studio is bog-standard — guests buzz in on one end, and a phone with a button releases the door lock on the other. The finite quantity of entry phones (2) and their wired nature means that they can be within reach of a very limited number of people. If these people are not at their desks, someone has to stand up and walk up to the nearest phone to let our lovely guests in. As a breed known for being efficient (lazy), we knew that technology can save us.
That job doesn’t seem difficult, does it? The right way of dealing with it would be to create a piece of hardware that directly replaces an entry phone. A “connected entry phone”, with Wi-Fi connection allowing everyone to open the door from their laptops. To make it happen, we would have to:
- remove the current way of interfacing with the system
- understand internal protocols of the system
- connect the thing
- test correctness of the solution
- and ensure that it doesn’t impact on the rest of the system.
Wait a minute! Internal protocols? Impact on the rest of the system? Ok, maybe the task is bigger than we thought. Not to say that these challenges are not exciting. They would definitely make for an interesting investigation, but you have to ask yourself — how long will that take? Is it worth the necessary time investment? If not, is there a way of getting to our goal faster?
We’re talking about a side-project — we want to benefit from the solution quickly. To see if it’s possible, let’s take a step back for a second. What if instead of looking “under the hood”, we look closely at what we already know and understand — the entry phone.
We know how to interact with it ✔︎
We know what action to take to open the door ✔
And we know that doing so doesn’t impact on the rest of the system ✔︎
With that knowledge all we need to do is to press the button — and what is the best tool for pressing buttons? A finger.
This is what we ended up building. We built it without having to worry too much about the internals of door opening systems. Instead of taking a deep-dive trying to learn about all the processes and connecting at the lowest possible level, we focussed on making the difference by building on top of what we already understood. Most importantly, by doing so, we didn’t lock ourselves out of the possibility of improving it in the future. From making it nicer, if such need arises.
You don't need an API
Before you scroll to the bottom of the page to jot down how “it’s never that clear-cut on a normal project”, let me assure you, we’ve done stuff the wrong way on many projects. The very reason for writing this article, is seeing how ignoring the rules helped us build amazing products.
One example is the project I hinted at at the start of this article. We were building an employee mobile app for YayHappyFunTimesCorp (before you start googling to see what they’re about — it’s not their real name). It was at MVP stage and based on our user testing we had picked a feature that would benefit the employees the most. Next step: running a pilot in a couple of shops to validate it with real users.
The functionality we were looking at was heavily dependent on the data in YayHappyFunTimesCorp’s internal, legacy systems. In situations like this, we would aim at integrating through an API-based system-to-system communication. Unfortunately, not only were those legacy systems devoid of APIs, they were also extremely internal, to the point of not having any access to the Internet. Of course it’s not the end of the world — firewalls can be opened and APIs can be built — but unvalidated assumptions and impatient employees are waiting.
Once again, we had to take a step back. Find a “quick and dirty” solution, that allowed us to release the pilot quickly. The one we found took “quick” to the extreme — it didn’t require any code. To move data between systems, we printed it out and manually keyed it in. Manual weekly sync. We might have wasted four hours a week for six weeks on tapping on our keyboards, but we validated if we were building what users want (surprise, surprise, yes we were).
Similarly with the finger project, we made sure to not lock ourselves out from refining the solution in the future. Not only that, we actually started working on the improvements straightaway. Over a few months, we moved from print-outs to manually uploaded CSV files, then to automatic CSV imports, to then reach our final stop — API communication. All the while we continued releasing to more people, learning about how our feature was being used and what was required. The experience that we gained meant that the API structure we used in the end was very different to the one we would’ve suggested at the start of the project (This whole story was also the background to an article that our awesome developer Kat wrote about using AWS Lambda).
We started with a completely unscalable solution, which enabled us to validate the need. We then evolved it, step by step, to make it support more and more users. On the way, we learned not only about our users, but also discovered what the technology requirements were. We can only speculate what the outcome of the project would have been if we hadn’t let ourselves find a “quick and dirty” solution.
Just hack it
On every project, sooner or later, the time for a decision like this will come. A decision between building something that feels good to build, and something that just does the job. Between something that takes time, and something that validates quickly.
It will impact the product. Some of them will increase technical debt. Some will work only on a small scale. Some will actually require people instead of code.
Whatever it is, don’t be afraid to close that “best practice” book and turn a blind eye to a dirty hack here and there. As long as you are aware why you’re doing it and ensure it doesn’t lead you to a dead-end, you will be fine.
And if you’re in doubt, remember…
if you ever code something that "feels like a hack but it works," just remember that a CPU is literally a rock that we tricked into thinking— @daisyowl March 15th, 2017 00:03
If you want to experience our approach first hand, we're looking for design, technology and product management interns for our Summer Internship Programme.
Making successful digital products is hard. For many businesses, it’s still a step into the unknown. It requires teams to experiment with new ways of work...
Summer in London is here again and that means it’s time for us to recruit this year’s team of interns. You’ll have to be quick: applications open today an...