The O2 GUIs follow a layered architecture:
- Controllers: Handle incoming requests, validate input, and coordinate responses. Controllers should not contain business logic.
- High-level Services: Contain business logic and orchestrate calls to lower-level services or services dealing with external systems.
- Low-level Services: Encapsulate direct interactions with external systems (e.g., gRPC clients, databases, or file systems).
- Utilities: Shared helper functions and classes used across services and controllers.
Typical flow:
Controller → High-level Service → Low-level Service → External System
- Controller Method Naming:
Controller methods should end withhandler.
Example:getEnvironmentDetailsHandler,deployEnvironmentHandler - Service Method Naming:
Service methods that are fetching data from an external service should start withretrieve.
Example:retrieveWorkflowMappings,retrieveHostsToIgnore - Linting: Code must pass ESLint checks - see
package.jsonfor command (e.g.npm run eslint) - Error Handling:
- Services should throw errors; controllers are responsible for catching and responding.
- Use custom error classes (e.g.,
InvalidInputError) for clarity.
- Logging: Use the provided O2 logger (
this._logger) for warnings and errors. - Testing:
- Write unit, integration, front-end, API tests (as per your use case) for all new features and bug fixes.
- Use Mocha and Sinon for testing and mocking.
- Place tests in the
test/directory, mirroring the source structure.
-
Create/Update Controller:
- Add a new method or endpoint in the relevant controller, ending the method name with
handler. - Validate input and call the appropriate service method.
- Add a new method or endpoint in the relevant controller, ending the method name with
-
Implement Service Logic:
- Add or update a method in a high-level service.
- If the method fetches data from an external service, start its name with
retrieve. - Encapsulate business logic and coordinate calls to low-level services.
-
Update/Implement Low-level Service:
- Add methods for direct communication with external systems if needed.
-
Write/Update Tests:
- Add unit tests for new or changed logic.
- Ensure tests cover edge cases and error handling.
-
Document:
- Update this README or add comments/docstrings as needed.
- Keep controllers thin: Only handle request/response logic.
- Keep services focused: Each service should have a clear responsibility.
- Write meaningful commit messages.
- Use async/await for asynchronous code.
- Prefer immutability: Avoid mutating input objects.
- Handle all possible error cases and provide clear error messages.
- Review and update documentation with every change.