QuantumLab Design Guidelines

[su_list icon=”icon: terminal”]

  • For indentation: set up your editor, so that one tab equals 8 spaces (tabstop=8, the vim and github default)
  • use CamelCase throughout
  • initial letter:
    • Uppercase: types and Modules
    • Lowercase: variables, fields, functions
  • Module names always end in `…Module`
  • all modules are on one level below QuantumLab.jl (no Subsubmodules)
  • all function names follow the naming scheme verbNounDescriptor
    • [table sort=asc]
      verb, description
      read, Read s.th. from disk. These functions typically require a filename and the descriptor is typically a file format.
      compute, Obtain s.th. by computation from objects that are already in memory.
      write, Write s.th. to disk. These functions typically require a filename and the descriptor is typically a file format.
      evaluate, Follow a defined process that is defined rather by its steps than by its result. A single SCF step for example is such a process. Typically these functions modify their arguments and thus end in an exclamation mark (!).
      [/table]
    • Nouns should be the common name for the most generic supertype that is still descriptive. E.g. the overlap matrix has the most generic supertype `Array{Float,2}` which a peasant would probably call a Matrix. This defines the noun, so the function to compute it should be called `computeMatrixOverlap`. A single overlap integral could similarly be considered a Float, but this would not be descriptive of the object but rather of its implementation. Here, the choice of the noun Integral is more suitable. Below is a list of example nouns:[su_spoiler title=”Nouns” style=”fancy” icon=”plus-circle”][table sort=asc]
      Noun
      Matrix
      Integral
      [/table][/su_spoiler]
    • Descriptors are appended as needed to make the result of the function unique. They should be listed in increasing specificity (starting from the most generic). Ask yourself if the distinction can be done by function argument already before adding a further descriptor.
  • Although good variable naming is strongly encouraged, inside of a function the variables etc. can be named as concise as the developer wishes (e.g. `mu1` is considered acceptable). The function arguments however should have telling names (e.g. `basisFunction1`)
  • Every function that implements an equation that is not immediately obvious to any reader (like `median(a,b)=(a+b)/2`) must contain a comment with a precise reference to this equation. Either “Where can I find that equation?” or “What steps are needed for me to derive this equation?”
  • The `Base.display` function should be overloaded if readable output for any custom type is desired. Users can always turn to `print` if they want to see the object in the default “forest of braces” representation.
  • Use of the Inception Pattern is strongly encouraged if several possible implementations or expressions coexist for any term/function.
  • For error messages and warnings: While humor can be fine in general, always prefer clarity over anything else. Error messages and warnings should also never be insulting.

[/su_list]

Further design requirements under consideration (not yet acted upon):

  • Functions may have at most three arguments (triadic) for better clarity
  • Renaming variables after any code change for more descriptiveness is encouraged. While this may lead to merging conflicts, these should be easy to resolve. Furthermore finding out about diverging concepts is better early than late.
  • Boolean Arguments should be considered a red flag. If you have a function with two cases (bool=true/false) than why isn’t it split into two functions? The exception here is the info variable to control whether output is given to the user.
  • try-catch: try as first line and only containing one function call. E.g.
    function func(x...)
      try
        unsafe_func(x...)
      catch
        #handle exception
      end
    end