KSS - Coding Standards

‍General ‍Coding ‍Principles

  • ‍1. ‍Use ‍go ‍fmt ‍to ‍format ‍your ‍code ‍before ‍checking ‍it ‍in. ‍
  • ‍2. ‍Favour ‍reliability ‍and ‍readability ‍over ‍strict ‍formatting ‍guidelines, ‍but ‍if ‍you ‍choose ‍to ‍break ‍one ‍of ‍our ‍guidelines ‍you ‍must ‍be ‍prepared ‍to ‍justify ‍your ‍decision.
  • ‍3. ‍Follow ‍[Programming ‍by ‍Contract] ‍patterns. ‍The ‍[gocontract] ‍library ‍contains ‍the ‍utilities ‍we ‍use ‍for ‍this ‍purpose.
  • ‍4. ‍Write ‍unit ‍tests ‍that ‍cover ‍your ‍code. ‍Your ‍code ‍must ‍pass ‍the ‍unit ‍tests ‍before ‍your ‍pull ‍requests ‍will ‍be ‍accepted. ‍Use ‍the ‍standard ‍Go ‍testing ‍package ‍for ‍implementing ‍your ‍tests.
  • ‍5. ‍Don’t ‍work ‍on ‍the ‍master ‍branch, ‍or ‍on ‍the ‍development ‍branches. ‍Create ‍your ‍own ‍suitably ‍named ‍branch ‍from ‍the ‍development ‍branch ‍on ‍which ‍to ‍do ‍your ‍work.
  • ‍6. ‍Ensure ‍that ‍your ‍work ‍will ‍be ‍usable ‍via ‍a ‍go ‍get ‍call. ‍Anything ‍that ‍requires ‍a ‍manual ‍intervention, ‍must ‍have ‍its ‍results ‍checked ‍in ‍so ‍that ‍go ‍get ‍will ‍work ‍properly.

‍Formatting ‍Guidelines

‍Since ‍we ‍are ‍using ‍go ‍fmt, ‍you ‍generally ‍don’t ‍need ‍to ‍worry ‍about ‍the ‍physical ‍formatting ‍of ‍the ‍source ‍code ‍- ‍it ‍will ‍be ‍automatic. ‍However, ‍we ‍do ‍have ‍the ‍following ‍additional ‍guidelines ‍that ‍you ‍need ‍to ‍follow.

  • ‍1. ‍Keep ‍lines ‍to ‍no ‍more ‍than ‍95 ‍characters ‍in ‍length. ‍(Our ‍code ‍reviewers ‍should ‍be ‍able ‍to ‍view ‍two ‍files ‍side ‍by ‍side ‍in ‍a ‍12pt ‍font ‍on ‍a ‍reasonably ‍sized ‍desk ‍monitor.)
  • ‍2. ‍Keep ‍methods ‍and ‍blocks ‍to ‍no ‍more ‍than ‍50 ‍lines ‍in ‍length. ‍(Developers ‍should ‍be ‍able ‍to ‍see ‍an ‍entire ‍block ‍at ‍once ‍in ‍a ‍12pt ‍font ‍on ‍a ‍laptop.)
  • ‍3. ‍Provide ‍documentation ‍comments ‍for ‍all ‍public ‍portions ‍of ‍the ‍API. ‍We ‍use ‍the ‍standard ‍Go ‍documentation ‍tools ‍found ‍at ‍godoc.org, ‍so ‍there ‍is ‍no ‍work ‍done ‍on ‍our ‍part ‍to ‍generate ‍the ‍documentation. ‍It ‍simply ‍has ‍to ‍have ‍the ‍comments ‍in ‍the ‍correct ‍location.
  • ‍4. ‍You ‍are ‍not ‍limited ‍to ‍one ‍structure ‍per ‍source ‍file, ‍but ‍all ‍the ‍items ‍in ‍a ‍single ‍source ‍file ‍should ‍be ‍closely ‍related.
  • ‍5. ‍Don’t ‍document ‍the ‍obvious. ‍It ‍should ‍be ‍possible ‍to ‍understand ‍your ‍code ‍simply ‍by ‍reading ‍your ‍code. ‍Instead ‍comments ‍(other ‍than ‍the ‍documentation ‍comments ‍mentioned ‍above) ‍should ‍describe ‍why ‍you ‍chose ‍a ‍specific ‍implementation, ‍or ‍why ‍you ‍are ‍breaking ‍from ‍one ‍of ‍our ‍standards, ‍or ‍just ‍to ‍make ‍the ‍code ‍more ‍navigable ‍(e.g. ‍// ‍TODO: ‍<something>).
  • ‍6. ‍Place ‍the ‍public ‍portions ‍of ‍your ‍API ‍near ‍the ‍start ‍of ‍your ‍file, ‍and ‍the ‍private ‍implementation ‍portions ‍near ‍the ‍end. ‍
  • ‍7. ‍Use ‍the ‍receiver ‍syntax ‍for ‍the ‍method ‍calls ‍of ‍the ‍public ‍portion ‍of ‍your ‍API. ‍For ‍the ‍private ‍portion ‍you ‍may ‍use ‍either ‍the ‍receiver ‍syntax, ‍or ‍a ‍non-receiver ‍syntax.

// Postconditions checks the expression(s) given to see that they are all true. If any 

// error message is logged and the program is halted if os.Exit(1).

//

// This method should typically be called near the end of a method, possibly right afte

// checking. However, that is not a requirement. (In fact Preconditions, Conditions, an

// all do exactly the same thing except for a slight difference in the message that is 

// three methods are provided instead of one simply as a means of documenting their int

//

// Typically this is called to check the post-conditions of a successful execution of t

// such it is generally not run when errors cause an early exit. However, if you wish i

// such cases, you can add defer before the call.

func Postconditions(result bool, results ...bool) {

    performConditionChecks("Postcondition", result, results)

}


func performConditionChecks(conditionType string, result bool, results []bool) {

    count := 1 + len(results)


    if !result {

        reportFailureAndExit(conditionType, 1, count)

    }


    for idx := range results {

        if !results[idx] {

            reportFailureAndExit(conditionType, idx+2, count)

        }

    }

}