Be a Master of Simplicity
The software engineer’s job is completely intertwined with their ability to design well. The better the designing ability of the software engineers involved in a project (especially the tech leader) the better the odds of a successful project (measured in efficiency of deliverance, maintainability over time, and ability to quickly resolve issues over time). Whether at the architectural stage, the coding stage, or the testing stage of development; designing never stops.
An engineer’s ability to design well is in direct relationship to their ability to understand the problem and implement a solution that is in its most simple form. What follows then is the understanding that simplicity is the absence of complexity. The presence of complexity, more often than not (although obviously not always) highlights a lack of understanding of the problem and therefore what the solution should be.
This seems to be counterintuitive to most. For example, recently one of my colleague’s did an architectural design for a team, in which the response was “this seems to be overly simplified for what we are trying to do.” What that engineer (who is pretty good at their craft) may have failed to understand, was that my colleague understood the complexities of other design options and made the most cost effective and easily maintainable choice.
Every Software Engineer is a Designer
It is important at this point to state what has hopefully been obvious, that if you need to have the ability to design to be a competent software engineer, it means that you are in effect a type of designer.
A designer seeks to make a concept or idea understood. Nothing is more understood, especially in software engineering, then an implemented idea that has sought simplicity.
Seeking simplicity means that the hard work happens more in the design, than in the implementation. The implementation should be the rewarding fruit of the hard work put into the design, not the impediment that it can become when design is an afterthought to an ad-hoc implementation.
Designing for Simplicity
Reducing complexity and seeking simplicity is hard work. However, developing a framework for arriving at a simple solution does not have to be. Here are some questions (although not exhaustive) that can help designing well as a software engineer:
Do I truly understand the problem?
This is the first step. If you can’t understand the problem well enough (and be able to explain the high level concepts of the problem to others), you are heading towards project failure, or adding unnecessary complexities that will make the application hard to maintain over time.
What are the possible solutions that can solve this problem?
Naturally as you grow as a software engineer you should be more familiar with patterns (as a wise engineer once told me, there is rarely anything new and there is a pattern for that). You should have a few patterns (including the permutations of combined patterns) that you are considering for the design. This is true both infra-structurally and in code.
Sometimes it is hard to see upfront what a pattern should be, but even picking a pattern that helps to solve the problem will allow for easier iteration to something that better solves the problem in the future.
On one particular project I remember a very junior developer was tasked with starting part of a bigger project. The best part about what they implemented was that they picked a pattern and everything within the implementation followed that pattern.
This pattern wasn’t the best pattern available for the solution, however, as more engineers contributed they were able to do so within the pattern with much less friction than a patternless, thoughtless design. Once a more senior engineer came to that team, they were able to follow the pattern and easily convert to a pattern that was simpler, more manageable, and led to a better understanding of what was going on in the code (and naturally more easily testable).
Does this solution introduce unnecessary points of failure?
In the modern age of software development, especially web development, this question is often missed. For instance, when thinking about the design of backend systems we often mistake the noble goal of micro services/front-ends to mean producing nano services/front-ends. What should be one service, ends up becoming 12. Or on the front-end littering the components and html with 1000s of lines of conditional logic, instead of taking the time to understand a pattern like redux and how a state store can drive the presentation layer in a predictable, repeatable, and more easily testable way.
Does this solution introduce unnecessary hurdles to testing?
Getting to the point where a piece of code is not able to be tested, there is either a gap in the design, it is in need of a slight refactor, or your doing that ad-hoc programming thing again.
Note: There are times when simplifying a design means choosing a less optimal solution (especially with the emergence of more elegant architectural solutions surrounding eventing). Some solutions may be better, but the tools for testing may not be readily available or easily able to be implemented. At that point you have to choose your complexity wisely, is no testing better than the most optimal solution?
Start Some Where
Becoming a good software engineer, is naturally the process of seeking simplicity. Removing complexities in the design guarantees a greater chance of success on any given project and will naturally lead to greater maintainability and simplicity of testing.
Choosing to go this route seems as thought it adds overhead (it does slow things down a bit upfront). However, my experience often shows that passing over seeking simplicity in the design of the infrastructure and code leads to overhead in the implementation and maintenance (that is AT LEAST two fold increase in the overhead of development over time). Some times you have to go slow to go fast. As the cool kids say, “Choose your hard.”
One thing to note is that over time this will become natural and you will go faster and the overhead will become less. To borrow a phrase from the money management industry, if you will code like no one else today, later you can code like no one else.
If you enjoyed reading this, consider giving me a follow -> Follow Me