Friday, June 17, 2016

Conjunctions we... hate

Recently I’ve written about implementation-related names and I’ve presented a few examples where the method name was incorrect because of its strong relation with the body.
At one moment, we had the following code:
boolean isComplexOrUnreadableWithTests() { 
    return (complex || unreadable) && tests.exist(); 

Just to remind you of the context: it was supposed to find out whether we may or may not do the refactoring:
if (code.isComplexOrUnreadableWithTests()) {

Recently I’ve told you that the name is wrong because of its direct relation to the implementation. However, this is not the only problem. The use of conjunctions in the method’s name is a sign that we could not find a right name and we just list all known things that we’ve done. It does not matter whether this list is implementation- or logic-related.

About implementation or logic?

What if I wanted to change the name of the isComplexOrUnreadableWithTests() method into:
boolean isJustifiedAndPossible() { 
    return (complex || unreadable) && tests.exist(); 

Would it be better? Isn’t it the logic-based name now?
We’ve got the part about justification:
(complex || unreadable)

And about the possibility of refactoring:

When the implementation changes, we don’t need to change the name, do we?

Well, not exactly. Let me explain.
We did not change implementation-oriented name into the logic-oriented one. We just made a mix. We used known words (probably from the domain area) to hide implementation behind those two terms. However, by reading the name of the method, we still know HOW the answer to the question looks like. And we still don’t know what the original question was anyway.

When the result is a boolean value I assume that asked question was something like “is it something?”. In the presented name we still don’t have any information about “something”.

Also the name of the method is not so lasting as we may think. If, during development, we decide to remove the tests.exist() part from the code, we need to reflect this change in the name and change it into:
boolean isJustified() { 
    return complex || unreadable; 

Additionally, you may notice that now the name tells you exactly what the question is.
However, the initial change required both changes inside the method’s body and with its name.

Missing term

Except the name of the method itself, situations in which we use known terms to describe something new, but without naming it, can lead to a few more problems:
  • Communication - you will explain the term each time you will talk about it. You just would like to put another person into the same context’s understanding. Wouldn’t it be better to have a separate phrase to express “The Something”?
    As an example, you may try to imagine how your conversations with other developers would look like if you could not use design patterns’ names. Those conversations would definitely be longer and would carry a higher risk of misunderstanding.
    Missing term leads to exactly the same problems.

  • Duplication - there is a chance that someone will ask the same question, but because of lack of a proper term they would not be one hundred percent sure whether the question is really the same, whether the same intention stands behind it. In that case there’s a chance they will choose an easier way and will just write the code that gives them the answer.

  • Asking the same question - missing term means that it would be hard to find this code when we would like to ask the same question. Why? Because we would not know what to look for. Or we may know, but the code itself could not express the intention and there may be no relation between what we are looking for and what was written.

How to spot the problem?

Well, it is not always as easy as in the given example. However, there are two things that may help you figure out whether the name is good or requires improvements:
  • Conjunctions - we are talking so much about Single Responsibility Principle and it is important to apply this principle when we are writing code. And aren’t conjunctions the sign that SRP is not followed? When we use words like “and” or “or”, we usually talk about more than one thing.
    Whenever you spot a conjunction in the name of your variable, method or class, you should treat it as a warning. There is a strong chance that improvement is needed.

  • Body change leads to name change - if the change in the code does not change the whole rationale behind functionality and yet still requires changing the name of the method/class, that’s a sign that probably the name does not express the true intention.
    In such case we should rethink the name and improve it.

Hi, my name is…

I know that sometimes it is much harder to find a good name than write an implementation, but it does not mean that we should not try. It is in our own interest to make the names as descriptive and accurate as possible. It will save our time in the future.