CS 121 “Ordering Chaos” Design II “Mike” Michael A. Erlinger Today: intro.12.ppt Design Principles…can we define them 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 –2– CS 121 Practices: Forms of Models Diagrams (UML) Text (hyperlinked) Prototypes Mathematical models Charts, graphs LAST TIME –3– CS 121 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? TODAY: Principles of design Are there any? Do they matter? Can we evaluate them? –4– CS 121 Goals at the Highest Level 1. Make it easy to build 2. Make it easy to test 3. Make it easy to maintain 4. Make it easy to change SIMPLE INTUITIVE FLEXIBLE –5– CS 121 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 –6– CS 121 Design Principle: DRY SIMPLE, INTUITIVE, FLEXIBLE Don’t repeat yourself data/code should occur once and only once Examples: ?? –7– CS 121 Design Principle: INTUITIVE Use real world objects Domain model Abstract: Game –8– Design model Real: Game console CS 121 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. –9– CS 121 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! – 10 – CS 121 EV example … Purpose: Convert images Image processor bmp, bmp, What happens when Input type changes? – 11 – CS 121 EV example … Image processor Image Loader bmp, Sometime Later: jpg, gif, … – 12 – bmp, Sometime Later: jpg, gif, … CS 121 Design Principle: HCLC related to SRP High cohesion Low coupling – 13 – A class is cohesive if its data and methods are strongly connected Classes have low coupling if they are only loosely connected CS 121 Cohesion: Examples Functional cohesion (SRP): Coincidental cohesion: Logical cohesion: ? Temporal/sequential cohesion: Communicational: – 14 – CS 121 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 – 15 – CS 121 Coupling: Examples Content coupling: Common coupling: Control coupling: ? Data-structure coupling: Message coupling: – 16 – CS 121 Coupling: Examples Content coupling: a module or class relies on the WORST 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 BEST – 17 – CS 121 Design principle Law of Demeter only talk to your friends Principle of Least Knowledge no no no: myGame->theBoard->cells[0][0].update() – 18 – CS 121 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. – 19 – no no no: myGame->theBoard->cells[0][0].update() Should not know details of theBoard CS 121 Design Principle: Open-Closed principle classes should be open to extension but closed to modification architecture of your game – 20 – CS 121 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 – 21 – CS 121 Composition and Inheritance shape is a has a ball sphere shape is a sphere is a Design heuristic: Think like an object! ball – 22 – CS 121 Design Principle Favor composition over inheritance A has a A B inheritance isa composition B – 23 – BLACK box reuse WHITE box reuse CS 121 Design principle Favor composition over inheritance A has a A B inheritance isa composition Caveat: sometime inheritance is the right thing (i.e. gives us polymorphism) – 24 – B CS 121 Design Principle: LSP Liskov substitution principle (LSP) void doSomething(B myThingOfTypeB) B isa void doSomething(C myThingOfTypeC) this should work as well C not just any banana – 25 – CS 121 LSP violation rectangle 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; }; isa square – 26 – some time later … CS 121 LSP violation rectangle 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; }; isa square – 27 – PROBLEMS? void Square::SetWidth(double w) { Rectangle::SetWidth(w); Rectangle::SetHeight(w); } void Square::SetHeight(double h) { Rectangle::SetHeight(h); Rectangle::SetWidth(h); } CS 121 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. – 28 – CS 121 LSP violation rectangle 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; }; isa square A square is not a rectangle!! Its external behavior is different – 29 – CS 121 Design Principle INTUITIVE SIMPLE FLEXIBLE – 30 – CS 121 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 – 31 – CS 121 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 CS 121 – 32 – 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 – 33 – CS 121 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 – 34 – CS 121 UNDER-PROMISE and OVER-DELIVER – 35 – CS 121 The End – 36 – CS 121 Trade offs Class B Class A Class C low cohesion high coupling – 37 – CS 121