Object-oriented design principles provide guidelines and best practices for creating well-designed and maintainable software systems. These principles help achieve modular, flexible, reusable, and easy-to-understand code. Here are some important object-oriented design principles:
SOLID Principles:
Single Responsibility Principle (SRP): A class should have only one reason to change, meaning it should have a single responsibility or concern.
Open-Closed Principle (OCP): Software entities (classes, modules, functions) should be open for extension but closed for modification. New functionality should be added by extending existing code, rather than modifying it.
Liskov Substitution Principle (LSP): Subtypes should be substitutable for their base types, meaning derived classes should be able to be used in place of their base class without affecting the correctness of the program.
Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use. Instead, interfaces should be fine-grained and specific to the needs of the client.
Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.
Composition over Inheritance:
Favor composition (combining objects) over inheritance (extending classes) to promote code reuse and maintain flexibility. Composition allows for better encapsulation, loose coupling, and easy modification of behavior.
Law of Demeter (LoD):
Also known as the Principle of Least Knowledge, it states that an object should have limited knowledge and should only interact with its immediate neighbors. It helps in reducing coupling and promotes modular design.
Favor Encapsulation and Information Hiding:
Encapsulate data and behavior within classes and expose only necessary interfaces. Hide internal implementation details to reduce dependencies and protect the integrity of the objects.
Design Patterns:
Utilize proven design patterns to address common software design problems and promote reusable, maintainable code. Examples include Singleton, Factory Method, Observer, Strategy, and many more.
High Cohesion and Low Coupling:
Aim for high cohesion within classes, where each class has a single, well-defined purpose, and low coupling between classes, where dependencies between classes are minimized. This enhances modularity, ease of maintenance, and code readability.
Design by Contract:
Apply the concept of design by contract, where classes clearly define their preconditions, postconditions, and invariants. This helps in specifying the expected behavior and responsibilities of classes and promotes robustness and reliability.
These design principles encourage good software design practices, such as encapsulation, modularity, loose coupling, and high cohesion. By following these principles, developers can create software systems that are more flexible, maintainable, and scalable. It's important to understand and apply these principles appropriately based on the specific context and requirements of the project.
Object-Oriented Design Principles we will be covering:
SOLID Principles (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion)
DRY Principle (Don't Repeat Yourself)
KISS Principle (Keep It Simple, Stupid)
Composition over Inheritance
The Gang of Four:
The "Gang of Four" refers to four authors - Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides - who co-wrote the influential book "Design Patterns: Elements of Reusable Object-Oriented Software."
This book was published in 1994 and it identified, named, and described 23 classic software design patterns. The patterns are grouped into three categories: Creational, Structural, and Behavioral.
Creational Patterns are about object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or in added complexity to the design. These patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly. Examples include the Singleton, Factory Method, and Abstract Factory patterns.
Structural Patterns are about organizing different classes and objects to form larger structures and provide new functionality. These patterns help ensure that when one part of a system changes, the entire structure doesn't need to change along with it. Examples include the Adapter, Decorator, and Composite patterns.
Behavioral Patterns are about identifying common communication patterns between objects and realizing these patterns. These patterns are specifically concerned with communication between objects. Examples include the Observer, Strategy, and Command patterns.
We will look at a few of the design patterns in this section.