Design conventions
Introduction
This document defines the Design Conventions for the Rodano platform. As the EDC platform evolves, common solutions and patterns will solve similar problems. Shared design practices and naming conventions need to be established to improve the quality of the software.
This document establishes several naming conventions around Rodano that shall be followed by developers at different phases of the life-cycle.
It is the responsibility of the maintainers to ensure that these conventions are followed in practice.
Naming conventions
Naming conventions must be established for the following objects:
- registries and storage structures for documentation artefacts
- development projects
- applications at the system, subsystem and support levels
- other executables such as jobs, tasks and scheduled events
- libraries, modules and packages
- reports
- files
- database objects (tables, views, columns, indexes, constraints)
- database migration scripts
Naming convention for each system should be unique and appropriate to its characteristics. Naming conventions for characteristics that are common across several systems should be consistent. Naming conventions should be consistent across documentation, module implementation, test cases, test summaries and reports.
Text editing conventions
Text editing conventions promote a unified way of editing the code and text files in general. This leads to improved readability and consistency across the team and projects. It also leads to less complex diff procedures.
- Use tabs over spaces.
- Establish code formatting conventions across the team. Once a common convention is established, the text editor configuration files should be committed to the project repository. This way the code style stays consistent, no matter the editor.
- Force all the editors to import the dependencies in the same order. This leads to less file diff clutter.
Design specifications
Design specifications provide a concise definition of each software module. These definitions must be traceable back to business functions expressed in the Requirement Specifications. It should be clear which function implements the designed solution.
Usage of common design patterns (standard across the IT industry) is highly encouraged. Design discussions between developers will consciously establish trade-offs with relation to these known models for solving common business problems.
Design conventions
Design standards are vital to ensure consistency and supportability of any computer system. It is the responsibility of the maintainers to ensure that design decisions are achievable during the implementation phase.
Evidence must be present that source code reviews have been conducted as part of the development process. This practice is ensured by developers while integrating their work into a common release branch, before deployment it to a validation environment.
The maintainers group is responsible for verifying the code is implemented according to the defined design and that the review practices are consistently and continuously followed.
Java best practices
To improve the general quality of the Java code developers should follow these best practices, unless there is a good reason to not use them:
- Design modular components instead of monolithic application blocks.
- Use interfaces instead of classes wherever possible in order to separate public testable APIs from their possible implementation (i.e. design by contract).
- Favour composition over inheritance.
- Avoid deep inheritance chains of 3 or more object levels.
- Inheritance must be used only for classes in the same domain or module.
- Each core entity of the application should be comparable, and all comparators must be declared statically at the beginning of the class.
- Apply the KISS-Principle principle as much as possible.
- When possible, avoid code duplication by applying the DRY-Principle principle.
- Avoid assigning too many parameters in a single function.
- Favour small focused functions (typically a few lines of code) over long and complex functions with many possible outcomes.
- Favour dependency injection over implicit dependencies.
- Follow the separation of concerns principles wherever possible.
- Favour constructor injection over setter injection.
Spring Boot best practices
Rodano uses Spring Boot framework as its main dependency. Spring boot is a framework with many features and has its own best practices that should be followed:
- Favour autoconfiguration wherever possible. Only manually configure components that absolutely need to be customized.
- Favour the logger provided by Spring for all system logs.
- Keep the DAO layer focused on database queries and keep it as simple as possible.
- Keep all the business logic in the service layer.
- Controllers should contain as little business logic as possible. Ideally they should just deal with the HTTP layer of the application and nothing else.
- Use the HTTP API documentation generation libraries in order to keep the API documentation up to date automatically.
- Try to keep the Spring Boot parent dependency up to date with each product release.
JavaScript best practices
In order to maintain the general quality of the JavaScript code, developers should follow these best practices, unless there is a good reason to not follow them:
- Use tools like ESLint to follow the established code style conventions in order to simplify the code readability.
- Use the latest JavaScript features (i.e. "let" and "const" instead of "var", arrow functions, etc.).
- Always use the "===" operator instead of "==".
Angular best practices
The frontend of the Rodano application is built in JavaScript using the Angular framework. Following practices shall be applied in this context:
- Split the application into multiple modules with each module contained in its own folder (logic, template, style and tests).
- Use proper naming conventions (e.g. suffix every controller name by Ctrl).
- Create a separate Angular service for each individual REST resource.
- The business logic shall reside inside Angular services.
- Use standalone components
- Favour import of components instead of modules
- Use Reactive Forms for all forms