> Oh, and for good measure--everytime you force yourself to use an accessor, you are providing the opportunity for somebody down the line to add debug and validation code.
So add it then. Don't pre-generalize everything just in case.
What, is there some kind of run on parens in your neck of the woods? Running such a lean startup you can't afford a function invocation?
This isn't premature abstraction or architecture astronautics--this is just good practice.
If you are in a language like Java or C, your compiler should optimize away the call if it doesn't do something clever.
If you are in Ruby, this is so easy to do that it doesn't even need mentioning--you just call the variable directly and behind the scenes you have replaced the variable name to be a function doing your magic instead.
If your fingers protest at the additional "get" in your function names, go and buy yourself a real IDE.
EDIT: Parent thread added clarification worth noting here. I'm not saying you should add accessors for every protected member--that's just as bad. I mean to say you should only expose members that absolutely require it (the fewer the better, generally), and only do so through function interfaces you can hook. :)
Sigh. If I had a dollar for every "your compiler should optimize away X", I'd be retired. Should doesn't mean does.
Plus, no, often I can't afford a function invokation. Because it's yet another cache miss.
If all of those things don't matter (or you work on a large enough team that the benefits of abstraction are worth it), yes, add getters/setters everywhere. For the rest of us, we might have actual _reasons_ why we don't cargo-cult our code.
one good reason would be because setters and getters are way easier to mock out than direct access to member variable
And we all want to have code tested , don't we ? :-)
Running such a lean startup you can't afford a function invocation?
This actually isn't as wildly hypothetical a situation as one might guess. At least in the Android world, "Avoid getters and setters" is on the short list of performance suggestions.
Ok, but in the general case (Sun/Oracle JDK) I'm pretty sure that there's almost no overhead for using an accessor anymore. That wasn't true of early JDKs though.
If you are in Ruby, you don't get a choice about accessors: "@foo" and "@bar" are private member variables. You have to create accessors for them. Like you said, though, the accessor / property generation command is easy: "attr_accessor :foo, :bar"
Even if the (Java, or otherwise) IDE can generate piles of crap code, I still hate reading piles of crap code, though. Sometimes I just want a "struct" :-)
> If your fingers protest at the additional "get" in your function names, go and buy yourself a real IDE.
If you can't see how abstraction layers affect performance, go buy yourself a real education. This isn't about premature optimization, it's about not applying premature generalization.
Sometimes it immediately makes sense to add accessors. In that case I add them right away.
Sometimes there is no apparent need for accessors, so I don't add them yet. They're easy to add (you argue so vehemently yourself), why would there be a problem adding them as needed?
A blanket rule of "just add them, always" is just a crutch for mediocre developers who aren't capable or willing to actively think about what they're working on.
This smells of bucking conventional wisdom simply for its own sake. Unless you have a good reason not to follow best-practices, you're a bad programmer if you don't (this doesn't always apply if you're writing a project for yourself).
Conventional wisdom is there for a reason--it was wisdom hard fought over many iterations from people who came before. Conventional wisdom has won out against many competing ideas, a survival of the fittest of sorts. You may not always fully comprehend the reasoning for a particular 'best-practices' rule, but you're foolish not to follow it for that reason.
Adding accessors is not 'premature generalization', it's just how you write well engineered code.
Accessors are hardly a pre-generalization. I believe he was simply telling various use-cases that can be applied. Yes, software requirements change and some things don't (in practice), but you won't know precisely what will and won't need them until you ship. And even then, you may not know what will be required years from now. It seems like the rational option is to sink a second or two more time into the development in order to save potentially long and annoying refactors later. I've been using Visual Assist and I can actually get it to dump an accessor into the console faster than I can type out the full variable name (for variables name that aren't i,j,k).
On a more serious note, trivial accessors generally don't result in any more compiled code than direct field accesses, but do have the advantage of abstraction. If your development process is limited by the time it takes you type out the name of an accessor (or in my case, the first 3 letters), then you must be really productive or not do other things like documentation or testing.
Except there are cases where it will be way more pain later and no perceptible loss ahead of time. Imagine you are debugging something and you want to know where your public variable is getting set to 3. If you are using java and public members you will have to check every single call site, whereas if you have a setter you can just add a single if(x==3){} and put a breakpoint in there and you have done in 30 seconds what would have taken 30+ minutes.
Eclipse can add a breakpoint to a variable. Any time that variable is accessed or set, the breakpoint is tripped. That's less than 30 seconds, that's like 5. You literally just click to the left of the variable definition.
The point of my example is you can put a breakpoint under any complex condition, I guess I should have made it more complex something like if(someComplexCalculatedValue() == 10). Anything that can be expressed can be added as a breakpoint if you use setters, then you won't have to step through every assignment, which could be thousands in applications.
So add it then. Don't pre-generalize everything just in case.