Skip to main content

Universal Principles and Concepts

Across different programming paradigms, there are several universal principles that have emerged. Many of these principles were first articulated or popularized within the context of object-oriented programming but are broadly applicable and still hold value across paradigms, including functional programming and imperative programming.

These principles, while originating from specific paradigms, transcend their boundaries and are valuable in various contexts. They guide developers in creating software that is not only functional but also maintainable, scalable, and efficient.


DRY (Don't Repeat Yourself)

This principle emphasizes avoiding duplication in code. The idea is to have a single, unambiguous, authoritative representation for every piece of knowledge and logic in a codebase.

KISS (Keep It Simple, Stupid)

KISS advises against unnecessary complexity in code. It suggests that systems work best if they are kept simple rather than made complex; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.

YAGNI (You Aren't Gonna Need It)

This principle comes from extreme programming and emphasizes not adding functionality until it is necessary. It discourages developers from adding features just because they think they might need them in the future.

Composition Over Inheritance

This principle suggests that object composition (forming complex objects by combining simpler ones) is generally preferred over class inheritance for achieving polymorphic designs and code reuse.

Program to an Interface, Not an Implementation

Relying on interfaces or abstract representations rather than concrete implementations, enhancing flexibility, testability, and adherence to good design principles.

Hollywood Principle "Don't call us, we'll call you."

This principle is used to prevent dependency rot. It suggests that higher-level components should dictate when lower-level components will execute their behavior, rather than the other way around.

Concurrency Principles

These include principles for safe and efficient concurrent or parallel programming, like avoiding shared mutable state, which is a key concept in functional programming.

SOLID Principles

Initially formulated for OOP but applicable more broadly, these are five design principles intended to make software designs more understandable, flexible, and maintainable. They include:

  • Single Responsibility Principle: A class should have only one reason to change.
  • Open/Closed Principle: Entities should be open for extension but closed for modification.
  • Liskov Substitution Principle: Objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program.
  • Interface Segregation Principle: Many client-specific interfaces are better than one general-purpose interface.
  • Dependency Inversion Principle: Depend on abstractions, not on concretions.

Law of Demeter (LoD) or Principle of Least Knowledge

Suggests that a unit should have limited knowledge about other units and only talk to its immediate friends. This principle helps in reducing coupling between classes and modules.

Principle of Least Astonishment (POLA)

Suggests that software should behave in a way that least surprises users or developers, making systems more intuitive and predictable.

Fail Fast

Encouraging systems to fail early and visibly. It's better to have a system fail on detection of a problem rather than having it proceed with uncertain results.



While most associated with OOP, the idea of bundling data with the methods that operate on that data is relevant in other paradigms as well. It's about controlling the access to the internal state of an object (or module) to prevent unwanted interference and misuse.


Prominent in functional programming, this principle states that data objects should not be modified after they are created. Immutability can lead to more predictable and less error-prone code.

Pure Functions

A concept from functional programming, advocating that functions should not have side effects and should return the same output given the same input, thereby not depending on or modifying the state of the program.

Code Cohesion and Coupling

Cohesion refers to how closely related the responsibilities of a module are, while coupling refers to how interdependent modules are. The goal is to have high cohesion and low coupling for more maintainable and modular code.