Come rifattorizzare il mio progetto per avere oggetti meno mutevoli? [duplicare]

3

Sembra esserci una tendenza verso oggetti immutabili e programmazione funzionale. Recentemente mi sono reso conto dei benefici dell'immutabilità. Tuttavia, non ho molta familiarità con questo stile di programmazione.

Le mie classi attuali possono avere alcune variabili mutabili private o pubbliche (variabili di stato). Penso che queste variabili siano la fonte dello stato mutabile per gli oggetti della mia classe. Se il numero di queste variabili è elevato, lo stato degli oggetti sarà più complesso. (se ci sono altri motivi per lo stato mutabile degli oggetti della mia classe, per favore guidami su di loro)

Quindi, la mia domanda è come refactoring questa classe o anche ridisegnare il mio progetto per avere oggetti con stato immutabile o meno complesso.
Ad esempio scomposizione della classe in altre classi con variabili meno mutevoli o qualsiasi altra linea guida?

O in altre parole, cerco alcune linee guida per progettare e implementare un progetto per avere oggetti meno mutevoli possibile?

    
posta Ahmad 21.02.2015 - 14:51
fonte

4 risposte

4

Non è chiaro cosa stai cercando di fare in questo esempio, e i dettagli di implementazione del tuo framework limiteranno un po 'quello che devi fare.

Ecco alcune linee guida che uso, che hanno avuto successo. Ci sono naturalmente altri approcci che hanno successo. Io uso C # come lingua principale, cose simili a C # possono usare questo approccio. Altre lingue potrebbero non essere in grado di usarlo bene.

Ogni volta che considero di creare una nuova classe, considero ciò che è necessario per fare . Alcune classi rappresentano alcuni dati. Alcune classi rappresentano alcune funzionalità (che potrebbero richiedere o meno lo stato di funzionare). Soprattutto, considero le dipendenze di quella classe.

Soprattutto per i principianti, queste dipendenze sono dove la mutabilità viene introdotta senza necessità. Ogni volta che è pratico, le dipendenze devono essere fornite nel costruttore. Non sono afferrati dalla classe. Non sono impostati in quanto la classe è "inizializzata". Li passi nel costruttore della classe in modo che la classe li possa scoiattolare come stato privato o come stato immutabile pubblico.

Per le classi che sono solo dati (colori, punti, testo, rettangoli) basta impostare il loro stato nel costruttore e lasciarlo essere. Se hanno bisogno di essere cambiati, creane uno nuovo.

Per le classi che sono in gran parte funzionalità, concentrati sulla funzionalità. Se hanno bisogno di uno stato privato, così sia. La funzionalità da sola non dovrebbe in gran parte richiedere lo stato pubblico. Le funzioni sono di gran lunga migliori quando sono pure e prendono le loro dipendenze come parametri (o dallo stato della classe privata o dello stato della classe immutabile).

Per le classi che sono cose che cambiano davvero nel tempo (dove il warlock è sulla mappa, quanti soldi ci sono nel tuo conto in banca), allora vai avanti e crea quelle classi mutevoli. Ma cerca di tenerli "stupidi". Le classi mutevoli sono le migliori quando sono come le collezioni. Puoi manipolarli e renderlo più facile, ma logic non dovrebbe essere lì a meno che non sia bruciato nella logica che garantito sia parte di ogni forma di quella classe.

La cosa fondamentale da notare è che le classi sono immutabili o non lo sono. Non c'è "meno" immutabile che ti procuri dei benefici.

    
risposta data 21.02.2015 - 16:38
fonte
3

Una buona cosa da fare è guardare la maggior parte delle lingue 'String class. Le stringhe in qualsiasi lingua a cui riesco a pensare sono immutabili, ma la maggior parte delle volte nessuno ha problemi a lavorare con loro. È bello pensare ai modi in cui interagisci con le stringhe e chiediti se puoi lavorare sulla tua classe allo stesso modo.

Ad esempio, se vuoi prendere una stringa e sostituire tutte le istanze di lettere maiuscole con lettere minuscole, c'è un metodo .toLower () o qualcosa di simile che restituisce un nuovo oggetto String che è una copia della vecchia stringa oggetto. La stringa originale rimane la stessa. Puoi fare cose simili con la maggior parte degli oggetti. Diciamo che hai una classe che rappresenta gli eventi per una sede. Al momento, c'è un evento di degustazione Bourbon davvero alla moda che è previsto che scenda giovedì, ma per qualsiasi motivo l'organizzatore dell'evento ha bisogno di cambiare la data dell'evento al venerdì. Sostituisci il vecchio evento con un altro che ha cambiato il campo della data da giovedì a venerdì:

bourbonTasting = bourbonTasting.replaceDate(DAYS.Friday);

