This article is an awareness of my shortfall as a developer. Out of this awareness I wanted to write an article that gets at this shortcoming that I’ve seen time and time again from developers just like myself. It’s this: As software developer’s we often develop to the problem rather than develop from the problem.
Coding for the problem is destructive
For most of us, when looking at code we’ve written we may find a pattern. This pattern would reveal that there was no pattern at all in the code we wrote.
This isn’t to say that there wasn’t an effort to use clean code principles, such as appropriate variable and method naming, functional and single duty methods, among other clean code principles. Unfortunately, when thinking about the composition of an application, clean code principles can only take you so far. Clean coding principles are not design principles in and of themselves, although we often treat them as though they are.
As software developer’s we often develop for the problem rather than develop from the problem.
As a result, there isn’t a clear logical pattern, and therefore a clear logical flow to solving the problem found in the code. This is what is meant by developing for the problem. It’s easier to see the problem and start coding until it works.
This is destructive programming. It doesn’t leave a map (pattern) to modifying or adding onto the current solution in place. The code, in these instances, may become unmanageable as features are added or changed. When future coders inherit this type of code, it significantly hinders their ability to efficiently do work within the bad framework of code that was given to them. This presents problems for those coders in knowing how they should go about modifying code for new features or even fixing bugs.
Some times the code is so bad and not easily traversable that other coders may suggest that a major refactoring needs to take place (if not just an outright throwing away of the code (destroying) altogether after years of patch work and feature add ons in weird places).
If coding for the problem is an issue, then there has to be an option that is better.
Coding from the problem produces stable long lasting code
To code from the problem is to design a solution that best fits the problem. It’s understanding the problem and working backwards to put the best solution forward from the problem.
To do this would help to establish a pattern that can be extended and a framework to work within that can produce easy to read, easy to test, predictable code.
However, there is rarely ever a need to invent a new pattern. Most solutions to problems can fit existing (tried and true) design patterns.
Are you implementing a static algorithm that has different behaviors depending on certain inputs? — Try using the Factory pattern.
Do you need to implement an algorithm that has the same steps across behavior types? — Try using the Template Method pattern.
Is there a set of static operations that, depending on the operation being performed, need a different runtime ordering in order for it to complete? — Try using the Chain of Command pattern.
Building a rule engines to allow others to define steps? — Try using the Interpreter pattern
By providing a solution with well established design patterns you are speaking in a format known to most developers (or should be known to most developers). This would be akin to picking up the meter in a poem and knowing how it should be recited.
What are the behaviors that are needed to solve the problem?
It is important to break down the problem into a behavior or multiple behaviors (what does the solution need to do, in order to solve the problem?). Once the behaviors are defined, these can be mapped to one or more design patterns to help solve the problem.
This is overly simplistic of course. It will take a good bit of work.
As a rule of thumb, you can do something like the following to figure out the behaviors an application needs to solve a problem (I like doing things in 7s):
- Understand the problem fully. Ask questions until you feel like all gaps are covered. Can you fully explain it back to someone else who wants to know what you are coding?
- Look to the edge cases. The edge cases often times can throw a wrench into how we think we understand a problem, but may also provide the key to solving the problem in the most holistic way.
- Devise a flow chart based on the previous two steps.
- Find the commonalities and differences of the different flows within the flow charts. Is there a pattern or patterns? If not, repeat step 3 to see if there is something you may have missed.
- Find the behaviors that can be encapsulated as design patterns
- Psuedo code out the final design.
- Code already knowing the solution (this is when I find coding to be most enjoyable)
Go love your fellow coder
However much longer this processes of breaking down the problem into behaviors takes, than just jumping into coding, will in the end still be worth the effort.
Outside of the many benefits like ease of testing, predictability of the code, ease debugging, etc, the greatest benefit may be that those who run into the code later on find it easier to work with the previous code (including yourself). When patterns are instituted, even porting from one language to another becomes a less time consuming task.
So go and love your fellow coder, by giving them code they would love to inherit and work with.