• Stars
    star
    2,424
  • Rank 18,977 (Top 0.4 %)
  • Language
  • Created about 10 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Categorized overview of programming principles & design patterns

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 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

  • Less code takes less time to write, has less bugs, and is easier to modify.
  • Simplicity is the ultimate sophistication.
  • It seems that perfection is reached not when there is nothing left to add, but when there is nothing left to take away.

Resources

YAGNI

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

Why

  • Any work that's only used for a feature that's needed tomorrow, means losing effort from features that need to be done for the current iteration.
  • It leads to code bloat; the software becomes larger and more complicated.

How

  • Always implement things when you actually need them, never when you just foresee that you need them.

Resources

Do The Simplest Thing That Could Possibly Work

Why

  • Real progress against the real problem is maximized if we just work on what the problem really is.

How

  • Ask yourself: "What is the simplest thing that could possibly work?"

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

  • Simplify development and maintenance of software applications.
  • When concerns are well-separated, individual sections can be reused, as well as developed and updated independently.

How

  • Break program functionality into separate modules that overlap as little as possible.

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

  • Duplication (inadvertent or purposeful duplication) can lead to maintenance nightmares, poor factoring, and logical contradictions.
  • A modification of any single element of a system does not require a change in other logically unrelated elements.
  • Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.

How

  • Put business rules, long expressions, if statements, math formulas, metadata, etc. in only one place.
  • Identify the single, definitive source of every piece of knowledge used in your system, and then use that source to generate applicable instances of that knowledge (code, documentation, tests, etc).
  • Apply the Rule of three.

Resources

Related

Code For The Maintainer

Why

  • Maintenance is by far the most expensive phase of any project.

How

  • Be the maintainer.
  • Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.
  • Always code and comment in such a way that if someone a few notches junior picks up the code, they will take pleasure in reading and learning from it.
  • Don't make me think.
  • Use the Principle of Least Astonishment.

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

  • It is unknown upfront where the bottlenecks will be.
  • After optimization, it might be harder to read and thus maintain.

How

Resources

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

  • When making changes to an existing codebase the code quality tends to degrade, accumulating technical debt. Following the boy scout rule, we should mind the quality with each commit. Technical debt is resisted by continuous refactoring, no matter how small.

How

  • With each commit make sure it does not degrade the codebase quality.
  • Any time someone sees some code that isn't as clear as it should be, they should take the opportunity to fix it right there and then.

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

  • Reducing connascence will reduce the cost of change for a software system.
  • Arguably one of the most important benefits of connascence is that it gives developers a vocabulary to talk about different types of coupling.

How

  • Each instance of connascence in a codebase is considered on 3 separate axes: strength, degree and locality.
  • It provides a system for comparing different types of dependency.

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

  • A change in one module usually forces a ripple effect of changes in other modules.
  • Assembly of modules might require more effort and/or time due to the increased inter-module dependency.
  • A particular module might be harder to reuse and/or test because dependent modules must be included.
  • Developers might be afraid to change code because they aren't sure what might be affected.

How

  • Eliminate, minimise, and reduce complexity of necessary relationships.
  • By hiding implementation details, coupling is reduced.
  • Apply the Law of Demeter.

Resources

Law of Demeter

Don't talk to strangers.

Why

  • It usually tightens coupling
  • It might reveal too much implementation details

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

  • Less coupling between classes.
  • Using inheritance, subclasses easily make assumptions, and break LSP.
  • Increase flexibility: accommodate future requirements changes, otherwise requiring restructuring of business-domain classes in the inheritance model.
  • Avoid problems often associated with relatively minor changes to an inheritance-based model including several generations of classes.

How

  • Identify system object behaviors in separate interfaces, instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance.
  • Test for LSP to decide when to inherit.

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

  • Ensure that a provider can make changes to support new demands, while causing minimal breakage to their existing clients.

How

  • Code that sends commands or data to other programs or machines should conform completely to the specifications, but code that receives input should accept non-conformant input as long as the meaning is clear.

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

  • Increase modularity of the program and make it extensible.
  • To decouple the execution of a task from implementation.
  • To focus a module on the task it is designed for.
  • To free modules from assumptions about other systems and instead rely on contracts.
  • To prevent side effects when replacing a module.

How

  • Using Factory pattern
  • Using Service Locator pattern
  • Using Dependency Injection
  • Using contextualized lookup
  • Using Template Method pattern
  • Using Strategy pattern

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

  • Reduced module complexity
  • Increased system maintainability, because logical changes in the domain affect fewer modules, and because changes in one module require fewer changes in other modules.
  • Increased module reusability, because application developers will find the component they need more easily among the cohesive set of operations provided by the module.

How

  • Group related functionalities sharing a single responsibility (e.g. in a module or class).

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

  • Improve maintainability and stability by minimizing changes to existing code.

How

  • Write classes that can be extended (as opposed to classes that can be modified).
  • Expose only the moving parts that need to change, hide everything else.

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

  • Maintainability: changes should be necessary only in one module or class.

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

  • When the implementation changes, the interface clients are using does not have to change.

