12. Design Principles 1

How do we quantify ‘good’? How precise can we be? Common language required to describe this.

Big-picture language

Cohesion:

Coupling:

Cohesion good; coupling bad.

Why is software design hard?

Problem: complexity

Solution: decomposition

Methodologies

Top-down:

Bottom-up:

Nucleus-centred (OO):

Aspect-oriented (e.g. security):

Nucleus-Centred Design

Start with the tricky bits.

Hide information; decisions, choices, things that may change in the future (David Parnas).

Identify decision decisions with competing solutions; isolate these details behind an interface i.e. OO-design; state/access methods encapsulated.

Example: Student

Student             StudentDialog
name      <-------- student
id
display()?          display()?

Where should display() go?

If in StudentDialog, allows for separation of concerns.

If in Student, keeps related data and behavior together, increasing cohesion.

Information-Hiding

Encapsulation: drawing a boundary around something.

Information hiding: hiding design decisions from the rest of the system to prevent unintended coupling.

Encapsulation = programming feature; information hiding = design pattern.

Encapsulation Leak

When implementation details get exposed, allowing implementation details to be exposed and private properties to be modified outside of the class, causing inconsistent/invalid states.

// Student
private Set<Enrolment> enrolments;
public Set<Enrolment> getEnrolments() {
  // Bad
  return enrolments;

  // Better: items cannot be added/removed, but setters/getters can still be called on elements
  // Deep clone?
  return Collections.unmodifiableSet(enrolments);
}

// Course
add(Student student) {
  // Bad: set is being modified outside of the Student class
  student.getEnrolements().add(new Enrolment(student));
}
Coping with Change

Figure out the solid bits; the invariants, and make them the framework of your program. Hopefully, the problem won’t change.

Find the wobbly bits and hide them away. In other words, make stable abstractions.

Hiding Design Decisions

If you chose something (i.e. multiple options available), hide it:

A DAO (data-access objects) allows us to define an interface to access and modify objects.

This allows the internal implementation details to be hidden and thus changed as needed.

Open-Closed Principle

Make your system open for extension but closed for modification.

Any new use case should be able to add to the interface without requiring it to be modified.

Tell, Don’t Ask

Decisions based entirely upon the state of one object should be made inside the object itself.

Avoid asking for information from an object and using it to make decisions about that object.

If this is happening, it may be a sign that the data is being stored in the wrong place.

Example:

m = new VendingMachine();
m.vend(3); // vending machine should check and restock itself
if (m.stock < 10) m.reorder(); // asking: bad