360 likes | 474 Views
Object-Oriented Analysis & Design. Chapter 1 NTPCUG Study Series. Welcome!. 10 (+) week book study Tom Perkins tomperki@gmail.com Books available at Nerdbooks.com. Session Objectives. Awareness of functional OO app Identify 3 steps to great software design
E N D
Object-Oriented Analysis & Design Chapter 1 NTPCUG Study Series
Welcome! • 10 (+) week book study • Tom Perkins • tomperki@gmail.com • Books available at Nerdbooks.com
Session Objectives • Awareness of functional OO app • Identify 3 steps to great software design • Use enums vs string comparisons • Use encapsulation to protect program parts • Use delegation to achieve loose coupling • Be aware of what makes a program functional, maintainable, reusable, and flexible
Rick’s Guitar Store App • Developed by “Down and Dirty Coding, Inc” • Inventory management system • Search tool – match a customer with their dream instrument • Handout (C# and VB) • Available on class website
Rick’s Guitar Shop ApplicationUML Class Diagrams Guitar Inventory serialNumber:string price: double builder:string type:string backWood:string topWood:string Guitars: List addGuitar(string,double,string,string, string,string,string) getGuitar(string):Guitar search(Guitar):Guitar initializeInventory: printInventory() getSerialNumber():string getPrice():double setPrice():double getBuilder():double getModel():string getType():double getBackWood():string getTopWood():string
Main Application Inv:Inventory g:Guitar whatErinLikes:Guitar initializeInventory(Inventory)
DEMO ricksGuitar_start
Nice app, but it has a few problems … • Doesn’t work (functionality) • Doesn’t give client choices • Heavy use of string comparisons • Dependencies • Inventory class must know internals of Guitar class • Maybe needs some architecture re-do • WHERE TO START????
3 Steps to Great Software • Solve the customer’s problem (do what it is supposed to do) • Apply OO principles (remove duplicate code, OO techniques, etc) • Strive for maintainable, reusable design (patterns, refactoring)
Step 1 – get it to do what it should be doing • Problem: search doesn’t return a hit (never, ever) • What’s the problem? • Possible solutions: • Use lowercase comparisons • Use enums instead of strings • (some problem fix, some improved design – using enums improves design and fixes problem)
Enums • Enumerations are user-defined sets of integral constants that correspond to a set of friendly names. • Using enumerations makes your code easier to read, easier to debug, and less prone to errors caused by typographical errors. • MS eLearning series – Windows-based Applications with C# and VB, chapter 3, lesson 2
Enums enum Wood { Indian_Rosewood, Brazilian_Rosewood, Mahogany, Maple, Cocobolo, Cedar, Adirondack, Alder, Sitka }
Enums – code GuitarEnums class InitalizeInventory method Note Intellisense -> fewer errors
Enums - Code To describe Erin’s dream guitar: Guitar whatErinLikes = new Guitar("", 0, Builder.Fender, "Stratocastor", GuitarType.Electric, Wood.Alder, Wood.Alder);
Step 1.b – Give customers choices Search should return a list of guitars instead of a single guitar Old: Guitar guitar = inv.search(whatErinLikes); New: LinkedList<Guitar> matchingGuitars = inv.search(whatErinLikes); See full code in ricksGuitars_choices
Step 2 – Apply some OO Principles • Encapsulation • Break your apps/objects into logical parts • Keep those parts separate • Apples in apple boxes, oranges in orange boxes • Code Cohesion – group like things together • Groups (blocks of code, objects) should have a single purpose
Good Object Design • Well-designed objects only one purpose • Name of object should tell what it does • Jet object • takeOff(), land() methods OK • takeTicket() method not OK • Object should represent only one concept • Duck object – should not represent quacker, rubber duckie, and getting out of the way of a foul ball • Unused values (null properties) are a dead giveaway
Encapsulation Candidate – • Guitar object as used in Search Method Guitar whatErinLikes = new Guitar("", 0, Builder.Fender,"Stratocastor", GuitarType.Electric, Wood.Alder, Wood.Alder); Unused variables • Clients never enter a serial number or price • Only guitar’s general properties used • Builder, topWood, etc
Solution: • Break object into separate parts and keep those parts separate • Encapsulation • Create a separate GuitarSpec object
Guitar GuitarSpec Guitar GuitarSpec serialNumber:string price: double builder:string model:string type:string backWood:string topWood:string spec:GuitarSpec builder:string model:string type:string backWood:string topWood:string getBuilder():double getModel():string getType():double getBackWood():string getTopWood():string getSerialNumber():string getPrice():double setPrice():double getBuilder():double getModel():string getType():double getBackWood():string getTopWood():string getSpec:GuitarSpec
Encapsulation Code Changes Search now using a GuitarSpec object: Old way Guitar whatErinLikes = new Guitar("", 0, Builder.Fender, "Stratocastor", GuitarType.Electric,Wood.Alder, Wood.Alder); LinkedList<Guitar> matchingGuitars = inv.search(whatErinLikes); New way GuitarSpec whatErinLikes = new GuitarSpec( Builder.Fender, "Stratocastor", GuitarType.Electric, Wood.Alder, Wood.Alder); LinkedList<Guitar> matchingGuitars = inv.search(whatErinLikes);
Encapsulation Code Changes • Guitar class contains a GuitarSpec object – composition • Design principle – Favor composition over inheritance • Use “has-a” instead of “is-a” class Guitar { private string serialNumber; private double price; private GuitarSpec spec; public Guitar(string serialNumber, double price, Builder builder, string model, GuitarType type, Wood backWood, Wood topWood) { this.serialNumber = serialNumber; this.price = price; this.spec = new GuitarSpec(builder, model, type, backWood, topWood); … private variables constructor
Encapsulation Code Changes Inventory search routine now uses GuitarSpec for comparisons: foreach (Guitar g in guitars) { GuitarSpec guitarSpec = g.getSpec(); if (!searchSpec.getBuilder().Equals( guitarSpec.getBuilder()) ) continue;…
Additional benefit of Encapsulation • Suppose Rick wants to start carrying both 6-string and 12-string guitars • Add a numStrings field to GuitarSpec only • Won’t need to change Guitar class • Encapsulation – change one part of your app without changing other parts • What to encapsulate – Isolate the parts of your app that might vary from the parts that will remain the same
What we’ve done OO Principles applied: Functionality – does what it is supposed to do Encapsulation – separated parts that might vary from parts that remain the same Flexibility – made code easier to change, change is inevitable Yet to come (tune in next week …) Polymorphism and Inheritance See: ricksGuitars_encapsulation
Step 3 – Make code reusable and extendable • Rick wants to offer both 6-string and 12-string guitars • Plan: • Add numStrings property and getNumStrings() method to GuitarSpec • Encapsulate GuitarSpec in Guitar class constructor • Delegate comparison of search object to GuitarSpec class – no longer Inventory’s job • Update Tester class and test everything
2. Encapsulate GuitarSpec parameter in Guitar constructor Old: public Guitar(string serialNumber, double price, Builder builder, string model, GuitarType type, Wood backWood, Wood topWood) { this.serialNumber = serialNumber; this.price = price; this.spec = new GuitarSpec(builder, model, type, backWood, topWood); } New: public Guitar(string serialNumber, double price, GuitarSpec spec) { this.serialNumber = serialNumber; this.price = price; this.spec = spec; }
New constructor with encapsulated GuitarSpec Create Guitar objects for Inventory static void InitializeInventory(Inventory inv) { inv.addGuitar("11277", 3999.95, new GuitarSpec(Builder.Collings, "CJ", GuitarType.Acoustic,6, Wood.Indian_Rosewood, Wood.Sitka)); inv.addGuitar("V95693", 1499.95, new GuitarSpec(Builder.Fender, "Stratocastor", GuitarType.Electric,6, Wood.Alder, Wood.Alder));
3. Delegation • Delegation – let someone else do it • Inventory search method – now has to know the insides of the GuitarSpec object to do its comparison • Delegate this comparison to the GuitarSpec object • “Does this other GuitarSpec object match you?”
Modified GuitarSpec object – match method public Boolean matches(GuitarSpec otherSpec) { if (builder != otherSpec.builder) return false; if ((model != null) && (!model.Equals("")) && (!model.Equals(otherSpec.model))) return false; if (type != otherSpec.type) return false; if (numStrings != otherSpec.numStrings) return false; if (backWood != otherSpec.backWood) return false; if (topWood != otherSpec.topWood) return false; return true; }
Using the match method Search method in Inventory class: foreach (Guitar g in guitars) { if (g.getSpec().matches(searchSpec)) matchingGuitars.AddLast(g); } return matchingGuitars; See: ricksGuitars_final for code
Review (and that rhymes with Whew!) • We’ve looked at • Enums • Encapsulation • Delegation • Code Reuse • To write good software: • Do what the customer wants • Apply OO principles • Design and code for flexibility, maintainability, and reuse
Assignment – Chapter 2 • Get the book! • Slow down! Make yourself comfortable! (Take your pants off!) • Do the exercises • Read “No Dumb Questions” • Drink lots of water • Talk about what you’ve learned • Get involved with the process • Use what you’ve learned at least one time this week