My question is for those developers that agree that getters/setters break encapsulation and should be avoided.
Consider Wikipedia's description of Encapsulation:
- A language mechanism for restricting direct access to some of the object's components.
- A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.
Based on this, perhaps a more useful soundbite for Encapsulation would be Implementation Hiding. Getters and Setters are generally used for accessing and mutating data (hence the more formal names for them as accessors and mutators), but not all data is necessarily part of a class' implementation, and not all of a class' implementation will necessarily be data (for example, a class may include a private method which internally modifies its state)
For example, consider a
TcpSocket class which supports reading and writing data packets via a network. Such a class may expose a pair of
set methods for configuring the socket's timeout duration - something which most programmers would reasonably assume they should be able to control. I don't think any reasonable programmer would argue that a pair of get/set methods to control these kinds of configurable parameters risks exposing the class' implementation.
- How do you display your data in a GUI if necessary without getters? I found this link, but to me it seems kind of strange for your class to be aware of components to display.
Typically I would separate the GUI away from those classes which represent core application logic and/or business logic. In general, I tend to keep a clear distinction between GUI components (i.e. the
View components which are responsible for appearance, layout, presentation of data and user interactivity) away from behavioural classes (which are responsible for an application's real functionality) as far as reasonably possible.
I prefer to use an MV* pattern (MVC/MVP/MVVM/etc.) to expose data to GUI Views using View Model classes which are composed entirely of 'plain' data fields, containing no behaviour or methods (or at least, as little behaviour as reasonably possible). Those types of classes typically don't even need getters/setters, because their purpose is to serve as simple data classes, and do not form part of any implementation detail for your business logic (so they don't break encapsulation for anything either).
With this kind of separation between GUI code and Application/Business logic, there are plenty of options for how to extract a ViewModel without polluting your Business logic classes with dozens of unnecessary
set methods; in fact, you might not even need the GUI to talk directly to your business logic at all, the GUI might just talk to a Web Service or Database to get the View data instead.
What if you designed a class where all the properties have getters for displaying, now I understand someone could call the getters and use them for calculations and behaviors other than displaying, but my point is, if you find it nessesary to provide getters for all your private variables to display, should you be rethinking your design? if so, how?
This type of design sounds to me like a symptom of insufficient separation between GUI/presentation logic and the core business or application logic. As mentioned above in the paragraph about MV* patterns, I would fundamentally rethink the design by providing a way to pull a copy of the relevant data out of the class into a separate data model, which can be pushed into the view.
One of the most important reasons for doing this is to allow the data to be freely modified by the GUI without instantly reflecting that change back into the core business logic.
On the flipside, if the GUI needs to push data back in to the business logic, then perhaps the business class needs to be able to receive a copy of that data and update itself.
On the note about working with copies of data; This could be for a whole range of reasons. For example, there may be validation steps involved, or the user might want to be able to hit a 'Cancel' or 'Undo' button to throw away their changes too. Typically I wouldn't allow a user to make changes to the state of an application until they've issued some kind of active 'Save' or 'Commit' type command (e.g. 'File -> Save', 'OK', etc.)