Sometimes a code smell is the odour of fearfulness. I have named two of those smells and share my advice for restoring a sense of safety.
Braces, belt and duct tape
There are null checks at each level of the code. The log prints messages of “this should never happen”. Every other line gives the impression of a bomb about to go off at any time. Only an infinite amount of safety checks will save our lives.
Solution. Have an explicit way to deal with the unexpected.
For the uncertainty of the outside world, such as user input or network data, create a validation boundary. Push that boundary as far out in your code as possible and make all the code after that a safe place where everything has a valid format. Let the boundary deal with input that would not be useful for your code.
For the fragility of our systems, hardware that break and buffer readers who get digestive issus, catch errors purposefully. What are the consequences for the rest of the system if this breaks? Who needs to know? What can they do about it? What do they need to know to handle it? This is also what the uncertainty boundary needs to do, in protecting the rest of the codebase in a constructive way in respect to different kind of users.
This way we will trust our braces or our belt. And we can leave out the duct tape.
Every line has to be read
Breaking the “single responsibility principle” can sometimes be caused by a believe that the highest design priority is how many lines of code that can be scanned per second. Then we hesitate to break things into smaller units and hide them behind abstractions. So why do we feel this distrust in code we have not read? I think that it happens when reading the code is the only way to know what it does.
Solution: What you see should be what you get.
Side effects are a good way to drive a developer crazy. Seemingly random things in a method intended for something else. That indicates code to be read line by line. Having collaborators that can be accessed without being provided by the outside is also a way to create a sense of uncertainty. Especially if it is a shared state that can be mutated. Explicit is better. Code that depends on inputs, dependency injection, will have to be clear on who it collaborates with. Together with language specific features, such as types, paths of exceptions or asynchrony and naming conventions, we can let the code tell its story.
Then the developer will feel safe not to read every line. Stay safe!
ps. Tests are also good for not being scared, especially when refactoring.
Comment on the blog!
Create a comment by emailing me.
I will then add the comment to the post.