Skip to content

Common Code Requirements

Ben Buie edited this page May 14, 2024 · 3 revisions

This file is a work in progress and we welcome additions/edits. The goal here is to include best practices that make code more readable and user friendly. This is by no means an extensive list, but it does include a lot of helpful tips.

Table of contents

  1. General
  2. Git
  3. JavaScript
  4. Angular
  5. User Experience
  6. Node.js
  7. PHP
  8. Laravel
  9. API Design

General

  1. Don't confuse

    1. Always think through what future developers will think when seeing your code
    2. Simple code always wins. If it is too confusing, you may have to simplify.
  2. Self documenting code

    1. The general rule is that your code should be human readable. It should read like a book, but a book of code.
    2. In a perfect world, every line of code should be understandable even without seeing much of its context
      1. This isn't always possible, but to the extent we can, we do
    3. Variables/properties/function argument names should represent what they are
      1. Recommend var permissionsCommaSeparated = 'string' not var p = 'string'
    4. Boolean variables/properties/function argument should be named as questions or as statements
      1. Recommend var isLoadingSomething = true not var spinner = true
      2. Recommend var codeHasBeenApplied = true not var applied = true
      3. The goal is to make logical statements more readable
        • Recommend if(codeHasBeenApplied){ vs if(s.applied){
    5. Function names should describe what they do.
      1. Recommend function getSomethingSpecific(){} not function s(){}
      2. Avoid anonymous functions whenever possible.
    6. Complex associative arrays need to be given a less complex name
      1. Recommend var someObject = someArray[someOtherArray[index]]; someObject.push; not someArray[someOtherArray[index]].push()
    7. Logical statement should always be readable
      • Recommend var noCompaniesFound = city['west_side'].length < 0; if(noCompaniesFound){...}
  3. Don't leave commented code

    • In otherwords, leave unused code in a codebase because you're worried about losing some previous logic
    • The only reason to leave commented code is if you're only commenting it temporarily
    • If you do leave commented code, leave a comment why and the issue number related to the change
  4. Comments in code

    • If you leave a to do comment or other explanation comment in your code, please also leave an issue number
    • Although there are sometimes where you'd want to leave some documentation as a comment, this should be rare. Comments often become outdated and confusing to future developers. Instead, if you're tempted to leave a comment, you should first think of ways you could document that logic within the property/method/function/variable names.
    • There are some rare cases when short comments are needed, but these should be the exception
  5. Code should be readable

    1. First comes first
      1. All exports or anything returned by a function should be visible within the first several lines of a file/function
      2. If something is run immediately when a file is loaded, it needs to be close to the top
      3. All variable declarations should be declared as close to where they are used first as possible
        1. Note, this is a departure from some common code practices where people like to list all the variables at the top of a function. To us, context and readability is more important.
    2. Functions should be defined after they are called
      1. The first functions in a file should be the ones that call other functions
      2. In other words, if you read a whole file from top to bottom, you should never wonder, "what function is dependent on this function?" because if you read that a function is called on line 10, you'll always know that the function definition is declared on line > 10.
    3. Correct indentation should be used
      1. Anything that has a an opening and closing (html tags, functions, etc.) should have all contents indented
    4. Indentation method should match throughout entire file
      1. It doesn't matter if the file uses 2 spaces, 4 spaces, or tabs for indentation. The important thing is that it matches.
      2. Whenever possible, use 4 spaces as the default and avoid tabs.
      3. Most indentation issues happen because of text editor settings
      4. If using sublime text editor you may want to make sure the default setting "translate_tabs_to_spaces": false, isn't overriden.
  6. Long lines should be broken up by line breaks

    1. The longer a line gets the harder it is to read quickly and understand
    2. Lines with a lot of logic are more likely to cause merge conflicts
    3. Object keys should each have their own line
    4. Look for opportunities to add line breaks, particularly in html
  7. Avoid merge conflicts

    1. Touch as few lines of code in a file as possible
      1. The more lines you touch, the more likely another developer has touched the same line.

Git

  1. Branching
    1. Every branch name should include an issue id
      1. There is no reason to create a pull request without documentation behind why that pull request is needed.
    2. Issues should only have one branch
      1. The code to resolve an issue should be all part of one branch
      2. This will make it easier to handle, trace, and merge in the future
      3. This will also prevent changes from being lost from development to staging and production

JavaScript

  1. Use forEach over for to loop through arrays of items
    1. Recommend arr.forEach(eachItem) not for(i; i<arr.length;i++){}
    2. Although forEach is less efficient, it is more readable and satisfactory for most use cases
    3. If you absolutely must use for(...){}, make sure to assign the iterated variables first thing withing the for enclosure
      1. Recommend for(...){var item = items[i]; item.push(newItem)) not for(...){items[i].push(newItem))
  2. Avoid pyramid code
    1. Don't use anonymous functions in callbacks
      1. Recommend Something.find(...).exec(findSomethingCallback) not Something.find(...).exec(function(){}))
    2. Use promises in favor of callbacks
  3. Avoid switch
    1. Most problems that tempt you to use a switch can be more robustly handled by an object and an if statement
    2. There are some exceptions, but always try to make the code as readable as possible
    3. If a switch does seem like the best tool for your problem, then encapsulate the inside of a case with a function.

Angular

  1. Code organization
    1. Contollers/Directives need to have a setup/init function where all controller variables and any functions that are run immediately are declared.
      function setup(){
        vm.someArray = [];
        getSomeData();
      }
      
  2. Create/Update Sub Data
    1. Sub data is data that may be stored in a different table or collection but that can be updated on the save of a parent.
    2. Sub data that is changed should be loaded via an id and saved on parent update
    3. Sub data is removed should be removed instantly via its api (unless it doesn't have an id and then it is deleted instantly from the view)
  3. Elements with lots of attributes need line breaks
    1. Some elements in angular become hard to read because of multiple attributes (e.g. ng=* or others).
    2. Recommend breaking long elements up with line breaks between every attribute

User Experience

  1. User driven design
    1. Buttons
      1. Button Feedback
        1. A user should never have to wonder if their action was received
        2. If a user clicks a button for an asynchronous action, the user should be shown a spinner or loader immediately
      2. Prevent double clicks
        1. The instant a button is clicked, it should be disabled or hidden to prevent double clicks
    2. Errors/Warnings/Success Feedback
      1. All actions should give both success or error feedback
        1. Sometimes this feedback is that they see their desired change take place (e.g. like a box is hidden)
      2. If there is no visual feedback (like on save) then they should be shown a success message
      3. All feedback should appear close to where the user took the action
        1. Avoid alerts that show at the top of the page when a button was pressed at the bottom
        2. Make sure a user can't miss the feedback

Node.js

PHP

Laravel

  1. Model/View/Controller Structure
    1. Controllers
      1. Controllers should primarily handle requests and build responses.
      2. The logic in controllers should mainly be related to requests and responses.
      3. Skinny controllers are preferred.
      4. Payloads are typically sent to the model mergeOrCreate function to create an instance or update an existing instance.
      5. If a request needs data from a third party api or resource, the controller should use a service to interact with the resource.
    2. Models
      1. Any logic related to pulling data from the database or updating data should be found here
      2. On smaller projects, we also include business logic here. On larger projects, we break the business logic out into different classes
    3. Views
      1. Views on most of our projects are handled by a JavaScript framework and should not be built in Laravel.
    4. Service
      1. A service is basically a class that we can use to separate third party logic or other self contained logic from the models or controllers
      2. The most common use case for a service is interacting with a third party api. We'd use the service to document the structure and functions necessary to get the data we want.

SCSS

  1. Media Queries
    1. Keep queries small
      1. Queries should be located very close to the styles they're overriding.
      2. Rather than have a long query with multiple classes and sub classes, have a short query within each class that overrides the related styles.

API Design

  1. Routes should be readable
    1. Don't put the method name in the url
      1. Recommend for GET method '/api/something' to getSomething() not '/api/something/getSomething' to getSomething()
    2. Avoid camelCase
      1. Web addresses are case insensitive so camel case may be readable in code, but it is confusing in the wild
      2. If you must use multiple words in a route, think about separating them by a / or a -