Object-Oriented Design Principles (SOLID)
=================================

(S) Single Responsibility Principle (SRP)
-----------------------------------

   A class should have only one reason to change.

   A class (type) definition should be highly cohesive.  Modifications
   to a class then are focused on the core functionality of the type.
   Multiple, varied changes implied that the class definition is not cohesive.

(O) Open/Closed Principle (OCP -- Bertrand Meyers)
-------------------------

   Classes (modules) should be open for extension but closed for modification.

   The chief idea here is to design software that can be modified
   without requiring changes in application code that uses that software. 
   The idea is to "add new code, but do not change working code". 
   At minimum, the interface needs to remain the same.  Moreover,
   working (class) functions should not change; isolate features.

   If a class hierarchy adheres to this principle, then a new subclass
   can be added without impacting old application code.  In C++, this
   kind of design is accomplished by using virtual functions.

(L) Substitution Principle (Liskov)
--------------------------

   An instance of a derived should be able to stand in for an instance of
   the base class.

   In other words, the application programmer can use derived classes through
   the base class interface without needing to know whether base or derived
   instances are being manipulated.  Substitutability comes into play with
   dynamic binding: the application programmer need not perform subtype
   checking in order to invoke the appropriate function.

(I) Interface Segregation Principle
-----------------------------------

   A user should depend only on methods used, i.e., a class interface should
   be confined to a core functionality.

   Like the Single Responsibility Principle, this principle promotes a tightly
   defined class.

(D) Dependency Inversion Principle 
----------------------------------

   Details should depend on abstractions.  Abstractions should not depend
   upon details.

   All high level functions and data should be independent of low level
   functions and data structures.  An abstract class defines the interface.
   The interface should not depend on implementation details, otherwise
   it cannot be reused.

