When developing FeatJAR code, we recommend to respect the following coding conventions to ensure consistency and high-quality code.
-
Rule of thumb: Prefer good naming (without documentation) over bad naming (with documentation).
-
Most classes are
- things, which actors operate on (e.g.,
Tree), - actors, which operate on things (e.g.,
TreeVisitor), or - buckets, which loosely collect related methods (e.g.,
Trees).
This should be reflected in their naming.
- things, which actors operate on (e.g.,
-
Prepend names of abstract classes with
Aand interfaces withI, so there is room for a canonical implementation (e.g.,ITreeand its primary implementationTree). Avoid using inner classes and interfaces - if using them, do not prepend their names. -
Abbreviations should be capitalized (e.g., prefer
ComputeCNFFormulaoverComputeCnfFormula). Only use well-known abbreviations. -
We recommend to move complex algorithms for manipulating a data structure
<Struct>into a class with static methods<Struct>s(e.g.,TreesmanipulatesITreeinstances). For common algorithms, consider adding a convenience method to<Struct>to ensure obvious visibility for API consumers (e.g.,ITree#traverse(TreeVisitor)as a shorthand forTrees#traverse(ITree, TreeVisitor)). The rationale is to keep the data structure class free from algorithm details (e.g., traversal iterators) and make better use of generic types. -
The same naming convention is also applied for extensions (e.g.,
Thing) and their extension points (e.g.,Things).
-
All Java classes in FeatJAR should be documented with a JavaDoc comment above the class, including the purpose of the class and its author(s).
-
Depending on the subjective importance of the class, either
- all attributes and methods should be documented, or
- all public and protected attributes and methods should be documented (recommended), or
- no attributes and methods should be documented.
That is, avoid documenting an arbitrary selection of methods. The rationale is to keep the documentation clear, concise, and correct.
-
Use the JavaDoc tags
@author(for classes),@param,@return,@throws, and@inheritDoc(when extending documentation). For further guidelines, see here. -
When documenting a method, consider its most important usage example and typical failure modes.
-
As an example for appropriate documentation, refer to the
basemodule. -
Tests need not be documented using JavaDoc. Instead, write small tests with telling names.
TODO
- Avoid global mutable state (i.e., non-final
staticfields). When it cannot be avoided, implement anIExtensionand register it (e.g., inInitializers). This way, global mutable state is at least encapsulated in a singleton and its lifetime is limited by the (un-)installer inExtensions. - Avoid
privatefields and methods. Useprotectedinstead to allow API extensions. - How To Design A Good API and Why it Matters
- Do not implement
Object.clone, which cannot be used reliably for all classes. Instead, write copy constructors. - Implement
Object.equalsandObject.hashCodewhere necessary (e.g., for objects cached in computations), but always in pairs. serialVersionUID,toStringformat:TODO- Avoid returning
nulland throwing exceptions. Instead, return aResultfor planned or erroneous absence of values. Exceptions to this rule:- You can return
nullwhen implementing an optional feature in an extension (i.e., a default method in an interface that inheritsExtension). If you do so, still document it ({@return ..., if any}). - You can throw (preferably checked) exceptions in
voidmethods to avoid introducing a necessarily empty return value. If you do so, document it, especially for unchecked exceptions (@throws ... when ...).
- You can return
- Concrete implementations of
IComputation,IAnalysis, andITransformationshould be namedCompute*,Analyze*, andTransform*, respectively. - Variables of type
IComputationshould be named withoutcomputationsuffix. Use the helpers inComputationsto convert between (a)synchronous computation modes. - Use
LinkedHashMapandLinkedHashSetinstead ofHashMapandHashSetto preserve order and guarantee determinism.