Naming

End-to-end Consistency

Try to keep an end-to-end consistency, and preferably, back-to-front consistency, in our naming conventions.

This sometimes would go against common/community (non-enforcing) conventions. For instance, if SQL column names are in underscore_connected_lowercases, associated JavaScript Object key names should be kept as so (even if the applied JS style convention suggests mixedCases).

This consistency allows for an easier time on end-to-end communication, development and debugging. It makes code less error-prone, as no explicit case conversion are involved in the transport and business logic. And as a side benefit, all participants are naturally familiar with the data structure being passed over the wire.

Example:

// some Node.js API server relaying PostgreSQL
router.get('/user/:first_name', (req, res, next) => {
  // đź‘Ť GOOD -- direct extraction, no transformation
  const { first_name } = req.query
  // đź‘Ž BAD -- wasteful transformation for "good" convention
  const firstName = req.query.first_name
  db.query({
    text: `
      SELECT
        id,
        first_name,
        last_name,
        role
      FROM user_table
      WHERE first_name = $1;
    `,
    values: [first_name],
  }).then(({ rows: [person] }) => {
    // đź‘Ť GOOD -- direct relay, no transformation
    // data structure can be easily understood through ^SQL
    // as the "single origin of truth".
    return res.status(200).json(person)

    // đź‘Ž BAD -- wasteful transformation for "good" convention
    // requires additional efforts to know what to expect from
    // this API endpoint.
    return res.status(200).json({
      id: person.id,
      firstName: person.first_name,
      // đź‘€ easily overlooked typo that cannot be caught at runtime
      lastNmae: person.last_name,
      role: person.role,
    })
  }).catch(next)
})

// cleaned up version with only đź‘Ť GOOD parts
router.get('/user/:first_name', (req, res, next) => {
  const { first_name } = req.query
  db.query({
    text: `
      SELECT
        id,
        first_name,
        last_name,
        role
      FROM user_table
      WHERE first_name = $1;
    `,
    values: [first_name],
  }).then(({ rows: [person] }) => {
    return res.status(200).json(person)
  }).catch(next)
})

Respect Common/Community Standard

Try to apply the commonly agreed naming standard by the given language/stack/framework’s community. This saves us time from debating on coding styles and allows for an easier onboarding experience.

Some are more enforcing than others, such as Golang attaches package interface visibility to naming rules, while Python’s PEP8 and Effective Go has recommended, but non-enforcing conventions.

Then there is JavaScript, with multiple popular style guides that can be adopted/borrowed based on the common agreement between project maintainers.

Respect Existing Conventions

Respect existing conventions applied in existing projects. Gradually revise upon common agreement between project maintainers, ideally toward an established common/community standard.

Scope Dependent Naming

Prefer comprehensive and concise names for classes, functions/methods, and shared variables (such as constants, globals).

Prefer short but relevant names for locally scoped variables and functions provided no conflict within the same scope, and the scope does not entail lengthy code. This is borrowed from the real-life convention of signing documents – often there is only one signature required per-page (or even per-document), but any “local” (significant fields) acknowledgments are in the form of initials.

Python example:

import os

# module constants/globals
PROD_SQL_URL = os.getenv('SQL_URL')

# classes
class PreAggregationPipeline:

    # functions
    def write_into_db(self, rows=None):

        # closure/enclosed local functions
        def proc(row):
            # some logic to process row
            return new_row

        # local variables
        for r in rows:
            # close context - `r` = row, `nr` = new row
            nr = proc(r)

Golang example:

// package constant/globals/structs
type Maintenance struct {
    Message string `json:"message,omitempty"`
    Start   int    `json:"start"`
    End     int    `json:"end,omitempty"`
    Service string `json:"service"`
    Remove  bool   `json:",omitempty"`
}

// functions, struct methods (public)
func (maint Maintenance) MakeMap() map[string]interface{} {
    // local variables
    m := map[string]interface{}{
        "service": maint.Service,
        "start":   maint.Start,
    }
    end := maint.End
    if end != 0 {
        m["end"] = end
    }
    if maint.Message != "" {
        m["message"] = maint.Message
    }
    return m
}

// functions (private, or special case such as main)
func main() {

}

JavaScript example:

// classes
function WonderfulPerson(data) {
  this.firstName = data.firstName
  this.lastName = data.lastName
}

// methods/functions
WonderfulPerson.prototype.toString = () => {
  // closure/locally scoped functions/variables
  const cap = s => s.charAt(0).toUpperCase() + s.slice(1)

  return `${cap(this.lastName)} ${cap(this.firstName)}`
}

Code and Files Associative Naming

Keep a consistent association between code and its containing files and folders (directories).

Prefer lowercase naming convention for file/folder names, because while the filesystems of Linux are case sensitive, macOS and Windows aren’t.

Prefer dash-connected naming convention, because - (dash) is a better delimiter than ' ' (space) and _ (underscore).

Examples:

Golang example:

// types/maintenance/main.go
package maintenance

type Maintenance struct {
    Message string `json:"message,omitempty"`
    Start   int    `json:"start"`
    End     int    `json:"end,omitempty"`
    Service string `json:"service"`
    Remove  bool   `json:",omitempty"`
}

// which is imported in other packages as
import "<module>/types/maintenance"

JavaScript example:

// connection-hub/index.js
export const ConnectionHub = (props) => (
  <Connections {...props} />
)

Python example:

# pre-aggregation-pipeline.py
def pre_aggregation_pipeline():
    pass