Object Oriented Technique Classification for C++
Abstract
The intent of this document is to capture and refine some thoughts on the various mechanisms available to object oriented programmers. Although I attempt to approach the subject in a general way, almost all of my object oriented experience comes from the use of the C++ programming language.The motivation for this rant are my often repeated encounters with other C++ practioners and the ensuing discussions about practices. Thus, this is an attempt to analyze, identify and capture the reasons for my beliefs regarding the Right Use(tm) of object oriented techniques.
My approach is to classify the various tools available and collectively labeled as Object Oriented, especially those available to C++ practitioners; identify, compare and contrast their attributes; and then attempt to form some heuristics for their proper use.
Like many of my rants, the outline for this document was scribbled onto a notepad in my car on the way to work one morning.
Table of Contents
Outlilne
This section is a raw collection of haphazardly organized classifications and attributes that do nothing more than quickly capture some of my thoughts. The following sections give a more verbose descriptions of the discoveries that come fom this process.
- Class 1 (Value Oriented)
- Creationally oriented
- Usage: Pass-by-value
- Wide interfaces (e.g. operators, copy constructors, casts, etc.)
- Best Use: fundamental, low level types.
- Reuse
- Fundamental components easily re-used.
- Generally difficult to reuse as complexity increases.
- Varies with dependency graph
- Link Time (Libraries)
- Inlining is common for architectural access enforcement and improved performance.
- Similar to built-in types (e.g. int,long,float, etc.) It is interesting to note that built-in types cannot be sub-classed. For example, the following C++ code is invalid.
class MyInt : public int { };
- Scalability
- Typically copied frequently, limiting performance scalability in terms of object size.
- Best for micro (small scale) level programming.
- Not a good candidate for inheritence
- V-table reference contributes to object's size.
- Clients typically create and destroy instances and therefore have no need for abstract interfaces.
- Variability.
- Link-time binding.
- One variant per application.
- Class 2 (Interface Oriented)
- Abstract
- Decoupling
- Reuse
- Component
- Compile Time (Compiled Components)
- Run Time (Shared Libraries)
- Distinct creational and usage interfaces.
- Usage: Pass-by-reference
- Best Use: decoupled, high level types.
- Infrequent use of inlining since inline functions are not abstract in the run-time binding sense. The function implementation is exposed in the header file.
- Scalability
- Not frequently created,destroyed, or copied and thus better for large objects.
- Best for macro (scale, not pre-processor) level programming.
- Hide implementation through virtual interfaces.
- Rarely (if ever) copied.
- Infrequently created/destroyed.
- Variability.
- Run-time binding
- Many variants per application.
- Best Use: High Complexity
- Narrow abstract interfaces
- Concrete objects often implement many interfaces.
- Class 3 (Behavior Oriented)
- Generics / Templates
- Algorithmic/Behavioral reuse
- Frequent inlining
- Reuse
- Fundamental (small) components easily re-used.
- Varies with dependency graph.
- Compile Time (Headers)
- No hidden implementation details since the entire implementation is contained in header file.
- Unrelated member names may be required. For example, a template may use a member function name of a parameter type, effectively requiring the specialization to implement a member function with a particular name and signature.
- Code Bloat Potential
- Encourages small template implementations.when many specializations are used.
- Encourages a limited number specializations within an application when the template implementation is large.
- Variability.
- Compile-time binding
- Many variants per application.
Value Oriented
Value oriented types are similar in use to the built-in types of the language (e.g. int, long, double, etc.). Clients depend on their ability to create, destroy, and copy these types. As a result various constructors and assignment operators are a required. A full complement of operators for conversions and comparisons are also quite typical. Value oriented types are often passed by value, and thus their performance suffers with an increase in their member variable size. Frequent usage of such types makes the efficiency of design an important aspect of these types. As a result, inlining is often used resulting in an exposure to implementation detail. The limitations in hiding implementation detail are traded for performance gains. A full complement of operators can improve a programmers ease of use, hide complexity in client code, and improve the high level readability of the client code.Interface Oriented
Interface oriented types make extensive use of run-time binding (virtual functions) to increase reusability by reducing dependencies between components. Interface segregation is king and component creational issues are distinct from the use of the components interfaces. Most clients know only the abstract interfaces of the components and not the concrete type.Interface Oriented
Behavior oriented types capture algorithms that are independent of the types upon which they operate. In C++, this implies the use of the template mechanism. A template's code is expanded for each unique set of its template parameters, and thus code bloat is a potential issue. However, many uses of templates are a means to capture small frequently used and frequently specialized algorithms in a type-safe way. Another use is to capture large complex algorithms in a type independent way, thus depending on infrequent specialization to prevent bloat.Contents