Tag Archives: Code Quality

The Heart of Software

The heart of software is solving business problems. Have you heard it? Yes, so have I. The fact that it’s so rarely recognized or practiced is just inexplicable.

It’s not about programming. Nor is it about technology. Nor is it about languages, testing, architectures, networking, whatever. Sure, these are nice tools. But they are only tools. It’s amazing how much focus is paid to tools and how little to the problem at hand. What would you say to a carpenter who delivered wobbly (but still expensive) furniture for your dream kitchen only because the tools he had were bought at a “as much as you can carry for $10” bargain? You don’t care about his tools. You want a functional, robust product.

The purpose of frameworks, libraries and architecture is to serve, not command. When a framework imposes uncomfortable restrictions or affects the way your business logic and model is shaping up, in the best case it’s unsuitable for the problem. Don’t use it. Choosing an unsuitable or unknown tool only because it looks nice in resume is a cardinal sin deserving capital professional punishment.

Whatever you do, focus on the big picture. In case of software, it should be solving the business problem of your customer.

By no means is it a novel idea, but still it is extremely important and too rarely understood. The reason why it’s here is that it’s going to be an introduction to a series of articles on Domain-Driven Design. It’s a great approach to software development itself (like the rant above), but also to object-oriented programming and design. That’s what makes all the trendy OO* techniques shine. It’s a shame how often it is overlooked by teachers. If there’s one book every OO/business developer has to read, it’s “Domain-Driven Design” by Eric Evans.

OO* without DDD (or at least its bulk concepts) is like giving a diploma in architecture to everyone who can hold a pencil and draw on a sheet of paper. Regardless of whether what she produces is a usable, solid construction.

Design by Contract – Simple but life-saving conventions

One of the possible implementations of programming by contract (aka design by contract) is use of informally defined invariants. Apart from being a useful theoretical concept, they have great impact on code quality and readability.

Nasty complexity and uncertainty

Suppose our system performs and tracks notifications. When one notification fails for some reason, it is retried. Each attempt is performed asynchronously by a third party process. In our system we record that an attempt was started, then call the 3rd party service. Callback from that service is supposed to update our attempt status. So we need record attempt state as one of: executing, successful, failed.

The callback is not 100% reliable, and the notification will only be retried if the last attempt failed. What we decided to do is assume that not hearing back in 15 minutes means a failure.

We could code it like this:

List<Notification> getNotifications(Date start, Date end) {
	if(start == null || end == null) {
		return null;
	}
	return repository.listNotifications(start, end);
}

List<Notification> filterExecutingNotifications(List<Notification> notifications) {
	if (notifications == null) {
		return null;
	} else {
		List<Notification> result = new LinkedList<Notification>();
		for (Notification candidate : notifications) {
			for (Attempt attempt : candidate.getAttempts()) {
				if(attempt.isExecuting()) {
					result.add(candidate);
					break;
				}
			}
		}
		return result;
	}
}
	
public void discardHungAttempts(Date start, Date end) {
	List<Notification> notifications = getNotifications(start, end);
	notifications = filterExecutingNotifications(notifications);
	if(notifications != null {
		for(Notification notification : notifications) {
			List<Attempt> attempts = notification.getAttempts();
			if(!attempts.isEmpty()) {
				Attempt attempt = attempts.get(attempts.size()-1);
				discardIfOldEnough(attempt);
			}
		}		
	}
}

How does it work? What can we tell about properties of each variable? What if it’s null? What properties does it satisfy? Can this collection be empty? It may seem that all these conditions are necessary. You can’t be absolutely sure that all variables aren’t nulls. Even then, you can’t be sure about their properties. You couldn’t call attempts.get() in the last loop if the collection was empty, so there’s the isEmpty() condition. And what if getNotifications() returns null instead of an empty list…?

This is just a simplistic self-contained blog sample. Normally it would most likely be spread across several classes and even modules. In a real project conditional complexity would explode. Number of paranoid if(this == null) and if(that.isEmpty()) conditions and possible scenarios would grow. At the same time readability and maintainability would shrink dramatically. And you still could not be 100% sure about everything.

The complexity is not only present in code. It’s a bit harder to read, but that may be bearable. What’s worse is it’s mental complexity. In any non-trivial project it would mean a lot of uncertainty, possible bugs and maintenance headache. Moreover, this is not domain complexity. It’s not a part of application logic. It produces no value. All this code is there for technical reasons only. And it makes the actual logic blurry.

Global contract: don’t pass nulls

What if the team agreed on the following contract: “We never pass nulls as arguments”? This is our invariant. At the beginning of each method we know that each argument is not null. That code would become:

List<Notification> getNotifications(Date start, Date end) {
	return repository.listNotifications(start, end);
}

List<Notification> filterExecutingNotifications(List<Notification> notifications) {
	List<Notification> result = new LinkedList<Notification>();
	for (Notification candidate : notifications) {
		for (Attempt attempt : candidate.getAttempts()) {
			if(attempt.isExecuting()) {
				result.add(candidate);
				break;
			}
		}
	}
	return result;
}
	
public void discardHungAttempts(Date start, Date end) {
	List<Notification> notifications = getNotifications(start, end);
	notifications = filterExecutingNotifications(notifications);
	for(Notification notification : notifications) {
		List<Attempt> attempts = notification.getAttempts();
		if(!attempts.isEmpty()) {
			Attempt attempt = attempts.get(attempts.size()-1);
			discardIfOldEnough(attempt);
		}
	}
}

A little bit better. Lost 9 lines along with a few code blocks and forks. The logic is exactly the same, but now it’s a lot easier to grasp.

Local contracts

Let’s have a look at filterExecutinglNotifications() method. What it returns is a list of notifications with an executing attempt. It implies that each of the returned notifications is guaranteed to have non-empty collection of attempts, one of which is executing. This is a useful invariant.

Taking this into consideration you could rewrite the last method to:

public void discardHungAttempts(Date start, Date end) {
	List<Notification> notifications = getNotifications(start, end);
	notifications = filterExecutingNotifications(notifications);
	for(Notification notification : notifications) {
		List<Attempt> attempts = notification.getAttempts();
		Attempt attempt = attempts.get(attempts.size()-1);
		discardIfOldEnough(attempt);
	}
}

Conclusion

Even simple chunks of code and interactions can benefit greatly from proper use of contracts / invariants. This trivial example was shrunk from 37 down to 26 lines. Cyclomatic complexity dropped by an order of magnitude. What’s more important, we can be sure that everything is as robust as it can be.

Using such conventions and invariants is really simple regardless of project size. On the other hand, the benefits are truly invaluable. It’s puzzling that many very large projects still don’t do it.