Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I often find myself breaking this principle (not intentially, just through bad design). However recently I've seen a bit of code that I'm not sure of the best approach.

I have a number of classes. For simplicity I've taken out the bulk of the classes methods etc

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
    }
}

In the code I have seen in a number of places calls like so

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

or within the block object itself in places it's

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

Upon reading this seems to break "The Law of Demeter" in that I'm chaining together these properties to access the method I want. So my thought in order to adjust this was to create public methods on SoilType and Paddock that contains wrappers i.e.

on paddock it would be

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

on the SoilType it would be

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

so now calls where it used would be simply

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

or this.GetProportionOfDrainage(); // if used within Paddock class

This seemed like a nice alternative. However now I have a concern over how would I enforce this usage and stop anyone else from writing code such as

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

rather than just

paddock.GetProportionOfDrainage();

I need the properties to remain public at this stage as they are too ingrained in usage throughout the code block. However I don't really want a mixture of accessing the method on DrainageType directly as that seems to defeat the purpose altogether.

What would be the appropiate design approach in this situation? I can provide more information as required to better help in answers.

Is my thoughts on refactoring this even appropiate or should is it best to leave it as is and use the property chaining to access the method as and when required?

share|improve this question
    
if you can do GetProportionOfDrainage(), then you have no parameters defined for that method. However, the end of your text shows one parameter in the method definition as public double GetProportionOfDrainage(double blockRatio) . Also, no one could do this: Soil.Drainage.GetProportionOfDrainage(paddock.Soil, paddock.GetBlockRatio()) unless you have 2 parameters defined - My confusion comes from your method definition with 1 parameter. –  Emmad Kareem Jun 29 '12 at 23:16
    
@EmmadKareem I've update the question to hopefully provide more clarity. My method with one parameter (on SoilType) passes to SoilDrainageType which takes two parameters –  dreza Jun 29 '12 at 23:24

1 Answer 1

up vote 5 down vote accepted

It seems to me that the issue is in part due to the GetProportionOfDrainage being probably the wrong method. It seems strange that you're having to pass all this information in through multiple levels of object in the first place. Surely it would be better to make the SoilType the focus for those sorts of computations, with it asking the DrainageType instance for just the information it is an expert on.

Once you've done that, you just have to deal with the complexities of real paddocks. I believe they're not all flat and don't always have a single soil type. Thus, the application of the ratios might need to be the responsibility of the Paddock, as that knows about such information. (I assume that this is a proxy for the real model, yes?)

share|improve this answer
    
+1 your correct ont the paddocks and in fact not all of them need drainage calculated. So perhaps it's like you said a matter of putting it in the right place. I'll take a look at whether I can move it as you mentioned. cheers –  dreza Jun 30 '12 at 20:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.