Week 2 Glossary

This "glossary" is arranged chronologically - in the order the material is presented in class - rather than alphabetically. The following Table of Contents links to the items alphabetically.

Table of Contents

  1. Class responsibilities
  2. Cohesion
  3. Coupling
  4. DRY
  5. Design pattern
  6. Java Observable / Observer
  7. Observer pattern
  8. Refactoring
  9. Separation of Concerns
  10. Technical debt

Terms, Definitions, and Examples

DRY (Don't Repeat Yourself)
The Pragmatic Programmer. Andrew Hunt & David Thomas. Addison-Wesley, 1999.
One to consider for your own Programming on a Remote Island  book list.

Every piece of information (data, algorithm, code sequence) should have a single, definitive location in the code base. Duplication wastes effort, leads to bugs when all copies of code are not found and updated at the same time. Redundancy always risks inconsistency.

Cohesion
Wikipedia

The degree to which a component addresses a single, well-defined issue; cohesion measures the strength of relationship between pieces of functionality within a given module. A primary design goal is to create highly cohesive components. Component is purposefully vague - depending on the level of abstraction it can be a method, a class, or a collection (subsystem) of classes.

A cohesive method solves one problem in the context of the class in which it resides. A cohesive class represents a coherent abstract entity in the application. A cohesive subsystem addresses one of the application's key issues (e.g., the printing subsystem).

SOC (Separation Of Concerns)
Wikipedia

A concrete principle supporting cohesion. A component - in our case, typically a class - should address a single aspect of the overall problem. An example of SOC failure is a weather station that controls and samples sensors AND directly controls the display of the samples it takes.

Class Responsibilities

What a class (or more likely its objects) knows and what it can do. Know in this sense is the state it manages - its instance variables, including those that refer to other application classes. Do means actions it can take in response to method invocations. What a class knows should be exactly what is required for what the class objects can do; avoid irrelevant information.

A class that knows nothing is pure computation. While this is sometimes appropriate, usually it is an indication that the behavior belongs in another class that contains the information needed to do the work.

A class that does nothing is pure data. These arise from time to time, but one should always ask whether the data belongs in another class - perhaps "broken off" from a class that does a lot and knows little.

Classes, of course, can have too many responsibilities, which is usually an indicator of low cohesion and violation of SOC.

Coupling
Wikipedia

Coupling is the manner and degree of interdependence between software modules. In general, the less the interdependence - the lower the coupling - the better.

A crude but useful measure of coupling is the number of other components a given component references; in a UML class diagram, this can be estimated by the number of lines going into and out of a given class.

More significant is the manner of the connection. Simply calling a method in a "logging" class to record an event is low coupling; depending on a variety of methods that must be used in a specific sequence is high coupling.

Technical Debt
Wikipedia

A term coined by Ward Cunningham in the 1992. From Cunningham's paper:

Shipping [...] code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite... The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise.

Technical debt can be thought of as work that needs to be done before a particular job can be considered complete or proper. If the debt is not repaid, then it will keep on accumulating interest, making it hard to implement changes later on.

Technical debt is not necessarily bad as long as you realize it is accumlating. Carrying a bit of debt that is promptly paid off (consider a house mortgage or student loan). But piling on debt thoughtlessly (as with credit cards) can lead to debt that can never be paid off. In the finance world this means bankruptcy; in software this means scrapping a useful program and starting all over.

Examples of technical debt include (but are not limited to):

Code that is poorly structured, uses arcane names, has inconsistent indentation, and is devoid of useful comments.

Code changes made without updating associated requirements and design documentation.

Quick patches to repair serious operational problems.

Short-cuts taken to make a hard release date.

In summary, consider this quote from Grady Booch

So it is [...] in software-intensive systems. Users suffer the consequences of capricious complexity, delayed improvements, and insufficient incremental change; the developers who evolve such systems suffer the slings and arrows of never being able to write quality code because they are always trying to catch up.

Refactoring
Refactoring: Improving the Design of Existing Code. Martin Fowler (Addison-Wesley, 1999).
One to consider for your own Programming on a Remote Island  book list.

Refactoring is restructuring existing computer code without changing its external behavior. Refactoring aims to improve nonfunctional attributes such as readability, maintainability, and design integrity. As such, refactoring is one technique to help keep technical debt under control.

In mature software organizations, refactoring is not a separate development phase. Instead, the programmers and engineers constantly improve the product by performing "micro-refactorings" in parallel with enhancing the product's function. It has been said that a good development team will proceed by "designing a little, programming a little, refactoring a little."

While refactoring is integrated into the normal workflow, it is a distinct activity. At any given time a developer may be refactoring or adding functionality, but not both. The reason is that refactoring should not change the behavior, and the only way to assure this is to keep the behavior the same. Once refactoring is complete and validated, then development can proceed (from a somewhat better code base).

Design Pattern
Design Patterns: Elements of Reusable Object-Oriented Software. E. Gamma, et.al. (Addison-Wesley, 1994).
One to consider for your own Programming on a Remote Island  book list.

A design pattern is the re-usable form of a solution to a design problem. Software design patterns derive from the work on (building) architectural patterns by architect Christopher Alexander. What Alexander said about architectural patterns applies as well to software design patterns:

Each pattern describes a problem that occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
The Timeless Way of Building, Oxford University Press(1979).

A software design pattern addresses a problem in a way that balances the application of design principles to enhance reuse and maintainability.

Observer Pattern
Wikipedia

Define a one-to-many dependency between objects so that when the one object changes state, all its dependents are notified and updated automatically. You don't want to maintain the consistency by tightly coupling the classes because that reduces reusability.

(GOF) Observer Class    (GOF) Observer Sequence

The object whose state is monitored is called the subject; those objects interested in state changes are called observers. In the canonical approach given in the Gang of Four, the subject comprises:

The superclass Subject and the subclass ConcreteSubject illustrate Separation of Concerns within a single object via inheritance:

The Observer interface simply defines the update method to be called when any observed Subject changes. The Observer then interrogates the changed information and does whatever is appropriate. Things get a tad more complicated if an Observer is observing multiple Subjects, because the Observer must determine which Subject called update.

Java Observable / Observer
Observer
Observable

The Java libraries support a version of the Observer pattern via the Observable class and the Observer interface in the java.util package: