Design Principles
Design principles are fundamental guidelines that help developers create high-quality,
maintainable, and efficient software systems.
They ensure that software design is structured, flexible, and easy to manage.
1. Abstraction
Focus on essential features.
Hide unnecessary details.
Allows designers to manage complexity.
Example: Showing what a module does without showing how it works internally.
2. Modularity
Divide the system into independent modules.
Each module performs a specific function.
Improves maintainability and testing.
3. Encapsulation
Hide internal data of a module.
Access data through defined interfaces.
Protects system integrity.
4. Information Hiding
Internal implementation details should not be exposed.
Changes inside a module should not affect others.
5. Separation of Concerns
Different parts of the system should handle different responsibilities.
Avoid mixing unrelated tasks in one module.
6. Low Coupling
Modules should have minimal dependency on each other.
Changes in one module should not heavily impact others.
7. High Cohesion
A module should focus on a single task.
All elements within a module should be closely related.
8. Reusability
Design components that can be reused in other projects.
Reduces development time and cost.
9. Simplicity (KISS Principle)
“Keep It Simple and Straightforward.”
Avoid unnecessary complexity in design.
Encapsulation
Definition
Encapsulation is a design principle in which data (variables) and the methods (functions) that
operate on that data are combined into a single unit (usually a class), and direct access to the
internal data is restricted.
In simple terms:
Encapsulation means hiding data inside a class and controlling how it is accessed.
Key Features of Encapsulation
1. Data Hiding
o Internal data is declared as private.
o It cannot be accessed directly from outside the class.
2. Controlled Access
o Access to data is provided through public methods.
o These methods are often called getters and setters.
3. Security
o Prevents unauthorized modification of data.
Example (Conceptual)
Instead of allowing direct access like:
[Link] = -50;
Encapsulation ensures data is accessed through methods:
[Link](50);
The method can validate the value before storing it.
Advantages of Encapsulation
Improves security
Protects data integrity
Makes system easier to maintain
Reduces system complexity
Supports modular design
Real-World Example
Think of a bank account:
You cannot directly access the balance.
You must use methods like deposit() or withdraw().
The internal balance is protected.
Program to an Interface, Not an Implementation
Definition
Program to an interface, not an implementation is a design principle that states:
Software components should depend on abstract interfaces rather than concrete classes.
This means we write code that interacts with general behavior (interface) instead of specific
implementations.
What This Means
Instead of writing:
MySQLDatabase db = new MySQLDatabase();
We write:
Database db = new MySQLDatabase();
Here:
Database is the interface (abstraction)
MySQLDatabase is the concrete implementation
The program depends on the interface, not the specific class.
Why It Is Important
1. Flexibility
You can change implementations without changing the main program.
Example:
Replace MySQLDatabase with OracleDatabase
No major changes in the rest of the system
2. Low Coupling
Reduces dependency between modules.
Makes the system easier to modify.
3. Easier Testing
You can replace real objects with mock objects.
Useful in unit testing.
4. Better Maintainability
Changes in implementation do not affect client code.
Real-Life Analogy
Think of a remote control:
You use buttons (interface).
You do not care about how the TV works internally (implementation).
The same remote design can work for different TVs.
Composition Over Inheritance
Definition
Composition over inheritance is a design principle that recommends:
Building classes by combining simpler components (composition) rather than relying heavily
on class inheritance.
It emphasizes “has-a” relationships instead of “is-a” relationships.
Explanation
Inheritance
Creates an is-a relationship.
Example:
class Car extends Vehicle { … }
o A Car is a Vehicle.
Composition
Creates a has-a relationship.
Example:
class Car { Engine engine; … }
o A Car has an Engine.
Why Use Composition Over Inheritance
1. Flexibility
Components can be swapped at runtime.
Example: Change Engine without changing Car.
2. Reduced Coupling
Classes are less dependent on parent classes.
Changes in one class do not break others.
3. Avoids Inheritance Problems
Deep inheritance hierarchies are hard to maintain.
Inheritance can lead to fragile code if parent changes.
4. Promotes Reusability
Components can be reused in multiple classes.
Real-World Example
A Car object:
Has an Engine, Wheels, and Transmission (composition)
Instead of creating a deep hierarchy like SportsCar extends Car extends Vehicle