Quindi è tutto bello e dandy ora! Qualunque cosa guardi la variabile "bourbonTasting" ora leggerà che è venerdì anziché giovedì.

La cosa che diventa difficile con l'immutabilità, tuttavia, è che dal momento che non hai mutato l'originale, qualsiasi altra cosa che stava memorizzando una copia del vecchio evento deve essere aggiornata. Ora immagina ci sono un sacco di calendari là fuori che hanno questo evento su di loro. Se tutti avessero un riferimento all'oggetto originale e l'oggetto originale fosse mutabile, questi calendari non avrebbero bisogno di essere aggiornati perché l'oggetto a cui puntavano avrebbe solo il nuovo valore. Ciò pone tuttavia molti problemi con la concorrenza, poiché se qualcosa sta guardando quel calendario e qualcosa sull'evento cambia a metà strada, la persona che consuma quel calendario potrebbe essere lasciata in uno stato incoerente. Questi sono gli effetti collaterali di mutare quell'oggetto.

Poiché il nostro ipotetico evento di calendario è immutabile, non dobbiamo preoccuparci di cambiare le cose da persone senza che se ne accorgano, ma quello di cui dobbiamo preoccuparci è come aggiornare tutti questi calendari. In questo caso, sarebbe opportuno che la persona "iscriva" il proprio calendario all'evento. Quando l'evento cambia, un nuovo evento può essere trasferito su quei calendari. Se anche quei calendari sono immutabili, allora dovranno essere ricreati con il nuovo evento che sostituirà anche quello vecchio. Se l'elenco degli iscritti all'evento è immutabile, è necessario creare un nuovo elenco di abbonati ogni volta che qualcuno si iscrive di nuovo.

Come puoi vedere, avere tutto essere immutabile può ripulire i problemi di concorrenza, ma può anche diventare costoso. Puoi finire per dover creare molti nuovi oggetti solo perché una piccola cosa è cambiata. La chiave per usare bene l'immutabilità è sapere quando usarla e quando no. L'oggetto evento è un dettaglio molto pubblico e averlo immutabile è probabilmente buono, in modo da non cambiare le cose da persone. L'elenco degli abbonati per l'evento può essere tenuto privato dell'evento o dell'organizzatore dell'evento, quindi potrebbe essere sensato tenerlo mutabile in modo che non si stia facendo una quantità pazzesca di ricreazione degli oggetti se si ha un evento caldo . I calendari delle persone che stanno pianificando di partecipare all'evento potrebbero andare in entrambi i modi, a seconda di cos'altro viene utilizzato per i calendari.

È una di quelle cose in cui devi essere attento a prestare attenzione sia alla creazione dell'oggetto che alle conseguenze del cambiamento e prendere una decisione razionale basata sul bilanciamento di questi due fattori. Se sarà costoso continuare a creare nuovi oggetti e non sarebbe difficile gestire chi guarda gli oggetti, potrebbe essere meglio mantenerlo mutabile. Se la chiave sta evitando effetti collaterali e / o la creazione dell'oggetto non sarà relativamente costosa, dovrebbe probabilmente essere immutabile.

Quindi, se ti imbatti in situazioni in cui hai difficoltà con l'immutabilità, prima assicurati di pensare correttamente all'immutabilità. Pensaci come String, e come agisci su quello. Se stai già lavorando in quel giusto modello mentale, allora è il momento di iniziare a chiedersi se l'immutabilità è la cosa giusta da fare. Se creare e sostituire oggetti è doloroso, forse l'immutabilità non è adatta a quel particolare caso.

    
risposta data 21.02.2015 - 19:40
fonte
2

Rendere immutabili alcuni dei tuoi oggetti è una decisione architettonica che dovrebbe essere modificata raramente in seguito, quindi non ti consiglio di iniziare a rifactoring di tutte le tue cose solo perché. Dovresti anche pensare agli svantaggi dell'immutabilità quando cambi il tuo progetto. Ad esempio, l'immutabilità può causare gravi problemi di prestazioni se è necessario ricreare migliaia di oggetti al secondo perché si desidera cambiarli.

Telastyn ha già dato una buona risposta su come rendere le cose immutabili. Il più delle volte è possibile rendere immutabile una classe mutevole se si restituisce un nuovo oggetto su ogni chiamata di metodo, ad es. come la classe String standard in Java lo fa. Ricorda solo che non dovresti usarlo alla cieca.

    
risposta data 21.02.2015 - 17:13
fonte
0

La risposta ovvia è che usi i costruttori.

class A {
public:
   A(int a, int b) : a(a), b(b) {}
private:
   int a, b;
 };

Se hai bisogno di modificare a o b -variabili, la linea di condotta corretta è creare un nuovo oggetto invece di aggiungere funzioni set_a () o set_b ().

    
risposta data 22.02.2015 - 14:22
fonte

Leggi altre domande sui tag