Object Oriented Programming/Design F.A.Q.

Table of Comments


1 Object Terminology

2 Object Oriented Programming

3 Object Oriented Design

4 Process/Methodolgy

5 Other Paradigms

6 CASE tools




1 Object Terminology

1.1 What does it mean for software to be object oriented?

Object oriented software is a term used to describe a program built using object oriented techniques. It is also used to describe a methodology for building software systems. In general, it boils down to the idea that everything in the system is an object. The behavior of the system is then defined as the operations the objects can perform. The available behaviors are usually implemented by building relationships between the objects. Object oriented software is often called noun-centric software. For example, in an accounting program, important objects may be accounts, ledgers, debits, and credits.


1.2 What is a class?

A class is a definition of data and operations on that data. It is one of the fundamental building blocks of object oriented programming. In general an object oriented program is composed of various classes and the relationships between those classes. A more formal definition of a class might include that classes have invariants, much like loops. During the lifetime of an instance of a class, the invariant should always be true from the perspective of the class's clients. Operations within the class are allowed to violate the invariant temporarily with the understanding that the invariant will be true by the time control is tansferred back to the client.


1.3 What is an instance?

An instance is an instantiation of a class. Essentially, the class describes what the data types and methods available to the instance, while the instance holds the values of those types.


1.4 What is encapsulation?

Encapsulation is the idea that data and the methods that operate on that data should be maintained together in a single unit (usually a class definition).


1.5 What is polymorphism?

Polymorphism is the mechanism that allows a single method invocation to call different operations for different types. One does not need to know the specific type of object in order to invoke the operation, only that the object supports the given operation. This technique is often used in concert with inheritance, so that the user has a handle to an abstract base class of the object, and when the client invokes the operation the correct method in the concrete class is invoked. Polymorphism can be correctly used in describing method determination thru static type inference as well (sometimes called static or parametric polymorphism -- see "What is generic programming?").


1.6 What is association?

