Chapter 5. Design – If It's Not Testable, It's Not Designed Well

 

"Simplicity is the ultimate sophistication."

 
 --Leonardo da Vinci

In the past, the software industry was focused on developing software at high speed, with nothing in mind but cost and time. Quality was a secondary goal, with the fake feeling that customers were not interested in it.

Nowadays, with the increasing connectivity of all kinds of platforms and devices, quality becomes a first-class citizen in customers' requirements. Good applications offer a good service with a reasonable response-time, without being affected by a multitude of concurrent requests from many users.

Good applications in terms of quality are those that have been well designed. A good design means scalability, security, maintainability, and many other desired attributes.

In this chapter, we will explore how TDD leads developers to good design and best practices by implementing the same application using both the traditional and TDD approaches.

The following topics will be covered in this chapter:

  • Why should we care about design?
  • Design considerations
  • The traditional development process
  • The TDD approach
  • Hamcrest

Why should we care about design?

In the coding world, whether you are an expert or a beginner, there are some scenarios where code seems to be weird. You can't avoid a feeling that something is wrong with the code when reading it. You even occasionally wonder why the previous programmer implemented a specific method or a class in such a bad manner. This is because the same functionality can be implemented in a vast number of different ways, each of them being unique. With this big number of possibilities, which is the best one? The answer is that all of them are valid as they all achieve the goal. However, it is true that some considerations should be taken into account while finding better solutions. This is where design becomes important.

Design principles

The TDD philosophy encourages programmers to follow some principles and good practices that make code cleaner and more readable. As a result, our code becomes easy to understand and safe to modify in the future. Let's take a look at some of the basic software design principles.

You Ain't Gonna Need It

YAGNI is the acronym for the You Ain't Gonna Need It principle. It aims to erase all unnecessary code and focuses on the current functionalities, not the future ones. The less code you have, the less code you're going to maintain and the less probability that bugs are introduced.

For more information on YAGNI, visit Martin Fowler's article available at http://martinfowler.com/bliki/Yagni.html.

Don't Repeat Yourself

The idea behind the Don't Repeat Yourself (DRY) principle is to reuse the code you previously wrote instead of repeating it. The benefits are less code to maintain and the use of code that you know that already works, which is a great thing. It helps you to discover new abstraction levels inside your code.

For additional information, visit http://en.wikipedia.org/wiki/Don%27t_repeat_yourself.

Keep It Simple, Stupid

This principle has the confusing acronym of KISS and states that things perform their function better if they are kept simple rather than complicated. It was coined by Kelly Johnson.

To read about the story behind this principle, visit http://en.wikipedia.org/wiki/KISS_principle.

Occam's Razor

Although Occam's Razor is not a software engineering principle but a philosophical one, it is still applicable to what we do, and is very similar to the previous principle with the main derived statement being as follows:

 

"When you have two competing solutions to the same problem, the simpler one is the better."

 
 --William of Ockham

For more information on Occam's razor, visit http://en.wikipedia.org/wiki/Occam%27s_razor.

SOLID

The word SOLID is an acronym invented by Robert C. Martin for the five basic principles of object-oriented programming. By following these five principles, a developer is more likely to create a great, durable, and maintainable application:

  • Single Responsibility Principle: A class should have only a single reason to change.
  • Open-Closed Principle: A class should be open for extension and closed for modification. This is attributed to Bertrand Meyer.
  • Liskov Substitution Principle: This was created by Barbara Liskov, and she says a class should be replaceable by others that extend that class.
  • Interface Segregation Principle: A few specific interfaces are preferable than one general-purpose interface.
  • Dependency Inversion Principle: A class should depend on abstraction instead of implementation. This means that class dependencies must be focused on what is done and forget about how it is done.

For further information on SOLID or other related principles, visit http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod.

The first four principles are part of the core of TDD thinking, since they aim to simplify the code we write. The last one is focused on classes construction and dependency relationships in the application assembly process.

All of these principles are applicable and desirable in both test and non-test driven development, because, apart from other benefits, they make our code more maintainable. The proper practical application of them is worth a whole book by itself. While we won't have time to go deep into it, we encourage you to investigate further.

In this chapter, we will see how TDD induces developers to put some of these principles in to practice effortlessly. We will implement a small but yet fully functional version of the famous game Connect4 with both TDD and non-TDD approach. Note that repetitive parts, such as Gradle project creation and so on, are omitted, as they are not considered relevant for the purpose of this chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.31.165