But I can write that in…
I have lost count of the times I have heard a developer exclaim ‘but I could write that in X days’ when discussing adopting an existing piece of technology developed somewhere else. This is usually given as a reason not to adopt an existing external solution but to instead write a custom solution with some minor improvement or feature. There are two big flaws in this line of reasoning.
The first is the assumption that you could create something with the same quality level as the existing solution in the stated number of days; most likely you will be lucky to have a functional prototype with minimal functionality. It is highly unlikely that you will have produced something that is as well tested, optimised and documented as the existing solution.
Secondly, as developers writing software which we intend to sell to users to pay the bills, we should be focused on the core features that define our product. It is these core features we should be pouring our energy and time into designing, building and testing. Developing alternatives to existing technology that is not in our core feature set is a waste of valuable time and energy and will not differentiate our product from that of our competitors.
We should instead be looking to leverage as many established technologies or components as possible when developing new systems as this lets us spend most of our time where it matters most on our core differentiating features.
Beware the Golden Hammer!
The ‘Golden Hammer‘ is a very common anti-pattern, which can be best summed up by the phrase “if all you have is a hammer, everything looks like a nail“. This anti-pattern occurs when the perpetrator has typically learned a particularly powerful technique or design (the hammer), which they then go on to apply blindly to all problems (the nails) they encounter whether it is a suitable solution or not.
This can be especially evident amongst beginner programmers, who are learning new techniques almost constantly, but it only seems to become a dangerous anti-pattern if the individual becomes overly fixated on a particular technique.
Interestingly this anti-pattern can apply to more than just individuals, in my experience it can also apply to teams or even entire organisations. One of the ways I have seen this manifest at a team or organisational level is with attempts to solve social problems with technology solutions. This trait seems to be especially strong in software development organisations: perhaps because technology is their usual solution to problems.
Such social issues faced by development teams and organisations can include things like not breaking the build, lack of communication or lack of testing. These problems really are not technology problems, they are social (people) problems, yet time and again I have witnessed technology solutions to these problems. For example, more elaborate and sophisticated check-in systems being introduced in response to constantly broken builds, where a much simpler social solution such as peer pressure to not break the build would be much more effective.
Avoiding the Golden Hammer when programming is achievable with some self awarness and honesty: are you using your current technique for the right reasons? However, identifying and interveening when a team or organisation is about to use the Golden Hammer is much more challenging as it can involve going against the solution favoured by the majority along with the polical implications that brings…
You Aren’t Gonna Need It!
A very common trap to fall into while implementing a new system or feature is to add functionality to ‘future proof’ your code for a use case that you imagine in may be required in the future. The future for the purposes of this post is any time that is not in your current development iteration.
This may seem harmless but consider that the future use cases you are imagining are not something you fully understand yet: as most of us will admit we are pretty bad at anticipating the future. So how can we hope to implement future functionality successfully? The most likely outcome is that whatever you implement now not be sufficient when you actually try to use it in the future. This will mean more time will have to be invested in the future to refactor or replace the functionality with what is actually required.
Unless you also plan to implement a full set of tests for this new functionality then you are adding extra code to your program that will not be correct and will not stay correct. This can also lead to really weird run time behavior if the flow of program execution goes into your new ‘future proof’ functionality unexpectedly: which can be very hard to debug. Adding functionality for future use without corresponding tests also means that as the rest of your program evolves the future functionality does not evolve with it, this means by the time you actually try to use it that it is most likely hopelessly out of sync with the rest of the code base.
The future functionality is also expanding the size of the source code of your program which leads to unnecessary code bloat. In some compiled languages (e.g. C++) code bloat will lead to increased memory usage and decreased program performance which is highly undesirable.
Another thing to consider from a business stand point is that you are spending time and money implementing future functionality when you are not being paid for it. This is a strong indication to me that implementing future functionality makes little business sense. As it means spending money now paying developers to implement functionality that you can’t sell right now.
There is a handy acronym for this: it is YAGNI which stands for ‘You Aren’t Gonna Need It’. The essence of this concept is to only implement the functionality you need right now and to implement in as simple and robust a fashion as possible. As simple robust code (preferable with acompaning unit tests) is code that can be easily refactored in the future to meet future needs and that is cost effcient!
Remove features, don’t add them!
There seems to be something about programming that makes software engineers seek the perfect solution to a given problem or design brief.
Something that drives them to keep adding things to their program or library until they kill it with love for example Microsoft Word has a gazillion features but until recently (its has improved a bit) the GUI which is the main component of the program the user uses was horrendous to use and you could not locate most of those extra features easily. This death by love seems to manifest especially consistently during framework, library and API development. There seems to be a burning desire in every software engineer to make every library so generic it can solve any problems, not just what it’s design specification demands.
It is very rare to hear of a program, library or framework being criticised for doing too little or being too simple. Usually the criticism is about the program or library being too bloated, too stuff full of features and love to be easy to use. This criticism is so common and yet every day bloated libraries and applications are released. It is rare and pleasant thing to discover a small concise application, library or framework that solves its problem domain excellently and no more. In fact I can only think of a few examples:
- SQLite is a C library which implements a compact, fast and efficient SQL engine, take a look at the list of companies using it, as well as all the open source wrappers available for it in most major modern programming languages. This library is a study in minimalism, it does only what is required to meet its design goal with no surplus frills or bling.
- DropBox is an online service with client applications (for PC and Mac) that provides file storage and synchronisation across multiple computers and operating systems in a refreshingly simple and efficient manner. I was stunned to see how easy to install it was and how few configurations options are provided (hint: few are required by the client as it works out what it needs).
- Google‘s search engine really needs no introduction. Take a moment to look at the Google homepage and compare it with Yahoo!‘s or MSN‘s homepage: Google’s hompage is a study in simplicity compared to Yahoo!’s or MSN’s homepages.
I think I can best explain this by a talking about model making: as a young lad I used to spend hours building and customising Games Workshop miniatures which I used to collect and play war games with. I got to the point in my teens were I was pretty good at the building, customising and painting of miniatures and won a few awards in local model competitions. I can’t remember when it happened but I remember coming to the realisation one day that there is such a thing as too much customisation, building or painting and that it is very hard to know when to stop without first ruining a few models. Later on I remember thinking about this concept some more and realising that this is applicable during just about any creative design work e.g. painting, gardening, music, programming etc. Think about what would have happened if Leonardo da Vinci had kept adding brushstrokes to the Mona Lisa, would we still know who he was?
The key I believe is not to think ‘what can I add’ but to think ‘what can I reduce (simplify), refactor or remove’ from my design while still meeting my design brief/requirements. As many compact, efficient libraries with concise, simple APIs can be combined in many more flexible and powerful ways than a few monolithic ‘kitchen sink‘ libraries with massively complex APIs.
In a nutshell: figure out your solution, then refactor and simplify it down until you meet your requirements in the simplest possible manner.
Resist the perfect solution, embrace the working solution!
It would seem that as a profession Software Engineers when left to their own devices will attempt to make a perfect solution to a problem, rather than accepting a working solution. This may sound innocent enough as being 75% perfect (with a working solution) is usually not too painful in time and effort to achieve, however the last 25% is typically brutal to achieve (if it is even possible to begin with).
This trend towards perfection is probably due to the medium with which we work: programming languages and mathematics. Both mathematics and programming languages are completely unlike the physical elements most conventional non-software related engineering disciplines have to work with. Our elements are much closer to pure thought stuff than the physical elements, limited only by our imagination and creativity as to how we can manipulate and combine these components to achieve a solution. This is computing’s greatest strength, as in many ways we are limited only by our conceptual abilities.
This is also perhaps one of our greatest weaknesses, as it makes accepting a non-ideal solution harder than it should be, as our natural inclination is towards the perfect solution. I think this manifests most visibly in the industry wide ‘not invented here‘ syndrome. Where engineers will resist taking components or systems developed else where and using them in their own systems and programs. Instead preferring to design and implement their own ‘better’ solution, usually this resistance will take the form of pointing out the flaws in the component and they could make it better.
This misses one of the key points of reusing components: reusing components saves time and effort that can then be better used to assemble our pre-built components in more creative and powerful solutions to the problem at hand. To insist on building our 100% perfect sub components every time means that you are spending time and effort on making sub components slightly more perfect than existing sub components. This time and effort could otherwise be better used in our higher level solution composition than spent perfecting low level components that have already been made, usually in several different ways by several different groups and tested thoroughly over several generations of software.
Think of what would happen if another engineering discipline like automobile manufacturers where to use such a methodology: rediscovering and design something as basic as a wheel, internal combustion or making steel every time they designed and built a new model of vehicle, the pace of automotive development and inovation would slow to a crawl.