Association is the relationship between two classes, where one class maintains a reference to another class. This association is often described as the "hasA" relationship because it often models the idea of one class having another class. For example, suppose you had developed a class for an advertising agency. An agency could have an association to a client, because a agency "hasA" client (to be successful, it probably needs to have more than one, but we'll talk about cardinality later).


1.7 What is aggregation?

Aggregation is a relationship between two classes, where one class contains another. Aggregation comes in both a weak form and a strong form. The weak form, sometimes called loose aggregation, means that the class instance that is aggregated into another class instance does not have its lifetime managed by the other class. The strong form of aggregation, somtimes described as a "composedOf" relationship, means that if the aggregate is destroyed, the aggregated class is also destroyed. The differences between the two forms of aggregation and association are subtle enough that it is probably beneficial to expand upon the example used for association. In addition to having clients, lets suppose that our agency is made up of agents and contracts. If one were to dissolve the agency, naturally the contracts would be dissolved as well. So it is fair to say that the agency is composedOf contracts (not wholly mind you, but partially). On the other hand, if the agency were dissolved, the agents would continue to exist most likely, however their role in the system would be changed (perhaps they would become free agents). The agents are loosely aggregated by the agency. Obviously the business could be one where the agents could not exist outside of the agency, in which case strong aggregation would be the preferred relationship.


1.8 What is inheritance?
Inheritance is the relationship between two classes, where one class is a specialization of the other class. The simplest way to describe it is to show a trivial example. If you already had a class called Airplane that described the basic data and operations of an airplane, and then later determined that in addition to your standard airplane, you also need to define a CargoAirplane, you might find it useful to have CargoAirplane inherit from Airplane, especially if all the data and operations that apply to an Airplane also apply to a CargoAirplane. The CargoAirplane class can then add any data useful to a cargo airplane (e.g. carryingCapacity). The class that is inherited from is often called the base class, and classes that inherit from the base class are often called derived classes. If a base class defines methods but does not give a callable default implementation, than the class is also abstract. In order to instantiate a derived class, it must implement the methods that do not have a callable implementation. These classes are sometimes called concrete derived classes. Sometimes the goals of inheritance are further qualified. Interface Inheritance is when classes derive from a base class to provide a specialized implementation of the base interface. Implementation inheritance is when a derived class wishes to leverage some functionality in a base class by way of inheritance. An often overlooked negative with the inheritance relationship is that it is not unusual to have the derived class coupled to the base classes implementation. For more information on coupling see the item on coupling.


2 Object Oriented Programming

2.1 What are some languages that allow object oriented programming?

In order to implement object oriented programming, a programming language needs only to support inheritance, polymorphism, and encapsulation. The following is a list of some of the more popular (or at least historically noteworthy) languages offering explicit syntactic support for object oriented programming:
Simula (1967)
Smalltalk (1980)
Ada (1981)
C++ (1982)
CLOS/LISP (1986/1959)
Python (1990)
Dylan (1992)
Java (1994)
C# (2001)
In addition, some languages don't offer explicit syntactic support for all the features of OO, but you can emulate them effectively using convention.


2.2 What is the best programming language for object oriented programming?

Every language has its own advocates. A good place to find out information about each of the languages above are their respective newsgroups:
comp.lang.smalltalk
comp.lang.smalltalk.advocacy
comp.lang.ada
comp.lang.c++
comp.lang.c++.moderated
comp.lang.lisp
comp.lang.python
comp.lang.java
comp.lang.java.advocacy
comp.lang.dylan
comp.lang.csharp

2.3 Is garbage collection neccesary for object oriented programming?

No. Though many languages that explicitly support object oriented programming have garbage collection as the default memory handler (Smalltalk, Java, etc.) or support garbage collection in terms of an addin library (C++). Many programmers prefer not to deal with the hassles of memory management, but other programmers are of the opinion that memory management issues are too important to be left to the language implementation.


2.4 Which is better, dynamic typing or static typing?

They both have their advantages. Static typing is the process where a tool (usually a compiler) is used to determine if a program declares variables of an incomplete type before that type has been defined. Dynamic typing is the process where the type of a variable is verified only when that variable is first used. Some languages that use static typing are Ada, C++, Java, and Dylan. Some languages that use dynamic typing are Smalltalk, Lisp, and Dylan. Static versus dynamic typing is independent of object oriented programming, but here is a quick argument for each, respectively:

Static typing is safer. Type checking is a tedious process best performed by computers. In the case where one does not test every execution path, you can at least be guaranteed that there will not be a type exception.
Dynamic typing is more flexible. It allows you to more easily develop your code, as it does not require that the code be developed in any specific order (e.g. making you fully specify a type before using it). The safety issue is a chimera, because you must test every execution path regardless.


2.5 What is dual (or multiple) dispatch?

Dual dispatch is the mechanism that allows a method invocation to determine the implementation based on the type of both arguments to a function, rather than only the type of the first object. Many object oriented languages do not support this feature explicitly, and the dispatch mechanism has to be hand coded. Other languages (such as Dylan, and Lisp) do offer explicit support for multiple dispatch.


2.6 What is subtyping, and how is it related to inheritance?

A is a subtype of B if the set of all possible values for A are contained within the set of all possible values for B. This is a slightly different than the definition given by Barbara Liskov, but in essence the definitions turn out to mean the same thing in the mathematical sense. Some languages choose to implement subtyping via inheritance (e.g. C++ and Java), many other languages don't make this distinction.


2.7 What is a "mixin" class?

A mixin is a class that is derived from in order to access the mixin's implementation. See implementation inheritance.


3 Object Oriented Design


3.1 What is object oriented design?

During object-oriented analysis the high level actors and tasks are typically identified and documented. Object oriented design is the process of converting the actors and tasks into classes, and describing the interactions between the identified classes. The unified modelling language, UML, is often used to document the discovered classes and interactions. TODO: Add example and more info.


3.2 What is coupling?

Coupling is another name for class relationship. Whenever the term coupling is used, though, the goal is generally to talk about the number of relationships a class has, and the nature of the relationships. For example, a class is tightly coupled to another class if the former is heavily dependent on the latter (e.g. a wrapper class). Coupling isn't bad in and of itself, however it often turns out to be the source of problems. Classes that have a high degree of coupling are often more difficult to understand


3.3 What is layering?

TODO: Add description and example.


3.4 What is UML?

UML is an acronym for the Unified Modelling Language. It is a graphical notation for representing the relationships between classes, packages, and components. It also includes a notation for capturing requirements (use case diagrams). The "unified" part of the name comes from the creators of the language, Booch, Rumbaugh, and Jacobson. Each combined components of their original notation to create a sindle standardized modelling language.


3.5 What is LSP (the Liskov Substitution Principle)?

Barbara Liskov wrote in a paper to the ACM: Family Values: A Behavioral Notion of Subtyping. Essentially this boils down to the idea that A is a subtype of B, if an instance of A can be substituted anywhere an instance of B is needed. Another way to think about this is that derived classes cannot violate the invariants of their base classes. This principle is often used to critique designs where a class inherits from another, but attempts to cripple some functionality of the base class. Of course the canonical example is circle/ellipse. Is circle a subclass ellipse? This issue has been discussed to death on the newsgroup comp.object. The answer depends on how exactly ellipse is defined and even which the language being used for implementation..


3.6 What is the Open Closed principle?

Simply stated, the open closed principle is the idea that classes are "open" for addition, and "closed" for modification. More completely, when modifying class, you should strive to add methods, rather than change existing methods. In order for modifications that follow this idiom to work, the class needs to be designed in such a fashion that functionality can be added in base classes, but used transparently by the parent classes interface. An example of two patterns that exemplify this principle are the strategy pattern and the visitor pattern.


3.7 What are patterns?

Patterns are attempts to document useful programming idioms. For an idiom to qualify as a pattern it generally must be proven to be useful in several different applications. Patterns (at least the object oriented type) usually attempt to document a way of relating classes that is particularly useful at solving a common problem. I've gone to the trouble to mention some of the more popular or useful patterns, but there is a whole ream of literature on patterns, how to find new ones, and how to document them. A good place to start is Design Patterns: Elements of Reusable Software by Gamma, et all.


3.7.1 What are creational patterns?

Creational patterns are probably the most widely used patterns, at least partially because they have the advantage of being non-controversial. Other categories of patterns don't always have that property. Creational patterns are proven idioms for constructing and initializing objects. Most object oriented software probably utilizes several of these patterns in some shape or form.


3.7.1.1 What is the Singleton Pattern?

A creational pattern that ensures that only one instance of a class can be instantiated. It also provides an encapsulated interface for accessing the singleton. The singleton pattern comes in many flavors, at least partially because the idea is so useful people have attempted to use it in situations it did not neccesarily fit well. Refer to Design Patterns: Elements of Reusable Software for a complete description of the singleton pattern.


3.7.1.2 What is the (Abstract) Factory Pattern?

TODO

3.7.2 What are behavioral patterns?

TODO


4 Process/Methodology



4.1 Is a methodology required for object-oriented development?

It depends. It definitely isn't required to use any well known methodology (often called big M, Methodologies). It is possible to develop object oriented code in an unstructured fashion, but it is generally preferable to develop the code with a little more structure, as class relationships can lead to excessive coupling. Often a process can help reduce coupling by requiring some degree of forethought be put into developed code, however there is no guarantee that any process will help deliver good software.


4.2 What is an iterative process?

An iterative process is one that attempts to build systems incrementally. A subset of the requirements is chosen for each iteration and developed to completion. Generally this means that the software for those requirements is designed and coded together. Then another set of features are designed to be added to the existing system and developed. One advantage of this approach is that the system can accomplish some of the required tasks after the first iteration, and then becomes more and more full featured after every iteration. Another advantage is that requirements are notoriously volatile, and this approach can help mitigate some of the risk of requirements change by not having spent any effort on requirements that have not been thru an iteration yet.


4.3 What is the waterfall process?



4.4 What is Extreme Programming?

Extreme programming, sometimes shortened to XP, is a relatively new methodology advocated by several respected industry veterans. The chief originator of Extreme Programming was Kent Beck, who developed the process for a project at Chrsyler called C3. Extreme programming is a so called lightweight process, meaning that it is a process that has little overhead and few rules. While strictly true, the XP rules alter the way developers work radically and is quite demanding in its application. The original 12 rules of XP are:
  1. System Metaphor - Develop a metaphor for the system
  2. Planning Game - a way to prioritize requirements
  3. Small Releases - the planned releases should be small (every 2 weeks is a guideline often used)
  4. Acceptance Tests - Every release must have a set of automated acceptance tests
  5. Pair Programming - All production code is written in pairs
  6. Test First Design - All production code is written to pass a unit test
  7. Simple Design - All software is written as the simplest thing that could possibly work
  8. Continuous Integration - The software should be integrated daily
  9. Refactor Mercilessly - Code refactoring should be done as soon as a need for refactoring is observed
  10. Collective Ownership - No specialization, everyone works on all the code
  11. Sustainable Pace - No overtime or pre delivery rush
  12. Onsite Customer - The customer must be available to answer team questions and participate in team activities
More information is available on the newsgroup comp.software.extreme-programming.


4.4 What is RUP(Rational Unified Process)?

RUP isn't actually a set of rules that make up a process, rather it is a set of rules that describe how a particular process would have to be tailored to be RUP-compatible.


5 Other Paradigms


5.1 What is a procedural/imperative programming language?

Imperative programming is essentially programming directly to the computer. Valid operations are assignments, memory allocation and deallocation, value swaps, math operations etc. Procedural programming is imperative programming with the addition of being able to organize imperative statements into reusable blocks. This style of syntax is common to Ada, C++, Dylan, Java, and Smalltalk. Lisp has many features of an imperative programming language.


5.2 What is a declarative/relational programming language?

Declarative programming is programming to generate logical closures. The program is a set of rules, and a supposition. The supposition is consistent with the rule set, or it is not. An example of a declarative system is a Makefile. The supposition is usually something along the lines of, "Is an executable up to date?". In determining if the executable is up to date, any out of date files will be recompiled to generate the object code, and the executable will be linked. Essentially the executable is always up to date after the supposition is posed. This is a common technique in declarative systems.


5.4 What is functional programming?

Functional programming is one implementation of declarative programming. The rule definitions are supplied as functions that then locate other rules. Functional programming is widely used in academic circles, perhaps partly because it has an associated calculus (lambda calculus) that proves its completeness. The existince of lambda calculus also lends some of the proponents of functional programming to consider the solutions elegant. One of the most popular functional programming language(s), LISP (it has many dialects), however also has many procedural artifacts. Though not needed for completeness, the procedural components sometimes allow more straightforward or efficient solutions to problems (for example the ability to use a loop in place of recursion).


5.5 What is generic programming?

Generic programming is another implementation of declarative programming. It is unique from the other two major flavors of declarative (functional and relational) programming in that it is widely applied in industry and is not of academic origin. The most popular application of generic programming, the C++ STL, is the brainchild of Alexander Stepanov. Though the mechanism is the same as the other declarative languages, the application is slightly different. Rather than controlling business logic, generic programming is used to generate type specific code. Declarations compose generic algorithms that are then applied to the type specified by the application. It would be fair to call programming based on this style algorithmic programming, as the algorithms are the chief items abstracted in the code rather than the specific business objects. Variations on this technique can be used for aspect oriented programming.


6 CASE tools



6.1 What is a CASE tool?

CASE is an acronym for Computer Aided Software Engineering. CASE tool refers to tools that purport to raise productivity by allowing programmers/designers to work more effectively. In general every software project needs some tools. Makefiles, source control, and bug tracking are some of the least controversial. However there are also tools that supposedly help at managing the project space by allowing the enegineers to better model the problem they are solving. An example of this kind of tool could be a UML drawing tool or requirements management software, but there are far too many types to list.


6.2 What CASE tools should I use?

It is impossible to give a solid recommendation to this question. It depends on a great many factors, including, but not limited to team size, scope of project, geographic location of team members. Some CASE tools that projects have found effective include UML modelling tools, refactoring browsers, pretty printers, static checkers, bounds checkers, etc. Still other prefer whiteboards and markers. No matter what CASE tools you choose it is important to understand their limitations. CASE tools don't actually produce working software, they just try to facilitate the development of better software. Accordingly, CASE tools alone are not the answer.