How

  • Minimize accessibility of classes and members.
  • Don’t expose member data in public.
  • Avoid putting private implementation details into a class’s interface.
  • Decrease coupling to hide more implementation details.

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

  • To minimize required modifications when a change occurs.

How

  • Encapsulate the concept that varies behind an interface.
  • Possibly separate the varying concept into its own module.

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

  • Keep a system decoupled and thus easier to refactor, change, and redeploy.

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

  • By clearly separating methods into queries and commands the programmer can code with additional confidence without knowing each method's implementation details.

How

  • Implement each method as either a query or a command
  • Apply naming convention to method names that implies whether the method is a query or a command

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

More Repositories

1

awesome-dotfiles

A curated list of dotfiles resources.
8,206
star
2

reveal-md

reveal.js on steroids! Get beautiful reveal.js presentations from any Markdown file
JavaScript
3,365
star
3

knip

βœ‚οΈ Find unused files, dependencies and exports in your JavaScript and TypeScript projects. Knip it before you ship it!
TypeScript
1,842
star
4

dotfiles

Dotfiles for macOS
Shell
983
star
5

dyson

Node server for dynamic, fake JSON.
JavaScript
832
star
6

DOMtastic

Small, fast, and modular DOM and event library for modern browsers.
JavaScript
763
star
7

awesome-newsletters

The best (weekly) newsletters
379
star
8

component-styleguide

Simple styleguide framework
JavaScript
122
star
9

Automated-SPA-Testing

Automated unit & functional testing for web applications
105
star
10

responsive-web-apps

Building Responsive Web Applications
JavaScript
63
star
11

grunt-release-it

Interactive release task for Git repositories. Optionally release a build to distribution/component repository.
JavaScript
48
star
12

versionify

Browserify transform to replace placeholder with package version
JavaScript
33
star
13

react-redux-demo

Fun Fair
JavaScript
30
star
14

baseplate

The baseplate project provides excellent workflow & tooling to develop, build, and test non-trivial SPAs.
JavaScript
24
star
15

bron

πŸƒβ€β™‚οΈ Fast & tiny test runner for Node.js
JavaScript
18
star
16

frameground

Compare JavaScript Frameworks. Please share your knowledge!
JavaScript
17
star
17

dyson-generators

Fake data generators, used by dyson and dyson-image
JavaScript
17
star
18

dyson-demo

Demo package for dyson
JavaScript
14
star
19

requirejs-handlebars

Simple Handlebars plugin for RequireJS
JavaScript
13
star
20

precompiled-templates

Performance, footprint and configuration of template engines and precompiled templates
JavaScript
12
star
21

ts-morph-helpers

Helpers for ts-morph
TypeScript
12
star
22

component-styleguide-example

Example for component-styleguide
CSS
9
star
23

DuckJS

Tiny and powerful module loader to lazy load HTML+CSS+JS
JavaScript
8
star
24

benchrunner

Benchmark Suite Runner for benchmark.js
JavaScript
8
star
25

sandbox

Source files for sandbox.webpro.nl (offline)
JavaScript
6
star
26

dyson-image

JavaScript
6
star
27

webpro.nl

Source code of webpro.nl
Astro
6
star
28

doxstrap

Yet another documentation generator
HTML
5
star
29

vars

Common patterns in Vue, Angular, React and Svelte
JavaScript
5
star
30

parse-openapi

OpenAPI v3 parser
TypeScript
5
star
31

nx-tsc

Nx executor to type-check project source files using `tsc --noEmit`
JavaScript
5
star
32

hyte

HYbrid TEmplating for the browser and Node
JavaScript
4
star
33

Websites-vs-Web-Applications

Responsive Adaptive Rainwebs FTW!
4
star
34

release-it-monorepo

4
star
35

github-pages-example

GitHub Pages Example
3
star
36

bookstore

Simple application to learn GraphQL and Next.js.
JavaScript
3
star
37

markdown-rambler

Yet another opinionated & powerful static site generator.
TypeScript
3
star
38

bump-file

Bump JSON files (e.g. package.json and friends)
JavaScript
3
star
39

openapi-parser

OpenAPI v3 parser
TypeScript
2
star
40

fix-sourcemaps

Fix sources and file in sourcemaps
JavaScript
2
star
41

jaguarundi

Ant build script to optimize and version Javascript, CSS, and HTML files
JavaScript
2
star
42

requirejs-hogan

Simple Hogan plugin for RequireJS
JavaScript
2
star
43

requirejs-dust

Simple Dust plugin for RequireJS
JavaScript
2
star
44

deprecated-obj

Compares deprecations against a configuration object, and returns a compliant object and violations
JavaScript
2
star
45

DOMtastic-release

JavaScript
1
star
46

is-subdir

Check if a directory is a subdirectory
JavaScript
1
star
47

SpringbokJS

Installs modules (traditional object or AMD-style) based on HTML attributes.
JavaScript
1
star
48

last-publish

Get the date of the last published version of a package in the npm registry
JavaScript
1
star