6

As a student in programming, I learned that encapsulation is one of the most important principles of object-oriented programming.

However, I only follow that principle when I feel like it suits my purpose. I sometimes leave internal class variables public if they are intended to be directly read at some time, and only use things like setters and getters when there are actual calculations (and assignments of other variables) involved in the assignment/evaluation of a variable (say, a getDegrees() of an Angle class that only stores radians internally).

If I find that some procedure done with a class involves a lot of modification of internal variables and is easily groupable into a single operation, I will put it into a function of the class rather than having the outside code call multiple smaller functions. However, I will not always enforce this in the interface by making the affected variables private instead.

Am I violating any principles by doing this? If so, how severely? The code that does this usually doesn't face outward, as I pay a lot of attention to how out-of-program input is processed.

7
  • 8
    Encapsulation isn't just getters and setters.
    – Joe Z.
    Feb 21, 2013 at 15:38
  • Having multiple smaller functions is an advantage. You don't realize it until you learn to program regularly this way.
    – Neil
    Feb 21, 2013 at 16:16
  • @Neil Having multiple smaller functions inside the class, I'd agree with you, because the one large function can refer to those multiple smaller functions. But having the outside code call multiple smaller functions when they can be logically grouped together in a single unit is asking for trouble.
    – Joe Z.
    Feb 21, 2013 at 16:18
  • For those voting to close, I think this is a different question than "Are Getters and Setters Justified?" Feb 21, 2013 at 16:24
  • @JoeZeng, you're right. But you're forgetting you can have a public single function which calls many smaller private functions within the class.
    – Neil
    Feb 21, 2013 at 16:27

3 Answers 3

11

One of the advantages of using getters and setters (or properties) rather than public fields is that the logic can change without having to change the consumer. Right now you might only need to simply read and write to/from a variable, but what about in the future?

For example, in your Angle class, what would happen if you decided that from now on you want to store the angle as degrees rather than radians? You would now need a getRadians() method that does the appropriate calculation, and all the code that accessed Angle.radians directly would need to be changed to use this new method. On the other hand, your getDegrees() method could still be used. All that would need to change is its implementation.

If you'd used both getRadians() and getDegrees() methods to begin with, this internal change (from radians to degrees) would not concern the object's consumers at all - its public contract stays the same.

One of the principles of encapsulation is that the internal representation of an object should not concern its consumers.

4

I'm working in a code base that sounds a lot like how you're programming. It's fairly awful. When you're in college (as I was recently) these principles don't make as much sense, because they're simply asserted to you. All of your assignments are going to be very small compared to real-world applications, however, and they will rarely get a chance to become complex enough to the point where they become difficult to handle.

This notion is a worrisome:

I sometimes leave internal class variables public if they are intended to be directly modified at some time

When working on small projects, it sometimes seems more convenient to let your member variables be altered by outside classes. This is almost always a bad idea. The more internal variables you allow the external program to alter, the less well you can reason about the state of your class at any given point in the program.

This kind of design is indicative of a bad object model. If you're finding that you have a class with variables that need to not only be read, but also written to frequently by other parts of the program, chances are those variables aren't logically a part of that class.

In my experience, the best kind of class to work with is one that is almost, if not totally, immutable from the outside, and only allowed to make changes to itself internally. Even better if it never changes once it's created.

Remember that not every variable needs a getter and setter. You should avoid writing either one entirely until you find out you absolutely must have them. Getters will almost always be more common than setters.

6
  • "You should avoid writing either [a getter or setter] entirely until you find out you absolutely must have them." Oh, I know this already. I rarely use either one, preferring more abstract methods (and just as you said, getters are always more common than setters).
    – Joe Z.
    Feb 21, 2013 at 15:45
  • Come to think about it, I might have lied about the "directly modified" thing. I can't think of any place in my recently written code where I actually did that. I probably meant "directly read".
    – Joe Z.
    Feb 21, 2013 at 15:50
  • @JoeZeng The idea is to keep as much stuff internal, and preferably unchangeable, as possible. It makes the program much more predictable and easy to reason with. You should give Scala a shot some time. It's a good way to learn how infrequently you actually need to have mutable state on variables.
    – KChaloux
    Feb 21, 2013 at 15:54
  • Also, I think I might have made half your answer (the one focusing on mutating internal variables) obsolete by editing the quoted part. You might want to take a look.
    – Joe Z.
    Feb 21, 2013 at 15:56
  • @Joe Zeng: the problem is: if a field is public (and not final), nothing prevents anyone from directly modifying it - including yourself in 6 months, after you've forgotten that it's only supposed to be read. Feb 21, 2013 at 15:56
0

As I have learned more about OO Development, I've realized that an object with a lot of getters and setters isn't really an object...it's more of a struct.

People like to use real world examples to illustrate especially when talking to learners. So let's use an example that everyone can understand.

When a person is conceived, he (or she) is giving certain parameters that will form his or her appearance. Height, weight, skin tone, eye color, jaw structure, etc., etc are all determined at conception via DNA. Consider conception as a person's constructor, and the mother and father's DNA as parameters to that constructor.

There are some properties about the person that can be set after construction (such as his name and birthdate -- although, that is MOSTLY determined internally), but everything else can only be observed not changed (well except through surgery but you get my drift). Changes to a person's height occur internally...no one says "Michael, grow two inches" my body determine how much I grow based on the inputs is give it (food, rest, whether or not I smoke, and of course my DNA).

Complex objects in an application should be like this model of a human. We provide some parameters at construction. We can perform operations on it (or even it performs operations on itself), and observe the results of our input and its interaction with the rest of the system. But its core data should be immutable to the outside.

Even simple objects that have data and little logic should be immutable because they represent values. For example look at a string in C# once you initialize it, you can't change that copy of the string the same with Dates. Data sent between objects should be immutable or a copy of the original (C# supports this natively via Structs which are passed by value versus Classes which are held by reference).

1
  • The times when I actually expose those public variables is when I want the class to have struct-like behaviour when it comes to those variables.
    – Joe Z.
    Feb 21, 2013 at 18:40

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