Object Orientation Principles / Best Practices

Whilst the vary to which these principles are supported by different languages vary, there are a certain set of principles to the OO paradigm which I hope to 'encapsulate' here. This page largely serves as a definition of terms and may be refered to from other documentation.

Encapsulation
The attributes and services/behaviors are encapsulated in a class. No direct access of an object's properties happens from outside the code associated with that class.
Information Hiding
The information that an object uses to drive its implementation are not visible from the "outside". This is usually not enforced with Perl.
Certain attributes and services may be internal to the class (private), the package (protected), or external (public). Again, these are distinctions not normally enforced in Perl.
Message Passing
Objects communicate by invoking services from other objects, passing the required information for the service. This means that even if an operation is thought to be happening between two objects of the same type, they must still communicate with each other through their "formal" interface.
An Object Oriented Surgeon would hand you a scalpel and say, “Now perform this operation on yourself!”.
Late Binding
An object is not linked to it's behaviors until run-time. This is important for polymorphism. In Perl 5, all method lookups are always bound (or verified) at run time.
Delegation
Objects may pass work on to other objects and behave as those delegated objects.
Class/Instance/Object
All objects are instances of a class. Objects which are similar enough to share the same implementation of methods are usually considered to share a common class, or be of the same "type".
This is not a hard and fast rule; it may also be possible for individual objects to be able to behave as two classes of object simultaneously. This is commonly called a mix-in, and the varieties of levels of this are called Roles in Perl 6. However, this functionality is only syntactically different from delegation.
Generalization/Specialization without Polymorphism
Classes may inherit attributes and services from another class, and behave exactly as the parent class. The test for this is called the empty sub-class test, where a new class is created that is a degenerately void specialisation of the parent class. The object should still behave exactly as if it were a member of the parent type.
Generalization/Specialization with Polymorphism
A class may override methods inherited from a superclass.  Polymorphism allows the language to call the correct method in the hierarchy. As well as polymorphism, there must be some method of calling superclass methods, so that you can augment, and not merely replace functionality.
Relationships (or Associations)
An object may be composed of other objects, which determine how it behaves. For example, a car is composed of body, engine, suspension, etc.; and these in turn are also composed of simpler objects. The major commonly recognised forms of relationships are associations, aggregations and compositions. The differences between them may appear to be minor, but a clear distinction between them whilst designing programs can be useful.
Interface/Implementation
An object may be of a type declared by an interface. That is, it does not provide an implementation that may be sub-classed; it simply prescribes a set of operations and they must be fully implemented by the provider of the interface.
Generalization/Specialization of Interfaces
A class may implement the methods of multiple interfaces at once. These interfaces should not place any undue restrictions on other specialization that the object may perform.
Reflection (aka Run-Time Type Information)
Each object knows the details about which class or interface of which it is a member. This is sometimes called “Run Time Type Inspection”, and is possible to do with Class::Tangram - in fact, this is used extensively in the interactive T2 schema browser.
Multithreading
Each object can have multiple concurrent execution paths. In practice, this means keeping all state information about what you are doing with an object on the stack (as the stack is never shared between threads), and committing changes back to the object in a "safe" fashion - that is, never leaving the object in a state where another thread reading the object might get confused.
References

Source material used for this page include:

  1. Principles of Object Orientation [now offline]
    http://www.math.grin.edu/~bishopd/csc223/Principles_of_Object_Orientation.html
  2. Object Orientation, from OutBack Software (Aus)
    http://www.outbacksoftware.com/oo/oo.html
  3. “Years of experience” - Dr. Phil