370 likes | 638 Vues
Design II. CS 121 “ Ordering Chaos ”. Today: Design Principles…can we define them. “ Mike ” Michael A. Erlinger. intro.12.ppt. Design. Practices Principles Patterns. How do we go about design and what do we produce?. What are the characteristics of good design?.
E N D
Design II CS 121 “Ordering Chaos” • Today: • Design Principles…can we define them “Mike” Michael A. Erlinger intro.12.ppt
Design Practices Principles Patterns How do we go about design and what do we produce? What are the characteristics of good design? What are good solutions to common design problems? LAST TIME
Practices: Forms of Models Diagrams (UML) Text (hyperlinked) Prototypes Mathematical models Charts, graphs LAST TIME
Design How do we go about design and what do we produce? Practices Principles Patterns What are the characteristics of good design? What are good solutions to common design problems? TODAY: Principles of design Are there any? Do they matter? Can we evaluate them?
Goals at the Highest Level • Make it easy to build • Make it easy to test • Make it easy to maintain • Make it easy to change SIMPLE INTUITIVE FLEXIBLE
Mountains and molehills Design principles help manage the complexity that arises as project size grows. Software development in the: Small vs Large Problem is: Small grows to Large without a plan
Design Principle: DRY SIMPLE, INTUITIVE, FLEXIBLE Don’t repeat yourself data/code should occur once and only once Examples: ??
Design Principle: INTUITIVE Use real world objects Domain model Design model Abstract: Game Real: Game console
Design Principle: SRP SIMPLE, INTUITIVE, FLEXIBLE Single Responsibility Principle (SRP) every class/object should have a single responsibility Foundation of Software Development: Functions with single purpose, Objects, etc. Several related principles Encapsulation, Abstraction, etc.
Design Principle: EV related to SRP Encapsulate Variation every class should have only one reason to change FLEXIBLE Change should not cause a domino effect!
EV example … Purpose: Convert images Image processor bmp, bmp, What happens when Input type changes?
EV example … Image processor Image Loader bmp, Sometime Later: jpg, gif, … bmp, Sometime Later: jpg, gif, …
Design Principle: HCLC related to SRP A class is cohesive if its data and methods are strongly connected High cohesion Low coupling Classes have low coupling if they are only loosely connected
Cohesion: Examples Functional cohesion (SRP): Coincidental cohesion: Logical cohesion: Temporal/sequential cohesion: Communicational: ?
Cohesion: Examples BEST • Functional cohesion (SRP): grouped because they contribute to a single well-defined task • Coincidental cohesion: grouped together because • Logical cohesion: grouped because they fall into some logical category, i.e. I/O • Temporal/sequential cohesion: grouped because they are processed at the same time or in sequence; i.e. error handling (create log, notifies user, etc.) • Communicational: grouped because they operate on same data, e.g., operate on same record WORST
Coupling: Examples Content coupling: Common coupling: Control coupling: Data-structure coupling: Message coupling: ?
Coupling: Examples Content coupling: a module or class relies on the implementation of another; i.e. accessing private data Common coupling: modules or classes share global data Control coupling: one module controls the logic of another (e.g. passing a what-to-do flag) Data-structure coupling: modules share composite data structure Message coupling: modules communicate through interface WORST BEST
Design principle Law of Demeter only talk to your friends Principle of Least Knowledge no no no: myGame->theBoard->cells[0][0].update()
Design principle The fundamental notion is that a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents). Law of Demeter only talk to your friends Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. Each unit should only talk to its friends; don't talk to strangers. Only talk to your immediate friends. no no no: myGame->theBoard->cells[0][0].update() Should not know details of theBoard
Design Principle: Open-Closed principle classes should be open to extension but closed to modification architecture of your game
Design Principle: Open-Closed principle classes should be open to extension but closed to modification idea was that once completed, the implementation of a class could only be modified to correct errors; new or changed features would require that a different class be created architecture of your game
Composition and Inheritance shape shape is a is a sphere ball sphere has a is a ball Design heuristic: Think like an object!
Design Principle Favor composition over inheritance A A B has a isa inheritance composition B BLACK box reuse WHITE box reuse
Design principle Favor composition over inheritance A A B has a isa inheritance composition B Caveat: sometime inheritance is the right thing (i.e. gives us polymorphism)
Design Principle: LSP Liskov substitution principle (LSP) B void doSomething(B myThingOfTypeB) isa void doSomething(C myThingOfTypeC) C this should work as well not just any banana
LSP violation class Rectangle { public: void SetWidth(double w) {itsWidth=w;} void SetHeight(double h) {itsHeight=w;} double GetHeight() const {return itsHeight;} double GetWidth() const {return itsWidth;} private: double itsWidth; double itsHeight; }; rectangle isa square some time later …
LSP violation class Rectangle { public: void SetWidth(double w) {itsWidth=w;} void SetHeight(double h) {itsHeight=h;} double GetHeight() const {return itsHeight;} double GetWidth() const {return itsWidth;} private: double itsWidth; double itsHeight; }; rectangle isa void Square::SetWidth(double w) { Rectangle::SetWidth(w); Rectangle::SetHeight(w); } void Square::SetHeight(double h) { Rectangle::SetHeight(h); Rectangle::SetWidth(h); } square PROBLEMS?
LSP: • Assume a Square class that derives from a Rectangle class, assuming getter and setter methods exist for both width and height. The Square class always assumes that the width is equal with the height. If a Square object is used in a context where a Rectangle is expected, unexpected behavior may occur because the dimensions of a Square cannot (or rather should not) be modified independently. • This problem cannot be easily fixed: if we can modify the setter methods in the Square class so that they preserve the Square invariant (i.e., keep the dimensions equal), then these methods will weaken (violate) the postconditions for the Rectangle setters, which state that dimensions can be modified independently.
LSP violation class Rectangle { public: void SetWidth(double w) {itsWidth=w;} void SetHeight(double h) {itsHeight=w;} double GetHeight() const {return itsHeight;} double GetWidth() const {return itsWidth;} private: double itsWidth; double itsHeight; }; rectangle isa square A square is not a rectangle!! Its external behavior is different
Design Principle INTUITIVE SIMPLE FLEXIBLE
Summary • Don’t repeat yourself (D.R.Y) • Use real world objects • Single responsibility principle • Encapsulate variation • High cohesion/low coupling • Program to an interface, not an implementation • Law of Demeter (talk only to your friends) • Favor composition over inheritance • Open-closed principle • Liskov Substitution Principle
Source: [Raymond, "Art of Unix Programming", Addison-Wesley, 2003] • Rule of Modularity: Write simple parts connected by clean interfaces • Rule of Clarity: Clarity is better than cleverness. • Rule of Composition: Design programs to be connected to other programs. • Rule of Separation: Separate policy from mechanism; separate interfaces from engines • Rule of Simplicity: Design for simplicity; add complexity only where you must • Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do • Rule of Transparency: Design for visibility to make inspection and debugging easier • Rule of Robustness: Robustness is the child of transparency and simplicity • Rule of Representation: Fold knowledge into data so program logic can be stupid and robust • Rule of Least Surprise: In interface design, always do the least surprising thing • Rule of Silence: When a program has nothing surprising to say, it should say nothing • Rule of Repair: When you must fail, fail noisily and as soon as possible • Rule of Economy: Programmer time is expensive; conserve it in preference to machine time • Rule of Generation: Avoid hand-hacking; write programs to write programs when you can • Rule of Optimization: Prototype before polishing. Get it working before you optimize it • Rule of Diversity: Distrust all claims for “one true way” • Rule of Extensibility: Design for the future, because it will be here sooner than you think
Agile Design Philosophies • Agile Designs are Emergent… • Unit tests form detailed design doc WHEN do test-driven development (TDD) • Design models need to be just barely good enough • Multiple models used • Use each model in multiple ways • Designers should code • Prove it with code • Feedback is your friend (team and/or outsiders) • Iterate, iterate, iterate • Do design every day • Document complicated things • Do not over document…until the end
Agile Design Philosophies… • Incorporate continuous User feedback • Understand your stakeholders…users, management, … • Design for the user experience • Make the app predictable • Bring objects to life through UI
UNDER-PROMISE and OVER-DELIVER
Trade offs Class B Class A Class C low cohesion high coupling