The following guidelines are used for Orekit development.
Orekit is a low level library. It may be used in very different contexts which cannot be foreseen, from quick studies up to critical operations. The main driving goals are the following ones:
The first goal, validation, implies tests must be as extensive as possible. They should include realistic operational cases but also contingency cases. The jacoco tool must be used to monitor test coverage. A very high level of coverage is desired. We do not set up mandatory objective figures, but only guidelines here. However,a 60% line coverage would clearly not be acceptable at all and 80% would be considered deceptive.
The second goal, robustness, has some specific implications for a low level component like Orekit. In some sense, it can be considered an extension of the previous goal as it can also be improved by testing. It can also be improved by automatic checking tools that analyze either source code or binary code. The findbugs tool is already configured for automatic checks of the library using a maven plugin.
This is however not sufficient. A library is intended to be used by applications unknown to the library development team. The library development should be as flexible as possible to be merged into an environment with specific constraints. For example, perhaps an application should run 24/7 during months or years, so caching all results to improve efficiency may prove disastrous in such a use case, or it should be embedded in a server application, so printing to standard output should never be done. Experience has shown that developing libraries is more difficult than developing high level applications where most of the constraints are known beforehand.
The third goal, maintainability, implies code must be readable, clear and well documented. Part of this goal is enforced by the stylistic rules explained in the next section, but this is only for the automatic and simple checks. It is important to keep a clean and extensible design. Achieving simplicity is really hard, so this goal should not be taken too lightly. Good designs are a matter of balance between two few objects that do too many things internally an ignore each other and too many objects that do nothing alone and always need a bunch of other objects to work. Always think in terms of balance, and check what happens if you remove something from the design. Quite often, removing something improves the design and should be done.
The fourth goal, efficiency, should be handled with care to not conflict with the second and third goals (robustness and maintainability). Efficiency is necessary but trying too much too achieve it can lead to overly complex unmaintainable code, to too specific fragile code, and unfortunately too often without any gain after all because of premature optimization and unfounded second-guess.
One surprising trick, that at first sight might seem strange and inappropriate has been used in many part for Orekit and should be considered a core guideline. It is the use of immutable objects. This trick improves efficiency because many costly copying operation are avoided, even unneeded one added for defensive programming. It improves maintainability because both the classes themselves and the classes that use them are much simpler. It also improves robustness because many (really many ...) difficult to catch bugs are caused by mutable objects that are changed in some deeply burried code and have an impact on user code that forgot to perform a defensive copy. Orbits, dates, vectors, and rotations are all immutable objects.
For reading ease and consistency, the existing code style should be preserved for all new developments. The rules are common ones, inherited mainly from the Sun Code Conventions for the Java Programming Language guide style and from the default checkstyle tool configuration. A few of these rules are displayed below. The complete definition is given by the checkstyle configuration file in the project root directory.
1 | validation | seek for a line test coverage of at least 80% (more is better) |
2 | robustness | fix all errors and warnings found by findbugs |
3 | robustness | do not make assumptions on the runtime environment of applications using Orekit (they may be embedded with no console, no possible user interaction, no network, no writable file system, no stoppable main program, have memory constraints, time constraints, be run in different linguistic contexts ...) |
4 | maintainability | follow Occam's razor principle or its declination in computer science: KISS (Keep It Simple, Stupid) |
5 | efficiency | seek efficiency, but do not overstep robustness and maintainability |
6 | robustness maintainability efficiency | use immutable objects as much as possible |
7 | style | fix all errors and warnings found by checkstyle |