Dev Advice, Best Practices, and Style Guide

Benjamin Pittman-Polletta edited this page Dec 20, 2017 · 63 revisions

Overview

  • Strive for backwards compatibility anytime you change the API (application programming interface)!
  • Test Octave compatibility with new features. Or block the for octave if they don't work (check reportUI).
  • Add an empty folder to dynasim directory called '_dev' that is ignored by git, but that triggers developer outputs.
  • Changes to many files in the codebase might be accelerated by using Atom, or using Codacy and writing our own patterns.
  • Always put rethrow(err) in a try...catch block. This enables using dbstop if error for debugging.
  • Put your personal use files that won't be synced to github in '_ignore'
  • Reopen old closed issues instead of making new ones
  • If commit references an issue, make the first line of the message "#XXX Max 50 char summary" followed by more explanation as needed on subsequent lines.
  • Use fileparts2 instead of fileparts. Use .. instead of fileparts for parent directory.
  • Use getAbsolutePath(thePath) instead of fullfile(pwd, thePath) to avoid double pwd concatenation bugs
  • use mfileFnName instead of mfilename to allow for package support
  • Update git version on cluster for easier use of submodules
  • Use 'X.mech' for mechanism files instead of 'X.txt'

Naming Conventions

  • User functions are camelCase with no underscore.
  • Utility functions are currently inconsistent; should be camelCase; some are currently lowercase or lower_case
  • Options are lower_case with underscore.

Branches

  • Name your feature branches after both the Issue # they're related to and a tiny explanation of the content. Some good examples include iss59_md_plotting_framework and iss90_one_file_mode_for_parallel.

Unit Testing

  • Documentation on Class-Based Matlab Unit Testing

  • Unit Testing Function Template

  • Automatic Unit Test Data Creation

    • flag name: auto_gen_test_data_flag
    • mat file name: fnName_autogen_hash.mat
  • If function makes figures or saves data, function should permit last 2 arguments to be 'xUnit',1 to enable unit testing mode that changes behavior, eg suppresses data saving

    • Example code:
    if strcmp(varargin{end-1},'xUnit') && varargin{end}==1
      output = struct('eachOutput',eachOutput, 'pathsToSavedDataVar',pathsToSavedDataVar, 'localfunctions',localfunctions);
    end
    
  • If function has nested or local functions

    • Convert/make all nested functions into local functions (doesn't share any scope/variables with main function)
      • This also enables cutting and pasting of local function into separate function file at any time
    • In unit testing mode, if pass empty arguments to function, that function should return the local function handles without evaluating the function
      • If needed to differentiate from normal behavior, main function should permit last 2 arguments to be {'xUnit', 1} to enable unit testing mode
      • localfunctions is a function that returns handles to all local functions
      • Example Code:
      if isempty(eachArg)
        output = struct('eachOutput',[], 'localfunctions',localfunctions);
        return
      end
      
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.