Back-end
Il back-end è organizzato secondo la Clean Architecture.
Il codice è diviso in 4 livelli:

- Presentazione (
Presentation.csproj): API REST e Autenticazione - Applicazione (
Application.csproj): Business logic - Dominio (
Application/Domain): Rappresentazione dei dati - Infrastruttura (
Infrastructure): Implementazioni di DB, Storage, etc.
Esiste un progetto aggiuntivo contenente file statici: "Risorse" (Resources). Questo progetto contiene file statici che vengono automaticamente copiati nella directory dell'eseguibile compilato. I file statici sono richiesti dai template di page element.
La direzione delle dipendenze va dai layer esterni a quelli interni, il che significa che infrastruttura e presentazione dipendono da dominio e applicazione.
Una classe A dipende da B quando B è citato dal sorgente di A. Es. A compare come tipo di parametro di un metodo, come tipo di un attributo o di una variabile locale.
L'unica eccezione alla direzione delle dipendenze riguarda l'iniezione dei servizi forniti dai livelli di applicazione e infrastruttura: infatti questo è compito del progetto di avvio (Presentation), gestito nel file Startup.cs e nei file ServiceConfiguration.cs presenti nella soluzione.
Dependency Injection
Una delle funzionalità e pattern principali di ASP.NET è la dependency injection: ovvero, un metodo per fornire le dipendenze richieste dalle classi in modo trasparente. Nella pratica questo si traduce come il "riempimento autormatico" dei campi del costruttore di una classe usando i servizi aggiunti ad un particolare registro.
Supponiamo di avere un controller API ToDoController:
[ApiController]
[Route("todo")] //https://site.org/todo/...
public class ToDoController : Controller {
private readonly IEntityCollection<ToDo> _toDoCollection;
public ToDoController(IEntityCollection<ToDo> toDoCollection) {
_toDoCollection
}
[HttpGet]
public async Task<IEnumerable<ToDo>> GetToDos() {
return await _toDoCollection.GetAll();
}
}
Durante l'inizializzazione del controller da parte di ASP.NET, il costruttore sarà chiamato popolando i parametri con riferimenti a servizi già registrati:
/* Da questa riga in avanti, l'implementazione ConcreteTodoRepository
* sarà iniettata in tutti i parametri di tipo IEntityCollection<ToDo> */
services.AddScoped<IEntityCollection<ToDo>, ConcreteToDoCollection>();
In Hydra, dato che il layer di infrastruttura implementa alcune delle interfacce definite nel livello applicatico, il layer di presentazione (basasto su ASP) deve configurare le dipendenze necessarie per conto del layer di applicazione. Nella pratica il file Startup.cs di Presentation delega parte della configurazione dei servizi a ServiceConfiguration.cs nei progetti Application e Infrastructure.
Invio di Messaggi
Per minimizzare la dipendenza tra i layer Presentation e Application e permettere un uso estensivo della dependency injection, viene adottato il pattern Mediator. Usare il mediator significa che quando il layer di Presentazione (REST API) intende invocare un'azione verso il livello applicativo (es. inserire un nuovo sito, leggere l'elenco delle pagine), non lo fa tramite normale chiamata a metodo, ma istanzia un oggetto che rappresenta l'azione eseguire e lo affida al mediator: quest'ultimo si occuperà di instradare il messaggio verso un'handler specifico per il tipo di azione. L'implementazione del mediator è fornita dalla libreria (MediatR).
Per ogni caso d'uso esiste una classe query (se azione di lettura) o comando (se azione di aggiornamento/modifica) corrispondente. Ad ogni query o comando è associato un handler, che implementa la business logic per la gestione del caso d'uso.
Es. UpdateMemberCommand => UpdateMemberCommandHandler,