Utilizzo di SRP con Object Thinking

2

Secondo David West , Thinking degli oggetti implica l'identificazione di oggetti nel dominio del problema / business che rispecchiano oggetti del mondo reale; l'interfaccia rifletterebbe quindi i comportamenti di quell'oggetto.

Cosa succederebbe se avessimo una classe oggetto con molto di comportamenti diversi. In che modo non violerebbe il principio di responsabilità singola ?

Ad esempio, prendi una classe OrderBatch con la seguente interfaccia:

public class OrderBatch{

    public Customer getCustomer(){...};

    public void addOrder(){...}

    public void removeOrder(Order order){...}

    public List<Order> getOrders(){...}

    public void queueForPicking(){...}

    public void markComplete(){...}

    public void printPicklist(){...}

    public void emailPicklist(){...}        

}

Questi metodi sembrano tutti comportamenti che ti aspetteresti da un OrderBatch .

Ora immagina la suddetta interfaccia insieme a tutto il codice di implementazione necessario per fare in modo che funzioni e hai una classe di Super-Duper God.

Si tratta di una violazione di SRP ? Perché dovrebbe essere, se questi comportamenti appartengono a quell'oggetto? E se si tratta di una violazione, come la dividerei?

    
posta IntelliData 30.05.2017 - 17:40
fonte

5 risposte

0

C'è una differenza tra una cosa e cose correlate a quella cosa. Per illustrare, considera il tuo esempio:

public class OrderBatch{
    public Customer getCustomer(){...};
    public void addOrder(){...}
    public void removeOrder(Order order){...}
    public List<Order> getOrders(){...}
    public void queueForPicking(){...}
    public void markComplete(){...}
    public void printPicklist(){...}
    public void emailPicklist(){...}        
}

Perché non dovrebbe essere più simile a questo?

public class OrderBatch{
    public int CustomerID;
    public int BatchID;
    public void removeOrder(Order order){...}
    public void markComplete(){...}
}

public class CustomerRepository {
    public Customer getCustomer(int customerID);
}

public class Order {
    public void AddToBatch(int batchID)
}  

public class OrderRepository {
    public Order[] getOrdersByBatchID(int batchID)
}

public class OrderQueue {
    public void Add(OrderBatch batch)
}

public class PickList {
    public PickList(OrderBatch batch);
    public void email(string recipient);
    public void print();
}

