(filtered by tag 'readability')

Test Driven Learning

Added: August 06, 2010

Tags: learning readability testing

I've just found interesting post Test Driven Code Review. Its title and the 2nd sentence caught my attention:

When reviewing or just reading such code, it's often best to first read the tests.
That is something I started to use some time ago and I had very good experience with it many times. But not always. As Philip Zembrod writes further he had similar experience and coined terms well-specifying tests and poorly-specifying tests. I like them. What could be the better place to understand code you've just got to review without deep understanding of requirements and domain it touches? Well, I agree with the author it should be tests. But they have to be clean, easy to read and simple.

After being guilty myself in writing obscure tests in the past, I try to make them as easy and concise as possible for last couple of years. I think my turning point was when I (gradually with time) created a unit test using 13 mocks. Every time some of test (usually more at once) failed I had to go to deep analysis whether I really introduced bug or I just need to tweak one of those inconvenient mocks, because requirements changed.

I have learned a lot from that experience

  • Limited responsibility of class will ask for less mocks. It is always possible to rearrange responsibilities in some way to allow simpler testing (and understanding both production and test code).
  • Test should explain main points, hiding irrelevant details (like creation of data it needs, but they are not the reason for existence of this test; hiding details of how mocking library works while saying what you want to achieve).
  • Test should be concise, only couple of lines all focused to tell you a story. What environment you have, what you do with tested class and what effects you should see as the result.
Last two points are not dissimilar to good story. You create some tension with method name and then let the readers to read through without getting them lost or loosing interest. As the result they should learn something and hopefully it will be about expected behaviour of tested code instead of how complicated mocking can get :-)

But not everybody does

Sad part is I always find hard to read tests that are completely obscuring the main point. Apart from plenty of "easy" to fix tests I have seen also couple of ugly ones. The worst was 3500 lines long test with 32 mocks! It was worse than really thick book with unappealing name. I've never bothered to look at production code. (Fortunately I did not need to). OK, there is even sadder part: I am afraid the author(s) will never learn anything from this test experience. Maybe only one incorrect thing - unit testing is meant to be hard :-)

Back to reviews

I usually try to spread good ideas and I've found the code reviews are pretty good medium for suggesting simple improvements in tests without being caught as mentoring. Many times I found developers are too proud to accept explicit help, which is pity in my opinion. Disadvantage of this approach is high probability helped person will miss the bigger picture. But that might come later.

Is Javadoc useful?

Added: November 30, 2008

Tags: java quote readability

About 2 weeks ago I had discussion with a few colleagues of mine. I have asked them what they think about following Javadoc and how to enhance it.

class Person
{
    // definition of attributes, I am not stating them to 
    // avoid attracting your attention now
 
    /**
     * Gets value of the first name property.
     * @return first name of person
     */
    public String getFirstName()
    {
        return m_FirstName;
    }
}
I have provided additional constraints:
  • the class is as-is, we do not care about e.g. persistence (to avoid temptation to define maximum size).
  • we do not care about constructor (or setter) and what constraints it brings.
  • only this getter for Java Bean interests us here as my idea is to represent any simple method in general.
  • do not speculate what else could be done in this method, just provide useful Javadoc.
  • I have selected Person and first name as widely understood concept to make it harder to provide useful Javadoc (in order to shed more light into this apparently confusing concept ;-) )
As I expected I did not receive any useful (and in my opinion valid) suggestion. Following was suggested for example:
  • "Maybe format could be described" (there is none in my example).
  • "In case of future enhancements (e.g. encryption) it is better to have Javadoc present since beginning, because some developers will not add one when they are modifying it" (I have simplified this suggestion to make it shorter. Well, I am not sure if a group of developers who would not modify existing Javadoc is not bigger...)
I have got also useful suggestion: "I think that javadocs should not add anything unnecessary (over restrictive or superfluous or presumptuous)." Exactly that's my idea! What could Javadoc add in this case that is not already described what we have learned about in kindergarten? Yet, I have to provide one otherwise our Checkstyle will protest.

