2014-12-18

[讀書筆記] Design and Testability

Design and Testability

1. Why should I care about testability in my design?

In a testable design, each logical piece of code (loops, ifs, switches, and so on) should be easy and quick to write a unit test against, one that demonstrates these properties:

FICC

  • Fast
    • Runs fast
  • Isolated
    • Is isolated, meaning it can run independently or as part of a group of tests, and can run before or after any other test
  • Configuration-free
    • Requires no external configuration
  • Consistent
    • Provides a consistent pass/fail result
If you were doing test-driven development, you’d have no choice but to write a testable system.

2. Design goals for testability

2.1 Make methods virtual by default

Java makes methods virtual by default, but in .NET, you need to explicitly set it as virtual so you can override it in a default class.

An alternative is to have the class invoke a custom delegate.

Using virtual methods is handy, but interface-based designs are also a good choice.

2.2 Use interface-based designs

Refer to chapter 3~5

2.3 Make classes nonsealed by default

If you can’t inherit from a class, you can’t override any virtual methods in it.

2.4 Avoid instantiating concrete classes inside methods with logic

Tests might need to control what instance is used in the class under test.

Solution:
(1) Use the external tools such as Mock tool
(2) Ways in the 3rd chapter such as Factory Method.

2.5 Avoid direct calls to static methods

Try to abstract any direct dependencies that would be hard to replace at runtime.

Solution:
(1) Ways in the 3rd chapter      
      Abstract a static method away using the Extract and Override refactoring.(2) Avoid using any static methods whatsoever
(3) Trying to minimize the number of singletons or static methods

2.6 Avoid constructors and static constructors that do logic

Things like configuration-based classes are often made static classes or singletons because so many parts of the application use them.

在Constructor建立多個邏輯或是static constructor 會因為很多地方有使用到導致難以替換

Solution:
(1) IoC Container

2.7 Separate singletons and singleton holders


SRP: Single Responsibility Principle

原則上就是將該做事的Class跟產生Singleton的Class權責分開
好處是 :
(1) SRP
(2) 可以替換

Sample:

原本的設計 Singleton

Singleton Holders抽出


3. Pros and cons of designing for testability


  • Amount of work
    • Let’s just say that more code, and work, is required when testability is involved, but that designing for testability makes you think about the user of your API more, which is a good thing.
    • 工作量增加是一定的 但是能多用User的角度來設計 這是好事
  • Complexity
    • Over design
    • 能用Tool來克服 (e.g. ReSharper)
  • Exposing sensitive IP
    • IP: Intellectual Property
    • Workaround : 
      • keeping things internal and using the [InternalsVisibleTo] attribute
    • Compromise
  • Sometimes you can’t
    • Political or other reasons


4. Alternatives to designing for testability

If a tool comes along that solves the testability problem for you, there will be no need to design specifically for testability.

5. Summary


Testable designs are what SOLID design principles have stood for. 
The end goal should not be testability, but good design instead.

0 意見: