敏捷软件开发笔记(二) 敏捷设计

Section II
Agile Design 敏捷设计

In an agile team, the big picture evolves along with the software. with each iteration. the team improves the design of the system so that it is as good as it can be for the system as it is now. The team does not spend very much time looking ahead to future requirements and needs. Nor does it try to build today the infrastructure to support the features that may be needed tomorrow. Rather, the team focuces on the current structure of the system, making it as good as it can be.

this is not an abandonment of architecture and design. Rather, it is a way to incrementally evolve the most appropriate architecture and design for the system. It is also a way to keep that design and architecture appropriate as the system grows and evolves over time. Agile


the symptoms of poor design are:

Rigidity: the design is difficult to change.
Fragility: The design is easy to break.
Immobility: The design is difficult to reuse.
Viscosity: It is difficult to do the right thing.
Needless Complexity. Overdisign.
Needless repetition. Mouse abuse.
Opacity. Disorganized expression.


The Object-oriented design principles are:

The Single-Responsibility Principle(SRP)

The Open/Closed Principle(OCP)

The Liskov Substitution Principle(LSP)

The Dependency-Inversion Principle(DIP)

The Interface Segregation Principle(ISP)


一,What is Agile Design
Design Smells 设计坏味

Design Smells--the Odors of Rotting Software

you know that the software is rotting when it starts to exhibit any of the following Oders.
Rigidity(僵化性)
Fragility(脆弱性)
Immobility(顽固性)
Viscosity(粘滞性)
Needless Complexity(不必要的复杂性)
Needless Repetition(不必要的重复)
Opacity(晦涩性)

二,Why Software Rots 软件为何会腐化


Chapter 8

SRP:单一职责原则
The Single-Responsibility Principle(SRP)

The Single-Responsibility Principle
A Class should have only one reason to change.
Why was it important ot seperate these two responsibilities into seperate classes? the reason is that each responsibility is an axis of change. when the requirements change, that change will bemanifest through a chang in reponsibility among the classes. if a class assumes more than one responsibility, that class will have more than one reason to change.


1)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 movtive for changing a class, that class has more than one responsibility. this is sometimes difficult to see. we are accustomed to thinking of reponsibility in groups.

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 smel 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.


2) Separating Coupled Responsibilities 分离耦合的职责

3) Persistence 持久化
  Binding business rules to the persistence subsystem is asking for trouble.
  fortunately, as we saw in Chapter 4, the practice of test-driven development will usually force these two responsibilities to be separated long before the design begins to smell . However, if the tests did not force the separation, and if the smells of rigigity and fragility become strong, the design should be refactored, using the FACAD, DAO, or Proxy patterns to separate the two responsibilities.



Chapter 9

OCP: 开放-封闭原则

The Open/CLosed Principle (OCP)

Software entities(classes,modules,functions,etc.)should be open for extension but closed for modification.

when a single change to a program result in a cascade of changes to dependent modules, the design smells rigidity. OCP advice us to refactor the system so that further changes of that kind will not cause more modifications. if OCP is applied well, further changes of that kind are achieved by adding new code, not by changing old code that already works.

Description of OCP OCP 概述

Modules that conform to OCP have two primary attributes.
  1.They are open for extension. This means that the behavior of the module can be extended. As the requirements of the application change, we can extend the module with new behaviors that satisfy those changes. In other words, we are able to change what the module does.
  2. They are closed for modification. Extending the behavior of a module does not result in changes to the source, or binary, code of the module. the binary executable version of the module of the modual--whether in a linkable library. a DLL, or .exe file - remains untouched.


  How is it possible that the behaviors of a module can be modified without changing its source code? without changing the modul, how can we change what a modul does?
  the answer is abstraction. In C# or any other object-oriented programming language , it is possible to create abstractions that are fixed and yet represent an unbounded group of possible behaviors.the abstractions are abstract base classed, and the unbounded group of possible behaviors are represented by all the possible derivative classes.
   it is possible for a module to manipulate an abstraction. such a module can be closed for modification,since it depends on an abstraction that is fixed.yet the behavior of that modul can be extended by creating new derivatives of the abstraction.
 


Violating OCP 违反OCP


Comforming OCP 遵循OCP

1.Anticipation and "Natural" Structure 预测变化和“贴切的”结构

This takes a certain amount of prescience derived from experience. Experienced designers hope that they know the users and the industry well enough to judge the probability of various kinds of changes. These designers then invoke OCP against the most probable changes.

   this is not easy. It amount to making educated guesses about the likely kinds of changes that the application will suffer over time. when the designer guess right, they win. when they guess wrong, they lose. and they wil certainly guess wrong some of the time.
   Also, conforming to OCP is expensive. It takes deveplopment time and effort to create the appropriate abstractions. Those abstractions also increase the complexity of the software design.
   How do we know which changes are likely? we do the appropraite research, we ask the appropriate questions, and we use our experience and common sense. and after all that, we wait until the changes happen!

   2. Putting the Hooks in 放置吊钩
   Fool me once "Fool me once, shame on you. Fool me twice, shame on me" this is a powerful attitude in software design. to keep from loading our software with needless complexity, we may permit ourselves to be fooled once. this means that we initially write our code expecting it not to change.when a change occurs. we implement the abstractions that protect us from future changes of that kink.In short, we take the first bullet and then make sure that we are pretected from any more bullets coming from that particular gun.

   Stimulating change
   if we decide to take the first bullet, it is to our advantage to get the bullets flying early and frequently. We want to know what kinds of changes are likely before we are very far down the development path. The longer we wait to find out what kinds of changes are likely. the more difficult it will be to create the appropriate abstractions.
   Therefore, we need to stimulate the changes. we do this through several of the means discussed in Chapter 2.
    (1)We write tests first. we will have built the abstractions that make the system testable. we are likely to find that many of these abstractions will protect us from kinds of changes later.
    (2)we use very short development cycles:days instead of weeks.
    (3)we develop features before infrastructure and frequenly show those features to stakeholders.
    (4)we develop the most important features first.
    (5)we release the software early and often. we get it in front of our customers and users as quickly and as often as possible.


Using Abstraction to Gain Explicit Closure 使用抽象获得显示封闭

Using a Data-Driven Approach to Achieve Closure


Chapter 10
LSP:Liskov替换原则
The Liskov Substitution Principle(LSP)

The primary mechanisms behind the open/closed principle are abstraction and polymorphism. it is by using inheritance that we can create derived classes that implement abstract methods in base classes.
    what are the design rules that govern this particular use of inheritance? what art the characeristics of the best inheritance hierarchies? what are the traps that will cause us to create hierarchies that do not conform to OCP? These are the questions addressed by the Liskov Substitution Principle

The Liskov Substitution Principle
Subtypes must be substitutable for their base types.

the importance of this principle becomes obvious when you consider the consequence of violating it.

Violation of LSP 违反LSP的情形


Chapter 11

DIP: 依赖倒置原则

The Dependency-Inversion Principle(DIP)

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions

why the author using the inverted as the name of principle

conculsion:
1,Hight-level modules reuse should be taken precedence over
2,when the high-level modules are independent of the low-level modules, the high-level modules can be reused quite simply.


Layering 层次化

According to Booch: All well structured object-oriented architecture have clearly defined layers, with each layer providing some coherent set of services through a well defined and controlled interface.

Owenership inversion 倒置的接口所有权

Note that the inversion here is one of not only dependencies but also interface ownership we often think of utility libraries as owning their own interfaces. but when DIP is applied. we find that the clients tent to own the abstract interfaces and that their servers derive from them.

using this inversion of ownership, policylayer is unaffected by any changes to Low-level modules.


Dependence on Abstractions 依赖于抽象

Simply stated, this heuristic recommends that you should not depend on a concrete class and that rather, all relationships in a program should terminate on an abstract class or an interface.
1) no variable should hold a reference to a concrete class.
2) No class should derive from a concrete class.
3) No method should ovrride an implemented method

this heuristic is usually violated at least once in every program. in some cases, the change must be propagated to the abstract interface that represents the class. Such changes break through the isolation of the abstract interface.

this is the reason that the heuristic is a bit naive. if, on the other hand, we take the longer view that the client modules or layers declare the service interfaces that need, the interface will change only when the client needs the changes. Changes to the classes that implement the abstract interface will not affect the client.



Conclusion 结论
Traditional procedural programming creates a dependency structure in which policy depends on detail. This is unfortunate, since the policies are vulnerable to changes in the details. Object-oriented programming inverts that dependency structure such that both details and policies depend on abstraction, and service interfaces are often owned by their clients.

Indeed, this inversion of dependencies is hallmark of good object-oriented design. It doesn't matter what language a program is written in. If its dependencies are inverted, it has an OO design. if its dependencies are not inverted, it has a procedural design.

The priciple of dependency inversion is the fundamental low-level mechanism behind many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reuseable frameworks. It is also critically important for the construction of code that is resilient to change.



Chapter 12

ISP:接口隔离原则
The Interface Segregation Principle(ISP)

This principle deals with the disadvantages of "fat" interface. CLasses whose interfaces are not cohesive have "fat" interfaces. In other words, the interfaces of the class can be broken up into groups of methods. Each group serves a different set of clients. Thus,some clients use one group of methods, and other clients use the other groups.
ISP acknowledges that there are objects that require nonchesive interfaces; however, it suggests that clients should not know about them as a single class. Instead, clients should know about abstract base classes that have cohesive interfaces.

Interface Pollution 接口污染

Separate Clients Mean Separate Interfaces.
分离客户就是分离接口

D










 








猜你喜欢

转载自guoapeng.iteye.com/blog/616206