This flexibility is not something you might think you need.
You might also never need to debug your own code, or check your assumptions about variables, or track who is accessing what when.
(for what it's worth, I don't use protection for data members of Plain-Old-Data types [say, messages or vectors] very often--they're too dumb to deserve this sort of extensibility or cost)
You replace
public var myAttribute:int;
with public function get myAttribute():int;
The caller uses both with the same "object.myAttribute", so you can just replace one with the other when the need arrives, without changing any other code.This allows you to use all sort of syntactic sugar ("object.myAttribute++", "+=" and other assignments), and for dynamic languages you can get and set values just from a reference to the object and the attribute's name. This last part is invaluable for animation engines.
So add it then. Don't pre-generalize everything just in case.
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. :)
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.
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.
http://developer.android.com/guide/practices/design/performa...
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" :-)
Now back to my Java work...
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.
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.
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.
sprite.render(context);
or some such...You want sprites to be an array, and render that in one go.
That said, consider the following. I've got a renderer that accepts a sprite to draw.
Version 1: I pass the sprite object to the renderer, and the renderer gets the texture contained in the sprite and draws it, scaling it according to the sprite's size and position public members.
I then decide that all of my sprites draw slightly differently (different scales/glow effects/color tint/whatever).
Version 2: I pass the renderer my sprite, it gets the size and render settings members from the sprite, and then draws it.
Oops! I now decide I want a hierarchy of sprites, so that I can add hats.
Version 3: Same as version 2, but in the draw routine now the renderer asks the sprite for its parent to calculate its position and size, and now I've got more renderer code and more sprite code. I can't just use the exposed position member of the sprite--it has context and logic behind it that must be done.
Oh wait, I have a problem in which the sprite glow might change depending on how many times its been drawn.
Version 4: The renderer now has to keep track of how many times it's drawn a sprite. My renderer is getting a bit chunky now.
Did I mention scale should change according to time but also the sprite's velocity?
Version 5: Renderer grabs these variables directly, and does all that other stuff too.
...and that now I want to let that scale be overridden by a isConstantSize flag on the sprite?
Version 6: aaaaaargh
...and that now the sprite can decide it wants to defer to a parent sprite's settings sometimes?
Version 7: what did i do to deserve this?
~
Proper encapsulation and use of accessors is clearly a sign of paranoia. That said, as your code evolves, you might find that this paranoia is completely justified. Hiding queries behind interfaces lets you future-proof them and trivially add more advanced behavior and hooks.
Even when you are working by yourself on an internal project, you are never working alone. You are also working with your future self, and that person is guaranteed to want something different from you and to make assumptions that you are not.