2012-03-09 13 views
7

Domanda"Tell, Do not Ask" sopra il dominio più oggetti

Come posso aderire al principio "Tell, Don't Ask" nello svolgimento di una funzione che coinvolge più oggetti.

Esempio - Generazione di un rapporto

Ho i seguenti oggetti (scopi illustrativi):

Automobile, Cavallo, Coniglio

Non v'è alcuna relazione tra questi oggetti , ma voglio generare un rapporto basato su questi oggetti:

createHtmlReport(Car car, Horse horse, Rabbit rabbit){ 
    Report report = new Report() 

    report.setSomeField(car.getSerialNumber()) 
    report.setAnotherField(horse.getNumberOfLegs()) 
    // ...etc  
} 

Il problema con questo metodo è che deve "estrarre" i dati da ciascun oggetto, che viola la regola "Tell, Do not Ask". Avrei preferito mantenere l'interno di ogni oggetti nascosti, e li hanno generare un rapporto per me:

car.createHtmlReport() 
horse.createHtmlReport() 
rabbit.createHtmlReport() 

... ma poi ho ottenere 3 rapporti parziali. Inoltre, non penso che un Coniglio debba sapere come generare ogni singolo rapporto di cui ho bisogno (HTML, JMS, XML, JSON ....).

Infine, mentre la generazione del rapporto mi può essere utile per accendere più elementi:

if (car.getWheels() == 4 || horse.getLegs() == 4) 
    // do something 
+0

+1 & fav per collegamento e domanda. – knownasilya

risposta

8

La relazione deve mantenere la capacità di creare la sua auto.

In questo caso, ogni oggetto IReportable deve implementare void UpdateReport(Report aReport).

Quando Report.CreateReport(List<Reportable> aList) viene invocato, si scorre la lista e ogni oggetto nella sua propria implementazione di UpdateReport invoca:

aReport.AddCar(serialNumber) 
aReport.AddHorse(horseName) 

Alla fine del CreateReport, l'oggetto report deve produrre il proprio risultato.

+1

Visitatore e regola doppia spedizione! –

+0

per essere chiari, 'Report' deve avere' AddCar' e 'AddHorse' implementati? presumo che questi nomi di metodi siano presi solo per esempio, ma sono molto fuorvianti e. in realtà, ho sprecato 10 minuti per capire che questi metodi non hanno nulla a che fare con i tipi di auto e cavalli stessi o_O –

6

L'obiettivo della regola "Dillo non chiedere" è di aiutarti a identificare le situazioni in cui la responsabilità che dovrebbe ricadere sull'oggetto dato finisce per essere implementata al di fuori di essa (cosa negativa).
Quali responsabilità possiamo vedere nel vostro caso? Quello che vedo è:

1) sapere come formattare il report (in formato XML, ASCII, HTML, ecc)
2) sapere ciò che accade su cui riferire

Prima uno, ovviamente, non appartiene con l'oggetto di dominio (Automobile, cavallo ecc.). Dove dovrebbe andare il 2)? Si potrebbe suggerire l'oggetto dominio, ma se nel proprio sistema ci sono più report diversi si finisce con l'appesantire gli oggetti con la conoscenza di diversi dettagli del report che apparirebbero e avrebbero un cattivo odore. Per non parlare del fatto che violerebbe il Principio di Responsabilità Unica: essere un Coniglio è una cosa, ma sapere quali parti delle informazioni di Coniglio dovrebbero andare sul rapporto X contro la relazione Y è un'altra. Quindi progetterei classi che incapsulino contenuti di dati che vanno su un tipo specifico di rapporto (e possibilmente eseguano calcoli necessari). Non mi preoccuperei che leggessero i dati membri di Coniglio, Cavallo o Macchina.La responsabilità che questa classe implementa è la "raccolta dei dati per un tipo specifico di rapporto" che hai deciso consapevolmente di trovarsi al di fuori dell'oggetto dominio.

1

Non so esattamente il nome di questo modello (Visitatore, Builder, ...):

public interface HorseView { 
    void showNumberOfLegs(int number); 
} 

public interface CarView { 
    void showNumberOfWheels(int number); 
    void showSerialNumber(String serialNumber); 
} 

public class Horse { 

    void show(HorseView view) { 
     view.showNumberOfLegs(this.numberOfLegs); 
    } 

} 

public class Car { 

    void show(CarView view) { 
     view.showNumberOfWheels(this.numberOfWheels); 
     view.showSerialNumber(this.serialNumber); 
    } 

} 

public class HtmlReport implements HorseView, CarView { 

    public void showNumberOfLegs(int number) { 
     ... 
    } 

    public void showNumberOfWheels(int number) { 
     ... 
    } 

    public void showSerialNumber(String serialNumber) { 
     ... 
    } 

} 

public XmlModel implements HorseView, CarView { 
    ... 
} 

public JsonModel implements HorseView, CarView { 
    ... 
} 

In questo modo è possibile avere più rappresentazioni dello stesso oggetto del dominio, senza violare "Tell non fare chiedere "principio".

Problemi correlati