#begin
Today we will take a look at a chapter where I think Prof. Ousterhout and Uncle Bob are somewhat on the same line again. Both of them want you to choose good names for concepts in your code. Uncle Bob has lot’s of practical advise and Prof. Ousterhout shares some more high level i.e. philosophical aspects of naming things. So let’s find out!
Choosing Names
Chapter 14 is called Choosing Names and again I think the title already spoils what this chapter is about. When we think back to Clean Code there is also a chapter dedicated to choosing good names for many concepts like fields, properties, variables, functions, arguments to these functions, classes and many other Unity3D specific resources likes prefabs, scriptable objects, models, textures and so forth. The main giveaway from the chapter about names in Clean Code was that names must be intention revealing. They must communicate the correct domain objects and there are some practices to do this correctly like a maintaining ubiquitous languages by referencing domain driven design concepts, using nouns for objects, using verbs, or a combination of a verb and a noun for function names. And adhering to generally accepted standard for things, like starting boolean fields or properties with an ‘Is’ or ‘Has’ prefix. Thus renaming a boolean called Moving, to IsMoving for example. Or that the scope of things will relate to the naming of thinks so for variables, the smaller the scope, the smaller the name of the variable. The best example here is a variable in a loop, so the I for forloops. For functions this scoping is the other way around, the larger the scope, the smaller the name should be since when the scope is large you are probably calling that function very often. So many public facing functions often have short names but private functions often have longer names. And Uncle Bob has a lot more really great advise in his Clean Code book which we all covered in the blogs about clean code. You can go back and read them, or you can pickup your copy of the book and read it yourself.
But let’s see what Prof. Ousterhout’s advise for choosing good names is. I honestly cannot really remember anymore, but let’s see and compare it to Clean Code. He starts of by saying that good naming is a really underrated aspect of software design. And I think I agree. The Domain Driven Design movement did a really great effort to counter this, but still, you will often see badly named code.
He then says something I think Uncle Bob would agree with and that is, and I quote: “Good names are a form of documentation: they make code easier to understand. They reduce the need for other
documentation and make it easier to detect errors”. This is literally exactly what Uncle Bob teaches you to do in Clean Code. Clean code is intention revealing and self describing. That’s the entire purpose of Uncle Bob’s Clean Code book.
John says that bad names will lead to bugs and increase complexity. And since we continue to write code and add features this complexity will grow and thus have a significant impact on complexity and manageability.
I totally agree and I bet Uncle Bob would as well. I think both of them are still on the same line here.
Next Prof. Ousterhout gives an example of bad naming that cause bugs. He says that bad names can have severe consequences. The example he gives is about an operating system he developed together with some graduate students. They would use a name “block” for referring to physical block numbers on disk, but also to logical blocks numbers within a file. I think you can feel the bug coming right. There was a bug where the block referred to a logical block number but was used in a physical block number context. They renamed such variables to fileBlock and diskBlock to make them more descriptive. This is indeed a really obscure bug you will only find after a long time of debugging. Prof. Ousterhout says he spend six months trying to find the bug. He says he just had to since he considers any unresolved bug to be an intolerable personal insult.
Haha, he’s so right. Bugs you wrote yourself, into your own code are indeed an insult. I feel the same way when it happens to me. And the bad part is that these bugs often occur in code that is really hard to test, so they might be just on the edges of bounded contexts for example.
So the example he gave was about a bad name causing a large bug. That took 6 months of Prof. Ousterhout himself to be fixed. Now that’s an investment right. The key giveaway is that good names are important. But unfortunately many developers do not spend much time thinking about names. Most of them, tend to take the first name that comes to mind.
We have talked about this in previous blogs as well. Nowadays we have very powerful IDE’s with automated refactoring tools. So there is no excuses for bad names anymore. You can just hit your rename shortcut in your IDE and the tool will do all the code changes. So Shift+F6 is really baked in my muscle memory. That’s rename in Rider with Intellij keybinds.
John says and I quote: “you shouldn’t settle for names that are just “reasonably close”. Take a bit of extra time to choose great names, which are precise, unambiguous, and intuitive. The extra attention will pay for itself quickly, and over time you’ll learn to choose good names quickly”. And I totally agree with him. Good names, make code a lot more readable and maintainable. And if they match your domain correctly, you will increase the abstraction level in my opinion.
Next up is a very short section about the goal of good names being to create an image in the mind of the reader about the nature of the thing being named. A good name must be intention revealing as Uncle Bob always says. John says you can ask yourself the following question when naming things: “If someone sees this name in isolation, without seeing its declaration, its documentation, or any code that uses the name, how closely will they be able to guess what the name refers to? Is there some other name that will paint a clearer picture?”
I think this is a really good question to ask yourself. Having precision in your naming will really add to the value of the code and reduce the complexity of the system. Although it will still sometimes be rather difficult to name things since some domains are inherently hard to understand. But I agree that you should be able to name things so that readers who reading it in isolation, without seeing its declaration or documentation should be able to understand what the name means. But I suppose, some domain knowledge is required.
John also specifically says that names are a form of abstraction. And I totally agree and I bet Uncle Bob would as well. And like other forms of abstraction, the best names are those that focus attention on what is most important about the underlying entity while omitting details that are less important. John talked about this in one of the earlier chapters already.
Next is a section called: “Names should be precise”. Prof. Ousterhout says that good names have two properties: precision and consistency. Most names are to vague or generic and thus do not provide much meaningful information. This is something Uncle Bob talks a lot about as well. A variable called time does not tell you much in most situations. Not even in like a stopwatch class for example. Does time mean, total time? Lap time? Some interval? I don’t know.
John provides some examples of bad names like a variable called “blinkStatus” which referred to the cursor carret blink state. The code was for some text editor project. But the work “Status” being tangled on the the end of the variable is far to vague since status does not provide meaningful information. What does the word status mean? John renamed this variable to “cursorVisible” and I think we can do better, my suggestion would be to rename it to “isCursorVisible” since we are dealing with a boolean variable here. And it’s an accepted standard to start a boolean with an ‘Is’ or ‘Has’ prefix.
Another example of a bad name, and where I’m definitely guilty of myself is a variable names “result” as a value being returned from a method. First, it might be misleading since result, might not even be the actual return value of the function. Which is pretty funny because I an definitely guilty of this. And second, a variable named result does not provide any information about what it means or contains.
Prof. Ousterhout then raises another red flag and it says, and I quote: “If a variable or method name is broad enough to refer to many different things, then it doesn’t convey much information to the developer and the underlying entity is more likely to be misused”. And he’s totally right.
He then continues with the fact that there are some exceptions, like choosing variables called I or j in for loops. This is industry standard and I agree and Uncle Bob says the same thing in Clean Code so I’m sure he’ll agree as well. If you choose other variable names in loops like a and b I can guarantee you people will be confused. And these variable names will probably be renamed at first sight.
Prof. Ousterhout then says something really, really interesting and I quote: “If you find it difficult to come up with a name for a particular variable that is precise, intuitive, and not too long, this is a red flag. It suggests that the variable may not have a clear definition or purpose. When this happens, consider alternative factorings. For example, perhaps you are trying to use a single variable to represent several things; if so, separating the representation into multiple variables may result in a simpler definition for each variable. The process of choosing good names can improve your design by identifying weaknesses”.
He’s so right about this. If you find yourself in the situation where you simply cannot come up with a proper name for something. You might want to reconsider your design and maybe refactor it so you can remove this thing you find difficult to name and simply remove it. I’ve ran into this issue before for sure, but I can’t really give you a nice concrete example of the top of my head.
He then raises another red flag, which refers to the section I just quoted and it goes: “If it’s hard to find a simple name for a variable or method that creates a clear image of the underlying object, that’s a hint that the underlying object may not have a clean design”.
Next up is the concept that you should use consistent names. Prof. Ousterhout says that in many systems specific variable or class names are used over and over again and you should stick to those and not come up with some random other name each time. This highly correlates with Uncle Bob’s advice in Clean Code. Uncle Bob also says you should be consistent about names for classes; So don’t have classes like PlayerSingleton, EnemyController and GameManager which refer to the same thing, suffix them all with Singleton, controller or manager. But not use these three different suffixes to mean the same thing, some kind of singleton class.
John says that consistent naming reduces the cognitive load on developer. Once a developer has seen some name in some context they can reuse that knowledge and instantly make assumptions when they see the name in a different context. This is so true!
He then continues with 3 requirements for consistent names: “first, always use the common name for the given purpose; second, never use the common name for anything other than
the given purpose; third, make sure that the purpose is narrow enough that all variables with the name have the same behavior.“
This is such great advice! It’s similar to clean code, yet different. Uncle Bob gives somewhat the same advise but I think Prof. Ousterhout articulates it very well here. Especially rule three “make sure that the purpose is narrow enough that all variables with the name have the same behavior”. I think this is a great rule since it really makes you think about names well enough. Consistency is an important thing in naming and I would also extend these rules not to just variables, but also fields, properties, methods and classes.
The chapter ends with a discussion about the Go style guide, which wants developers to do the exact opposite. In Go variables should be as short ans you can make them so for example: ‘ch’ for character or channel, and just a single ‘d’ for data, difference, or distance, and so on.
I’m not much of a big fan of this personally but I think, once you get the hang of it in a Go context it will probably make sense. Especially when the entire community does it this way. Don’t divert from best practices. In Clojure for example, or maybe any kind of LISP, there is this practice that you put a ‘!’ at the end of a function with side effects and a ? at the end of a function when it’s some kind of query. Clojure prefers a snake-case naming convention by the way. So it’s not short, as Go.
Concluding arguments for this chapter go as follows, and I quote: “Well chosen names help to make code more obvious; when someone encounters the variable for the first time, their first guess about its behavior, made without much thought, will be correct. Choosing good names is an example of the investment mindset discussed in Chapter 3: if you take a little extra time up front to select good names, it will be easier for you to work on the code in the future. In addition, you will be less likely to introduce bugs. Developing a skill for naming is also an investment. When you first decide to stop settling for mediocre names, you may find it frustrating and time-consuming to come up with good names. However, as you get more experience you’ll find that it becomes easier; eventually, you’ll get to the point where it takes almost no extra time to choose good names, so you will get the benefits almost for free.”
#end
01010010 01110101 01100010 01100101 01101110
Recent Comments