Hacker News new | past | comments | ask | show | jobs | submit login

"I still stubbornly believe the whole “private members accessed via accessors” thing in java is bullcrap for internal projects. It adds piles of useless boilerplate code for absolutely no gain when you can just right click a field and chose “add setter/getter” if you NEED an accessor in the future."

Is this a controversial stance? It seems like common sense, unless I'm misunderstanding something.

EDIT: To clarify: I assume he's saying "don't add accessors by default for all private members unless you need to, because you can always go back and add it if you really need it", which is common sense for any project, external or internal. I'm pretty sure he's not saying "don't add accessors, just use public members", which is controversial, IMO, even for internal projects.




Eh, using protected/private members is one of those things that makes sense only insofar as you are paranoid that you can't just access internals directly.

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.


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. Or to add locking and critical sections. Or replace a dumb get and recalculation with caching. Or replace caching with a dumb get. Or a database access.

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)


For that I prefer the ActionScript3.0 solution: methods that imitate attributes.

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.


Sure, but Java doesn't have that. =) Some of the Java.next languages (Scala among them) do, though.


> 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 ? :-)


No, I most certainly don't.


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.

http://developer.android.com/guide/practices/design/performa...


Avoid internal getters and setters. This is a different issue vs. object to object getters and setters.


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" :-)

Now back to my Java work...


> 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.


"The advantage of abstraction" is not always an advantage, which is the whole point of this whole thread.


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.


Wait... why wasn't the sprite responsible for rendering itself from the beginning?

  sprite.render(context);
or some such...


Because that's roughly the worst way to render sprites, in terms of performance :)

You want sprites to be an array, and render that in one go.


ssssshhhhhhh

(contrived example for making a point... visiting a draw() method with a solid renderer interface is the answer we usually use)


Engineering has been always about trade offs. Every time I'm raced to use reflection to get to private members, I'm reminded that these abstractions are never free.


Controversial might be too strong a word, but there is a counterargument to be made.

Suppose you have a member named "x." Someday, you might want to stop storing x, and instead make it a calculated value. At which point you'll need a method. Or, when setting x, you may someday want to increment a counter, or transform the input data, or take some other action. Again, you'll need a method.

Yes, it's very easy to add an accessor later. But then you'll most likely have to edit every line of code that accessed the now-defunct member variable. Your IDE may make this easy, but I'd still prefer not to have to do it.

That's not to say writing accessors is always the best choice. I'm just saying there can be good reasons to do it. Like all things in software engineering, there's no one-size-fits-all rule about this. Notch is right about the bloat accessors create, so you have to weight the advantages and disadvantages yourself in each case.


I think this idea is that you can use "properties" rather than public class variables.

Then you can convert your public vars into properties at a later date.

This means that you will not have to (necessarily) rewrite your code as the language knows that

a = myobj.myvar

now should call getmyvar() in the containing class and:

myob.myvar = a

should call setmyvar(a) , I know that C# certainly allows this.


C# allows it but but Java doesn't have this. Hence why it's standard operating procedure to just use setters from the beginning, because it might be nontrivial to update all references.


Play! framework allows you to use getters and setters with public members as you would in C#.

Not sure how this is implemented.


Spring Roo does the same through the use of aspect programming (code generation, essentially - it generates the boilerplate behind the scenes).


No.

C# and Objective-C (And I assume similar languages too) can have public accessors which are not used like function. No need to add ()'s everywhere.


The way current C# does accessors / properties is just about perfect, I wish more languages would adopt it.


> The way current C# does accessors / properties is just about perfect

As far as I'm concerned it's quite far from it, because C# still allows public fields, properties and fields are incompatible, properties and methods are separate and Microsoft specifies different naming conventions for fields on one hand and properties & methods on the other.

Perfection is Smalltalk's way of doing it.

And in a syntactic line closer to ALGOL, Ruby is about as good as it gets: no public fields, "properties" are normal methods (setters have a little bit of syntactic sugar, but not much) and auto-generating a bunch of getters, setters or both is a class-level method call.


What is wrong with different naming conventions for fields vs. properties, and methods? It makes it immediately obvious what is what at a glance.

*Honest question - I first learned programming with C#, and so those conventions seem 'correct' to me.


> What is wrong with different naming conventions for fields vs. properties, and methods? It makes it immediately obvious what is what at a glance.

Which is precisely one of the problems of properties in C#, it makes fields and properties look and feel extremely different from the outside which violates the uniform access principle.

As I noted, ideally C# should not have public fields in the first place.


I should have been more clear--I was referring to Java, which seems to be what the OP was talking about.


You say "No." so defiantly, but the reality for Java - which is what everybody else was talking about in this thread and the article - the answer is quite often "Yes."


Code bloat, at least _compiled_ code bloat, tends to be less on an issue with trivial accessors in C++ since they are generally inlined, but it does add a lot ()s. For non-trivial accessors, yeah, you can inline a lot of copies of that logic.

Vector v1(v2.getX(), v2.getY(), v2.getZ()); vs Vector v1(v2.x, v2.y, v2.z);


IMHO most software 'service life' it's not long enough to justify the annoyance of the accessors.

Most software are outdated after a couple of years.

But I still think that accessors are a must if you know that the software will be immortal (like Internet banking applications)


That's a pretty brutal stance. :|

I can't say I know the average shelf life of a software component in various languages, but I can say that at least things like Java have managed to justify their use of accessors by that metric. Maybe the focus should be on writing less throwaway code than deciding whether to "invest" a few extra minutes or not on accessors.


That is an understatement. I am currently working on a code which was written at 10 years back. And that code is still running on production server.

tl;dr; Usually enterprise Java applications does have long "service life".


