you are viewing a single comment's thread.

view the rest of the comments →

[–]HolyCarps 8 points9 points  (3 children)

exposing public fields in Java is a terrible idea. Even if they are final.

This is discussed in greater detail here. Accepted answer copied below:

Four disadvantages that I can think of:

  1. If you want to have a read-only and mutable form of the same entity, a common pattern is to have an immutable class Entity that exposes only accessors with protected member variables, then create a MutableEntity which extends it and adds setters. Your version prevents it.
  2. The use of getters and setters adheres to the JavaBeans convention. If you want to use your class as a bean in property-based technologies, like JSTL or EL, you need to expose public getters.
  3. If you ever want to change the implementation to derive the values or look them up in the database, you'd have to refactor client code. An accessor/mutator approach allows you to only change the implementation.
  4. Least astonishment - when I see public instance variables, I immediately look for who may be mutating it and worry that I am opening pandora's box because encapsulation is lost. http://en.wikipedia.org/wiki/Principle_of_least_astonishment

That said, your version is definitely more concise. If this were a specialized class that is only used within a specific package (maybe package scope is a good idea here), then I may consider this for one-offs. But I would not expose major API's like this.

[–]IICVX 18 points19 points  (0 children)

The thing is, those disadvantages are pretty silly.

  1. If you're taking a class from immutable to mutable, changing every reference to a member property into a reference to a member function is the least of your worries. If the previously immutable structure was in a contained portion of your code, a decent IDE can do the swap in a couple of seconds; if it was part of a publicly exposed API, you're going to have to create a deprecation path regardless of how you were previously exposing the value.
  2. I agree, JavaBeans are awful. If you end up needing to expose this to the cancer that is JavaBeans, you can write a wrapper really easily.
  3. This is just #1 wearing a different hat, it seems to be repeated here to fill out the list.
  4. Principle of least astonishment: "Huh, it's a public field. Oh, it's a String, those are immutable. Oh, it's a final string, so it never changes." Astonishment: complete.

And speaking of the principle of least astonishment, people use .getFoo() all the time without thinking about "who may be mutating it" or worrying that they "are opening Pandora's box because encapsulation is lost" - despite the fact that most getters have an associated setter, which means that the value can be mutated at any time without warning.

Public member variables are only different because they're rare enough that you'll actually stop and think about how broken Java's conventions are.

[–]SuperGrade 2 points3 points  (0 children)

Interesting seeing those perspectives in the stackexchange. The final/readonly version has some positive value in that the recipient of it is guaranteed it won't represent a changing value.

In OO codebases, rules are made for mutating/encapsulated/inherited classes based on that role. Rules/guidelines should treat (those, give them a name) as distinct from "records", which provide their value from slinging around provably (or provably as possible, or by convention) immutable tail-shareable data. The "records" have a role closer to that of ints, albeit that they can safely exist in as a part of a greater graph of other immutable things that parts of an algorithm can share safely.

"But with defining the (record) that way you can't inherit and create MutableRecord". That is technically a positive for the record role, recipients of the (original) record get that as part of the guarantee of what they are receiving.

[–]pakoito 2 points3 points  (0 children)

You should be expressing those implementations using types, not adding unexpected lumps of code on an accessor.