Object-Oriented Design Principles
This post gives an overview of fundamental object-oriented design principles. It was inspired by the book Head First Design Patterns, which I highly recommend.
Separation of Concerns
Separation of Concerns (SoC) is the principle of breaking a monolithic design into smaller modular components, such as routines or objects. The resulting components should have as little overlap in functionality as possible. When you use this principle, you end up with components that are easier to understand, build, and manage.
Encapsulation
Encapsulation is the practice of hiding the implementation details of a component behind an unchanging public interface. This makes your app more stable because the interaction between components remains the same even though the inner workings of the components may change.
Single Responsibility principle
A class should have one, and only one, reason to change. If your class has only one responsibility, it will be smaller, simpler, less likely to need maintenance, and easier to debug and test. This may mean that you have to create many small, simple classes. Don’t be afraid to simplify your design by adding classes.
Identify the parts of your application that vary and separate them from the parts that stay the same.
Take the parts that vary and encapsulate them so they won’t affect the rest of your code. By doing so, you will have fewer unintended consequences from code changes and more flexibility in your app.
Program to an interface, not an implementation.
When you program to an implementation, you create a strong bond between parts of an application and lose flexibility. When you program to an interface, you retain the option to use different behaviors without change to the related code.
Favor composition over inheritance.
Implementing an object’s behavior with composition gives you the flexibility to specify that behavior at runtime. Inheriting behavior locks you in to the implementation provided by the superclass.
Strive for loosely coupled designs between objects that interact.
By minimizing the knowledge one class has of another, you decrease dependency between those classes. Independent classes provide more flexibility in design, and they are easier to test.
The Open/Closed principle
Classes should be open for extension, but closed for modification. Design your classes so they can be easily extended to provide new behavior instead of requiring changes to the existing code. This prevents you from introducing new side effects or bugs into existing classes, yet makes your app flexible enough to deal with changing requirements. This is commonly solved with polymorphism.
Dependency Inversion principle
Depend upon abstractions, do not depend upon concrete classes. Here are some guidelines to follow:
- No variable should hold a reference to a concrete class.
- No class should derive from a concrete class.
- No method should override an implemented method of any of its base classes.
Obviously, you can’t follow these rules 100% of the time, but by being aware of them you will create more flexible classes.
Principle of Least Knowledge–talk only to your immediate friends
By limiting a classes knowledge of other classes, you avoid deep dependencies and increase loose coupling for more flexibility and reuse.
The Hollywood principle—don’t call us, we’ll call you
Lower-level classes should have no knowledge of higher-level classes—it’s the higher-level classes responsibility to call the lower level classes.






