Neil Ernst
- understand the importance of design
- introduce basic principles in OO design
A good design principle should help generate ideas and enable you to think through design implications. — Rebecca Wirfs-Brock
- Cohesion is internal to an object, describing its independence. High cohesion implies doing one thing well.
- Coupling is the amount of dependency between components. High coupling makes the preceding modularity approaches harder.
- Modular systems have objects with high cohesion and low coupling
- the class that does it all
- common when moving from imperative languages or scripting
- low cohesion - does many things, not connected
- low coupling externally but now high coupling internally
- look for classes with many many methods.
- Surprisingly, one of the most important tasks developers have
- Rely on naming conventions (yours, project, language, corporate)
- Name classes to describe effects and purpose, not implementation
public void paint (Paint paint) {
v = v + paint.getV(); //after mixing, sum volume
//complex color mixing logic
// assign new r, b, y values
}
public void testPaint() {
Paint yellow = new Paint(100.0, 0, 50, 0);
Paint blue = new Paint(100.0, 0,0,50);
yellow.paint(blue);
//should get green with 200.0
}
public void betterTestPaint() {
Paint ourPaint = new Paint(100.0, 0, 50, 0);
Paint blue = new Paint(100.0, 0,0,50);
ourPaint.mixin(blue);
//should get green with 200.0
assertEquals(200.0, ourPaint.getVolume(), 0.01);
}
//in Paint
public void mixIn(Paint other) {
volume = volume + other.getVolume();
double ratio = other.getVolume()
pigmentColor = pigmentColor.mixedWith(other.pigmentColor(), ratio);
}
in PigmentColor
// many lines of color-mixing logic
For example, in the HotDraw drawing framework, my first name for an object in a drawing was DrawingObject. Ward Cunningham came along with the typography metaphor: a drawing is like a printed, laid-out page. Graphical items on a page are figures, so the class became Figure. In the context of the metaphor, Figure is simultaneously shorter, richer, and more precise than DrawingObject."
If a class is hard to name, it is probably doing too much.
Rate of change:
Things that change at the same rate belong together. Things that change at different rates belong apart. This principle is true of both the data manipulated by the program--two variables that always change at the same time belong in the same object--and the structure of the program--two functions that change at the same time belong in the same class.
"Empathy in naming" -> "if I searched for this function, what would I want it called?"
https://www.facebook.com/notes/kent-beck/naming-from-the-outside-in/464270190272517/
- Cohesion/Coupling
- SOLID
- Single Responsibility
- Open/Closed
- Liskov Substitution
- Interface Segregation
- Dependency Inversion/Inversion of Control
- Refactoring
- Cohesion is internal to an object, describing its independence. High cohesion implies doing one thing well.
- Coupling is the amount of dependency between components. High coupling makes the preceding modularity approaches harder.
- Modular systems have objects with high cohesion and low coupling
- CRC diagram for MSG case -> "A responsibility is anything that a class knows or does"
- a class should have a single purpose, collecting together a set of related sub-responsibilities
- "class only has a single reason to change"
- a Rectangle that calculates area and draws itself
- what two types of responsibility should almost certainly be separated?
"Objects are open for extension but closed for modification."
- use inheritance and abstraction
Ask: if a new object of type X is needed, where do you make changes?
- minimize changes to existing objects
- contrast: lengthy
switchstatements (or usinginstanceof)
Encapsulation: keep data and operations together. Ensure internal details don't have external effects (eg. member variables)
- Does inheritance violate this?
"Functions that use Base Classes must be able to use Derived Classes without being aware of it"
- a change to a derived class (subtype) shouldn't affect the program using the base class (OCP)
The validity of a model can only be expressed in terms of its clients (tests).
"Clients should not depend on interfaces they don't use"
- do not create coupling between objects through implicit dependencies on a common interface (rich interface)
A. High Level Modules Should Not Depend Upon Low Level Modules. Both Should Depend Upon Abstractions.
B. Abstractions Should Not Depend Upon Details. Details Should Depend Upon Abstractions."
Separate configuration from use, especially in the use of 3rd party libraries.
Frameworks like Guice, Spring allow for "injection" of the dependencies
- e.g., at runtime, allow new instances of Report
- especially useful for testing (code no longer cares if it gets a mock or the real object)
public class RealBillingService implements BillingService {
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
CreditCardProcessor processor = new PaypalCreditCardProcessor();
TransactionLog transactionLog = new DatabaseTransactionLog();
public class BillingModule extends AbstractModule {
@Override
protected void configure() {
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
// more bindings
}
...
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(CreditCardProcessor processor, TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
refactor if there is a symptom, not just for the sake of it. (somewhat violated in learning refactoring!)
Critique and refactor/redesign the code.
A program to calculate and print a statement of a customer's charges at a video store. The program is told which movies a customer rented and for how long. It then calculates the charges, which depend on how long the movie is rented, and identifies the type movie. There are three kinds of movies: regular, children's, and new releases. In addition to calculating charges, the statement also computes frequent renter points, which vary depending on whether the film is a new release.



