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.

Joe Z.
  • 667
  • 7
  • 14
  • 8
    Encapsulation isn't just getters and setters. – Joe Z. Feb 21 '13 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 '13 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 '13 at 16:18
  • For those voting to close, I think this is a different question than "Are Getters and Setters Justified?" – Michael Brown Feb 21 '13 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 '13 at 16:27
  • @Neil I believe I was referring to that concept. I'm not sure what you're implying with your comment. – Joe Z. Feb 21 '13 at 16:49
  • Even though this is a duplicated question, I find this also very helpful. Because, the way this question has been presented is somewhat different from the other (linked) question; hence the nature of the Answers also have become different. In that case, the concept has been described in different perspectives, and it has added more clarity, quality and usability/readability to the answer in both threads. So, this is also a worthy duplicate indeed! – Chathura Kulasinghe May 19 '14 at 21:35

3 Answers3

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.

Cyanfish
  • 816
  • 6
  • 9
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.

Michael Borgwardt
  • 51,037
  • 13
  • 124
  • 176
KChaloux
  • 5,773
  • 4
  • 35
  • 34
  • "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 '13 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 '13 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 '13 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 '13 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. – Michael Borgwardt Feb 21 '13 at 15:56
  • @MichaelBorgwardt I see. – Joe Z. Feb 21 '13 at 15:57
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).

Michael Brown
  • 21,684
  • 3
  • 46
  • 83
  • 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 '13 at 18:40