refactor(commercial) : découpler l'hydratation des collections de la sélection clients (ERP-100) #50
Reference in New Issue
Block a user
Delete Branch "fix/ERP-100-decouple-list-hydration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
Issu de la review ERP-62 (#44).
DoctrineClientRepository::createListQueryBuilder()portait 3leftJoin+addSelectto-many imbriqués (categories × addresses × addresses.sites) partagés entre :ClientProvider) — bornée, OK ;?pagination=false—getResult()sans pagination → hydratation du produit cartésien sur tout le référentiel (1 client à 5 cat × 4 adr × 3 sites = 60 lignes SQL, × N clients).Défaut d'altitude : un « QueryBuilder de liste » (contrat = filtres) imposait une stratégie d'hydratation à tout appelant.
Changements
createListQueryBuilder()redevient filtres + tri seuls — conforme au contrat de l'interface.hydrateListCollections(array $clients): recharge les collections en 2 requêtesWHERE id IN(...)séparées (catégories d'un côté, adresses+sites de l'autre) via l'identity map Doctrine. Casse le triple cartésien encat + (addr × site).fetchJoinCollection: false(COUNT simple) + hydratation de la page ;?pagination=false: hydratation aprèsgetResult();getResult().Tests
make test: 465 OK.ClientExportControllerTest::testExportPopulatesCategoryAndSiteColumns: garde-fou sur les valeurs Catégories/Sites de l'export (qu'un oubli d'hydratation rendrait silencieusement vides).php-cs-fixer: 0 correction.Notes
addr × sitereste un join imbriqué (inévitable pour agréger les sites par adresse), désormais non multiplié par les catégories.Closes ERP-100.
Review (relecture ciblée) — LGTM, non bloquant ✅
Refacto correct et même légèrement plus correct que l'existant. Synthèse :
Ce qui est bon
INdistinctes re-hydratant via l'identity map (mêmes instances managées) cassent biencat × addr × site. Pattern Doctrine canonique.fetchJoinCollection: falsejustifié : plus de jointure to-many dans le QB de sélection →COUNTtrivial et exact (gain de correction, pas seulement de perf).AbstractPaginator::getIterator()met l'itérateur en cache etDoctrinePaginatorrenvoie unArrayIteratorrewindable → la re-itération de sérialisation rejoue le même tableau (vérifié dans le vendor).2 remarques non bloquantes (info)
IN (:ids): déplie enIN (?, ?, …)→ plafond ~65 535 paramètres PostgreSQL. Exposition théorique (l'export chargeait déjà tout, c'est strictement mieux qu'avant) ; si l'export peut grossir, prévoir un chunk des ids. Pas à corriger ici.?pagination=falsehydrate 2 requêtes en plus alors que cette échappatoire alimente surtout des<select>ne sérialisant pas catégories/sites. Coût marginal, cohérence défensive acceptable. OK tel quel.Rien à corriger. (Suite
make testnon exécutée côté review : container monté sur un autre checkout — lint + analyse statique seulement.)