blog.christoffer.online
Hi, my name is Christoffer and I am an Internet addict.

10 principles I try and follow in my day to day work based on 10 years of coding experience

2016-06-19 13:41

I have been coding professionally for more than 10 years now, and like most, I have been coding in different languages at different stages of my life, most notable, PHP, Java, JavaScript and Dart. A mix of object oriented's prototype vs class based, compiling vs scripting, concurrent vs single threaded, structured and functional languages.

From what I have learned is that coding pretty much follows Bushnell's law for a great computer game:

It's easy to learn, and hard to master.

The more you code in different languages, the easier it is to adopt new ones (as you recognize and become more familiar with different patterns and paradigms) and the more time you invest in mastering a language, it helps you write really great code even though you are totally new to a language.

Here are my 10 principles I try and follow in my day and day work, based on all the experience and knowledge I have accumulated over the last 10 years.

I try to write my code as if it was part of an open source project on GitHub

Let me ask you this simple question.

If you each time you write code imagine it's a part of an open source project on GitHub and will be published and public and to the whole world to see, I think you would have a totally different mind set when coding. I think you will spend more time on making the code and structure as professional as it can be, right?

Of course you will, since you that code will have your name on it and the whole world will see and judge you as a developer based on that code - especially if it contains any bugs! So you will probably always try and ensure writing clear non-ambiguous structured code, with no silly names or junk debug statements leaving around, have great documentation and you would probably even spend time writing unit tests.

