3 ms·
Public, bare getters/setters! Hisss!!!!! To elaborate, this is one of the most common annoyances I have with Java ecosystems. In an attempt to make everything
by halosghost 11y ago
Public, bare getters/setters! Hisss!!!!!
To elaborate, this is one of the most common annoyances I have with Java ecosystems. In an attempt to make everything Objectionable (ho-ho!), coders write classes with their internal data structure marked as private but then make getters and setters (which do nothing other than set or retrieve the value) which are public.
The result is that their internal data structure is actually public (since its advertised through the getters/setters), but with the added bonus of extra function calls and member offset resolutions (i.e., it makes execution slower while single-handedly destroying the main benefit that OOP offers—backwards compatibility through isolation of the internal data structure).
While it doesn't surprise me to see new-to-OOP coders making this kind of mistake, I find it troubling that many FAQs/tutorials/classes actually advocate for these patterns.
On the bright side, the web page looks nice :)
- pimlottc 11y agoI can't imagine the minor performance penalty of calling a trivial getter makes any noticeable difference in 99.99% of cases. JIT can inline them anyhow.
- ossreality 11y agoThat's because you're wrong. Really wrong.
- lemming 11y agoTheir internal data structure is not public, since the details of how the value returned by the getter is calculated can be changed later, transparently to calling code. This is the point of encapsulation. Getters and setters can be made to access member variables in thread-safe ways, which you can't do with bare member fields. If you start with bare member fields and then suddenly realise that you need to encapsulate (for example, to obey some internal concurrency invariant) you have a major refactoring on your hands. If the clients of that code are not under your control, you're screwed. The performance impact is total FUD - the JVM eats that stuff for breakfast.
- mercurial 11y agoI agree on the performance impact. Where I think parent is right (but this is in no way unique to Java) is that it's much better to hide a class' structure as much as possible. In particular, it is important to avoid the traditional bean pattern, with an empty constructor and plenty of setters. It makes it impossible to reason about which fields are mandatory for the object, and makes it possible for the method foo(yourObject) to change the object behind your back to something which doesn't make sense. Passing all fields through the constructor and/or using a builder pattern is much preferable.
- halosghost 11y agoWell, actually, since the getters/setters advertise the type of the internal data structure, it is public. True, you could change the return type of them (which would require you to do just as much refactoring as if you changed a public internal data structure) or change the internal data structure and cast to the return type but many times that will make the getter/setter meaningless. This is all not to mention that since the setter is public, you don't have any protection of your internal data structure anyway since anyone can modify it. It's true that getters/setters offer thread-safety; I'm happy to concede that. However, the performance impact is not FUD (or at least, I did not mean it as such); ask any systems programmer and they will happily tell you that one of the most common optimizations you can make is removing function calls where they are unneeded. Another comment mentioned that the JVM can JIT this problem away through inlining; I honestly do not know if that it is true—if it is, then great; that would be a significant benefit over this same kind of formulation in, say, Cxx. Finally though, I don't really understand why Java programmers cling to backwards compatibility so when their own language shows you what happens when you commit to never removing anything to avoid breakage (i.e., you build in a huge amount of cruft). Keep in mind, none of my posts are meant to be flamey here; I was just giving my opinion of one of the patterns displayed in the FAQ that I find distressing.
- lemming 11y agosince the getters/setters advertise the type of the internal data structure No, they don't - that's the whole point. You can change the type of your internal data structure however you want, but as long as the getters and setters accept and return the same type, your contract remains the same with your clients. since the setter is public, you don't have any protection of your internal data structure anyway since anyone can modify it Of course you do. You can check invariants in your setter before applying any changes, and throw an exception if the passed value violates them. You can take a lock in your setter, to ensure that the passed information is applied in a thread-safe way. Again, this is the whole point of encapsulation. Another comment mentioned that the JVM can JIT this problem away through inlining; I honestly do not know if that it is true—if it is, then great The JVM can do this, and much much more, at runtime. Basing your optimisation advice on what a systems programmer might have told you 20 years ago is a really bad idea. All good JITs and compilers have inlined small functions for a very long time now. The JVM is particularly impressive in that it can do that for virtual calls too.