Solo perché qualcosa è correlato a una classe non significa che la sua implementazione appartenga a quella classe. Il tuo OrderBatch potrebbe avere la sola responsabilità di archiviare tutti i dati per un gruppo di ordini (e di mantenerne l'integrità). Altre classi possono fare cose con con ordine batch.

    
risposta data 30.05.2017 - 22:09
fonte
4

Un lotto di ordini è una cosa reale. La sua responsabilità consiste nel tenere insieme un sacco di articoli dell'ordine. Ciò lo rende un'entità abbastanza complessa che richiede molte attività di gestione. Così sia. Finché hanno senso nel contesto del batch dell'ordine, va bene.

Ciò che tipicamente viene chiamato una classe di Dio è una classe che ha un comportamento e / o dati eterogenei, non tanto una che ha un gran numero di metodi e / o proprietà.

[modifica]

Guardando il tuo esempio, alcune cose vengono in mente. Non sembra giusto avere i metodi Email ... e Stampa .... Innanzitutto, l'elenco di selezione è una classe a sé stante che può avere un costruttore che accetta una raccolta di elementi che possono essere ottenuti dal batch dell'ordine. Quindi, la stampa o l'invio via email è una preoccupazione separata. Potrebbe essere necessaria una classe PickListFormatter che prepara gli elenchi di selezione per scopi di presentazione.

OrderBatch potrebbe essere un brutto nome, forse è davvero un ProductionBatch. Chiedi qual è lo scopo della classe batch (cosa hanno in comune gli ordini?) E avere quello espresso nel nome. Questo definirà la responsabilità. È un patto di spedizione? OrderBatch dice nient'altro che "un mucchio di ordini" che ti lascia indovinare per quale scopo, rendendo impossibile giudicare se un particolare metodo appartiene o meno. Per prima cosa devi definire la responsabilità, una volta che è chiaro, scegliere il comportamento giusto non è più così difficile.

    
risposta data 30.05.2017 - 18:07
fonte
3

"Identificare gli oggetti nel problema / nel dominio aziendale" è un'attività analisi dei requisiti , che non deve essere confusa con la progettazione dettagliata della classe tecnica. È un modo di usare le classi come uno strumento di ordinamento approssimativo per "user story" o requisiti, ma non dovrebbero essere le classi finali che si vogliono creare durante la progettazione e l'implementazione (almeno non se si preferisce ottenere un pezzo di software gestibile ).

Le classi implementate nel codice reale, tuttavia, dovrebbero seguire l'SRP. Saranno più a grana fine rispetto alle classi che si usano durante l'analisi dei requisiti e in genere a un diverso livello di astrazione.

    
risposta data 30.05.2017 - 22:33
fonte
2

What would happen if we had an object class with alot of different behaviors. How would that not violate the Single Responsibilty Principle?

Molto probabilmente.

Parliamo di più in termini di dominio stesso. Anche se non sono un esperto al momento dell'ordine di batching e di pick list order:

Un ordine batch è una raccolta di ordini, non necessariamente dallo stesso cliente, ma nella stessa fase di adempimento.

Un lotto di ordini può passare attraverso diverse transizioni. Il lotto dell'ordine può essere inizialmente non ordinato; successivamente viene stabilito un ordine di lista di selezione basato su alcuni criteri di adempimento.

And if it is a violation, how would I split it?

Potresti considerare queste astrazioni separate: (1) il batch di ordinazioni non ordinato, (2) l'elenco di prelievo ordinato basato su (3) criteri di evasione che forniscono un raggruppamento di elementi pubblicitari tra gli ordini.

I criteri di adempimento sono più probabili legati alla strutturazione del magazzino; un diverso magazzino potrebbe fornire un diverso criterio di adempimento, il che avrebbe l'effetto di ordinare diversamente l'elenco di selezione. Pertanto, i criteri di adempimento sono una responsabilità separata.

L'invio di e-mail e la stampa sono probabilmente fuori portata per uno di questi. Ognuno deve semplicemente essere attraversabile / navigabile in modo da poter enumerare gli elementi sottostanti con altri componenti che gestiscono i problemi di posta elettronica e di stampa.

Anche la creazione del lotto ordini è una responsabilità indipendente, poiché possiamo immaginare che la scelta degli ordini effettivamente raggruppati può produrre un'efficienza più o meno ottimale.

Is this a violation of the SRP?

Se dovessimo tentare tutte queste astrazioni in una singola classe sarebbe effettivamente una violazione di SRP.

Tuttavia, SRP non significa separare tutto in piccole astrazioni che poi devono essere cucite insieme dal consumatore o sono scomode e innaturali da usare. Dobbiamo bilanciare SRP con l'astrazione di qualità. L'SRP tende a sostenere la separazione, mentre l'astrazione di qualità tende a sostenere l'aggregazione. A volte, se non riusciamo a trovare un equilibrio tra separazione e raggruppamento, è perché abbiamo più concetti indipendenti che devono essere presi in esame nella loro stessa astrazione.

In questo caso particolare, abbiamo bisogno di concetti separati per un batch di ordini stesso rispetto alle strategie per raggruppare gli ordini insieme e per ordinare gli elenchi di selezione, che sono legati più al loro ambiente. Il lotto dell'ordine può passare attraverso stati e transizioni, che di per sé è una responsabilità sufficiente (e può utilizzare diverse classi) senza anche realizzare le strategie di ordinamento / raggruppamento.

    
risposta data 30.05.2017 - 18:11
fonte
0

Gestisco sempre la responsabilità dei moduli sul livello di astrazione di cui fa parte. link . Una classe e i suoi metodi hanno entrambi delle responsabilità, ma operano a diversi livelli.

Penso che sia importante mantenere sia il "gap rappresentazionale basso" sia l'SRP. Lo farei per delega / composizione / eredità. cioè l'interfaccia di OrderBatch viene mantenuta, ma l'implementazione è delegata.

    
risposta data 10.07.2017 - 13:39
fonte

Leggi altre domande sui tag