Principles

March 20th, 2010 Leave a comment Go to comments

As a software developer I normally use general purpose languages to build software. I need the flexibility. But there’s a flip side to that coin. Great flexibility means more ways to bring the code into unmaintainable chaos.

So it comes to no surprise that a significant number of programming principles have been formulated to battle the code rot that seems to strike every software system sooner or later.

Here are the programming principles I try to keep in mind while designing code. I don’t always follow them but my goal is to know when and why I break them.

General Principles:

  • Once and Only Once
    Each and every declaration of behavior should appear once and only once.
  • Don’t Repeat Yourself
    Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
  • You Aren’t Gonna Need It
    Always implement things when you actually need them, never when you just foresee that you need them.
  • Law of Demeter
    You have no business with other object’s objects.// Asking for the customer's wallet is
    // a LoD violation
    customer.Wallet.Withdraw(100.00);

    // Better to Tell the customer
    // to pay you
    customer.Pay(100.00);

  • Tell, Don’t Ask
    It’s better to Tell an object to do something for you, than to ask for its internal state and perform the task yourself.
  • Keep It Simple and Stupid
     All design should be as simple as possible, but no simpler.
  • Fail Fast
    In case of unexpected errors, your system should fail straight away and in a clear manner.

    It’s […] well known that the cost of failure increases with time. The sooner you discover the flaw, the easier it is to fix. In other words, if we are going to fail, there are good reasons to do it fast.

    Tools of the Effective Developer: Fail Fast

  • Self-Documentation Principle
    The designer of a model should strive to make all information about the module part of the module itself.
  • Command-Query Separation Principle
    Functions should not produce abstract side effects.

Of course, the S.O.L.I.D. principles:

  • The Single Responsibility Principle
    A class should have only one reason to change.
  • The Open-Closed Principle
    Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
  • The Liskov Substitution Principle
    Subtypes must be substitutable for their base types.
  • The Interface Segregation Principle
    Clients should not be forced to depend upon methods that they do not use. Interfaces belong to clients, not to hierarchies.
  • The Dependency Inversion Principle
    Abstractions should not depend upon details. Details should depend upon abstractions.

Principles regarding packaging and dependencies:

  • The Release-Reuse Equivalency Principle
    The granule of reuse is the granule of release.
  • The Common Closure Principle
    The classes in a package should be closed together against the same kind of changes. A change that affects a closed package affects all the classes in that package and no other packages.
  • The Common Reuse Principle
    The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all.
  • The Acyclic Dependencies Principle
    Allow no cycles in the package dependency graph.
  • The Stable Dependencies Principle
    Depend in the direction of stability.
  • The Stable Abstractions Principle
    A package should be as abstract as it is stable.
  1. March 19th, 2010 at 16:24 | #1

    How do you reconcile Tell, Don’t Ask with the Single Responsibility Principle? For example, suppose you have an ORM model class: should it know how to render itself into HTML? If not, how can the HTML renderer do its job without asking the ORM class for all its data? Perhaps I’m simply unclear about the scope of applicability of the TDA principle?

    (Also, typo: “resuse” -> “reuse”).

  2. March 20th, 2010 at 12:28 | #2

    @Marius: Excellent question, one that deserves an article of its own. Tell, don’t ask is yet another example of a non-universal principle; It can not be applied at all levels, someone has to retrieve (ask for) the data. But as my experience tells me, the higher the level the more applicable TDA is.

    There are more examples of contradicting principles. For instance, YAGNI and KISS are difficult to apply in combination with any of the S.O.L.I.D. principles. Not to speak of OCP, which is impossible to achieve to a full extent.

    So, I look to these principles merely for guidance, I don’t let them control everything I do. After all, what the program does is more important than the code design. (I’m not saying the latter is unimportant.)

    Once again, thank you for your comment and for pointing out the typo.

    Cheers!

  1. March 19th, 2010 at 15:40 | #1