Let’s learn how to write function in a clean way.
In a previous post I talked about clean code and how much it is important to me.
In this new post I will talk about another topic of the uncle bob clean code book: functions.
How can we have write a good function/method? This is the list of the features that a function must have to be considered “good”:
Let’s go deeper in the details of each one of these features.
What does Uncle Bob mean when he talks about “small” functions? How much small must be a function to be considered “small” in the clean code dictionary? Let’s take a quote from his book clean code:
In the eighties we used to say that a function should be no bigger than a screen-full. Of course we said that at a time when VT100 screens were 24 lines by 80 columns, and our editors used 4 lines for administrative purposes. Nowadays with a cranked-down font and a nice big monitor, you can fit 150 characters on a line and a 100 lines or more on a screen. Lines should not be 150 characters long. Functions should not be 100 lines long. Functions should hardly ever be 20 lines long.
Honestly I think that also 20 lines are already too much. You must consider that most of the automated code quality tools available on the market consider a function of 20 lines too much long by default. Sometimes you will be tempted to break this rule , but remember: smaller functions will always be more readable. To write such small function you have to follow some simple rules:
if elsemust be of one line (most of the time a call to another function)
forloop must be of one line (most of the time a call to another function)
whileloop must be of one line (most of the time a call to another function)
This is simple: function should do just one and only one thing. Uncle Bob wrote this phrase in his book:
FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.
But wait: how can we be sure that a function does just one thing? Our function doesn’t do just one thing If we can extract other functions with a name and an implementation that is not a restatement of the implementation of the current function.
Our function must contains instruction that are at the same level of abstraction. Every instruction in a function must express a concept at the same level of the others contained in it. This basically means that we will have function/method with higher concept at the top level of our classes/programs, and by going deeper in the source code we will find functions/methods with lower concepts. This top-down relation between higher-lower level concept is called The stepdown rule. Uncle Bob described this rule very well (and it is basically a remark of the concept expressed in this paragraph):
We want the code to read like a top-down narrative. We want every function to be followed by those at the next level of abstraction so that we can read the program, descending one level of abstraction at a time as we read down the list of functions. I call this The Stepdown Rule. To say this differently, we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.
This is a consequence of the fact that our function should do one thing: our function should not generate side effects when it is executed. In particular our functions should not:
This feature for “clean function” it is strictly correlated to my previous post clean code: meaningful names. There’s one more thing that it is import to note: the most of the IDE available on the market today let the developer speed up their writing abilities with a lot of autocomplete and refactoring features (check out my previous article to better understand what I mean). So don’t be afraid and use very long and expressive functions/methods name. Your code will really become like a beautiful poem to read .
How much arguments should a perfect clean code function have? zero . Then we could have monadic (1 argument), dyadic (2 arguments) or triads (3 arguments) functions. Functions with more than 3 arguments should be avoided whenever possible. When the number of arguments start to growth to more than 3 arguments it is possible wrap them in specific class that describe better their meaning. This kind of classes are called argument objects. For example Uncle Bob shown us a beautiful example in his book, where he rewrote a factory method to create a circle using arguments objects. Let’s see his code snippet:
/// Simple version Circle makeCircle(double x, double y, double radius); /// With arguments objects Circle makeCircle(Point center, double radius);
Do you see how much more readable and clear it is the second version of the
makeCircle function? Yes, I can see it
Let’s see what Uncle Bob says about the command query separation:
Functions should either do something or answer something, but not both. Either your function should change the state of an object, or it should return some information about that object. Doing both often leads to confusion.
I think there’s nothing else to ad to this point .
This is a feature strictly related to languages that supports exceptions. Generally speaking if you need to return an error to a user of your class, try to avoid as much as possible error code. Always use exceptions whenever possible. In this way the user of your class will not abuse of nested if cases to check returned error code from your functions.
Duplication may be the root of all evil in software.
This quote from Uncle Bob’s book is more expressive than any other explanation. Developers can choose from a wide range of programming techniques to avoid duplication in their code. Generally speaking duplication make your code hard to maintain, because often you need to propagate an a modification for a new feature in a lot of different places. We can close this section with another quote from Uncle Bob that I think it is quite interesting:
It would appear that since the invention of the subroutine, innovations in software development have been an ongoing attempt to eliminate duplication from our source code.
That’s all for Uncle Bob and functions. If you didn’t read yet Uncle Bob “Clean Code” book it’s time to catch up the gap and get a copy for yourself .
I recently discovered MockK, a mocking library created for Kotlin. Let’s see how it is possible to write modern unit tests with MockK + JUnit 5.Read More
During the last months I worked a lot with Spring Boot backend applications. In this post I explain how you can consume a REST api from a Spring Boot application using RestTemplate and (the new) WebClient.Read More
Recently I upgraded my ID3TagEditor swift package to the latest Swift tools version (5.3). During the upgraded I discovered that now you can bundle reources with your Swift package. In this post I will show you how you can do this, and also a interesting trick in order to be able to build a project as a Swift Package and as a standard project from Xcode.Read More