As is written in book Clean Code:

Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration.
I am not as strict about this (I am probably not able to express all my ideas cleanly often), but in general I agree that strict asking for Javadoc is healing symptoms instead of real root cause in typical code. Are you not persuaded yet? Well, what do you think about following example describing common usage of Logger?
/** Logger */
private static final Logger LOG = Logger.getLogger(Person.class);
While it is probable that there is only one Person.getFirstName() in codebase and it deserves some kind of documentation, what should I think about comment describing well known way how logger is used in about 2000 classes I have seen in our project till now?

Conclusion

I wanted to make title of this post attractive... I generally consider Javadoc to be useful. But I wanted to point out that sometimes there are valid reasons to skip it. Unfortunately Checkstyle is not able to identify these situations while people are.

Readable tests

Added: October 12, 2008

Tags: readability testing

I mentioned readable tests yesterday and I have found following text in book Clean Code today.

What makes a clean test? Three things. Readability, readability, and readability. Readability is perhaps even more important in unit tests than it is in production code. What makes tests readable? The same thing that makes all code readable: clarity, simplicity, and density of expression. In a test you want to say a lot with as few expressions as possible.
It is nice to find confirmation of my beliefs in the book I like a lot.

Thinking about it I am not sure how I acquired this knowledge. Whether it was from some book or article or I just realized it after seeing a lot of bad tests (and writing them too). Indeed, it happened many times that I found much easier to understand production code and then I was not able to decipher tests to see how to modify them (or how to add new test). Or to find why test is failing.

Many times it seems that people care much less about the tests. It would be interesting to know whether they do not care or do not believe they are worth of effort or they just do not know how to do them better. I suspect the last possibility is culprit most of the times. Fortunately this is the easiest to fix. It just needs learning...

My colleague wanted to add comment to recent post, asking how it is possible to achieve good quality of code. Somehow it did not work as he did not see captcha code. Anyway, I owe him an answer (I hope it was not rhetorical question).

What to do?

In my opinion it is not very hard task. To achieve good internal quality of code (easy to modify and extend, no bugs, no environment for breeding new bugs) a few "simple" things must be in use:

Continuous learning

Without learning we cannot grow, but because our code base grows, new situations happen all the time and some of them cannot be handled by applying of old tricks (like for example "comments and Javadoc everywhere" that was useful in old days). If you look at your code written 5 years ago and you are satisfied with it, you are probably doing something wrong.

Writing readable and expressive code

If code is not readable it takes long time to understand what is going on. If we do not understand code we need to modify problems will occur sooner or later.

Continuous and merciless refactoring

Everybody should try to enhance any code they believe can be enhanced. Piece of code could be written nicely, delivering all expected behaviours in the beginning, but it will inevitably rot with time as new features are added, requirements are changed an so on. So it is important to counter attack it with refactoring.

Nobody should be blamed if piece of code looks strange and contains code smells after some time. But I believe that all developers should be blamed if they allowed it to happen without trying to fix it.

Continuous enhancement of existing code might look like daunting task, but it does not need to be. Any small enhancement every day will do (like renaming local variable or extraction of method). If all team members are doing it continuously they will be rewarded with great code base after some time.

Good tests - unit, integration, acceptance

With "good" I do not mean covering everything, but written in way they do not stand in way of future enhancements. They need to be simple, readable and modifiable. Otherwise they will become part of legacy code we wanted to avoid by introducing them.

Coverage is important too, but if you are afraid to look at test code because there is no way you could understand it quickly, you have bigger problem, that gets even bigger with time until tests stop serving their purpose and only prevent changes (enhancements) of production code.

It works for me

There are more approaches, like pair programming, code reviews, working reasonable hours and so on, but I wanted to mention those that are in grasp of everybody. I said they are simple. What I mean is that there is no magic or something unachievable in them. They only need dedication, persistence and enthusiasm.

There might be another virtue needed - courage. Courage to go against main stream of developers (and managers) that are afraid of changes ("If it ain't broken don't fix it" is their mantra). They are just paralysed by their fear. For example I have heard excuses like "But you don't know what class in other module could depend on this so you should not change public API." Well, it seems reasonable, but unfortunately it is good as excuse only. Many potential problems caused by refactoring will be caught by tests for module and all others by integration build. So if it really happened, that some unforeseen dependence failed to compile I will know soon enough. Compare that risk with its alternative - having that terrible code staying as is for next 2-3 years, causing unforeseen problems as other people will hack new features into it in the future. Does refactoring of code still look like bigger risk to you?