Do you enforce the usage of them? Why would you say that they are better style than public fields?
public class Metadata {
private String id;
// ...
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// ...
}
// ...
Metadata myData = new Metadata();
myData.setId("abc");
vs.
public class Metadata {
public String id;
// ...
}
// ...
Metadata myData = new Metadata();
myData.id = "abc";
I haven't used a current version of IBM's WSAD/RAD (whatever they call it today) or IntelliJ IDEA for about 10 years. Since retiring to no more than temp, part-time freelance, I use nothing but Eclipse Classic (Java JEE version) with plugins for a few special, extra things related to UIE, PHP, and version control. However, back in my corporate days (when dinosaurs walked the Earth) the defaults for both WSAD and IntelliJ were to provide TODO auto-stubs for both getters and setters any time you declared a variable in class scope. I note those platform defaults by way of observing that the JEE aspects embedded in the assumptions of the IDEs' creators may have unduly influence developers to think of public mutators and accessors as non-optional.
I think Mark got it right. If a field/variable can, well, vary under manipulation by its parent or close relatives, but should be protected from direct manipulation by strangers, then you offer a getter. MAYBE you provide a non-operational setter to make clear to other developers that there should be no mutation allowed by external calls (I think lack of setter documents that just as well, but I don't write the coding bible for every shop).
There are cases in which public setters are entirely reasonable and correct. Make sure yours is one of those cases before creating that setter.
Bottom line, I can go either way with no strong (pun intended - <strong>strong</strong>) leaning, but I want there to be a shop-wide bible about these sorts of "standards" and lightning strikes upon heretics. At least locally, let's all be on the same page.
At work they're required, but not allowed to contain any logic. They feel pretty useless.
I think the main use cases are:
I don't think they should always be used, but sometimes the benefits apply. Some of my opinions:
X is an implementation detail that you want to encapsulate, getX and setX are not genius names. Describe the behavior, not the storage layout.()), like Python @property. Some allow one to attach functions to properties, or even to names that don't have a storage representation. Some call setters when you do x.a = 7 (Kotlin). I generally like this, though it does hide potentially expensive operations.library.get_books().add_all(my_books). The library should be responsible for validating it's collection of books.&mut self method should return nothing). I am not decided about this.So to summarize: prefer a language that has some sugar for getters/setters, try to describe behaviour instead of data, use 'getters'/'setters' to protect validity of internal state, and prefer immutability.
The getter setter logic esp in the java language originates in the bean concept to allow discoverability.
to me the question of value objects vs variable objects is very important. it's along the lines of Mark a value object should be immutable and can have public reads.
As soon as we go for variable objects I kinda differ from his point of view where a getter and setter still should only contain set and get logic to define the communication of change but the idea of having explicit validation logic in a data object .... I would rather prefer validation decorators along the lines of Design By Contract or what mark mentioned with python decorators.
Although I would rather prefer a Validator outside so I can compose the logic. This is a mental design question.
So the main problem of mutation is control of change and public means no control which also makes it harder for the compiler to reason. (depends on the language)
The problem of coupling logic to your data is as always context and polymorphism / subtyping. It's a language specific type-cohesion concepts where in one classification certain rules apply and not in the other.
Which can lead to bloat in the getters / setters. But than lets be real for a second ... it's very unlikely outside an algebraic concept that those problems arise and it really depends on the language concept.
Please do correct me if I am wrong. I can think of some cases where the previous statement isn't valid.
In PHP for example I insist on them for example because I cannot enforce scalar types on fields (yet).
Also the access for the debugger does not work on properties so the loss of 20% performance for function method call deference is a price I am willing to pay to ensure that my code:
although I hate the bloat of getters and setters they are a constraint in this particular language design.
The getter and setter problem solution in dart for example is interesting, if you don't access a property it's private as soon as you do it's public.
I think this also helps the compiler to do certain optimizations since it's based on behaviour.
In an OO approach that is about messaging, mental models and mutation a getter and setter can be perfectly reasonable. It depends heavily on the language, the concept and the goals.
Everything else would be imitation and not understanding and if you only imitate it sounds more like religion than reason :)