OOT is a mini series on writing maintainable Object Oriented code without pulling your hair out. Click here for trick #1, trick #2.
“Each one can confuse and confound, breaking your flow as you’re reading down the code, causing you to double-take.” — Uncle Bob Martin
So rather than using them recklessly as conveniences, we should apply a significant amount of restraint and treat each argument as a liability.
The best functions have as few arguments as possible. Ideally zilch.
niladic > monadic > dyadic > triadic > polyadic
The same guidelines apply for constructors.
**Mutable State: *Not Recommended***Perhaps the best known and most widely scorned approach in all of software development for using state to reduce parameter methods is the use of global, instance variables. Although not the best solution, but may be appropriate in some cases. Use with caution especially in highly concurrent programs.
“Any global data is always guilty until proven innocent.” — Martin Fowler
Most of the time when you pass a boolean
into a function, you are declaring that you’ve written a function that does two things. One thing for the true
case and another for the false
case. Instead, you should have written two functions, one for each case.
A boolean hanging out in the argument list can be a huge source of error and confusion. What does it mean if it’s true? What does it mean if it’s false? If the name of the function and the argument fail to make this perfectly clear, then every time you use this function, you need to dive into the implementation details to understand the right value to be passed. Passing in two booleans is even worse. A function that takes two booleans does four things!
Try guessing the booleans, their order and the behaviour:
Makes you squint, doesn’t it? Avoid guesses and double-takes by using the Builder Pattern:
Passing null
to a function or writing a function that expects null
to be passed in is almost as bad as passing a boolean into it. In fact, it’s even worse as it is not at all obvious that there are just 2 possible states.
Ofcourse, there is behaviour for the non-null case and one for the null case. A better approach is to create two functions, one that takes a non-null argument and the other that doesn’t take that argument at all. Don’t use null
as a pseudo-boolean.
Listen to Gandalf. Null args shall not pass.
Let’s be honest, defensive programming sucks. It’s horrible to litter code with null checks and error checks. We don’t want to think that our teammates carelessly allowed to slip null
into our functions. It also mean that we don’t trust our unit tests that prevent us from passing that null
.
This doesn’t apply for public APIs, as we don’t know who is gonna pass what. If your language supports the @NotNull
annotation or a similar concept, use it to mark your public functions and you can fail fast by throwing something like an IllegalArgumentException
.
I hope this helps you avoid writing error-prone code as it has helped me. What are your views? Let’s chat on Twitter.
Click here for trick #4.
As always, this post was inspired by Uncle Bob and his book Clean Code.