Coding Guidelines
Coding Guidelines for the Reporting Projects
- Use minimal dependencies.
When importing functionality from existing libraries, always judge whether the newly added dependency is worth the time you saved for the initial coding. Especially on trivial algorithms or a very limited use of the code to be used and trivial data-structure or utility code, it can be much more efficient to simply copy the code into the project or to re-implement a slimed down version of the code that should be imported.
Any external dependency adds a integration nightmare later and unevitable leads to bloated projects. While the first use of the library could have been easily avoided, several iterations later that dependency will be so carved into the project (by the reasoning, that once the library is there, other code from it can be used, no matter whether that is the most efficient way to do in the long term) that it is costly to remove this dependency later.
- Write with modularization in mind. Document!
Avoid overly long methods or highly complex classes. A method or class should serve a clearly outlined purpose and nothing more. Code that tries to do everything leads to a unmaintainable mess.
Document all your classes and all complex methods using JavaDoc. If you cannot document the purpose of your class or method in a single paragraph, then refactor it so that it becomes simple enough to be documented.
- Avoid anonymous inner-classes.
Anonymous inner classes create a maintenance nightmare, as they lead to undocumented code that implicitly depend on the state of internal variables of a method, without explicitly documenting it. Therefore a refactoring of such code becomes dangerous and in case of multiple nesting levels of anonymous classes next to impossible. Almost all cases of the use of anonymous inner classes can be easily avoided by using named (inner) classes and a clean data-model in the application.
If you use anonymous classes, they still have to be documented. If you cannot sensibly document your class, then refactor it so that the code becomes sense.
- Avoid untyped models.
Any backend data-model must be strongly typed. Strings or integers must never be used for enumerations. If the backend system does not provide a strong typing (Platform, Metadata), then create a private strongly typed model for your project and file a bug report to the weakly typed dependency project.
- Write unbreakable code. Use strong assertations, avoid Null-Values.
All public methods of a class must document whether a parameter or return value can be null and must enforce the validity of all provided parameters (Object-references not null, indexes within valid bounds, etc) as soon as they receive the parameter. If a method is called that can return null, explicitly check the value for null before using it. Any NullPointerException your code throws should have a clean message and should not be one of the automatically generated exceptions that indicate sloppy programming.
When returning lists or arrays, always never return null. Return empty lists or arrays if needed.
Always clone the array and lists returned, so that modifications to the returned value do not affect the internal object state. (There may be exceptions to this rule in case of internal code or for performance reasons. In that case, document that the array or list must not be modified.)
- Protect your code from stupidity, as there are no smart users and definitely no smart developers.
Never assume that the user of your code is smart enough to use it correctly. Anticipate abusive patterns and structure your code so that it is hard and next to impossible to go the wrong way. Code that is not meant to be extended should be final by default. Reduce the visibility of your methods to the minimum, as every protected or public method is a technical dept, as the method and its semantics must be maintained for the lifetime of the library or application.
- Never swallow exceptions.
Exceptions from the client code must be handled gracefully or must be (possibly wrapped up and) re-thrown. A caught exception should never cause your code to fail with a null-pointer-exception and generally should not cause your code to return null (unless this is the documented semantics, which it rarely is).
- Never use System.out or Throwable.printStackTrace(..)
Use commons-logging instead. There is no sane reason for polluting the standard output streams.
- Follow the secure coding guidelines