OOD Class Principles and Testability

This is the final post in my series on OOD class principles and testability. It has included:

There was a pit stop at YAGNI and Testability as it had some bearing on the OCP. It was all kicked of by Benefits of Testability. Which was inspired by Dr. Stefan Jungmayr’s dissertation Improving testability of object oriented system.

BTW Stefan’s site http://www.testability.de/ is a great resource (English Translation).

Here is a table that I think quickly summarizes how, when followed, the principles relate to the three aspects of testability.

Observability Controllability Understandability
Single Responsibility Principle Yes-less Yes-less Yes-less
Interface Segregation Principle Yes-less /w doubles Yes-less /w doubles Yes-less /w doubles
Dependency Inversion Principle Yes-less /w doubles Yes-less /w doubles Yes-less /w doubles
Open Closed Principle Yes-less /w doubles Yes-less /w doubles Yes-less /w doubles
Liskov Substitution Principle No No Yes-reuse
Law of Demeter Yes-less Yes-less Yes-less

Yes-less = Because the surface area and or type population of the test subject has been reduced, there is less to: observe, control, or understand.

Yes-less /w doubles = The benefits of Yes-less are gain only by using test doubles (e.g. mock) and interaction based testing.

Yes-reuse = Because test fixtures can be reused to test all subtypes.

After studying the table I noticed two things. It pays to have less to work with in a test. That is to say that when there are very few types and members involved in a test it will be easier to understand. It is easier to observer and control less than more. When you can’t have less it pays to have a test double.

It seems there two general fulcrums that you have to control testability. They are decreasing the surface area and type population or introducing test doubles. As well, they help in increasing the effectiveness of unit tests by eliminating failure points other than the test subject.

Single Responsibility Principle and Testability

Straight from the source:

THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A
CLASS TO CHANGE.

What is a Responsibility?
In the context of the Single Responsibility Principle (SRP) we define a responsibility to be “a reason for change.” If you can think of more than one motive for changing a class, then that class has more than one responsibility. This is sometimes hard to see. We are accustomed to thinking of responsibility in groups.

The SRP is one of the simplest of the principle, and one of the hardest to get right. Conjoining responsibilities is something that we do naturally. Finding and separating those responsibilities from one another is much of what software design is really about.

SRP has the broadest relationship to testability out of all the OOD principles. It relates to all aspects of testability; Observability, Controllability, Understandability. To test something you must be able to observe or sense that it did what it was supposed to do. To test something you must be able to control or manipulate it. Control is needed at the very least to instigate it to do the thing that you desire to test. In the case of unit tests and some other testing the control will be used to isolate the test subject. To test something you must be able to know: What needs to be controlled and observed. How to control what needs to be controlled. Lastly what the out come should be.

The fewer the responsibilities of the test subject the less that needs to be; observed, controlled, and understood. Chances are the fewer the responsibilities the less surface area the test subject will have. As well the less need to have interactions with other types. This reduces coupling and the type population tied to the test subject. All this effects testability.

The Interface Segregation Principle and Testability

So c2.com does not maintain a good page on ISP. I will lean on David Hayden to round up a quick explanation of ISP:

The Interface-Segregation Principle focuses on the cohesiveness of interfaces with respect to the clients that use them. Here are some other descriptions I found while Googling:

  • “Many client specific interfaces are better than one general purpose interface“
  • “The dependency of one class to another one should depend on the smallest possible interface“
  • “Make fine grained interfaces that are client specific.“
  • “Clients should not be forced to depend upon interfaces that they don’t use. This principle deals with the disadvantages of fat interfaces. Fat interfaces are not cohesive. In other words the interfaces of classes should be broken into groups of member functions.“

One of the first things that comes to my mind when exploring how ISP effects testability is surface area. ISP is aimed at reducing how much a client is exposed to, and a test is a client. Reducing surface area can have the affect of reducing the type population as well. This is only really helpful in the context of test doubles (e.g. mock). Using the class behind the slim interface in the test can increase the type population possibly negating all benefit to testability. This constructor to the backing class or it’s implementation can negate the benefit.