3

I was thinking about encapsulation in Java and then I thought how getters/setters break encapsulation. After I went through this , I saw many recommendations like to avoid getters/setters on fields not necessary, or some policies on how to implement them.

What I failed to understand is in-case of a MVC model, how do getters/setters break encapsulation. Incase if someone wants to take an example MVC framework, I would like to consider Spring-MVC.

So, basically, in MVC the data is manipulated generally by the business code, implementing an interface. The business code is getting orders from Controller, which is not messing with Model at all.

This way, I see that the model is nicely isolated or buried across 2 layers i.e Controller and Business. Can anyone explain me why in an MVC model as well, getters and setters break encapsulation.

I hope my question was clear. If anything is missing, kindly let me know. Thank you.

Edit

Perhaps people have not been reading but just flagging around. My question mainly deals with MVC and encapsulation rather than why getter/setters are justified. My point of focus still remains on MVC, that's why I have not accepted the answer.

  • 1
    Getters and setters don't break encapsulation (unless they don't preserve class invariants), but they massively broaden the interface of a class and thus are an invitation to increase coupling. – Sebastian Redl Sep 17 '15 at 12:15
  • @SebastianRedl But the model does not have an interface have as such... it is just serving a template as to for example how a Person object looks like, and that it contains age, height, weight, etc. – We are Borg Sep 17 '15 at 12:16
  • Describing a Person by its attributes reveals a data-oriented approach, as describing a Person by its methods reveals a behaviour-oriented approach (the one I try to do when doing OOP). – Spotted Sep 17 '15 at 12:28
  • @Spotted : Getters and setters directly manipulate the fields, which is data. I fail to understand your point though! – We are Borg Sep 17 '15 at 12:29
  • 1
    @DavidArno Try the first definition in Wikipedia. "A language mechanism for restricting access to some of the object's components." Setters that preserve invariants do that. – Sebastian Redl Sep 17 '15 at 20:25
5

Quick answer : Using getter and setter methods in the way you describe will most likely be fine. And removing them will not solve any concrete problem.

Longer answer

Remember that encapsulation is about information hiding. Formally, what you want is a data structure - your private fields - that is only ever accessed and modified via a fixed set of routines - your methods. That improves maintenance, because if you want to change the inner data-structure, you only have to go through your finite set of routines to make the update, rather than the whole program. It's easy to see the advantage :) .

The problem in get/set come when you expose implementation information. Let's take the example of exposing a database connection. Suddenly, you declared to the world that your object talks to a database. Client code will use that connection to do other stuff. 2 years later, you remove the database, it's not needed anymore. But the client code expects a connection to the old database! You can't change your object the way you want, and you have to carry around useless junk... you have exposed details you shouldn't!

In another case, though, you don't have something to hide : A Customer is an ID, a name and a phone number. Don't hide that, it's the very thing client code needs! Multiple parts of the application require this to do their job : your UI will display a formatted version to the user, your database will save and read the value, a JSON library will serialize the information to send an order to a 3rd party. This is business information. It need to be accessible to be useful. In that case, a getter - and maybe a setter - is perfectly valid.

In your case : If the getter in your business logic hides your model, it's perfectly fine. Use them. A getter-less design may not be better.

As a finishing note : people are often against getter because of something called "tell don't ask". This is a whole different issue than encapsulation. It's a design philosophy, and the benefits are less clear than with information hiding. The latter was already known in the 70s, while the former is a more recent invention. "Tell don't ask" is wonderful for some applications - event driven ones in particular. Alas, it work poorly with CRUD applications, where the whole point is to ask about information. Assuming you're outside the specific set of problems "tell don't ask" solves, use getters without any guilt. Just remember to hide your implementation.

  • Thank you for clearing that up. This is what I failed to understand, as my implementation is hidden, why are they a problem. You just cleared it. :-) – We are Borg Sep 17 '15 at 15:02
2

Its down to the fact that a getter/setter exposes the same data as a public variable would, as they're simply method call wrappers around the variable.

Once people realised that public variables were a bad idea - they could be modified externally to the object without constraint. The solution to this is to make all member variable private and introduce methods that act upon them to allow for more control and to expose an interface that made sense in terms of what the class was designed to do (ie not how it does it).

But unfortunately, the syntactic sugar of properties was introduced to fudge the distinction - so now we have methods that allow access to the variables which pretend to be part of the class interface, when they're plainly nothing more than method-equivalents of public variable access.

For an example, imagine a Person class that holds your age. You can set this in a member variable and allow a caller to set p.age = 20; if it was a public variable. Or, you could have a property and it becomes p.age_set(20); instead (effectively, I know the syntactic sugar is there to make it look like a variable assignment). Or you could have a p.Age(20); that calculates a year of birth and stores that in a variable, ignoring any age member variable.

This latter is maintaining encapsulation - the caller does not know, or care how the person object tracks your age, only that there are ways to set and fetch the data. Its the difference between designing a struct and a class (or data-driven design as opposed to behaviour-driven. The latter is far better for maintenance and system use)

  • 1
    Thanks for thinking m 20.. ;-) . ..This makes a bit more sense now. This way there is a 'policy' to set Age, based upon birth-year or so. But why would this be necessary in MVC as the Model class is already shielded behind Business and Controller layer? – We are Borg Sep 17 '15 at 12:35
  • Wouldn't there be certain cases where the properties might still be appropriate? – Panzercrisis Sep 17 '15 at 12:58
  • @WeareBorg Why separating business and model ? By doing so your model objects are no more than anemic bags of data (containing attributes). MVC was created with object thinking in mind, advocating that objects must be "living" organisms you can interact with (containing behaviour). By merging business into your model, you achieve what MVC was designed for. (otherwise it would be called MBVC, Model-Business-View-Controller :) ) – Spotted Sep 17 '15 at 13:03
  • 1
    @Spotted I am not splitting model in model and controller. I am talking about the Controller, the controller receives input and then request is processed by Business logic. – We are Borg Sep 17 '15 at 13:04
  • Your distinction between the second and third techniques is meaningless. The whole point of property procedures/getters-and-setters is that you have an entire method in which to do whatever you want, so long as your external interface is usable in a way that is similar to a member variable. There is no more need to actually use a member variable than in your p.Age(20); example, and your p.Age(20); example is just a setter in disguise. Put another way, getters and setters are the constraints to prevent misuse. – Nathan Tuggy Sep 17 '15 at 17:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.