Domanda di progettazione orientata agli oggetti

6

Sto usando una classe attraverso una dll a cui non ho il controllo diretto. Quindi, in effetti, sono solo un cliente di questa classe.

La classe rappresenta un modulo che può essere stampato, inviato ai client e monitorato nel sistema. Devo calcolare due tipi di date dopo le quali, se il modulo viene ricevuto, viene considerato tardivo.

Invece di calcolare semplicemente le date tardive nel metodo in cui sto già gestendo il modulo, voglio estrarre l'algoritmo per calcolare le date scadute in una classe separata in quanto è complicato e può essere soggetto a modifiche per ragioni amministrative.

Poiché non posso modificare la classe originale. Ho trovato queste possibili soluzioni:

(Per riferimento il codice è in C # 4 / .Net 4.)

A- Creare una classe FormLateDateCalculator con metodi per restituire una data tardiva per un determinato modulo.

B- Crea una classe FormLateDate che accetta un modulo nel suo costruttore e ha una proprietà per ogni tipo di data tardiva.

C- Creare due metodi di estensione nella classe Form che calcolano le date ritardate.

Mentre tutti e tre questi metodi funzionano (e sono sicuro che ce ne sono altri), mi piacerebbe sapere quale è il migliore per quanto riguarda la progettazione orientata agli oggetti e perché?

    
posta Gilles 27.01.2012 - 20:48
fonte

4 risposte

7

Vorrei usare l'approccio A e nasconderlo dietro un'interfaccia, poiché renderà l'algoritmo facilmente scambiabile dove lo si usa.

Userei solo B quando devo memorizzare / memorizzare più valori multipli creati da un singolo algoritmo. Se i costi di un calcolo sono a buon mercato e devo calcolare solo due date, rimango con A e calcoliamo le date ogni volta che è necessario. È inoltre possibile utilizzare una combinazione di A e B in cui B è il contenitore e contiene internamente l'interfaccia di strategia (A). Ma, come ho detto, creerei un contenitore del genere solo se avessi davvero a che fare con molti valori (più di 4?)

Mi asterrò dai metodi di estensione in quanto non si possono avere più implementazioni e poiché non è possibile scambiare facilmente l'algoritmo durante il runtime, che può essere o non essere un requisito un giorno, che può prevedere il futuro dopo tutto ?

Modifica:

...separate class as it is complicated and can be subject to change for administrative reasons.

Utilizza un modello di strategia. Dovrai avere la metà dei moduli calcolati con il vecchio algoritmo e l'altra metà calcolata con un nuovo algoritmo o anche peggio? È probabile che siano necessarie due o più implementazioni dell'algoritmo simultaneamente? Vuoi mantenere gli algoritmi o configurare quale usare? Se devi rispondere a una di queste domande con "sì", allora C non è più un'opzione.

L'opzione C è semplice e completa e fa totalmente il lavoro quando hai sempre bisogno di un singolo algoritmo per ogni momento.

    
risposta data 27.01.2012 - 20:56
fonte
2

Tutte le opzioni sono valide, non vedo niente di particolarmente brutto su nessuna di esse (beh, forse A a meno che non sia una classe statica ... ma che logicamente si risolva in C alla fine comunque) ma vedo C come quello che sceglierei. Ecco perché:

  1. Nel codice, avrai già un modulo, ed è davvero tutto ciò di cui avresti bisogno per scoprire se è tardi.
  2. myForm.IsLate () o myForm.IsLateOn (DateTime) è breve e perfettamente chiaro.
  3. I futuri sviluppatori vedranno questo e non dovranno chiedersi quale sia il suo scopo. La classe statica può essere denominata FormExtensions e non dovrebbe esserci confusione.
risposta data 27.01.2012 - 20:56
fonte
2

Vorrei andare con l'opzione A. Sembra che devi calcolare 2 diversi tipi di date "date scadute", con le cose soggette a modifiche, una delle quali potrebbe aggiungere un nuovo mezzo per determinare il ritardo. L'astrazione dei calcoli di ritardo in un'altra classe ti consente di utilizzare il modello di strategia per capire quando il modulo è in ritardo.

Per riferimento sul modello di strategia:

Wikipedia

DoFactory

    
risposta data 27.01.2012 - 20:57
fonte
1

Prima riassumilo.

Guarda il comportamento generale prima di saltare in un'implementazione.
Dimentica i dettagli e isola il comportamento: cosa stai cercando di fare?

Se pensi di provare a stabilire se un modulo è arrivato in ritardo, non lo stai estorcendo abbastanza. Chiediti che cosa deve fare il codice per essere in grado di identificare e gestire i moduli che arrivano in ritardo? Il codice deve 1) identificare se un modulo è in ritardo e 2) gestirlo. In altre parole, si sta tentando di 1) valutare una condizione e 2) attivare la funzionalità in base a tale valutazione.

Questa è la funzionalità che dovresti incapsulare per il riutilizzo: la prima, ma quasi certamente non l'ultima, l'implementazione è il problema specifico della data tardiva.

Questo mi parlerebbe delle seguenti cose ... Un'interfaccia che fornisce una specifica per le classi che possono valutare una condizione e attivare un metodo quando tale condizione è vera. Sono sicuro che esiste un modello per questo anche se non potrei nominarlo. Almeno una implementazione di tale interfaccia che verifica le date scadute ed esegue l'elaborazione richiesta. Una classe che rappresenta un elenco di questi, li chiamerò validatori, che ha un metodo performValidations () che prende il modulo come input e che esegue tutti i validatori su di esso.

Alcune persone diranno che dovresti semplicemente scrivere il codice per il comportamento specifico richiesto, ovvero dimenticare l'interfaccia e codificare il codice specifico della data finale in un metodo o classe da qualche parte - Dico che non appena lo fai, tu verrà chiesto di fornire un'altra cosa proprio come, o scoprirai che ci sono già molti altri requisiti che potrebbero essere gestiti allo stesso modo.

Linea inferiore: identificare e isolare i comportamenti alla base della funzionalità che si desidera fornire e fornire la funzionalità desiderata come sintomo del funzionamento di questi comportamenti.

    
risposta data 12.02.2013 - 19:28
fonte

Leggi altre domande sui tag