4 ms·
tl;dr: “Don’t use getters and setters” shouldn’t be a goal to strive for. Good OO design should be the goal, and the reduction of getters and setters (and of pu
by klmr 9y ago
tl;dr: “Don’t use getters and setters” shouldn’t be a goal to strive for. Good OO design should be the goal, and the reduction of getters and setters (and of public data members) is a consequence of that.
I fundamentally agree with the author: Getters and setters often break Tell, don’t ask, increase the public interface of a class (and expose implementation details), and add mutable state, which makes reasoning about the program’s state harder — for getters, this is often mitigated by defensive copying, which has its own set of issues (it can introduce glaring inefficiencies in the code base, which, in many cases, could have been entirely avoided).
The extreme case is when getters and setters lead to quasi-classes [1]. All this is uncontroversial when you think about it (and is backed by a vast consensus in the literature and by what little evidence we have in evidence-based software engineering). On the other hand, I agree with the author that accessors are sometimes a practical solution and shouldn’t be banned entirely.
But I don’t think the author states the case well at all. There’s too much talk about feelings, which is a poor substitute for arguments. This starts with the first example that’s provided: Contrary to what the article claims, there’s of course a difference between `Car1` and `Car2`. Namely, `Car2` can add logic to its accessors without creating introducing API changes. `Car1` cannot do this: If I for instance need to ensure that `engine` is never set to `null` by the user, or I need to add logging, or I need to add deferred loading, etc, I need to make `engine` `private` and add public accessors.
Future-proofing isn’t always relevant but it unfortunately tends to become relevant unexpectedly. Anyway, neither example is probably very good code and, conversely, either piece of code can be appropriate. But they’re emphatically not the same.
I also don’t think the “list of options” at the end is particularly useful because it seems to be a substitute for properly thinking about the architectural design of the code (which doesn’t need to happen up-front, it can happen iteratively): Many accessors are simply never necessary and were instead added “just in case”, or because the programmer thinks about objects as “bags of data” instead of, more appropriately, “[black] boxes with a specific observable behaviour”. This simple change of perspective will drastically reduce the number of public accessors in a code base; but this happens as a side-effect of better OO design, rather than a goal in itself.
[1] http://www.idinews.com/quasiClass.pdf http://www.idinews.com/quasiClass.pdf