Comments on ThoughtWorks Anthology

I’ve just finished reading the “ThoughtWorks Anthology” book, motivated by Guilherme Silveira and learned some really useful things on it, that I would like to expand a little.

Besides the less technical articles published on it, I really enjoyed the chapter written by Jeff Bay called “Object Calisthenics”, where the writer propose 9 exercises in order to improve the reader way of writing code, making it’s code cleaner and easiear to understand therefore easier to test.

I’ll just sum up the 3 ones that I found more interesting and add a few things:

Do not have more than one identation level inside a method

Take the following method, which simply increase the price of some products if it’s value are above 50:

public void redefinePrices(List products, Integer toIncrease) {
	for(Product p : products) {
		Integer actualValue = p.getActualValue();
		if(actualValue > 50) {
			p.setActualValue(actualValue + toIncrease);
		}
	}
}

As you can see, inside this method there are two identation levels, which makes the code easier to read if we had only one, like the following:

public void redefinePrices(List products, Integer toIncrease) {
	for(Product p : products) {
		increaseValue(p, toIncrease);
	}
}

private void increaseValue(Product product, Integer toIncrease) {
	Integer actualValue = product.getActualValue();
	if(actualValue > 50) {
		product.setActualValue(actualValue + toIncrease);
	}
}

Ok, now there’s two methods, but, there’s no doubt that the redefinePrices method is clearer than in the first version. The advantage of this approach is that your code becomes self-descriptive, with the method call inside it. When you need to read the method redefinePrices, instead of interpret conditional logics or loops, just read what is being done inside the nested method described by the increaseValue method name.

Avoid abbreviation on names

One of the largest mistakes I see on projects nowadays are the use of abbreviation on classes, methods and variables name. The use of abbreviation often leads to a code full of hard to understand names, which affects mostly those who are new to the project, increasing their learning curve on the domain model and consequently from the software itself.

I use to say that abbreviation is a plague that exists on software development, and it’s hard to get rid of it. It’s tempting to, for instance, instead of writing generateCardCode to write generateCC. This may also indicate that you have some problems regarding ubiquitous language on your project.

Jeff Bay also says that you may try to make your names to take no longer than 2 words. I’m not so severe on that, but I believe that 3 words are enough to make a good name (of course, this do not include test names).

Do not use else clauses

When using if/else clauses, it’s common to make the code inside these clauses hard to understand. This is even more evident when you have a complex block of if/else clauses, making the logic cumbersome and complex. There are some approaches used to deal with this problem. The first, and simpler one is to just return the value you want. Say, that you have the following code:

public boolean shouldAcceptRequest(Destination destination) {
	if(destination.address().equals("foo")) {
		return true;
	} else {
		return false;
	}
}

You can simplify it to just one line, and also improve the readability of this piece of code:

public boolean shouldAcceptRequest(Destination destination) {
	return destination.address().equals("foo");
}

However, there are some cases when only returning the value is not enough, you may want to perform a small check before deciding what to return, like in the following example:

public Integer divideValues(Integer a, Integer b) {
	if (b == 0)
		return 0;
	else
		return a / b;
}

You can introduce ternary operator to make the code above cleaner:

public Integer divideValues(Integer a, Integer b) {
	return b == 0 ? 0 : a / b;
}

There’s also the classical case when what you’re wanting to test against an if/else clause can be abstracted on objects, and you can introduce the Strategy pattern, so you can remove the if clauses, and the executed behavior will be decided from the implementation it’ll be passed to be executed, like the example below:

public void applyDiscount(Customer customer, Product product) {
	product.applyDiscount(customer.discountRate());
}

In the previous example, it doesn’t matter if it is a RegularCustomer or a SporadicCustomer, they have different discount rates, but since I’m using polymorphism (note the Customer interface), I can treat them the same way, but the discountRate method return different values for each kind of customer.

Conclusion

While reading the book, there are others techniques proposed by Jeff Bay, that I didn’t went into here. Some might say that a few of these issues are very radical, in fact, as proposed as an exercise from the writer, you won’t need to do this everyday, but just try to save some 1000 lines of code, or a time-box (say, a week) to follow these advices, and you’ll see how this changes the way you’ll write your everyday code.

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.