Spesso ho componenti (servizi) relativamente contenuti che fanno cose specializzate. Questi sono anche quasi sempre immutabili per rendere il loro cambiamento meno incline agli errori. Nota che il sotto è all'interno di un progetto relativamente grande, non di piccoli servizi in processi separati, ma che non cambia molto.
Prendi questo sistema come esempio:
- Input: pacchetto di cartone che contiene libri rossi
- Lavorazione
- Prendi un libro
- Esegui alcune elaborazioni complesse come:
- Se il libro ha meno di 50 pagine, rifiuta con il messaggio "Troppo corto"
- Altrimenti, leggi le pagine 15, 21 e 38
- Trova tutte le parole che iniziano con X alle pagine 15 e 21
- Se abbiamo più X-words a pagina 15, trova il numero di occorrenze della parola "play" a pagina 38, altrimenti leggi l'ultima parola su quella pagina. Fai che sia A
- Scrivi un nuovo libro in cui cambi tutte le parole "alcuni" in A. Se non ci sono parole "alcune", invia un messaggio di avviso "Nessuna parola trovata trovata"
- Stampa e colora le copertine blu
- Output: pacchetto plastico che ora contiene libri blu e vari messaggi di rifiuto o di avviso, se necessario
Considera che ora disponiamo di molti servizi che eseguono operazioni nella parte 2.2 precedente. Per esempio. ci sarebbe un servizio che scrive un libro nel passaggio 2.2.5.
Considera anche che i messaggi di rifiuto o di avvertimento devono essere propagati attraverso tutti i servizi. Nel caso semplice sopra riportato che potrebbe non sembrare tanto, ma considera che questo è di solito molto più profondo dell'esempio sopra. Per esempio. potremmo avere qualcosa di simile:
[one thread]
book service
-> chapter service
--> title service
--> paragraph service
---> sentence service
----> word service
--> footnote service
[another thread]
printing service
-> font chooser service
-> cover coloring service
Ciò significa che o manteniamo lo stato globale (yuck) o creiamo miliardi di oggetti separati (SentenceServiceOutput, PrintingServiceOutput, ...) e facciamo in modo che ognuno dei servizi restituisca tutti i pezzi, cioè il libro di scrittura restituirebbe (book, reject messages, warning messages)
tuple e quindi collegali come necessario in alcuni servizi parent.
La seconda soluzione presenta alcuni inconvenienti:
- Inquina il codice in modo significativo e rende molto difficile la lettura e la tracciabilità. Per esempio. invece di un servizio (2.2.3 sopra) che restituisce un elenco di parole trovate, restituirebbe un oggetto
([words], [reject message], [warning message])
- Rende il codice significativamente più lungo e più complicato - praticamente ovunque abbiamo
[words]
ora dobbiamo decomprimere([words], [reject message], [warning message])
, cambiare un pezzettino e poi reimballare in un nuovo([words], [reject message], [warning message])
. - Tutto ciò rende molto più difficile mantenere la struttura complessiva del progetto nella tua testa, poiché il numero di nomi (ad esempio i nomi delle classi) aumenta drasticamente e a causa del loro numero di nomi si allunga (non puoi chiamarlo solo
Output
, dato che mescoleraiSentenceServiceOutput
eFontChoosingServiceOutput
), rendendo il codice ancora più lungo e difficile da leggere - Anche se rende ancora più semplice ragionare su pezzi più piccoli rispetto all'utilizzo dello stato globale, rende le modifiche al codice notevolmente più lente e difficili da controllare, testare & ad esempio
Esistono modelli che consentano di mitigare uno o tutti i problemi sopra riportati?