Object Oriented Programming

Summary

A discussion of what an Object is in OOP.

What is an Object?

In OOP, what is an Object?

There are several layers of answers for this:

  • An Object is an instance of a class
  • An Object is a collection of methods (i.e. functions) and member variables
  • An Object has a single purpose
  • An Object is a collection of methods and variables that are associated
  • An Object is a collection of methods and variables that are strongly associated to the single purpose of the class

In the order listed, these answers refine the concept of an Object. The last is a very good definition of a well-designed Object.

It's an Instance of a Class

This is the most common answer.

The normal textbook answer, but it does not address why use Classes/Objects at all.

Also, while it is technically true for some languages like Java and C++, it is not true in other languages like Ruby and smalltalk. In these a class itself is an object and can be manipulated as an Object.

A similar answer is "OOP supports Encapsulation, Polymorphism and Inheritance". This is another textbook answer, but does not reveal a deeper knowledge of Classes/Objects. Also, it is clear that none of these is necessary for a program to use OOP. For example, it is possible to write an OOP application in Assembler, a language which has little if any support for these concepts.

It's a Collection of Methods and Variables

This is the next most common answer.

https://en.wikipedia.org/wiki/Object-oriented_programming

It is a better answer than the first in that it begins to outline why OOP may be a useful methodology. Collecting functions/methods and variables together is a first-cut attempt at OOP. This is a natural activity for programmers to do and was done even in Modular Decomposition Programming where functions were grouped together into "Modules". (Search for "OOP for Rust" as a modern day example of this).

Sometimes people say a class is similar to a Noun and methods are similar to Verbs. Again this shows that there is some underlying reason to group methods together. It does not address which functions and variables should or should not be in the class.

It's Methods and Variables are Associated

A rare answer.

This is a better answer again because it is much closer to the core of the definition of a Class/Object. The Methods and Variables of a well-designed Class are not randomly chosen. They are associated in some way, but unfortunately this answer does not address why and how they are associated.

It has a Single Purpose

A rare answer.

A well-designed Class has a single purpose. It has the functionality and data to do one "thing" very well.

This is a good answer as well but does not tie in the methods and variables of the Object/Class.

It's Methods and Variables are Strongly Associated with the Class's Purpose

In a well-designed Class:

  • every method is strongly related to the Class's Purpose
  • every variable is strongly related to the Class's Purpose
  • every variable is usually one of these:
    • an attribute of the Object, i.e. it describes a facet of the Class's Purpose
    • a state the Object can be in

In other words, every method and variable is necessary and sufficient for the Class's Purpose. The Class contains only the code it needs and not anything more than that. The Class is as complex as it must be and not more.

Why use OOP?

Simply, it tends to promote code that does not change. The #1 cause of bugs is code changes.

In a well-designed Class, the Class's Purpose is very clear and singular. Every Method is strongly related to the Purpose and so removing that Method would, in some sense, diminish the Class. Altering the Method (beyond bug fixes) also becomes unlikely since the Purpose is clear and the Method supports that Purpose. Adding additional Methods may occur but in popular or common Classes this will be very rare.

Similarly, every Member Variable is strongly related to the Purpose and so removing, changing or adding Variables is a rare activity.

A well-designed Class with a clear and singular Purpose becomes a "magnet" for new behavior that supports that Purpose. As an application evolves, new behavior naturally splits up and attaches to the correct Class(es). If the new behavior does not fit well in any of the existing Classes, it tends to suggest a new Class is required.

Based on all of these effects, a well-designed Object solidifies and matures. Changes become rare. The code becomes static, predictable and well-behaved. Other Objects in the system can depend on them to behave the same way and do not change.

Bugs in a well-designed Class/Object are:

  • much easier to detect by inspection or code review
  • much easier to fix
  • have less impact on other parts of the code, i.e. fixing them does not cause "whack-a-mole"
  • much easier to locate at the Application level. Since a Class/Object has a single purpose, and the application is having problems behaving in some aspect X, then the Class/Object(s) whose Purposes are to implement X are easier to identify.

Object Normal Forms?

Well-designed Classes seem to have a similarity to Database Normalization. In Third Normal Form "all the attributes in a table are dependent on the primary key and only the primary key". The Boyce-Codd Normal Form says "Each attribute must represent a fact about the key, the whole key, and nothing but the key."

Draw a line from the concept of a "primary key" in a relational database table to the idea of the Class's "single purpose" and then draw a similar line from the "attributes" in a database table to an Object's "member variables". And then paraphrasing the Boyce-Codd Normal Form: Each of the Class's member variables are directly and strongly related to the main purpose of the Class/Object, to the whole purpose, and nothing but the purpose.

If a member variable is not related to the main purpose of the Class, it belongs, perhaps, in another Class. Can it simply be removed without affecting the Class's behavior?

If a member variable is related only to a portion of the Class's purpose, then the Class may be multiple Classes-in-one and subsets of the member variables describe each of the sub-Classes.

If a member variable describes (or is an attribute of) another member variable in the same Class, then there is a sub-Class that should contain the two (or more) member variables .

Refactoring

The primary intent of refactoring in OO applications is to disentangle two (or more) classes intertwined within a Class. There are other reasons to refactor, but the one gives the most benefit for the effort is "Extract Class".

Here are some of the symptoms:

  • The Class's Purpose is vague or sprawling
  • The Class's Purpose is clear but has one or more additional behaviors that seem tangential
  • Contains methods/variables that do not relate to the Object's Class at all
  • Contains methods/variables that are weakly associated to the Class's Purpose but strongly associated to each other
  • There is a cluster of related methods that work only on one of the variables (e.g. open/read/write/close a file variable)
  • There is a cluster of methods that have very similar signatures (i.e. the same formal parameters in all of them)

- John Arrizza