SMNG coding conventions
Variable names and file names
Our variables and file names often look something like this:
- gen_vowelSegment_dataTable_vsaPD
- check_audio
- setup_exptFigs
- audioGUI
- run_noGoAdaptObserve_expt
- make_fig4Screen
- hz2mels
This naming style is a combo of lowerCamelCase, where the first letter is lowercase then subsequent starting letters are capitalized without spaces in between, and snake case, where underscores go between words. Broadly speaking, we use camel case to connect words that are more closely related, and underscores to separate words that are less closely related.
Variable names should be descriptive. Avoid using variable names like temp or x y z. (Short variable names are okay if meaningful: y and fs for audio signal and sampling rate; i and j for iterators.)
Function names shouldn't start with capital letters. On rare occasions, a variable can start with a capital letter. For example, in a hypothetical function gen_foobar_allData, if you have a variable that gets referenced 500 times to store data, you could call it D or some such.
String vs char array
In MATLAB, text can be stored in strings, which use double quotes str = "This is a string" or a character array, which uses single quotes charArray = 'This is a character array'. Strings are newer and technically superior, but both data types perform identically for the kinds of tasks we normally use them for, such as collecting a user response of 'y' or 'n'. Most of the lab code uses char arrays, so be prepared to see single quotes.
"Boolean"/"binary" variables
We often use use variables with names like bTestMode or bGoodTrial, where the 'b' in the variable name indicates the variable has a binary set of possible values, either 0 or 1. (MATLAB has an actual 'logical' data type that stores Boolean data, i.e. a binary true or false value, but we don't normally use it.) Our "fake" Boolean/binary variables perform very similarly to real logicals: you can have a statement such as if bPrintIt, disp('hello world.'), end and it will display 'hello world' only if bPrintIt is set to 1, even though bPrintIt is technically just a number.
Use section dividers (%%)
In MATLAB, %% is the section divider. If you start a line with %%, it will put a horizontal line and bold the text. Use this to separate broader sections of code. For separating smaller sections of code, use a stand-alone comment line. You can use whitespace (blank lines) to also help separate sections, but 1 or max 2 lines of whitespace is plenty. Here's an example using both:
%% Calculate area% Get lengthx = 1;y = 2;len = x+y;% Get heighta = 1;b = 2;height = a+b;area = len*height;%% Calculate something else
...
Don't use global variables
Global variables are variables that can be referenced by multiple functions without explicitly passing that variable back and forth. In MATLAB, globals are colored turquoise. In the words of MATLAB's warning on globals itself: "Global variables are inefficient and make errors difficult to diagnose." If you need a variable in another function, pass it in as an input argument.
Respect a function's scope
A function's "scope" is what it knows -- what variables it has access to. Generally, a function only knows any variables you passed into it as input arguments, or any variables you created inside the function. If you want to pass data back to another function, send it as an output argument. Don't get fancy and save data to another scope or the base workspace; that would make troubleshooting much more challenging and could lead to unexpected behavior.
Use `params` when sending lots of info to a function
A common situation is that, over time, a function gets more and more input arguments added to it. After several years of people adding "just one more input argument," a regular old function call becomes hard to read: run_foobar(data, [], [], 1, [], [], 'normal', [], [], 0). There's nothing technically wrong with this. However in some circumstances it may feel better to instead make a struct params with fields for each of the parameters you want to send.
params.bAlpha = 1;params.mode = 'normal';params.bBeta = 0;run_foobar(data, params);
If you use this "params" method of collecting input arguments, in the function you're sending params to, use the function set_missingFields to set any default values of params that weren't sent by the user. For a real example, see plot_audapterFormants in free-speech\plotting\plot
Prepend "h_" to handles
Commands to open a new figure will often look like this: h_fig = figure;. The "h_" is for "handle", since MATLAB treats figures and axes as objects. (MATLAB is technically always an object oriented programming language, but normally you don't have to treat it like one.) It's useful to name figure handles with this "h_" prefix to denote that they will behave differently than other types of variables. In some functions you may see it written hax for "axes handle".
Iterator names
You can use i, j, ii -- whatever. i is probably most common.
Use a mostly flat file structure
If you are making lots of files/functions for an experiment, generally we prefer a relatively "flat" file structure. A flat file structure has fewer folders with more contents per folder, as opposed to lots of folders with a small number of files in each folder, or a series of nested folders.
Listen to the MATLAB Code Analyzer
MATLAB has many conventions and code efficiency practices it automatically checks for, and MATLAB will warn you about them if you don't follow them. For example: if you create a variable but never use that variable again, it will tell you that the variable may be unnecessary. These checks are done automatically by the Code Analyzer.
Code Analyzer messages show up in orange in the coding window. If these messages show up, they'll normally tell you what to do to avoid them. All of these warnings are generally good coding practices. By the time your function/script is "done," you should have addressed all these messages, either by actually fixing them or suppressing the message. (Code Analyzer message suppressions appear as a comment in that line and look something like %#ok<ABCDE>
