Funzioni di supporto statico / condiviso vs Metodi incorporati

2

Questa è una semplice domanda, ma una considerazione progettuale che mi imbattete spesso nel mio lavoro di sviluppo quotidiano. Diciamo che hai una classe che rappresenta alcuni tipi di raccolta.

Public Class ModifiedCustomerOrders
     Public Property Orders as List(Of ModifiedOrders)
End Class

All'interno di questo corso fai tutti i tipi di lavoro importante, come combinare molte diverse fonti di informazione e, alla fine, creare gli Ordini dei clienti modificati.

Ora, hai diversi processi che consumano questa classe, ognuno dei quali ha bisogno di una porzione leggermente diversa degli oggetti ModifiedCustomerOrders. Per abilitare ciò, si desidera aggiungere funzionalità di filtro. Come vai su questo? Ti:

  1. Aggiungi il filtraggio delle chiamate alla classe ModifiedCustomerOrders per poter dire:

    MyOrdersClass.RemoveCanceledOrders ()

  2. Crea una classe di strumenti "Static / Shared" che ti consente di chiamare:

    OrdersFilters.RemoveCanceledOrders (MyOrders)

  3. Crea un metodo di estensione per ottenere lo stesso risultato del # 2 ma con meno digitando:

    MyOrders.RemoveCanceledOrders ()

  4. Crea un metodo di "Servizio" che gestisca l'acquisizione degli Ordini come appropriato per la funzione chiamante, mentre usi uno degli approcci precedenti "sotto il cofano".

    OrdersService.GetOrdersForProcessA ()

  5. Altro?

Tendo a preferire gli approcci al metodo degli strumenti / estensioni in quanto rendono il test un po 'più semplice. Sebbene io dipenda di iniettare tutti i miei dati di sourcing in ModifiedCustomerOrders, averlo come parte della classe rende un po 'più complicato da testare. In genere, scelgo di utilizzare i metodi di estensione in cui eseguo trasformazioni / filtri senza parametri. Man mano che diventano più complessi, lo sposterò invece in una classe statica.

Pensieri su questo approccio? Come ti avvicineresti?

    
posta Nathan 07.07.2011 - 16:07
fonte

2 risposte

1

Penso che il problema per me con questa domanda sia come incapsulare i dati per cominciare. È lì che vorrei iniziare a fare il refactoring per cercare di creare un design che abbia un po 'più senso (e che quindi potrebbe rendere la risposta alla soluzione più ovvia, o eliminare la domanda a titolo definitivo).

Esempio: non avrei mai una classe o una raccolta chiamata "ModifiedCustomerOrders". Mi occuperei di cose come clienti, ordini e shoppingart. Direi fin dall'inizio che un Ordine può trovarsi in uno dei tanti "stati" in un dato momento. Questa è la natura dei dati in qualsiasi dominio: può cambiare stato. Non abbiamo bisogno di collezioni o classi speciali per rappresentare quegli stati, possiamo solo chiedere l'oggetto stesso.

Un Ordine, per esempio, può essere in uno stato di "In sospeso", o "Completo", o "Annullato", o "Spedito", ecc. Vuoi classi / collezioni per tutti questi stati diversi? No, non proprio. Quello che è preferibile è fornire un modo per chiedere a un Ordine in che stato è. È un problema aziendale per un Ordine.

Se un ordine è "Modificato" - che di nuovo è una domanda, dovresti semplicemente essere in grado di chiedere un Ordine.

if(Order.IsModified)...

Quindi ora arriviamo alla domanda principale: di chi è la responsabilità di RemoveCancelledOrders ()?

Questo è il contesto in cui contano. Perché stiamo rimuovendo gli ordini annullati? E da cosa? Perché abbiamo l'ordine (s) (plurale) per cominciare? Perché stiamo aggregando una serie di ordini in "stati" potenzialmente diversi insieme in una raccolta? Di cosa hanno bisogno le aziende? E se stiamo aggregando tutti questi ordini insieme, allora cosa li trattiene e da cosa li rimuoviamo? Un carrello della spesa? È così che li stiamo aggregando? Ciò non ha molto senso, perché un carrello della spesa dovrebbe trattare solo un ordine alla volta.

So che questo non risponde direttamente alla domanda (quale approccio scegliere per affrontare il codice che effettivamente lo fa), ma questo è un aspetto importante della progettazione di un sistema. La soluzione corretta dipende dal contesto. Progettare il sistema in un modo specifico potrebbe eliminare la necessità di porre questa domanda a tutti.

Lo so per me, quando sto progettando un dominio, preferisco che gli aggregati di root manipolino il contenuto delle loro raccolte figlio. Il lavoro di aggiunta o rimozione di un OrderItem ao da un Ordine, ad esempio, è in realtà il compito dell'Ordine, in modo che la logica aziendale possa essere eseguita quando l'operazione viene eseguita.

Rimozione di un oggetto figlio da una raccolta è qualcosa che vorrei normalmente fare un oggetto genitore. Oppure un UnitOfWork ...

    
risposta data 07.07.2011 - 23:41
fonte
0

Vorrei che l'utente di quell'oggetto Data eseguisse il lavoro.

L'oggetto dati dovrebbe rimanere semplice e abbastanza generico da rendere l'intero processo più gestibile.

Se alcune classi hanno bisogno di una certa porzione dell'oggetto dati, è compito di quella classe personalizzare e manipolare tali dati. Se si attribuisce tale responsabilità nella classe dell'oggetto dati, si introduce implicitamente un accoppiamento nella direzione dell'oggetto dati nelle sue classi utente quando non è realmente necessario. Non mi sembra una buona idea.

Detto questo, ci sono casi in cui è necessario fornire operazioni personalizzate sulla classe dell'oggetto di dati. Questi sono i casi in cui puoi mettere trucchi extra e l'ottimizzazione per quella particolare operazione. Gli utenti dell'oggetto dati non avranno la possibilità di farlo poiché non hanno accesso alla struttura interna dell'oggetto dati.

    
risposta data 05.06.2014 - 05:32
fonte

Leggi altre domande sui tag