breaking encapsulation ?

Started by
9 comments, last by OrangyTang 16 years, 9 months ago
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
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.
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Only reason to have get/set functions instead of modifying the variables themselves is to make it harder to modify them by accident.
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/settersprivate:  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++.
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
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.
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]
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
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)'.
Quote:Original post by Antheus


Excellent summary.
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.

This topic is closed to new replies.

Advertisement