On Wed, Jan 22, 2014 at 8:43 PM, S. Dale Morrey <[email protected]> wrote:
> Well ok I see your point. A getter and a setter would be irrelevant extra
> verbage at this point.
> Nevertheless if it were me I would make the value a const.
> The point of protecting the variable at all is to prevent anyone from
> changing it (accidently or maliciously) and instead making sure that they
> have to explcitly change it. In my mind a variable that must be read, but
> not altered is the definition of a constant.
It would probably be a good idea to make it a constant. I don't think
anyone would argue that point.
>
> This is not intended to start a flame war on Java vs C/C++ ways of doing
> things.
>
> Consider for a moment the hypothetical bit of code.
>
> if(pStart->nVersion = 2){do something new}else{do the old thing}
>
> if nVersion was defined as a constant, then this would throw a compile
> error the first time you built it. But with the current code the "do
> something new" block would ALWAYS run, and the "do the old thing" block
> would NEVER run. Thus, you might never know there was a problem until
> existing clients started breaking.
>
> Obviously the problem here is that the programmer accidently assigned 2 to
> nVersion instead of comparing it for equality.
> (Be honest, we've all had this happen more often than we care to admit).
It's so obvious that compilers these days will warn you about
assignments inside conditional expressions.
The C idiom for avoiding that (if you don't trust your compiler to
warn you, or the people who review your code, etc) is to write it like
this:
if (2 == pStart->nVersion) { ... } else { ... }
Now you've got an rvalue on the left hand side, and it's *definitely*
a compiler error when you assign instead of comparing.
I don't do it very often, though, because I think it's a bit awkward
and the compiler catches it the other way now anyway.
> Now consider, what would happen if in a later revision we wanted to change
> nVersion to a string for internal accounting purposes for instance
> "2.1.1"? As a const or var we would have to go back through and change all
> references to it so that all subsequent actions are ready for a string
> type. With a getter method we only need to make sure we have a getter that
> returns an int and nothing else would break (assuming this had been done in
> the beginning, or a 1 time change if done later on). That's the power of
> encapsulation.
A method that does nothing but get a value, combined with a method
that does nothing but set a value, together make what is semantically
equivalent (albeit less efficient) than directly reading and writing
it. C# and C++ both have ways of letting you do the refactoring you
describe without changing the syntax at the accessing sites, so
there's really no need to write a bunch of silly wrapper functions
preemptively. But that's really not a great way to do OO design; it's
not actually encapsulating anything.
The point of encapsulation is not to put a transparent layer between
attributes and access to them. The point of encapsulation is to
completely hide the implementation, and to make the object responsible
for managing its own state. An article describing what I mean in more
depth:
http://www.javaworld.com/article/2072302/core-java/more-on-getters-and-setters.html
Don't get me wrong; encapsulation and abstraction are definitely
powerful tools, and you should take advantage of them. But there are
many different ways to encapsulate and abstract, and some of them
interfere with others. I am not an OO purist, but when doing OO, you
ought to fully take advantage of the facilities it's good at rather
than just doing procedural code with a bit of modularity. So just
wrapping access with a method isn't helping; to make it OO, you'd have
to give the object responsibility for serializing its own version
rather than just making the field available to a serializer.
And to Michael: There's nothing about Java the language that makes
getters/setters required. Good object-oriented design in java looks
very similar to good object-oriented design in python, albeit
significantly more verbose. The general principles are the same,
anyway.
There's just a lot of bad Java code out there. Probably because
there's a lot of demand for Java code and a lot of money to be made
writing it. :)
--Levi
/*
PLUG: http://plug.org, #utah on irc.freenode.net
Unsubscribe: http://plug.org/mailman/options/plug
Don't fear the penguin.
*/