Jump to content
  • Advertisement
Sign in to follow this  
mindrot

breaking encapsulation ?

This topic is 4163 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

this is more of a justification for encasulation more than anything else ive always made all my members private and all my functions to get/set them public if you want my members use my functions i have some members in an object some members are used all the time others would be very rarely used, if ever many of these get/sets are very simple though.. just setting a new int or return a double why should i not just make these values public and more easily modified? someone told me...because its breaks encapsulation... well if thats the case its a practice that needs to die because its silly i can understand doing it this for more complicated members like other objects where it can be a multi step process... if i have the class booger and it has members int a, b; double c, d; and string e, f; should i or should i not just make these members public

Share this post


Link to post
Share on other sites
Advertisement
Generally speaking, if your class has a lot of "get" and "set" members and it is not a POD type, the data isn't where it is supposed to be anyway.

Take a look at what is calling all those "get" and "set" members, and think about whether it would be smarter to move the data into that class.

Share this post


Link to post
Share on other sites
Only reason to have get/set functions instead of modifying the variables themselves is to make it harder to modify them by accident.

Share this post


Link to post
Share on other sites
Heavily practiced in Java (somewhat less in C# due to get/set), it's a recommended technique.

Personally, I prefer to use functional approach where possible.

Let class keep its members private, but let it expose *functions*.

Consider something like this:

class Person {
public:
// A whole bunch of getters/setters
private:
std::string firstName;
std::string middleName;
std::string lastName;
int yearOfBirth;
int monthOfBirth;
int dayIfBirth;
};





Why should anyone who cares about person know about these fields? This isn't encapsulation! It's grouping, a naming convention, an obsoleted paradigm.

What do I want my class to do? I don't want it to sit there and look pretty.

What will a Person do? Let's say we want to store it to database, print it on a label, display it, and do a few more things.

How about this:
class Person {
public:
// No more getters/setters
void persist( Database *db ) {
db->insert( Person, firstName, middleName, lastName, ... );
}

std::string fullName() {
return firstName + " " + middleName + " " + lastName;
}

void print( PrinterCanvas *page )
{
page->drawText(0, 0, fullName() );
}

// for std::cout or other streams.
friend std::ostream &operator( std::ostream &os, const Person &person );
private:
std::string firstName;
std::string middleName;
std::string lastName;
int yearOfBirth;
int monthOfBirth;
int dayIfBirth;
};





Here is where encapsulation comes in. I can change internal representation of date, of name, use different structures, omit them - it doesn't change the public interface.

By using get/set for every private property, you not only don't encapsulate anything - you make a future mess, since the getters and setters will become entangled in the rest of your code.

If you're using getters and setters - might as well not. It's not encapsulation, it doesn't help anything, it merely triples the codebase.

EDIT:

A valuable read for getters/setters in C++.

Share this post


Link to post
Share on other sites
The problem is not get/set, the problem is how you are using get/set.

A few reasons for using get/set. First you can change the underlying data type and still not break anything because everything is still going through the get/set and you just change the implementation of that.

The biggest reason for get/set instead of public. One point of failure. I rarely have setters that just set the private member. I use setters to make sure the value is valid. Because everything has to go through the setter it is a great place to make sure you are going to have valid data.

theTroll

Share this post


Link to post
Share on other sites
Yeah, Java is notorious for the getter/setter mentality, and it doesn't always help. Usually I try to avoid it. If it's a compound data type, there's no real reason to add getters and setters. Those are generally only useful when you want to perform some complex operations or bound checking on the input. So I do not want incrementDate() on a Calendar class to accept negative numbers because my calendar is only meant to go forward (trivial example and maybe not too useful since you might want a calendar to go backward, but you get the idea). If it's something that operates on data, like how Antheus points out, then let the class operate on the data and not expose the data to other classes, breaking encapsulation.

Share this post


Link to post
Share on other sites
Quote:
Original post by Pzc
Only reason to have get/set functions instead of modifying the variables themselves is to make it harder to modify them by accident.


That's a decent point, however I think it's fair to note that if all a class does is hold data that is only manipulated through outside stimuli (calling a "setter") or returned unchanged (calling a "getter") that's a code smell that needs to be refactored.

Quote:
A valuable read for getters/setters in C++.


That's an interesting read... though it seems like a terribly naughty idea at first :) Then you realize the internals of the helper class are not exposed. Interesting.

Quote:
The biggest reason for get/set instead of public. One point of failure. I rarely have setters that just set the private member. I use setters to make sure the value is valid. Because everything has to go through the setter it is a great place to make sure you are going to have valid data.


Another good point.

I am finding that TDD tends to generate plenty of getters/setters which for some reason annoy me [smile]... (into refactoring).

If a setter is only used once to put your object into a good state, consider moving it into the constructor as Fowler suggests.

If you're using a getter, make sure that you're not just checking that the data is valid (which should be done inside the class), and that the returned data cannot be mutated outside the class.

EDIT: Another good article to consider

[Edited by - Verg on July 22, 2007 7:41:18 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Verg
Generally speaking, if your class has a lot of "get" and "set" members and it is not a POD type, the data isn't where it is supposed to be anyway.

Take a look at what is calling all those "get" and "set" members, and think about whether it would be smarter to move the data into that class.


Or (more likely IMX), smarter to move that functionality into the class with the accessors and mutators. (It's often repeated in a few places, too, further indicating refactoring in that direction.)

For example, if you commonly find structures like 'x.set_foo(x.get_foo() + y);', it's a strong indication that you should instead have something like 'x.increase_foo(y)'.

Share this post


Link to post
Share on other sites
Smart use of friend classes furthur protects and encapsulates your code from the client user of your library and reduces the needs for accessors/mutators.

For instance, let's say you have some values in a class that you want to keep private from the client user, but you also want some class to be able to use them. Mutators/accessors are not the best solution, because now the client can access those members using the mutators/accessors. By making a friend class, you ensure that only that friend can access those particular values and the values are still private and restricted from the client user's perspective.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!