Come rifattorizzare un metodo che infrange il principio "La legge di Demetra"?

4

Spesso mi trovo a rompere questo principio (non intenzialmente, solo attraverso un cattivo design). Comunque recentemente ho visto un po 'di codice che non sono sicuro del miglior approccio.

Ho un numero di classi. Per semplicità ho eliminato la maggior parte dei metodi delle classi ecc.

public class  Paddock
{
    public SoilType Soil { get; private set; }

    // a whole bunch of other properties around paddock information
}

public class SoilType
{
    public SoilDrainageType Drainage { get; private set; }

    // a whole bunch of other properties around soil types
}

public class SoilDrainageType
{
    // a whole bunch of public properties that expose soil drainage values

    public double GetProportionOfDrainage(SoilType soil, double blockRatio)
    {
        // This method does a number of calculations using public properties
        // exposed off SoilType as well as the blockRatio value in some conditions
    }
}

Nel codice ho visto in un certo numero di posti chiamate così

paddock.Soil.Drainage.GetProportionOfDrainage(paddock.Soil, paddock.GetBlockRatio());

o all'interno dell'oggetto del blocco stesso nei punti in cui è

Soil.Drainage.GetProportionOfDrainage(this.Soil, this.GetBlockRatio());

Leggendo questo sembra che si rompa " The Law of Demeter " nel senso che sto concatenando queste proprietà per accedere al metodo che voglio. Quindi il mio pensiero per aggiustare questo è stato quello di creare metodi pubblici su SoilType e Paddock che contengano wrapper, ad es.

sul paddock sarebbe

public class Paddock
{
   public double GetProportionOfDrainage()
   {
      return Soil.GetProportionOfDrainage(this.GetBlockRatio());
   }
}

su SoilType sarebbe

public class SoilType
{
   public double GetProportionOfDrainage(double blockRatio)
   {
      return Drainage.GetProportionOfDrainage(this, blockRatio);
   }
}

quindi ora chiama dove sarebbe stato semplicemente

// used outside of paddock class where we can access instances of Paddock
paddock.GetProportionofDrainage()                                      

o     this.GetProportionOfDrainage (); // se usato all'interno della classe Paddock

Questa mi è sembrata una bella alternativa. Tuttavia ora ho una preoccupazione su come potrei far rispettare questo uso e impedire a chiunque altro di scrivere codice come

paddock.Soil.Drainage.GetProportionOfDrainage(paddock.Soil, paddock.GetBlockRatio());

anziché solo

paddock.GetProportionOfDrainage();

Ho bisogno che le proprietà rimangano pubbliche in questa fase poiché sono troppo radicate nell'uso in tutto il blocco di codice. Tuttavia, non voglio davvero un mix di accesso al metodo su DrainageType direttamente perché sembra che sconfigga del tutto lo scopo.

Quale sarebbe l'approccio progettuale appropriato in questa situazione? Posso fornire ulteriori informazioni come richiesto per un migliore aiuto nelle risposte.

I miei pensieri su come refactoring questo appropiato o dovrebbe è meglio lasciarlo così com'è e utilizzare il concatenamento delle proprietà per accedere al metodo come e quando richiesto?

    
posta dreza 30.06.2012 - 00:25
fonte

1 risposta

7

Mi sembra che il problema sia in parte dovuto al fatto che GetProportionOfDrainage è probabilmente il metodo sbagliato. Sembra strano che tu debba passare tutte queste informazioni in più livelli di oggetti in primo luogo. Sicuramente sarebbe meglio rendere il SoilType il punto focale per quei tipi di calcoli, chiedendo l'istanza di DrainageType solo per le informazioni su cui è esperto.

Dopo averlo fatto, devi solo affrontare le complessità dei veri paddock. Credo che non siano tutti piatti e non abbiano sempre un singolo tipo di terreno. Pertanto, l'applicazione dei coefficienti potrebbe richiedere la responsabilità del Paddock , in quanto questo è a conoscenza di tali informazioni. (Presumo che questo sia un proxy per il modello reale, sì?)

    
risposta data 30.06.2012 - 02:22
fonte

Leggi altre domande sui tag