Sunday 24 February 2019

The Art of Imperfection


If you've spent any amount of time with a development team you will recognise the obsessive, compulsive and perfectionist behaviour that whilst possibly a stereotype also has a bucket full of truth.

This strive for perfection can be a teams downfall, leading to stagnation caused by a reluctance to commit and release. Clearly this is a difficult juggling act, swing too far the other way and pragmatism gives way to simply bad software.

The ability to apply well reasoned pragmatism to everyday development situations is a core skill that will generally come with experience as idealism is complemented by the experience of shipping, or indeed not shipping, software.

This isn't an exact science and this post is by no means a definitive guide on how to achieve it. You'll have to find your own way to achieve this in your world but hopefully these pointers will help you.

Imperfections in Architecture

If any architect tells you they are 100% happy with their architecture I would question how much they understand about how it has been implemented. We all strive to follow a ratchet mechanism where every change we implement improves our technical capability and moves our architecture forward. However, software engineering is a far too complicated discipline to never take a wrong step.

You will at various points define an architecture that you think will provide a structure for never ending success and be proven wrong when the implementation goes in a direction you didn't anticipate and is less than ideal.

Whilst a good architect will hopefully keep these situations to a minimum they won't be able to eliminate them entirely. Instead they can be judged on how quickly they recognise these situations, how they contain their impact and how they formulate a plan to reverse and try a different direction.

Adherence to SOLID design principles will help you in these situations, they will naturally ensure that loose coupling avoids the transmission of technical debt across a code base. They will also allow for a cookie cutter approach to fixing the issue where the problem area can be cleanly removed and improved upon.

Imperfections in Code

All developers will recognise the situation where you can't let go of the feeling that a piece of code can be improved. Either adding functionality or trying to achieve the same functionality with less code are common goals that lead to a reluctance to declare something as done.

Both of these goals are to be applauded but they must be approached with due to regard to the YAGNI principle (Your Aren't Going to Need It). Coding for a situation that will never arise is a fairly good definition of over-engineering, along with coding for a level of performance that you will never need to obtain.

The major benefit of following SOLID principles is how they allow for effective future refactoring. They allow for simple extensions to functionality along with the ability to change the implementation of existing functionality.

The majority of code must be accepted as a continual work in progress, only the most trivial areas of a code base are ever "finished". It's fine for code to be good enough for now if this is coupled with a clear plan of how it would be changed in the future should requirements change.

Imperfections in Features

We write software to implement features and our willingness to declare a features as ready is equally as problematic as our willingness to declare code as done. What we must realise is that it is the vacuum caused by a lack of user feedback that leads to this gun shy nature.

Obviously the initial inception of an idea requires reasoned thought as to the best way to address a user need, however before long this idea will have been implemented well enough that the overhead of continued refinement will not be matched by addtional user positivity.

Any time we place ourselves in the shoes of our users we are in danger of over thinking based on incorrect assumptions. Any refinement cycle that isn't driven by observations of users using released software has reduced odds of hitting the mark.

Getting ourselves to be comfortable with releasing what might be deemed good enough is an important mindset for a team to attain. Create something functional, prove that users will engage it with and look for where this engagement could be streamlined, increased or otherwise improved.

Perfection in software development is all about the journey and not the destination for the simple fact that perfection will never be achieved. Those that excel are able to optimise in any given moment whilst also managing the areas that need improvement in the longer term.

Whilst shipping code that doesn't work is never going to benefit anybody this aside failing to ship is likely to do you more damage in the long term than shipping something that might not be 100% perfect.