I feel this way at least, so having this mindset (regardless if its company's code, my side projects, or actually a real open source projects) pushes me to write the best code I possibly can.

I try to write my code testable, even though I am not actually writing any tests

Let's be honest, even though everyone knows units tests are great, you as a coder won't always have or have been given time to write them. That's okay, but even though you know you won't have time to write any tests, you should still write your code test friendly.

Learning how to write testable code is something you simply learn from experience though. For example, if you adopt TDD (Test Driven Development) for a project or a period of time, or have a goal to have 100% in coverage for a product part, you will quickly learn what code is impossible to test and which code is perfectly setup to be able to be unit tested.

From my experience, this always almost results in using patterns such as inversion of control, dependency injection, following the SOLID principles, etc. With other external dependencies should always be given and never fetched, writing small but many methods with a very clear input and output with a clear separation of concerns and with single responsibilities.

I always try to write defensive code

After 10 years of coding, I have serious trust issues. The code I write never trusts anything or anyone any more.

The thing is that different developers have different experiences, personal styles and even mind sets. Based on personal experience, one simple function can be interpreted in two totally different ways depending on the developers and their own past experience and each developer thinks their interpretation is the clear obvious one.

That's why I always often code practice defensive programming. With other words, I always make sure that methods and functions I write will be called as I intended them to be called, for example by adding assertions in the beginning of the function body. Regardless if its a private of a public function, and especially if I am coding in loosely typed languages or functions with optional arguments.

Yes, the code becomes more verbose, but it helps me ensure that the function cannot be abused now, or in the future, hence making my code less error prone or being a cause of any misinterpretations for anyone using the code.

Here is a JavaScript example:

function isValidAge( age, countryISOCode ) {

    // Make sure age is provided
    if( age === undefined )  {
        throw new Error("Age is undefined.");
    }

    // Make sure age is a number
    if( typeof age !== "number" )  {
        throw new Error("Age is not a number.");
    }

    // countryISOCode is optional
    if( !countryISOCode ) {
         
        // Make sure the code is a string
        if( typeof countryISOCode !== "string" ) {
            throw new Error("Optional argument country ISO code is not a string.");
        }

        // Make sure its a 3 character ISO code
        if( countryISOCode.length !== 3 ) {
            throw new Error("Optional argument country ISO needs to be 3 character code.");
        }

    }

    ...

}

I always try to fail fast and fail immediately

Another pattern I have adopted a long the years is to always try and figure out if the execution should fail as soon as possible by practicing the fail fast design.

Here is a bad example in JavaScript where the code slowly dies.

function doSomething( arg1, arg2 ) {

    ... 

    if( arg1 ) {

       ...

        if( arg2 ) {
            ... 
        } else {
            throw new Error("Argument 2 is undefined");
        }

    } else {
       throw new Error("Argument 1 is missing.");
    }

    ...
 
}

And here is a rewritten version that fails fast and fails immediately. Please also note that this design decreases code indentations.

function doSomething( arg1, arg2 ) {

    if( !arg1 ) {
        throw new Error("Argument 1 is missing.");
    } 

    if( !arg2 ) {
        throw new Error("Argument 2 is missing.");
    }

    ...
 
}

I always try to write truthy conditions

We humans gets easily confused with double negation conditions. When other people read my code, I want them to instantly understand the conditions. That's why I always try and write truthy statements.

Here is a simple bad example in JavaScript, which probably confuses most people:

function driveCar(age, country) {

    if( country !== "sweden" || !isUnderAged(age) ) {
        ...
    }

    throw new Error("Person is not allowed to drive this  car!");

}

Compared to this rewritten to only use truthy conditions statements, which probably is easier to read and understand:


function driveCar(age, country) {

    if( livesInSweden(country) && isUnderAged(age) )  {
        // Failing fast
        throw new Error("Person is not allowed to drive this car!");
    }

    ...

}

As soon something is done twice, I try to extract it into its own function

I am a strong believer of DRY (Don't Repeat Yourself) in order to avoid code duplication, so as soon as I see a piece of code, or even a string, being used again, I try extract the logic into a new function, or if it is a variable, into a constant.

I have noticed that having this habit, regardless of language and project, it is a very cheap way to keep the code healthy.

For example, if I notice the code is already:

function updatePageTitle(page) {
    ...
    if ( page.type === "about" ) {
         ...
    }
    ...
}

And in another place I need to check if the page type is about, I will instantly refactor the code to be:


// This is the new function that is shared
function isPageTypeAbout( page ) {
    return page.type === "about";
}

function updatePageTitle( page ) {
    ...
    if ( isPageTypeAbout(page) ) {
         ...
    }
    ...
}

function myNewFunction( page ) {
    ...
    if ( isPageTypeAbout(page) ) {
        ...
    }
    ...
}

Instead of duplicating page.type === "about" check.

Even if this is a very simple case, I usually follow the "one method, one responsibility" philosophy. Meaning, the logic to determine if the page type is about, should not be duplicated. There should only be one method that has responsibility to figure that out.

I try to use "we" and "this" instead of "you" and "your" in code reviews

Humans become very defensive when they are being criticized. That's natural, even during a code review process.

In order to put the code in focus as a separate entity our job is to maintain - compared to portraying that I am criticizing the developer directly - I deliberately try and to shift my terminology when writing code review comments. So instead of using "you" and "your", I try and use "we" and "this".

For example, instead of writing:

Are you sure want to do it like this? Because ...

or

Your solution will break the database migration task.

I try and write:

Are we sure we want it like this? Because ...

and

This solution will break the database migration task.

I always try and provide a link with proof if I fail someone else's code during a code review

As we all know, in code review it's very easy that your own personal opinions on how things should be implemented and work gets pushed. Even so hard that can even lead to a toxic discussion between developers.

Personal opinions are great, but should probably most times only be suggestions in the code review while things that can really break or hurt the solution warrants a rejected revision.

In my personal experience, in order to make a clear distinction between my personal opinions and what is factually good things to point out, I always try and provide a link to an external resource explaining the problem or the reason why the code revision is a bad idea, when rejecting it.

For example a comment could look like:

-1

I think we should check for a falsy value instead (if( !name ) { ... }), since Element.getAttribute() can return both null and an empty string "".

https://developer.mozilla.org/en/docs/Web/API/Element/getAttribute

If someone asks a question on my code during code review, I will try and add the answer as a comment in the code as well

If I ever get a question on what my code does during the code review process, then this is a great warning flag that the code was not so obvious as I thought it would be (regardless of reason).

In that case, lets be honest here, the chances are pretty high that if the code reviewer had to ask it about, then someone else in the future will be confused about it as well, once it has been submitted to the VCS (Version Control System).

That's why I always try and update the actual code with more comments, or rewrite existing comments, prior to sending it into the VCS, to help future developers reading and understanding my code.

Update the static code analysis tools along the way to prevent unnecessary code review work

All glory to cheap test processes such as unit testing, but over the last few years, I think that static code analysis and linting is equally important in a software development process.

Unit testing checks business requirements and code, but a proper static code analysis setup in a build process can check literally everything in a project, before it even reaches human eyes in a code review.

Everything from enforcing file name conventions to checking that that the type attribute is always explicitly specified for <button>s in HTML, or that no <a> elements uses target="_blank" to avoid obscured vulnerabilities.

The more you can catch by machines by linting and static code analysis before it even reaches human interaction, the better, as machines will remember to check everything with code.

Comment on Reddit

As always, feel free to share your comments, opinions and feedback over at the Reddit threads. There are some great discussions over there!