[Study Note] Design and Testability 20100410

之前在4月1日的时候,开始看 Jeremy D.Miller 的一些关于 TDD 和 Unit Test 的文章,结果没看两篇,就先去补课了。到今天为止,看完了几篇 Patterns in Practice 系列的文章,然后回过头来,开始看 Design and Testablity

似乎 TDD Design Starter Kit 这个系列文章的先后顺序有点乱,至少我看到了两个版本——TDD Design Starter KitDesign and Testability,不过其实顺序没有什么关系。

[TDD Design Starter Kit: Responsibilities, Cohesion, and Coupling]

Separation of Concerns

In computer science, separation of concerns(SoC) is the process of separating a computer program into distinct features that overlap in functionality as little as possible. A concern is any piece of interest or focus in program. Typically concerns are synonymous with features or behaviors. Progress towards SoC is traditionally achieved through modularity of programming and encapsulation (or “transparency” of operation), with the help of information hiding. Layered designs in information systems are also often based on separation of concerns (e.g., presentation layer, business logic layer, data access layer, database layer.)

Cohesion – A measure of whether a class has a well defined, meaningful responsibility. High cohesion is desirable.

Couling – More or less, how entangled or dependent a class is with other class. A loosely coupled design implie that classes or subsystems can largely be modified independently of one another.

It’s also much easier to make mistakes in big methods than in smaller methods.

[TDD Design Starter Kit: Dependency Inversion Principle]

Dependency Inversion Principle (DIP)

Depend upon Abstractions. Do not depend upon concretions.

Rules of Thumb to Use DIP

  1. Anytime your code calls out of the CLR, and maybe just the current AppDomain itself.
  2. Singleton’s.
  3. Interface points between major subsystems.
  4. Extension points.

Injected Singleton

这个貌似是StructureMap 曾经在  SourceForge.NET 上的一篇文章,不过在迁移到新的主站上之后不知去向。当然,在互联网上所有的文字都不会凭空消失。

Singleton Design Pattern

Ensure a class only has one instance, and provide a global point of access to it.

Usage

  1. Caching or object pooling.
  2. Easy access to an object instance.
  3. Using a Singleton as a single point of object construction to control a plugin.

Unit Testing witha a Singleton

Singleton with StructureMap

Singletons are Evil

[TDD Design Starter Kit: State vs. Interaction Testing]

interaction-based testing is verifying the expected interaction between a class and its dependencies. Typically you would use either a mock or a stub object as a stand-in for the real dependency. The unit test will verify that the expected interaction via method calls took place.

看到这里,我就知道自己一直不太会使用 mock 的原因就是我只是使用 State Testing 模式,而没有按照 Interaction Testing 的方式来考虑问题。

[TDD Design Starter Kit: Static Methods and Singletons May Be Harmful]

you cannot mock (or stub) a static method, period

never do anything in a static method that calls out of the current AppDomain (HttpContext objects, database calls, MSMQ manipulation, etc.)

Mocking the guts of the repository may end up obfuscating the real intention of a unit test.

我打算对于 singleton 的问题新开一篇学习笔记;对于 static method 的问题,我也需要尽快弄清楚,因为我自己的代码里面有太多的 static。

[TDD Design Starter Kit: It’s All about Assigning Responsibilities]

Just Use Mock Objects, Right?

use mock objects to test the interaction of our code with teh external resources.

“Bottom Up” Construction

unit tests should be simple to setup, isolated, fine-grained, and reveal the intention of the code being tested.

Single Responsibility Principle(SRP)

There should never be more than one reason for a class to change

One class, one responsibility

cohesion

Responsibility Driven Design

The structure of an OO application is largely determined by how you assign reponsibilities to the classes in the application.

Responsibility Driven Design (RDD)

an obligation to perform a task or know information

  1. Know things
  2. Do things
  3. Make decisions

Object Role Stereotypes

Stereotypes are simplified views that help you understand an object or component’s purpose.

five object role stereotypes

  1. Controller – Controls application execution. Makes decisions and delegates to other classes.
  2. Service Provider – Provides a service to other classes.
  3. Interfacer – Communicates actions to other layers or systems.
  4. Information Holder – Hold facts. Domain classes.
  5. Structure – Maintains relationship between other classes.

isolate the ugly - take any thing that is inconvenient during unit testing like database access and isolate this functionality behind an abstracted wrapper interface.

suggest Interfacer classes for the SMTP, MSMQ, and external interaction, these classes will definitely be mocked in unit tests.

The Skeleton Code

Wrapping Up

Responsibility Driven Design is well suited as a supplement to Test Driven Development

.

[A Simple Example of the “Humble Dialog Box”]

The Humble Dialog

  1. Create a class for the smart object, and an interface class for the view. Pass the view to the smart object.
  2. Develop commands against the smart object, test first. Write your tests against a mock view.
  3. Create your dialog class and implement the view interface on it. Gestures on the dialog should delegate to commands on the smart object. Call from the smart object to the dialog should resolve to simple setter methods

posted on 2010-04-10 17:32  zhaorui  阅读(180)  评论(0编辑  收藏  举报

导航