Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. Note further, that we follow and would like to emphasize the following additional examples of unacceptable behavior:
- Publishing or applying others' algorithms, implementations, or research ideas present in the private development repository (e.g. in a WIP branch or merge request), without their explicit permission.
When contributing to this project, please note the following style conventions that are enforced (partially strictly enforced by the CI server).
Most importantly, reflect your changes in the Changelog so we do not have to reconstruct it from the GIT history.
When you have contributed code to M-M.E.S.S., you and the content of your contribution will be mentioned in the project's contributors file. Contributions are grouped by release, so if you have contributed code to multiple releases, you will be mentioned for each of these releases.
If, for some reason, you do not wish to be mentioned in the contributors file, please give us a short note. Also note that we cannot give attributions to trivial changes, such as fixing a typo in the documentation or correcting a very simple bug. However, your changes including your authorship will always be included in the git history of the project.
In general we prefer descriptive identifiers that support easier reading and understanding of the code. Other than that, follow the guidelines below:
Naming of functions:
- to avoid shadowing of functions from other toolboxes/packages or
the MATLAB/Octave core, all M-M.E.S.S. solver functions start with
mess_
- demonstration routines can have names deviating from the above principle, but should be descriptive enough such that a basic idea of their contents is evident.
- user supplied functions need to have a special naming scheme
described in the documentation and found in the
operatormanager
function inside theusfs
folder - Routines that do not obey the above have to be put into a
private
folder, or embedded into their calling functions source file.
Code Style:
- We try to follow the Mathworks recommendation for maximum line lengths where possible. In exceptional cases lines of at most 120 characters are allowed. The latter is enforced by our CI settings, i.e. the tests will fail when a longer line is detected. Documentation strings should strictly keep the 80 characters bound for readability reasons.
- any checked-in code must pass the
checkcode
tests in MATLAB, i.e. you are not allowed to have red or orange marks in the MATLAB editor. However, when absolutely necessary those warnings may be suppressed. (E.g. in ADI the growth of the solution factor is avoidable only with significant implementation overhead) - We always use
not()
rather than~
for negation for easier reading. (Enforced by CI!) - To support our abstraction and provide maximum flexibility to users,
all functions that are not explicitly intended for matrices need
to have
eqn
,opts
, andoper
as mandatory input and output arguments. For examplemess_lradi
is a core Lyapunov solver that is intended for maximum abstraction and needs these arguments, whilemess_lyap
is intended as a large-scale replacement for MATLAB'slyap
and thus intended for matrices. - For the same abstraction reason, in core solvers, all operations
with the system matrices have to be implemented via the
usfs
system and access to, e.g.,eqn.A_
oreqn.E_
is prohibited. (seehelp mess_usfs
for details on theusfs
system and philosophy) - The options structure
opts
should contain a separate substructure for each algorithm/solver-function and options are only allowed on the top level when they are absolutely necessary for consistent operation. For examplemess_lrnm
andmess_lradi
have their options inopts.nm
andopts.adi
. On the other hand,opts.LDL_T
oropts.norm
used to decide global settings like the shape of the factorization computed, or the norm that should consistently be used for measuring progress are allowed on the top level. - Avoid code duplication. If code blocks, or variations thereof, need to be repeated, consider to put them into a function and call it where necessary. If a helper function lacks functionality consider extending rather than doubling it.
- We prefer comments to start with a space for readability, i.e.
% comment
rather than%comment
. - We use blanks around operators and after commas in argument lists,
e.g.
y = a * x + b;
and noty=a*x+b;
- Transposes, denoted by
'
, only occur on capital letters. (this is currently required by our spellcheckers and may be dropped in the future)
Warnings, Errors and Logging:
- We provide or own logging mechanisms. We, therefore, do not call
error
, orwarning
directly, but viamess_err
andmess_warn
found in thelogger
folder. mess_log_matrix
additionally allows to write matrices to.mat
files.mess_log_plot
can store the figures in image files.- All M-M.E.S.S. code must use these and demonstration examples have
to initialize and finalize the logger via
mess_log_initialize
,mess_log_finalize
. - It is mandatory to use
mess_fprintf
rather thanfprintf
ordisp
. - CI tests in
_tests
can be an exception from this rule.
Our GIT repository provides maximum flexibility for forking, branching, merging, and commenting on work done. For the sake of maintainability follow these guidelines:
- Try to break down things to as small issues as possible.
- Work on a single issue per merge request or branch.
- branch and merge often, since long living branches tend to become messy to handle and synchronize with the master.
- Try to 'rebase' your work onto the main branch before merging or requesting a merge, if possible.
We use an extensive test system on our continuous integration (CI) server to ensure that new features do not break old functionality and all features work in both MATLAB and GNU Octave, both with and without toolboxes/packages installed. Currently CI time is limited to 6 hours and all tests should be finished in that time.
We distinguish between so called unit tests, system tests, and extended tests. Here, unit tests are testing the smallest possible building blocks. As a rule of thumb, a routine that does not call external functions, or only private functions is a candidate for a unit test.
Larger routines that run a hierarchy of other stuff, such as our
demonstrator functions in the DEMOS
folder should be used to perform
the bigger system tests.
If runtimes become an issue, consider moving system tests to the extended tests category. While unit and system tests are executed on every push that affects them and included in our weekly pipelines, extended tests (that run exceptionally long) are executed only in our monthly extended pipelines.
- All files in
DEMOS
should be accompanied by a system test calling them on an, ideally, small example. (See comment about the CI time above) - All
usfs
sets should be checked by unit tests. Use non-symmetric systems and system matrices where possible! - Consider to provide a unit test for every helper routine in your code.