logo

NJP

Every piece of knowledge or logic must have a single, unambiguous representation within a system

Import · Sep 08, 2019 · article

DRY (Don't Repeat Yourself)

DRY is a programming principle that states "every piece of knowledge, or logic must have a single, unambiguous representation within a system". The purpose of this post is not really to go in length about DRY, as a web search for 'DRY principle' will yield better written posts than can I. The objective, instead, is to explain through code examples how code readability is affected by it.

Sample One:

var Human = function Human(Person) {

    var someone = Object.create(Person);

    if (Person && Person.hasOwnProperty('name') && Person.name === undefined || Person.name === null) {
        someone.anonymous = function anonymous (something) {
            return something || 'I do not have a name';

        };
    }

    return someone;
};

Sample Two:

var Robot = function Robot(name) {
    var bot = {};

    if (name !== undefined && name !== null) {
        bot.name = name;
        bot.move = function move() {
            return 'I\'m moving';

        };
    }

    return bot;
};

Both samples above violate the DRY principle in quite subtle ways. In the few lines of code, the scripts already repeat null checks; furthermore, the first one checks for a property of an object (name) for null. The basic null check, as trivial as it is, can proliferate throughout a code base cluttering code and increasing interpretations times. That means a larger, more complex, less maintainable and less readable code base.

name !== undefined && name !== null 
//while familiarity makes this line 'simple' to read, it's clarity can be greatly improved

To dispose of any familiarity bias when reading, or any hint of ambiguity, the null check logic can be wrapped inside a function (single unambiguous place). Then used throughout the code base. An example of this practice is the OOTB globally scoped function isNil().

For scoped applications, this may be addressed by creating utility functions named with the exact meaning of our intention.

Utility Functions

function isNothing(value) {
    return value === null || value === undefined;

};

function isInObject(obj, propertyName) {
    return obj && obj.hasOwnPropertyName(propertyName);

};

function isInObjectAndIsNothing(obj, propertyName) {
    return isInObject(obj, propertyName) && isNothing(obj[propertyName]);

};

The above functions will replace null checks throughout the code base. If null check needed to be updated, then it should be done in one function, and no where else. In addition to replacing familiarity biases by explicitly expressing intentions, the functions decreases interpretation times, and help build a more concise code base. A smaller code base can lead to less bugs as code surface decreases and, well, cost.

Updated Code

var Human = function Human(Person) {

    var someone = Object.create(Person);

    if ( isInObjectAndIsNothing(Person, 'name') ) {
        someone.anonymous = function anonymous(something) {
            return something || 'I do not have a name';

        };
    }

    return someone;
};
var Robot = function Robot(name) {
    var bot = {};

    if (!isNothing(name)) {
        bot.name = name;
        bot.move = function move() {
            return 'I\'m moving';

        };
    }

    return bot;
};

isNothing
//vs
value === null || value === undefined

The utility functions make the updated scripts more explicit for a human to read. The need to interpret null checks is decreased by stating what we meant to do, check if something*isNothing*

In all, the goal is to use DRY as part of a repertoire to communicate more eloquently our thoughts when coding. Code should be seen as well written thoughts for readers.

Other places not as obvious where this might be used are GlideRecords and try/catch.

View original source

https://www.servicenow.com/community/architect-articles/every-piece-of-knowledge-or-logic-must-have-a-single-unambiguous/ta-p/2330591