This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.

Anomaly ~ G. Wade Johnson Anomaly Home G. Wade Home

October 18, 2007

Objects, Reuse, and Complexity

Over the last few years, I have spent a lot of time talking to lots of different people about object-oriented programming (OOP). I have spent a fair portion of the last three years interviewing and screening people over the phone for development positions. This activity has caused me to spend some time re-evaluating what I know about objects.

Reuse?

Some of the people I talk to say that OOP is about reuse. They say the main thing we get out of objects is reuse. We can reuse the data and functionality from a class by deriving from it. We get more reusable code by packaging it up in classes. Unfortunately, reuse is not confined to OO. Back when I was doing structured programming, we captured reusable code in functions. We used libraries and modules for larger granularity reuse. Obviously, OO is not the only way to reuse code. So, it's kind of hard to claim that the main reason for OO is code reuse.

OO Concepts

So, if reuse is not the purpose for objects, what is? One of the maintenance benefits of OO has to do with the concept of encapsulation. If a class is defined reasonably, the only way to access its data is through its member functions (methods). The practical result of this is the amount of code that can change a piece of data is limited. In a large system, this drastically reduces the amount of code that must be examined to troubleshoot a data problem.

OO provides good support for abstraction. It is possible to make an abstract interface without OO, but it requires more discipline on the part of the programmer and the clients of the library. With classes, it is easier to specify an abstraction and encourage clients of your class to use it.

Complexity

These two concepts are different aspects of the same issue: controlling complexity. By reducing the number of methods that can touch a given piece of data, you are reducing the communication paths in your code. This reduces complexity by introducing constraints in the way data is accessed and modified. Abstraction also reduces complexity by encouraging the client programmer to focus on the concept of the class rather than on its implementation.

In some cases, the complexity isn't actually removed, but only quarantined inside the class. This helps keep complexity inside the class from leaking out, and complexity from the surrounding system from leaking into the class. In many cases, reducing the way complex things interact is the best tool we have for managing complexity in our systems.

By providing interfaces that hide implementation details behind some form of abstraction, we reduce the complexity that the programmer needs to be aware of at any given point in time.

Increasing Complexity

This also highlights one of the points where OO has failed in its promises. Without careful thought about your designs, an OO system can add to the complexity in a system. Several kinds of OO design decisions can add complexity to a system:

  • deep hierarchies
  • badly thought-out interfaces
  • objects that are just collections of random data and methods
  • large quantities of unrelated classes

Another dark side of objects is that hiding the complexity of the system allows us to develop even more complex software because we don't have to deal with all of the complexity all of the time. This has caused many people to ignore the complexity cost of their designs.

Conclusions

People who really understand that OO is about reducing complexity avoid adding one more method to a class to make it more reusable. Classes with only one responsibility abstract the implementation details while providing a lower complexity interface to the functionality. Combine two classes inappropriately and the complexity increases again, because you need to know more to use the two halves of this split-personality class.

Keeping the importance of reducing complexity in mind should help in the creation of cohesive classes. Using classes to provide coherent interfaces that hide complex implementation details should help to reduce the complexity in our software.

Posted by GWade at 07:29 PM. Email comments