Skip to content

Chapter 8 of 8

General Software Design Principles

Beyond the SOLID principles, several general design principles guide object-oriented programming toward clearer, more maintainable code. The DRY principle, Don't Repeat Yourself, holds that every piece of knowledge should have a single authoritative representation in the system. Copy-pasted logic, duplicated validation rules, and repeated SQL queries are all violations; the fix is to extract shared logic into reusable methods, base classes, or utility functions so that any change happens in one place. The KISS principle, Keep It Simple Stupid, argues that systems work best when kept simple rather than made complex, counseling against over-engineering and premature abstraction in favor of straightforward, readable code. Closely related, the YAGNI principle, You Aren't Gonna Need It, warns against implementing functionality until it is actually needed, discouraging unused configuration options, abstract factories for a single implementation, and features built for hypothetical future requirements.

Coupling and cohesion describe two complementary qualities of well-designed systems. Coupling measures the degree of interdependence between modules: tight coupling, where classes depend heavily on each other's internals, makes code hard to change and test, while loose coupling, where classes interact through abstractions, enables modification and independent testing. Cohesion measures how closely related the responsibilities within a single module are: high cohesion means a class does one well-defined job, like an EmailSender focused solely on sending email, while low cohesion means a class handles unrelated tasks. The combined goal is to minimize coupling and maximize cohesion.

The Law of Demeter, also called the Principle of Least Knowledge, refines the goal of loose coupling with a specific rule: a method should only talk to its immediate friends, not strangers. An expression like order.getCustomer().getAddress().getCity() reaches deep into unrelated objects and violates this principle; the fix is to delegate the responsibility with a method like order.getShippingCity(). The principle formally states that a method may only invoke methods on itself, on its parameters, on objects it creates, and on its own direct fields. Closely related is Design by Contract, introduced by Bertrand Meyer, which formalizes the agreements between a method and its callers through preconditions that must hold before the method is called, postconditions it guarantees afterward, and invariants that must always hold for the class as a whole. A withdraw method, for example, might require a positive amount as a precondition and ensure a non-negative balance as a postcondition.

Finally, dependency injection is a practical technique that supports the Dependency Inversion Principle by providing an object's dependencies externally rather than constructing them internally. In constructor injection, dependencies are passed through the constructor; in setter injection, they are assigned through a setter method; and in interface injection, the dependency is supplied through a dedicated injector interface. Combined with the design principles above, dependency injection produces code that is testable, flexible, and easy to maintain as systems grow.

All chapters
  1. 1The Four Pillars of OOP
  2. 2The SOLID Design Principles
  3. 3Classes, Objects, and Language Mechanics
  4. 4Object Relationships
  5. 5Polymorphism and Method Dispatch
  6. 6Abstraction Through Interfaces and Abstract Classes
  7. 7Composition, Inheritance, and Code Reuse
  8. 8General Software Design Principles

Drill it

Reading is not remembering. These come from the Oop Principles deck:

Q

What is encapsulation in OOP?

Encapsulation is the bundling of data and methods that operate on that data into a single unit (class), while restricting direct access to some components.Key b...

Q

What is inheritance in OOP?

Inheritance allows a child class (subclass) to acquire the properties and behaviors of a parent class (superclass).Example in Java:class Dog extends Animal { }B...

Q

What is polymorphism in OOP?

Polymorphism means "many forms" — the ability of an object to take on different behaviors depending on its type.Two main types:Compile-time (static): method ove...

Q

What is abstraction in OOP?

Abstraction is the process of hiding complex implementation details and exposing only the essential features of an object.Achieved through:Abstract classes — pa...