8

Something I really have not thought about before (AS3 syntax):

private var m_obj:Object;
protected function get obj():Object
{
    return m_obj;
}

private var m_str:String;
protected function get str():String
{
    return m_str;
}

At least subclasses won't be able to set m_obj or m_str (though they could still modify m_obj).

My question: Is this just blatant overkill?


This Programmer's question: When or why should one use getters/setters for class properties instead of simply making them public properties? has been suggested as a duplicate.

That question is different because it only addresses public vs. private properties and whether a property should be wrapped with getters & setters. For my question, I'm focusing on protected variables and how inheriting classes would interact with those variables.

So the alternative implementation would be:

protected var m_obj:Object; //more accessible than a private variable with a protected getter
protected var m_str:String; //more accessible than a private variable with a protected getter

My question is similar because I am talking about using trivial protected getters to block subclasses from writing to the variables, but to allow them all other access.
In languages like AS3, this will even allow them to make any changes to mutable object variables, as long as the references themselves are not modified.

2
  • 2
    ask yourself; is it dangerous that subclasses can set it to something arbitrary if the answer is yes then it isn't overkill Commented Oct 24, 2013 at 13:15
  • 1
    I edited the question to make it more clear what I'm talking about not doing instead. Commented Oct 24, 2013 at 14:01

4 Answers 4

6

Is this just blatant overkill?

Often times it is, sometimes it's not.

Keeping m_obj in some known good state helps protect the Liskov Substitution Principle, keeping your code more resilient and higher quality. Sometimes you can trust inheritors to respect that behavior, sometimes you can't (either due to usage pattern or the subtlety of the contract it implements). Though this code/question also stumbles towards some of the reasons for "Why is Clean Code suggesting avoiding protected variables?"

2
  • Is it sometimes worth it when the subclasses could still do just about anything they want to m_obj except set it to null or another instance? Commented Oct 24, 2013 at 14:45
  • @Panzercrisis - it depends on the language. In non-memory managed languages, setting it to null/something else is a big deal.
    – Telastyn
    Commented Oct 24, 2013 at 15:22
14

Trivial protected getters have at least two practical advantages over an exposed variable:

  • For debugging, they are a perfect place to put a conditional breakpoint which triggers when “that funny value gets into your program”. It is much harder to get the same control if you access the value directly.

  • For mocking an object, if you are using this method to test descendants.

The cost of using getters is virtually zero, so there is no real reason not to use them. Is there?

10
  • Thank you. The question has been edited for clarity though. Commented Oct 24, 2013 at 14:05
  • My answer does not refer to the public or protected attribute of the getter! :-) Commented Oct 24, 2013 at 14:07
  • Oh, sorry about that. Commented Oct 24, 2013 at 14:08
  • 4
    The cost is in the code bloat. The cost is not large, but it's greater than zero. Sure, the getters are trivial, but they have to be passed over every time someone works on the class. And they can be wrong: get x() ... { return _y; } No one would ever type that, but it might happen due to an incorrect cut-and-paste. Commented Oct 24, 2013 at 19:17
  • 3
    It's a tradeoff between different costs, though. And in my experience the cost of tracking down bugs where subclasses compromise their parent class in subtle ways is huge compared to the cost of maintaining getters and setters. Commented Nov 6, 2013 at 9:53
7

No matter if you use getters or field access, any experienced reviewer will find out the issue in your design and complain that your objects expose data instead of behavior.

Note that appealing to "protected" won't help, because the purpose of inheritance is to allow subclasses adjust / tune behavior of the parent (LSP), not to justify indiscriminate messing with parent data. As Bertrand Meyer puts it,

Neither the Open-Closed principle nor redefinition in inheritance is a way to address design flaws... (The only potential exception for this rule is the case of flawed software which you are not at liberty to modify.)

"Getters are evil" reasoning applies irrespectively on whether you spell get explicitly or mask it behind the field access.

see this article or this article by Alan Holub...

You shouldn't use accessor methods (getters and setters) unless absolutely necessary because these methods expose information about how a class is implemented and as a consequence make your code harder to maintain. Sometimes get/set methods are unavoidable, but an experienced OO designer could probably eliminate 99 percent of the accessors currently in your code without much difficulty.

Getter/setter methods often make their way in code because the coder was thinking procedurally. The best way to break out of that procedural mindset is to think in terms of a conversation between objects that have well-defined responsibilities...

If you are seriously concerned about the issue, first thing to consider is redesign of the code to get rid of both getters and non-private field access, instead of playing fruitless mind games picking which way is least inappropriate.

Worth stressing once again, hiding troublesome design behind "protected" smokescreen won't make the problem go away - inheritance does not justify tricks like that. Paraphrasing your question, strive to design things in a way that avoids having inheriting classes interact with those variables at all - neither via getters nor via field access. Tell, don't ask:

Procedural code gets information then makes decisions. Object-oriented code tells objects to do things.

Spending time and effort on deciding which way to prefer to get information, against classical principle recommending to avoid this altogether, now that sounds like a blatant overkill to me.

1
  • We're from the same school. The question shouldn't be, "oh, the base class doesn't work right so how do I mess with its data," it should be, "how do I make the base class work so that I don't need to mess with its internal state?" Rarely do I implement getters. Almost never do I implement setters. The methods on my classes are commands in the vein of "Tell Don't Ask." Sometimes I feel like one of my primary work responsibilities is to fix bugs by hiding implementation details exposed by lazy or thoughtless programmers. Commented Dec 30, 2017 at 20:01
1

In the case of an immutable class implementation, making your internal variables protected would break the contract you have set, in which case the protected getters would not be overkill andnecessary (though you would have to return copies of your variable, not a pointer to it).

In mutable classes, I still prefer getters/setters to granting direct access to my internal variables. This makes sure that you can change how you handle your internal variables as you wish, without fear of breaking any client code. For instance, imagine you have a Java class as follows:

public abstract class SomeClass {
    protected int[] someVariable;

    // Rest of implementation
}

Client class extending SomeClass would then directly access someVariable, manipulating it how they see fit. Now, this can create all sorts of problems if these classes do not leave someVariable in an acceptable state. Moreover, if you decide in a subsequent release to change the definition of SomeClass to use a List<Integers> instead of an array, you will then break compatibility with the existing code base, which expect SomeClass to have an internal array of ints, not a list of ints.

Using protected getters in this case would allow you to make this change without breaking any pre-established contract.

public abstract class SomeClass {
    List<Integer> someVariable;

    protected int[] getSomeVariable () {
        // Return int[] version of someVariable
    }

    // Rest of implementation
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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