Disaccoppiamento degli oggetti divini

0

Come terze parti, sto scrivendo un programma per interfacciarsi con un webservice. Il problema che ho incontrato è che alcune classi finiscono per essere comunemente utilizzate come ints / stringhe (ad es. Utente), quindi devo stare attento a quali responsabilità attribuisco ad ogni classe per prevenire mega oggetti che dipendono da ogni altro mega oggetto .

L'esempio migliore è la classe del gruppo (si pensi al gruppo Facebook). Un gruppo ha un AuditLog (componente) che contiene LogItems. Questi LogItems specificano il target di un'azione, tra le altre cose come il tempo / ecc. A volte l'obiettivo di questi log è un altro gruppo, quindi AuditLog deve sapere come creare un nuovo oggetto Group dai dati forniti dalla risposta del webservice. Ciò si traduce in una dipendenza circolare in cui il Gruppo deve sapere come creare il suo componente, AuditLog e AuditLog devono sapere come creare Gruppi.

Quindi come risolverei questo? Potrei usare dependency injection per passare un oggetto AuditLog al gruppo al momento della creazione, ma questo è dannoso per l'astrazione perché l'utente deve sapere in che modo l'oggetto del gruppo si collega internamente. Questo diventa anche impossibile quando ci sono molti componenti che devono essere aggiunti all'oggetto Gruppo in questo modo. Potrei invece creare una classe statica per AuditLog:

from group import Group
from auditlog import AuditLog

ourGroup = Group(ourGroupId)
adLogs = AuditLog.getLogs(ourGroup, logType=Advertisement)
groupsWeAdvertised = [log.target for log in adLogs if isinstance(log.target, Group)]

Questo è molto meglio, ma non sembra ancora ideale. AuditLog è un componente di Group - è utilizzato solo da Group e non ha uno scopo senza un gruppo, quindi scomporlo in una classe di alto livello sembra scomodo. Non c'è modo di sapere facilmente che questo è un oggetto figlio di gruppo (non può esistere senza Gruppo) piuttosto che un servizio di primo livello.

C'è un modo più ideale per disaccoppiare questo sistema? Ho esaminato vari Modelli software e ho trascorso ieri a cercare problemi analoghi nel softwareengineering SE, ma tutte le soluzioni che ho trovato riguardano rompere l'astrazione richiedendo all'utente di inizializzare manualmente i componenti di Gruppo o disaccoppiarli interamente dove non c'è forse un accoppiamento sufficiente per essere sani come nell'esempio sopra.

Nota: sto usando Python, quindi anche se la dipendenza circolare è in qualche modo l'ideale, Python3 non lo consente.

    
posta Drew 12.11.2017 - 18:27
fonte

1 risposta

1

Potresti convertire l'attributo target in target_type e target_id , e questo avrà i seguenti vantaggi:

  • LogItem avrà gli stessi tipi di attributi per tutte le istanze e può essere riutilizzato per qualcosa più facilmente
  • LogItem si arresta in base a Group
  • Group può ospitare la logica di analisi dei log e creazione di istanze di Group laddove appropriato, ponendo fine alla dipendenza circolare.

Tuttavia, sembra che questo sarà un progetto subottimale perché le tue classi, in particolare Group , sembrano sapere / fare troppo e senza l'iniezione di dipendenza non sarà possibile testare efficacemente nessuno di questi codici.

Una soluzione migliore sarebbe quella di fare quanto segue:

  • ha un GroupRepository in grado di restituire un gruppo con il suo id
  • avere una factory che può darti un GroupRepository , in modo che i dettagli della costruzione di uno esistano in un solo posto e siano astratti
  • sposta tutta la logica dell'interrogazione dei record di controllo su AuditLog (un metodo per ogni query di cui hai bisogno)
  • muovi il movente per far sì che queste cose parlino tra loro al livello precedente (ad esempio Controller ), dove avrai iniettato% istanze GroupRepo e AuditLog , e userai GroupRepo per risolvere Group s nei singoli logItem secondo necessità.
risposta data 13.11.2017 - 02:23
fonte

Leggi altre domande sui tag