I think most companies have tons of legacy code that is stilly lying around and in production use. When I was at Dreamworks Animation, we were still using tools written back in the 1980s to create animated features; albeit we kept improving on it whenever it didn't fit the bill.


"""Most software are outdated after a couple of years."""

You'd be surprised. Tons of code runs in production, even in the latest of shiny systems, that was written 10 and 20 and 30 years ago -- either in whole or in parts, refactored etc.

From 1986's NeXT OS that is now OS X Lion and iOS 5, to Bill Joy's TCP/IP, to Emacs.

And tons of enterprise/banking/financial/military systems use ancient code, even 70's COBOL...


Gosu supports a property syntax that lets you use = to assign things to get/set method pairs. In fact, when you load existing Java code, it replaces getFoo() and setFoo(foo) methods with a property.

This makes the code neater and enforces the abstraction--the user of the property does not need to know whether you've implemented it as a simple variable or a complicated method.

A bunch of other language let you do this as well.



A lot of languages have constructs that allow changing an attribute into a method call transparently (@property in python and D)


"""Yes, it's very easy to add an accessor later. But then you'll most likely have to edit every line of code that accessed the now-defunct member variable. Your IDE may make this easy, but I'd still prefer not to have to do it."""

Easy is an understatement. It's 2-3 clicks away in Eclipse.


The getter/setter stuff in java is a huge waste of space and time. However, at least in the enterprise space, all of the tooling and frameworks assume your code follows the java bean naming conventions. For this reason alone I always make sure all my classes follow the pattern and whenever I train new developers I make sure they get a large amount of experience building out bean definitions and understand how much time is saved with Spring and Hibernate as long as the conventions are followed.

But yeah, its a bunch of ridicules, generated spam.


Joshua Bloch in Effective Java argues that the java bean is an anti-pattern and should be avoided.


Oh thank God somebody in authority is calling this bean bull_hit what it is.

After reading the Eiffel book and thinking about things like programming by contract and class invariants, the bean pattern which constructs empty, initially useless (or at least unreliable) objects seemed like a huge step back.


Cool story, bro.

(Mime aside, do we get to hear what the argument was?)


The crux of the argument (and most of the book for that matter) is that you want to avoid mutability whenever possible. Adding setters for every field by default means mutability is the default mode for your application. Adding getters for every field by default means you lose any advantages of encapsulation. At one time, Java Beans were a heavily marketed pattern by Sun. Joshua Bloch came along and said "hey, this is a bad pattern" (and maybe others, but he's the one I always think of).


Why does everything have a getter/setter by default? That is a pretty horrible anti-pattern, is it something to do with being able to serialise the state (including internal state) of the whole object?


It's about hiding implementation. If you access an object only through methods then the implementation can change without the client code having to know or care (aka be recompiled)


The problem is when those getters and setters have other effects (maybe invalidating a cache?). In Java, it's considered best to just go ahead and add the getters and setters first, so that when you need to add these side effects later you don't have to modify lots of code using your library (if that is even possible). Languages like Python make this unnecessary since they have first class properties:

  # Old
  class Foo(object):
      def __init__(self):
          self.x = 0
  foo = Foo()
  foo.x = 1

  # New
  class Foo(object):
      def __init__(self):
          self.__x = 0
      @property
      def x(self):
          return self.__x
      @x.setter
      def x(self, val):
          self.__x = val
          do_other_stuff()


"In Java, it's considered best to just go ahead and add the getters and setters first"

I don't think this is true. I'll concede that it may be a requirement for certain things like an ORM API, but in the general case, it's bad practice. The mere act of adding a getter violates immutability.


> The mere act of adding a getter violates immutability.

Uh what? No it does not. Writing stupid getters (or classes) might, but writing getters does not "violate immutability".

Naturally, getters are not of much use if all your fields are final and hold immutable objects, but the latter can be tricky in many OO languages.

Getters significantly improve the situation there, by providing a point at which you can clone your internal state and return a copy, letting you keep your object immutable even if you have mutable fields (of course this assumes you can deeply copy all your mutable member objects)


Oops, meant to say "adding a setter violates immutability"


Bean-type setters, definitely.

On the other hand, you could have "setters" using the same naming convention which do a clone-and-replace (and return the new object), that would not violate immutability (and would be easier than building objects from scratch every time from the outside) e.g.

    Type setFoo(FooType foo) {
        return new Type(
            this.field0,
            this.field1,
            this.field2,
            foo, // bam
            this.field4);
    }
many functional languages have that behavior when manipulating "records".


All of your objects are immutable? Besides that's hardly an argument for having public members, being able to remove the setter or getter (or conditionally throw exceptions in them) is one of the exact reasons why you write them.

The intent of the comment you are replying to "best practice is if you would add a public member, instead add a private member and a setter & getter" which is generally correct.


Yep, I think I misread his comment, which was probably a misread of my original post, which I'll admit wasn't stated very clearly.


We just discussed this at our local JUG meeting last night. My take is that accessors are popular in Java because most popular frameworks (esp. Spring) have a heavy reliance on JavaBeans. Once you start using objects everywhere as JavaBeans, you've no choice but to add them. And the IDE makes it trivial. Yes, there's constructor instantiation in most DI containers, but it's not frequently used.

I do agree that most modern languages have a much more elegant solution for this.


Not that controversial in Python. GvR's attitude is use conventions, and "after all, we are all consenting adults. :)"

I found this worked very well in real life.


It's a bold stance, at least. From my experience, it's idiomatic Java and just one of those things you have to do.

In practice, it's useful because it allows more easily for instrumentation later on. And you can easily throw a "synchronized" on the method if necessary.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: