Home

Awesome

Programming Principles

Every programmer benefits from understanding programming principles and design patterns. This overview is a reference for myself, and maybe it is of help to you during design, discussion, or review. The list is incomplete, and sometimes trade-offs need to be made between conflicting principles. However, higher ranked principles usually beat lower ranked ones.

The list was inspired by <!-- markdown-link-check-disable-next-line --> The Principles of Good Programming (down? Google's cache). I've added a bit more reasoning, details, and links to further resources. Let me know if you have any feedback or suggestions for improvement!

Contents

Generic

Relationships between modules, classes, components, entities

Modules, classes, components, entities

Test

KISS

Keep It Simple, Stupid: most systems work best if they are kept simple rather than made complex.

Why

Resources

YAGNI

You Aren't Gonna Need It: don't implement something until it is necessary.

Why

How

Resources

Do The Simplest Thing That Could Possibly Work

Why

How

Resources

Separation of Concerns

Separation of concerns is a design principle for separating a computer program into distinct sections, such that each section addresses a separate concern. For example, the business logic and the user interface of an application are separate concerns. Changing the user interface should not require changes to the business logic and vice versa.

Quoting Edsger W. Dijkstra (1974):

It is what I sometimes have called "the separation of concerns", which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts, that I know of. This is what I mean by "focusing one's attention upon some aspect": it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect's point of view, the other is irrelevant.

Why

How

Resources

Code For The Maintainer

Why

How

Resources

Avoid Premature Optimization

Quoting Donald Knuth:

Programmers waste enormous amounts of time thinking about, or worrying about, the speed of non-critical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

Understanding what is and isn’t "premature" is critical.

Why

How

Resources

Optimize for Deletion

Why

Code should be optimized for change. Code that's easy to delete is easy to replace or change.

How

Don't try to predict future changes today, instead focus on deletable and rewriteable code.

Principles such as separation of concerns, low coupling and the Single Responsibility Principle result in increased deletability. In general, high modularity helps to increase deletability of individual parts.

Resources

Keep things DRY

Don't Repeat Yourself: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts.

Why

How

Resources

Related

Boy Scout Rule

The Boy Scouts of America have a simple rule that we can apply to our profession: "Leave the campground cleaner than you found it". The boy scout rule states that we should always leave the code cleaner than we found it.

Why

How

Resources

Connascence

Connascence is a software quality metric that describes different levels and dimensions of coupling. Two components are connascent if a change in one would require a change in the other as well. Lower connascence means higher code quality.

Why

How

Resources

Minimise Coupling

Coupling between modules or components is their degree of mutual interdependence; lower coupling is better. In other words, coupling is the probability that code unit "B" will "break" after an unknown change to code unit "A".

Why

How

Resources

Law of Demeter

Don't talk to strangers.

Why

How

A method of an object may only call methods of:

  1. The object itself.
  2. An argument of the method.
  3. Any object created within the method.
  4. Any direct properties/fields of the object.

Resources

Composition Over Inheritance

It is better to compose what an object can do than extend what it is. Compose when there is a "has a" (or "uses a") relationship, inherit when "is a".

Why

How

Resources

Orthogonality

The basic idea of orthogonality is that things that are not related conceptually should not be related in the system.

Source: Be Orthogonal

It is associated with simplicity; the more orthogonal the design, the fewer exceptions. This makes it easier to learn, read and write programs in a programming language. The meaning of an orthogonal feature is independent of context; the key parameters are symmetry and consistency.

Source: Orthogonality (wikipedia.org)

Robustness Principle

Be conservative in what you do, be liberal in what you accept from others

Collaborating services depend on each others interfaces. Often the interfaces need to evolve causing the other end to receive unspecified data. A naive implementation refuses to collaborate if the received data does not strictly follow the specification. A more sophisticated implementation will still work ignoring the data it does not recognize.

Why

How

Resources

Inversion of Control

IoC inverts the flow of control. It's also known as the Hollywood Principle, "Don't call us, we'll call you". A design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. It carries the strong connotation that the reusable code and the problem-specific code are developed independently even though they operate together in an application.

Why

How

Resources

Maximise Cohesion

Cohesion of a single module or component is the degree to which its responsibilities form a meaningful unit. Higher cohesion is better.

Why

How

Resources

Liskov Substitution Principle

The LSP is all about expected behavior of objects:

Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.

LSP is the L in SOLID.

Resources

Open/Closed Principle

Software entities (e.g. classes) should be open for extension, but closed for modification. Such an entity can allow its behavior to be modified, without altering its source code.

Open/Closed is the O in SOLID.

Why

How

Resources

Single Responsibility Principle

A class should never have more than one reason to change.

Long version: Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Responsibility can be defined as a reason to change, so a class or module should have one, and only one, reason to change.

SRP is the S in SOLID.

Why

How

Resources

Hide Implementation Details

A software module hides information (i.e. implementation details) by providing an interface, and not leak any unnecessary information.

Why

How

Resources

Curly's Law

Curly's Law is about choosing a single, clearly defined goal for any particular bit of code: Do One Thing.

Encapsulate What Changes

A good design identifies the hotspots that are most likely to change and encapsulates them behind an interface. When an anticipated change then occurs, the modifications are kept local.

Why

How

Resources

Interface Segregation Principle

Reduce fat interfaces into multiple smaller and more specific client specific interfaces. An interface should be more dependent on the code that calls it than the code that implements it.

ISP is the I in SOLID.

Why

How

Resources

Command Query Separation

The Command Query Separation principle states that each method should be either a command that performs an action, or a query that returns data to the caller but not both. Asking a question should not modify the answer.

With this principle applied the programmer can code with much more confidence. The query methods can be used anywhere and in any order since they do not mutate the state. With commands one has to be more careful.

Why

How

Resources

Dependency Inversion Principle

Dependency Inversion is the strategy of depending upon interfaces or abstract functions and classes rather than upon concrete functions and classes. Simply put, when components of our system have dependencies, we don’t want to directly inject a component’s dependency into another. Instead, we should use a level of abstraction between them.

DIP is the D in SOLID.

Why

How

Resources

SOLID

A subset of programming principles:

FIRST principles of testing

The FIRST testing principles mean that tests should be Fast, Isolated, Repeatable, Self-validating and Timely.

Resources

Arrange, Act, Assert

The 3A's are a pattern to arrange and format code in unit tests. Arrange all necessary preconditions and inputs. Act on the object or method under test. Assert that the expected results have occurred.

Resources