0

Lets say I have an immutable class with a few properties, some of which can be calculated from with in the class, now, I could let the caller calculate the value of each property, or, I could let the class calculate each the properties itself.

For example, in the class below A must be defined. B & C's values can be calculated from A.

Letting the caller define the properties,

class Z
{
    public int A { get; private set; }

    public int B { get; private set; } 

    public int C { get; private set; } 



    public Z(int a, int b, int c)
    {
        A = a; // Must always be explicitly defined.
        B = b; // Explicit definition is optional.
        C = c; // Explicit definition is optional.
    }
}

Letting the class define as many properties as possible,

class Z
{
    public int A { get; private set; }

    public int B { get; private set; }

    public int C { get; private set; } 



    public Z(int a)
    {
        A = a; // Must always be explicitly defined.
        B =    // Calculation logic involving A...
        C =    // More calculation logic involving A...
    }
}

So are there any conventions stating when/where to use one method over the other (and why)?

Sam
  • 7,252
  • 16
  • 46
  • 65
  • Is the calculation logic "cheap"? Is there a way of validating values faster than computing them? – Jon Skeet May 23 '14 at 13:53
  • 1
    This seems out of focus. It depends on whose responsibility it is to calculate `b` and `c`, and when. The constructor then follows. – H H May 23 '14 at 14:01
  • @JonSkeet Yes, the calculation is relatively fast. Probably, I was just wondering if there are any extra benefits to implicitly defining them instead. – Sam May 23 '14 at 14:12
  • 1
    @Sam The question isn't about whether the properties are implicitly or explicitly defined. Your properties are identical in both cases. What you're asking is whether the computation should be done within this class or if the responsibility should be pushed to the caller. – Servy May 23 '14 at 14:16
  • @Servy Ah right, sorry, I wasn't quite sure how to explain what I meant. I'll rephrase. – Sam May 23 '14 at 14:19

3 Answers3

2

I'd say that the best way would be something like this:

class Z
{
    public int A { get; private set; }
    public int B { get {return a*a;} }
    public int C { get {return b*a;} } 



    public Z(int a)
    {      
        A = a; // Must always be explicitly defined.
    }
}

In this case you don't need setters for B and C and you have a getter for them which neatly calculates the value. You also evaluate B and C only when it is needed.

Kamil T
  • 2,232
  • 1
  • 19
  • 26
  • This doesn't explain anything about whether this class should be responsible for computing the value or not. Deferring the computation to the property getters is unrelated to the question at hand. Additionally, it means that if the values are requested more than once that the values are re-computed each time, instead of only the once if they are in the constructor. – Servy May 23 '14 at 14:14
  • If the calculation is expensive and likely to be reused, you could stash the results in a private int?. `public int B { get { if (!_b.HasValue) { _b = SomeLongFunction(A); } return _b; } }` Note that if any function in the class can change A, this would be a bad idea. – Carl Bussema May 23 '14 at 18:09
2

You should go with the second approach. It seems pretty clear in this case that computing these derived values is the responsibility of this class. By requiring the caller of the class to do the computations and provide the data to this class it allows the possibility for the class to end up in an invalid state; when it computes the values itself it is able to ensure that it is never in an invalid state.

Servy
  • 202,030
  • 26
  • 332
  • 449
1

couldnt you do the following:

class Z
{
    private int a;
    public int A { get; 
                   private set
                   {
                      a = value;
                      B = //calculation
                      C = //calculation
                   } 
                 }

    public int B { get; private set; } 
    public int C { get; private set; } 



    public Z(int a)
    {
        A = a; // Must always be explicitly defined.
    }
}
Steven Wood
  • 2,675
  • 3
  • 26
  • 51
  • In this way, you ALWAYS calculate `B` and `C` when `A` is set, even when it isn't needed. If calculation cost is high, `A` is set many, many times, and `B` and `C` is hardly ever checked, you end up with many unnecessary operations. – Kamil T May 23 '14 at 13:58
  • @KamilT The object shown here is an immutable object. `A` is only ever set on construction, and B and C can be read any number of times. So unless there are high odds that they will *never* be read, this is preferable. Of course, the ideal solution is to defer computation of the value and then cache it. – Servy May 23 '14 at 14:09