Production Code: Where abstraction and maintainability collide
Introduction
Fizz Buzz - one of the cornerstones of technical interview questions as well as a suitable exercise for any first-year computer science student.
"The player designated to go first says the number "1", and each player counts one number in turn. However, any number divisible by three is replaced by the word fizz and any divisible by five by the word buzz. Numbers divisible by both become fizz buzz. A player who hesitates or makes a mistake is eliminated from the game." - source: Wikipedia
There is any number of implementations that can be used to accomplish the above programmatically, for a quick break down - I recommend looking at this video by Tom Scott.
The Problem
In the real-world scenario, it is not simply enough that our code is implemented this simplistically and it often requires integration with other systems as well as keeping maintainability in mind. Leveraging the example of Fizz Buzz, here is an enterprise-grade Fizz Buzz solution, complete with unit-tests, dependency injection and a firm use of design patterns within its software architecture, we can see that the enterprise-grade implementation is what some would deem as "over-kill" but it does make my point.
The problem we see here is that if the software is too complex, it will be hard for the next developer or group of developers to provide appropriate solutions that keep the entire software architecture at it's highest standard. There could be any number of reasons for the lack of understanding - however, the initial developer/developers will always have a superior understanding to anyone inheriting that project.
To the left, there is a graph of how code, that is minimal in size, is typically more understandable. As the size of the code base increases and has more complexity, the less understandable it becomes. In this age of computing, complexity is sometimes a fact of life, especially within the corporate world. The trick is to find the "sweet spot", where you can provide the extensibility and capability of expansion where it is needed and leave simplistic implementations where complexity is just "showing off".
Personal Analysis of South African VAT changes of 2018
VAT - Value Added Tax on every single transaction done is applied to all goods and services that have been charged for.
During my time as a developer within South Africa's financial sector - I would, especially in my inexperienced years, ask "Should we make VAT configurable?" to which the answer always was "No, it's VAT it will never change and always be at 14%". A change to VAT occurred from 14% to 15% - More information can be found here.
This has led to a large storm of changes countrywide to change every single implementation of the hard-coded change detailed in the last paragraph.
Do I think they were right to hardcode the value? Yes, because with all the information provided indicated that this would not change and it would have been an additional complicated effort to make this configurable.
What does this have to do with complexity/maintainability? In short, making something such as this configurable would have made the code base more complex as this would require another means to fetch, parse and test this data and handle any breakage along the line.
Conclusion
Be smart about your choices, make sure that you don't overly-complicate components which have a very low risk of changes and focus on the areas that do. Write unit tests with meaningful descriptions to easily track features that require changes. The idea is to keep your software maintainable so that it has as much long-term use as possible while making sure it is complex enough to be resilient to changes and faults within the organisation.
Software Engineer
6 年Nice one man.
Great article Greg, 100% agree that you must build as little as possible to achieve what you have to achieve, adding complexity to 'show off' is always a bad thing, especially if it's new (which indicates you don't fully understand the space fully as yet). At the end of the day, the end consumer of your software is more than likely not a developer, so no matter how complex and shiny you think you've made it, they don't give a hoot, as long as it works and works well <--key I think in terms of design regarding the VAT, I largely agree that making it configurable could've added more complexity to the solution and 100% agree that at the time the 'spec' would've indicated that this value would never have changed and so it shouldn't have been made configurable. I do think though, that at the very least, the mechanism for retrieving the VAT value should've been designed to be a consistent and separate one, and not one where it's merely a hard-coded value that's referenced everywhere. I've found (often to my own peril ;) ) that when you are referencing hard coded values, you will almost always inevitably have to change them at some point and that you should always look at different ways of making them future proof (did I just say that *lol). Putting such hard-coded values behind a method or common retrieval mechanism, even if the value is hard-coded in that method leaves you with at least the ability to change it should the need arise without destroying the solution. Loved the article, love the 'complexity vs get it to work' debate, keep 'em coming Greg!