teams: implement team roster SD-269
This MR introduces an improved implementation for code reuse through class inheritance, with a focus on abstracting concepts for better modularity. The Memberships
module has been used as an example to demonstrate how to implement a generic concept within a specific business use case (Team Roster
).
Class Inheritance for Reusability
- Using class inheritance for better code reuse. The generic parent classes encapsulate common logic, while child classes specialise for specific use cases.
- The abstract classes are intended to reflect database structures (lower layers) and should not contain use-case-specific logic.
- The
TeamRoster
class, for example, is a specialised implementation of a more abstractMembership
concept.
Renaming to TeamRoster
- The renaming emphasises the distinction between abstract concepts (e.g.,
Memberships
,Groups
) and concrete business logic (things that HQ people know). These abstract concepts exist in the backend and may remain internal to the system. - Since they are internal, the DTOs of Groups have already been removed. The ones from Memberhips require further refactor.
Generic, Scalable Parent Modules
- Parent modules should focus on generic functionality that applies across multiple use cases. This ensures code remains clean and reusable.
- For new use cases, the primary change should be updating type declarations in the parent module, without altering the core logic.
Future Example
- For instance, in the future we should have the concept of
TeamSubmission
which should be a class that handles all common logic for submissions, and different use cases should inherit from it (AttributionsForm
,SafetyForm
, etc). - A similar structure was implemented for
TeamVideos
, but we should make it more generic to accomodate forms. -
NOTE: There should NOT be any code about forms or videos inside
TeamSubmission
, but only what deals with a "submission" concept. - This way, we will hopefully reduce the size of services that deal with dozens concepts at the same time
Authorisation Integrity
- Controllers are the top layer of the backend, and they expose the most specialised actions that the backend supports.
- Each endpoint should be minimal, perform a single action (it can be an abstracted action, or an action with consequences, but the action itself should be clear)
- Each use-case module should declare its own controller, which helps to keep the logic segregated and aligned with business requirements.
Decomposing Events:
- Also,
AsyncEvent
has been extended for fine-grained events, allowing different modules to listen for and respond to specific events, making the system more flexible and maintainable. - The goal is to use precise events when needed, and avoid
Types
- With more dedicated endpoints, functions and use cases, we should use more appropriated DTOs that reflect the types of properties correclty
- See the new
TeamRosterDTO
that hasmember: AccountDTO
instead ofmember?: AccountDTO
. This makes code much clear and reduce runtime type errors in FE (see FE MR for several examples)
Closes SD-269
Edited by Fabio Maschi