To make sure that the report designer stays clean and maintainable over time, I'm enforcing a strict rulership over the code rejecting code that is not "clean" according to my standards.
Clean, what does that mean:
- No anonymous inner classes.
anonymous inner classes are only ok for primitive one-line event forwardings. For executing larger portions of code, create named inner classes (so that the code can be documented and has a name that tells what the code is doing) instead.
- Separation of concerns, encapsulation
Code that works together on the same task, should go together and stay in the same class. When writing event-handlers or actions, keep the code dealing with one task in the same inner class.
Example: A action (as an example of a ActionListener) that can only succeed when a item on a list is set, should also take care of the ListSelection-event. Even if more than one action has to listen to the same event, they should be separate listener-instances. This way, when we month later have to change the action, we have all code dealing with the action in one place and don't have to search/change event handlers all over the place.
- Prefer javax.swing.Action instead of maintaining the button/menu states manually.
- For non-trivial dialogs, create a data model. Even if the data model you create does not fully match the "perfect" model, it is easier to tweak a dialog's data model to new or changed requirements than o tweak a dialog that stores all data only in the components itself.
- Use real data models in the code
A non-trivial "data model" that consists only of presentation data (or worse, of localized strings) and generic collections is not acceptable. A maintainable data model must be a type-safe model implementation that maintains and guarantees the integrity of its internal state. When creating GUI elements for the model use custom renderers and editors if the model does not create user-friendly representations on its "toString()" methods.
Likewise, I prefer that GUI elements are bound to the model instead of creating a incomprehensible web of event-listener dependencies between UI-components.
- Encapsulation II: There is no way how I could ever accept non-private members on a class. Likewise, I do not accept public non-static inner classes, as these constructs easily lead to memory leaks (as every non-static class holds a implicit reference to its parent-class instance)
- Separation II: It is no shame to create a separate class for each dialog or larger task to be done. Maintaining a 1000-lines monster class is no fun, and usually the local complexity can be greatly reduced by splitting such monsters into separate areas of concern.
- Be error-resistant:
Each public method must and each protected method should check all incoming parameters for Null-Values or other invalid values and should throw explicit Exceptions in that case.
This helps us to discover errors early and prevents that classes can enter a invalid state without getting noticed. When we (again) months later have to change the dialog for whatever reasons, then any error introduced by us will be easily spotted, which reduces our maintenance efforts.
- Write the code clean enough that an average student has a realistic chance to understand and work with the code.