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.
- 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.
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 values
void initOptions(String)- Process command line options
void initVariables(String)- Any additional setup that is required after processing command line args
void 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
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.
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, and then running the tests.
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.
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.
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
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.
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
- Another ScriptTest.out.somewhere exists that is newer than ScriptTest.out.
Please see the testing page for more information.