Saturday, September 29, 2007

The Reuse/Release Equivalence Principle (REP)

The granule of reuse is the granule of release.

What do you expect from the author of a class library that you are planning to reuse? Certainly, you want good documentation, working code, well-specified interfaces, and so on. But there are other things you want, too.
First, to make it worth your while to reuse this person's code, you want the author to guarantee to maintain it for you. After all, if you have to maintain it, you are going to have to invest a tremendous amount of time into it, time that might be better spent designing a smaller and better component for yourself.
Second, you are going to want the author to notify you of any changes planned to the interface and functionality of the code. But notification is not enough. The author must give you the choice to refuse to use any new versions. After all, the author might introduce a new version just as you are entering a severe schedule crunch or might make changes to the code that are simply incompatible with your system.
In either case, should you decide to reject that version, the author must guarantee to support your use of the old version for a time. Perhaps that time is as short as 3 months or as long as a year; that is something for the two of you to negotiate. But the author can't simply cut you loose and refuse to support you. If the author won't agree to support your use of older versions, you may have to seriously consider whether you want to use that code and be subject to the author's capricious changes.
This issue is primarily political. It has to do with the clerical and support effort that must be provided if other people are going to reuse code. But those political and clerical issues have a profound effect on the packaging structure of software. In order to provide the guarantees that reusers need, authors organize their software into reusable components and then track those components with release numbers.
Thus, REP states that the granule of reuse, a component, can be no smaller than the granule of release. Anything that we reuse must also be released and tracked. It is not realistic for a developer to simply write a class and then claim that it is reusable. Reusability comes only after a tracking system is in place and offers the guarantees of notification, safety, and support that the potential reusers will need.
REP gives us our first hint at how to partition our design into components. Since reusability must be based on components, reusable components must contain reusable classes. So, at least some components should comprise reusable sets of classes.
It may seem disquieting that a political force would affect the partitioning of our software, but software is not a mathematically pure entity that can be structured according to mathematically pure rules. Software is a human product that supports human endeavors. Software is created by humans and is used by humans. And if software is going to be reused, it must be partitioned in a manner that humans find convenient for that purpose.
What does this tell us about the internal structure of a component? One must consider the internal contents from the point of view of potential reusers. If a component contains software that should be reused, it should not also contain software that is not designed for reuse. Either all the classes in a component are reusable, or none of them are.
Further, it's not simply reusability that is the criterion; we must also consider who the reuser is. Certainly, a container class library is reusable, and so is a financial framework. But we would not want them to be part of the same component, for many people who would like to reuse a container class library would have no interest in a financial framework. Thus, we want all the classes in a component to be reusable by the same audience. We do not want an audience to find that a component consists of some classes that are needed, and others that are wholly inappropriate.

The Single-Responsibility Principle (SRP)

The Single-Responsibility Principle (SRP)© Jennifer M. Kohnke
None but Buddha himself must take the responsibility of giving out occult secrets . . .
—E. Cobham Brewer 1810–1897, Dictionary of Phrase and Fable (1898)
This principle was described in the work of Tom DeMarco[1] and Meilir Page-Jones.[2] They called it cohesion, which they defined as the functional relatedness of the elements of a module. In this chapter, we modify that meaning a bit and relate cohesion to the forces that cause a module, or a class, to change.
[1] [DeMarco79], p. 310
[2] [PageJones88], p. 82
The Single-Responsibility Principle
A class should have only one reason to change.
Consider the bowling game from Chapter 6. For most of its development, the Game class was handling two separate responsibilities: keeping track of the current frame and calculating the score. In the end, RCM and RSK separated these two responsibilities into two classes. The Game kept the responsibility to keep track of frames, and the Scorer got the responsibility to calculate the score.
Why was it important to separate these two responsibilities into separate classes? The reason is that each responsibility is an axis of change. When the requirements change, that change will be manifest through a change in responsibility among the classes. If a class assumes more than one responsibility, that class will have more than one reason to change.
If a class has more than one responsibility, the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class's ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.
For example, consider the design in Figure 8-1. The Rectangle class has two methods shown. One draws the rectangle on the screen, and the other computes the area of the rectangle.
Figure 8-1. More than one responsibility
[View full size image]
Two different applications use the Rectangle class. One application does computational geometry. Using Rectangle to help it with the mathematics of geometric shapes but never drawing the rectangle on the screen. The other application is graphical in nature and may also do some computational geometry, but it definitely draws the rectangle on the screen.
This design violates SRP. The Rectangle class has two responsibilities. The first responsibility is to provide a mathematical model of the geometry of a rectangle. The second responsibility is to render the rectangle on a GUI.
The violation of SRP causes several nasty problems. First, we must include GUI in the computational geometry application. In .NET, the GUI assembly would have to be built and deployed with the computational geometry application.
Second, if a change to the GraphicalApplication causes the Rectangle to change for some reason, that change may force us to rebuild, retest, and redeploy the ComputationalGeometryApplication. If we forget to do this, that application may break in unpredictable ways.
A better design is to separate the two responsibilities into two completely different classes, as shown in Figure 8-2. This design moves the computational portions of Rectangle into the GeometricRectangle class. Now changes made to the way rectangles are rendered cannot affect the ComputationalGeometryApplication.
Figure 8-2. Separated responsibilities

Defining a Responsibility
In the context of the SRP, we define a responsibility to be a reason for change. If you can think of more than one motive for changing a class, that class has more than one responsibility. This is sometimes difficult to see. We are accustomed to thinking of responsibility in groups. For example, consider the Modem interface in Listing 8-1. Most of us will agree that this interface looks perfectly reasonable. The four functions it declares are certainly functions belonging to a modem.
Listing 8-1. Modem.cs -- SRP violation
public interface Modem
{
public void Dial(string pno);
public void Hangup();
public void Send(char c);
public char Recv();
}
However, two responsibilities are being shown here. The first responsibility is connection management. The second is data communication. The dial and hangup functions manage the connection of the modem; the send and recv functions communicate data.
Should these two responsibilities be separated? That depends on how the application is changing. If the application changes in ways that affect the signature of the connection functions, the design will smell of rigidity, because the classes that call send and read will have to be recompiled and redeployed more often than we like. In that case, the two responsibilities should be separated, as shown in Figure 8-3. This keeps the client applications from coupling the two responsibilities.
Figure 8-3. Separated modem interface
If, on the other hand, the application is not changing in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them would smell of needless complexity.
There is a corrolary here. An axis of change is an axis of change only if the changes occur. It is not wise to apply SRP—or any other principle, for that matter—if there is no symptom.

Friday, September 28, 2007

Saturday, September 15, 2007

O'Reilly - Safari Books Online - 0131857258 - Agile Principles, Patterns, and Practices in C#

O'Reilly - Safari Books Online - 0131857258 - Agile Principles, Patterns, and Practices in C#

asdasd

asdasd

Abstract Factory

definition
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

UML class diagram

Chain of Responsibility



definition
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

participants
The classes and/or objects participating in this pattern are:
Handler (Approver)
defines an interface for handling the requests
(optional) implements the successor link
ConcreteHandler (Director, VicePresident, President)
handles requests it is responsible for
can access its successor
if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor
Client (ChainApp)
initiates the request to a ConcreteHandler object on the chain

Chain of Responsibility

Follow the Chain of Responsibility The Chain of Responsibility (CoR) pattern decouples the sender and receiver of a request by interposing a chain of objects between them. In this installment of Java Design Patterns, David Geary discusses the CoR pattern and two implementations of that pattern in the Java APIs—one from client-side Java and the other from server-side Java.

Design Principle

  • DIP
  • SRP