Skip to content

Guidelines

undead robot edited this page Apr 20, 2017 · 5 revisions

How to do things right

Assumptions

For the sake of this document let's assume that the nail's _name_ is Example.

Namespace

# prefix all your global variables with two underscores and upcased _name_
declare -gr __EXAMPLE_VERSION='0.0.0~dev'
# prefix all your functions with a capitalized _name_
function Example.print_version {
    echo "${__EXAMPLE_VERSION}"
}
# avoid defining a function named _name_
function Example {
    : 'functions like this are discouraged'
}
# delimit nested namespaces with double colon
function Example::Program.run {
    ${__EXAMPLE_PROGRAM} "$@"
}

Options and arguments

  • bash itself makes almost no use of GNU long options and its getopts builtin does not support those; it's recommended to go with this old-school flow and limit options to a single character
  • programs should use command-line options and should not generally rely on environment
  • functions on the other hand should NOT take options and instead should make use of positional arguments and environment variables
$ example -n -vv -p /var/run/example.pid
function Example.mutate_state {
    local new_state="$1"
    shift
    local cmd="mutate $new_state $@"
    [[ "$VERBOSE" ]] && echo "$cmd" >&2
    $cmd
}
VERBOSE=true Example.mutate_state :done

Sugar

  • when you need a string to enumerate something (a case case, an array key etc.) consider prefixing it with a colon
  • consider naming boolean functions with a trailing question mark: Example.dry_run?
  • consider naming impure functions, i.e. those that has side-effects with a trailing bang: Example.clear_env! (setting __ERROR is not considered a side-effect)
Clone this wiki locally