2

I notice that web related code uses setter methods to set class fields instead of setting them directly since they are in scope. I find this to be a bit odd. Using setters is certainly safer, but if unit tests are implemented then bugs will be found. And it's not worth the extra stack call, imo.

Does any production code do this or is this just what you see in sample code online?

Edit: I have to make clear that I'm only talking about the case whereby the setter consists solely of a single assignment expression and nothing more.

8
  • I know I was taught in school to ALWAYS use the getter and setter functions, even within the class. Of course, that was 10 years ago and web apps weren't so much a thing back then. Aug 26, 2011 at 2:59
  • 1
    Using what language? In C# I very much prefer writing public int Age { get; private set; } to any other way to use getters and setters in an OOP language.
    – Job
    Aug 26, 2011 at 3:07
  • 7
    "not worth the extra stack call" - be careful of early optimization!
    – user1249
    Aug 26, 2011 at 7:54
  • 2
    Are you sure this only a performance question or isn't it also an encapsulation/abstraction one ?
    – David
    Aug 26, 2011 at 9:23
  • 1
    You're forgetting that the set() function may actually DO something, if you start poking at variables directly they may bite back. You're also forgetting that nothing is an optimization problem until it's measured and found to be a problem. Aug 27, 2011 at 18:36

6 Answers 6

6

You should follow the open/closed principle. Not using the setter means your class is not open to extension, because subclasses overriding the setter to maintain internal consistency by adding some according logic within the call will not have that logic executed and thus wind up with an inconsistent state.

As opposed to that, the argument with the extra call is virtually void.
Either the setter is overriden in a subclass, which means not using it is strictly not an option. Or the setter is not overriden, in which case any decent (JIT) optimizer will be able to inline it and thus achieve the same performance.

1
  • All good answers. The clincher is the inlining by an optimizing compiler and then this open/closed prinicple which I forgot. Thanks everyone.
    – Tom Jones
    Aug 27, 2011 at 0:55
11

Never, ever, depend on unit tests when you can not depend on them. Safety 101: Guarantee it at compile-time instead of hoping, testing, or checking for it at run-time. If you have a setter for a variable, it's for a good reason, and you should not circumvent it without an even better reason.

6
  • 3
    Sounds like you are reciting a rule or guideline. Do you have a reference of some sort? An author, textbook, etc..
    – Tom Jones
    Aug 26, 2011 at 3:03
  • 9
    @Tom Jones: It's common sense to guarantee safety at compile-time if you have the option.
    – DeadMG
    Aug 26, 2011 at 3:12
  • please dude, just give us some kind of reference.
    – Tom Jones
    Aug 26, 2011 at 3:23
  • 2
    @Tom Jones: He gave it to you: "Safety 101" ;) ... I don't think there's a particular source for this. It's really just common sense. I've seen many people say this or a corollary of it in one way or another.
    – back2dos
    Aug 26, 2011 at 9:55
  • 3
    @Tom The reasoning is trivial: the earlier a failure can be detected, the better, since no individual component is error-free. If you don’t have to rely on a unit test, don’t rely on it, since any test can be flawed. Static checking in compilers is much more heavily tested, and fails much more rarely, than your custom unit tests. Thus failing early has exactly one (primary) effect: it reduces the chance of failure (which is always nonzero). Aug 27, 2011 at 11:39
5

To the performance aspect, a modern Just In Time compiler will In-Line the setter call if it is truly just a trivial set. There's no allocation of a new method stack or any of that cost to consider. Avoiding using getters/setters isn't really a performance concern even as a micro-optimization. (yes there is a cost to perform the inline, but the question refers to webapps, where ostensibly that happens once and the server remains up indefinitely.)

So some things in favor of using the setters

1) The setter may not be just a simple set for all time. I guess this is some personal opinion, but hoping automated tests will catch any and all bugs possibly introduced by skipping a setter that later gains side effects seems naive.

2) Set methods may be instrumented at run time by other frameworks. Persistence systems and aspect oriented programming frameworks can both add additional functionality to set methods that isn't seen in the source of the class. And again, just because one isn't in use now, doesn't mean it never will be.

3) A field that is accessed via a set method is clearly externally visible and changable state, as opposed to a truly private field with no accessors that is clearly internal state. It can improve understanding if the fields that represent only internally managed state "stand out" in code for lacking set calls.

4) Fewer worries about bugs where people leave off the 'this.' and set a method scope variable instead of the instance scope variable that they hid sloppily. (It's amazing how many people have conditioned themselves to completely ignore compiler warnings, even in IDEs that highlight them.)

In favor of not using the setter

1) All I can come up with is some people may find it easier to read.

1
  • 1
    +1 for #1. Code evolves. It's just an assignment today, but tomorrow? Or two years from now? Perhaps it won't be. Aug 26, 2011 at 9:13
3

A lot of it goes back to Bertrand Meyer's book and his Uniform Access Principle, or else with the Bean standard.

If we aren't filtering or massaging the data in our getter/setters I don't see a lot of point in writing getter/setter methods. If you have 'int getX()' and you change the implementation to double, you still will lean on the compiler to find the places to change. Likewise if you want to add an edit to an old public member.

Most people follow the rule slavishly. Why don't you try breaking it sometimes and seeing what it teaches you? Think about what situations would warrant additional wrapping, and when it is wasted effort. Keep notes.

1
  • Yes, I didn't start seeing this until Java Beans came out. Also, most auto-generated code tends to use setters in this way. Personally, I've always used a setter if the method did more than a simple assignment otherwise it seems silly. Each case is different. I just wanted to make sure I didn't miss some new way of doing things.
    – Tom Jones
    Aug 26, 2011 at 3:34
2

In object oriented code, where the setters/getters of child classes can be different, you should always use them.

2

what constitutes a valid value and the accessor's implementation changes more often than you should care to manage manually.

it's highly tedious and error prone to verify all direct accesses follow the requirements set by the setter when implementations change. at that point, you realize you are validating and copying code all over that place (well, there are a lot of programmers that just trust they will not introduce a bug), which only makes the problem worse by giving you more implementations to validate manually and more chances for error. as the program evolves, it's easier and simpler to always use the setter and just move on with life.

in some cases, you will need direct access. this varies by language, but is common during initialization and destruction.

regarding performance: if the cost of function calls is a valid performance problem, you may be using the wrong tools, language, or approach. i do a lot of work in c++ -- the cost is trivial to nothing in optimized builds if well written. other languages are not as good in that regard.

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.