Camino code organization and standards
This page describes in detail how Camino code is (or should be - work in progress) organized.
Workflow for developing code
- Check out a version of the code
- Run unit tests
- Run ScriptTest and save the output as ScriptTest.yourmachine.check
- Check that ScriptTest.out.yourmachine.check has no diffs with ScriptTest.out.yourmachine in camino/test
- Make your changes, including
- Comments and Javadoc in the code
- Tests for your new code
- Updated man page to reflect any changes to applications
- Run tests again; make further changes and test as necessary.
- Copy
ScriptTest.out.yourmachine
tocamino/test/ScriptTest.out.yourmachine
- Commit with a detailed message describing what you did
The user interface
Camino users interact with the commands in the bin/
directory. These are executable files that may call one or more Camino program. Currently, most of the executables are bash scripts that do some simple system checks and then forward the application name and arguments to EntryPoint
. New scripts should be written in bash, though we may allow other scripting languages later. Users never invoke Java or any other interpreter explicitly.
Applications (apps)
Apps have a special structure to accomodate Matlab wrapping and provide a consistent user interface. All applications should extend the Executable
class. Executables provide the following methods, which are executed in the following order:
void initDefaultVals()
- Set all class variables to default valuesvoid initOptions(String[])
- Process command line optionsvoid initVariables(String[])
- Any additional setup that is required after processing command line argsvoid execute(data.OutputManager)
- Runs the executable and passes output to the OutputManager
Executables must also provide a String usage()
method, which returns basic information on how to run the application. This method is called by EntryPoint
only if the command is run with -help
and no other options.
Once you've written an app, you need to add it to the getExecutable
method of the EntryPoint
class, which is what actually gets executed in the script called by the user:
java [options] EntryPoint AppName [options]
EntryPoint
simply constructs an AppName
object, forwards the command line arguments, and then calls its execute method - unless the command is called with -help
.
Other modules
Other modules are arranged by theme. These classes should not have main methods (a couple currently do, eg AnalyzeHeader / Nifti1Dataset), they should be objects with a well-defined and documented API. We don't have well-defined coding standards, but Effective Java by Bloch has some good guideines.
Compiling
Compilation is performed via a Makefile. Each class in apps
is compiled individually, which should in turn compile the rest of the code. However, this relies heavily on Java to correctly work out all the dependencies with other classes, which it doesn't always do correctly. You can bypass this issue with make allclasses
, which will compile everything under the Camino tree that isn't in the test directory. Alternatively, you can do make clean
and then make
, which should be equivalent, but this is slower. However, most users will download the code and just do make
, so be sure that your apps all work by doing make clean
, make
, and then running the tests.
Documentation
Applications should be documented with command-line usage, man pages, and online tutorials as appropriate. All classes should be documented with Javadoc for all methods.
Javadoc
By default, public, package and protected methods will appear in the javadoc. Private methods should be documented in the code with a Javadoc comment, but this is more for the benefit of people coding the class itself.
You can build the Javadoc with make docs
. See the Javadoc tutorial for more information on coding doc comments.
Usage
All applications should provide a basic usage when passed the -help
option. This is handled by EntryPoint
so applications don't have to do anything except implement the usage()
method.
Man pages
Man pages are written in NROFF. Check how your man pages look when you type man <command>
. The man pages should follow a consistent format:
NAME program - One or two sentence description of what the program does SYNOPSIS program -mandatoryOption <arg> [-notMandatory <arg>] [...] Some programs have too many options to list; in which case just list the most common ones and indicate that there are more DESCRIPTION Detailed description of what the program does OTHER SECTIONS AS NECESSARY EXAMPLES Some common examples with a brief explanation OPTIONS Complete listing of options with explanation of their syntax and function AUTHORS Who wrote the program or a substantial portion thereof SEE ALSO Other programs of interest CAVEATS Formerly bugs, but more general. Includes known bugs, limitations, or common misconceptions
The HTML man pages are auto-generated nightly - but new man pages need to be added to the Wiki. If you commit a new command, update the Wiki command list to point to the HTML version of that man page.
Testing
Please see the test page for information about tests. Avoid embedding test code in the main methods of classes, or by writing test classes inside the packages themselves. For application tests, write a real-world use of the class and place it in ScriptTest. For unit tests, use the JUnit framework in the test directory. Java packages are virtual, you have the same access to package / protected methods in test/numerics
as you do in numerics
. A JUnit test is accessible to all users rather than just the person who wrote the test, and it can be run automatically by all users.
The automated testing system requires one of two things to be true each night. Either
- ScriptTest produces no diffs with the repository ScriptTest.out
or
- Another ScriptTest.out.somewhere exists that is newer than ScriptTest.out.
Please see the testing page for more information.