210 likes | 228 Views
Understand the principles of software design concepts to enhance productivity. Learn about Single Responsibility Principle, Don’t Repeat Yourself, and best practices for good software design in the real world. Explore design diagnostics and examples for achieving clean and efficient code.
E N D
Introduction to Software Design In the “real world” we’re taught that design is pretty. Here we learn that design is about productivity.
Introduction to Design Concepts and Diagnosis
Mostly about easing CHANGE Easy to find what code to modify to add a feature …I only have to modify one class (in addition to writing the new code) …It’s easy to understand the class I have to change …My teammate can addanother feature without us colliding or stopping working to talk …When I test my code, nobody else’s code needs to work Good software design gets us close to these ideals Some things we’d like to be true
Single Responsibility Principle (SRP) • Each class should be responsible for one thing(capability, entity, computation, etc.) • Can phrase this as “mind your own business” • object do its own calculations • object should not do calculations for another • Easy to violate this because objects need to be connected to one another • e.g., Events happen as part of Dates • Don’t Repeat Yourself (DRY) • Each computational idea should be expressed just once • Violations often the result of • cut-and-paste programming • incomplete class (others have to do calculations for it, which also violates SRP) • But also over-specialization of classes (class = object) Two Diagnostics for Good Design
Tendency is to cram “related” functionality into existing classes, rather than creating new ones So OO Design is easy, right? Uh, no.
SRP design has classes for “doers” The four misplaced methods
A related challenge is when two classes closely collaborate, like the iSwoon Date & Event classes So OO Design is easy, right? No. (pt II)
Example: iSwoon Repetition(violates DRY)
Example: iSwoon (continued) This code violates SRP. Why? reuses the responsibility of which events go with which date it checks validity of events and also stores list of events Better phrasings: Date does not “validates-events itself” Changes to Event (like adding new event type) requires changing Date
Example: iSwoon (continued) Not just calling event method (that’s OK), but calculating on event data to derive event property Responsibility for Events (violates SRP) Also note that the only difference between subclasses is a constant data value
Repetition (violates DRY) Also note that only difference in subclasses is a constant
Refactored iSwoon Design No class for each date! Replaces 3 Event constructors
Refactored iSwoon Design (cont’d) No class for each event! Moved from Date to get SRP. “Factory” Methods keep Event details local
Refactored iSwoon Design (cont’d) But now date functionality here! Why OK? Why is it OK to have dateSupported(int) in Event, but not validateEvent(Event) in Date? Because whether an Event is allowed is a property of the Event itself, not the Date The only thing that’s going to use a Date is an Event Dates are hard numbers, while events are flexible You wouldn’t have to change bit of code if you were to add another valid Event
Refactored iSwoon Design (cont’d) But now date functionality here! Why OK? Why is it OK to have dateSupported(int) in Event, but not validateEvent(Event) in Date? My answers: dateSupported is checking the appropriateness of an individual Event for how mature the relationship is (not about the ordering of selected events) Said another way: Date class is about the ordering of selected Events for a date (not event validity) dateSupported is computing on an int, not a Date
Consider the Java class: class Car { private Engine engine; private Transmission trans; … public start() throws BadDayException { for (int attempt=0; attempt < MAX_START; attempt++) engine.start(); } } A Car is composed of a transmission and an engine. That is to say that a “Car has a Transmission and a Car has an Engine.” Composition is implemented via instance variables. Composition = “Has A”
Sub Type = “Is A” Consider the Java classes: class Vehicle { private Engine engine; … public start() throws BadDayException { for (int attempt=0; attempt < MAX_START; attempt++) engine.start(); } } class Car extends Vehicle { private unsigned intpassengerCount; … public unsigned intgetPassengerCount() { return passengers; } } A Car is (necessarily) a type of Vehicle. That is to say that a car is asubtype of a vehicle. Subtypes can be implemented via Inheritance.
A form of operational subtype relationship Shares only interface, not implementation Appropriate when behaviors in common, but not because otherwise the same type. Enables interoperability, even among otherwise different types via interface reference. Avoid inheriting baggage, imposes desired disciple. Many types of things can be turned on and off. interface Switchable { public on(); public off(); } Names are often, but not necessarily, derived from verbs, e.g. Sortable, Iterable, Serializable, Cloneable, Runnable, etc. Interfaces (Pure Abstract Base Classes)
Three common mistakes in design • TOO MUCH: Put all X-related functionality in class X (Automobile) • TOO FRIENDLY: Blending of closely related classes (Date & Event) • TOO LITTLE: Defining object-like classes (Date & Event) • A few diagnostic techniques • SRP: do the “____ itself” test on methods • SRP: achange in one class causes change in another class • DRY: repetitive code • DRY: A “small” change requires many similar changes across methods or classes • Constant Classes: Only diff. between classes is constants (same methods) • “Is a” vs “Has a” vs “Can do” Test • Determine if stand-alone, sub-type, or composite type • If sub-type, determine if interface is shared, or implementation, and why Design Diagnosis Review
For non-SRP functionality • Create additional classes, move there (Automobile) • Move into existing classes (Date & Event) • For DRY violation • Create new method out of repetitive code, call it • Merge repetitive, similar classes and encode differences with variables • For “Has A” violation • Replace inheritance with composition (Delegation pattern coming soon!) • For “Is A” violation • Use subtypes/inheritance to leverage commonality • For “Can do”, but not “Is A” • Use interface (pure abstract base class) to ensure no implementation leaks into common defintion Design Repair
Object-oriented design is intuitive, but subtle • Java is just a tool, does not guarantee good design • (Just because I have an expensive camera does not make me a good photographer :) • Easy to put functionality in wrong place, make classes too big, or make too small • Possible to diagnosis and repair a designbefore or after the coding (may require both) • SRP, DRY • Is-A, Has-A, Can-Do • Change in one class affects another (SRP) • Small change affects multiple classes or methods • Unfortunately, there are many kinds of design mistakes, and unique repairs for them Take-Aways from Class Today