Is it a correct DDD design? or at least close to it?
Sembra ok, anche se trovo che i "luoghi" di denominazione come spot WiFi siano un po 'confusi.
While being a data-centric programmer, I still wonder how would I list all the places for all the Institutions, if the rule of thumb is accessing aggregates through the aggregate root?
Devi passare attraverso la radice aggregata per ottenere il suo elenco di luoghi, ad es. %codice%. È possibile utilizzare i posti restituiti per la durata della transazione o dell'inchiesta corrente e, nella successiva transazione o richiesta, ricominciare dalla radice aggregata per raggiungere le attività.
Is the idea of generating Uuid inside of the entity itself (Place::create) good?
Non particolarmente. Mentre un UUID è appropriato per le radici aggregate, non è proprio appropriato per gli aggregati secondari (cioè non le radici).
Come puoi vedere nell'esempio che stai citando, le aggregazioni secondarie usano un semplice meccanismo di contatore per i loro id invece di un UUID. Questo contatore è root per aggregato, vale a dire che le voci di un id figlio di una radice aggregata possono sovrapporsi a quelle di un altro figlio di radice aggregata.
In sostanza, ciò richiede che per l'acquisizione a lungo termine, un client obbligatorio (anche) acquisisca l'ID radice aggregato e che l'implementazione non debba generare UUID per le varie entità figlio.
Should an idea, that only assignee (User) can add/remove places be expressed on the domain itself or should it be the responsibility of client?
No, in generale la logica aziendale come questa dovrebbe essere convalidata nel dominio stesso e non lasciata (solo) al client.
Isn't the Institution::placeById breaking any principles of DDD? Maybe it is the responsibility of the repository?
La responsabilità del repository è di fornire la persistenza per il modello di dominio. Quindi, vi è una certa responsabilità in merito alla memorizzazione di luoghi di istituzioni. Tuttavia, idealmente, il cliente parla direttamente con il dominio e non con il repository del dominio poiché il suo repository è il dettaglio dell'implementazione privato nel dominio.
I repository tendono ad essere piuttosto primitivi e l'idea è che cerchiamo di stratificare le cose. Il dominio fornisce un livello aziendale che è un wrapper attorno al livello di persistenza più primitivo.
Ogni livello dovrebbe fornire al programmatore successivo (il suo client) un'astrazione coerente, utilizzabile, sicura e completa. Quando lo facciamo, l'accoppiamento è ridotto e la manutenibilità è migliorata. Usando un design a strati, è un'indicazione negativa quando un cliente raggiunge la nostra astrazione e tocca direttamente l'implementazione sottostante (livelli inferiori) - questo indica che l'astrazione è incompleta e, il client usa impropriamente la conoscenza dei dettagli di implementazione del livello fornendo l'astrazione.