Your classes will likely have data members so how do you work with these data members? Should they be public? Private? Do you let other code access them directly? And what’s the difference between a field and a property? This episode will help you get and set your data members.
I recommend that you keep your data members private and to create getter and setter methods if you’re using C++ and to create properties if you’re using C#. Even if you don’t think you’ll need the methods or properties right away, they give you so much more control over how your class is used and almost all classes will eventually want this control. There’s just too many ways that outside code can misuse direct access to your class data.
And if that’s not enough of a reason, then consider the benefits of testing. Methods and properties help to reduce the exposed surface area of your class and provide well known entry points which can be better tested. Any problem found can then be fixed in one place instead of then trying to figure out where are all the other places in your code where you were working directly with the data.
Listen to the episode or read the full transcript below.
Classes allow you to combine data with methods. That doesn’t mean that your data has to be read or written directly. You have options.
Your first option is to just make the data available publicly. Let’s say we have our adventure hero class that has an integer value called health. If some other code wants to work with the hero class, it will declare a variable of type hero, give it a name, let’s say, mainHero, and then it can read and write the health value directly with mainHero.health. This is simple and direct.
If you don’t want outside code to be able to access the health value directly, then you can just make it private or protected. That’s sort of an all or nothing approach but you can do better.
Before we talk about making the design better, what’s wrong with just exposing the health value publicly? Imagine that your game has health potions that restore health and these potions come in different sizes. If some outside code has direct access to the health value, then it might try applying a large health potion that restores 100 points of health. But if your hero was only slightly injured, then letting outside code add 100 points could bring your hero far above his maximum health.
And a similar problem can happen in the other direction. If your hero is low on health with only 5 points remaining and takes 10 points of damage, this should cause your hero to die and the game end. But what if the outside code only knows to subtract 10 points and didn’t realize that it also needs to check the remaining health to see if the hero is still alive or not?
What you really need is the ability to run some of your own hero class code anytime the health value needs to change. And maybe even when the health value is read too.
If you keep the data private, then your second option is to provide methods for reading and writing the value. The methods will have access to the private data because they’re class members.
The method to read a value is called a getter and it normally requires no parameters, returns the value, and will be named after the value it returns. Many implementations are trivial and just have a single line of code that returns the private value. But you can do whatever you want including calculate the value if you have no direct value to return. You probably don’t want to change the value before returning it because most callers would find that unexpected.
The method that writes a value is called a setter and it normally requires a single parameter with the new value, returns void, and is also named after the value it changes. The implementation of this method can range from trivial to complex depending on what you want to do with the new value. At a minimum, you’ll want to verify that the new value makes sense before updating it. This keeps your class in a good state at all times. It’s also a good idea to avoid side effects. In other words, try to avoid changing other data when setting a value. This is not a hard rule or anything, just think about it and make sure it makes sense.
In case you want to allow outside code to read your data but not be able to modify it, then using this option is the only way to go because you can make your setter private so that outside code only has access to your getter.
I advise that you don’t try to have a public setter and a private getter. Being able to set a value only and not read it might seem like a secure thing to do but all it really accomplishes is to make your class harder to use.
To organize the data itself, the getter, and the setter, I tend to follow a similar pattern. Whatever pattern you use is up to you, but having a pattern will help other developers use your class because it becomes familiar.
In both C++ and C#, I like to name the private data member with a prefix of the letter m. So for the health, I’ll call this mHealth. Then it gets a little different between C++ and C#.
For C++, I like to name my getters after the value. So my health getter will just be called health. And I like to prefix my setters with the word set. So my health setter will be called setHealth.
I normally recommend that if you want to update several values at the same time, then don’t use a setter. Create a method that’s designed just for this purpose and you’ll have a more intuitive class. Make sure to name this method something different than whatever pattern you’re using for your setters so it’ll be obvious that there’s something special about the method.
It’s important to note that in C++, the getters and setters are both methods and need to be called like methods. If you design your class initially with the first option of just making your data available publicly, then later switch to getter and setter methods, then be aware that any code that makes use of your class will need to change. It used to access the data directly and now it’ll need to call methods.
While you can do the same thing in C#, you have another option and this is where C# takes a different path.
C# introduces a special concept called a property. C# calls the data member itself a field and you have the same option to make your fields public as in C++. But while changing from public fields to getter and setter methods as in C++ causes a disruption in any code using your class, in C# you can change from public fields to properties without needing to change any outside code that was using the public fields. Just remember that while the source code doesn’t need to change in that other code, it will need to be recompiled. There is a fundamental difference after all between a public field and a property.
C# properties make it seem like you are accessing a field because they don’t require the calling code to use what looks like a method. Behind the scenes though, properties really are just getter and setter methods.
I recommend that you avoid entirely the option of exposing data members publicly no matter if you’re using C++ or C#. For C++, go ahead and create your getter and setter methods. You’ll be glad you did. Even if you don’t need to do anything special in your methods, always having getter and setter methods will give your code consistency. That’s always a good thing. And for C#, go ahead and create properties. C# even gives you the ability to create a property with a special shortcut syntax that makes it about the same amount of typing anyway as exposing a public field.