0

I wasn't sure how to formulate the title, but there's something that's made little sense to me in OOP

I understand the idea of encapsulation, which is to create a layer of protection, and abstraction, so that there's no direct access to a given variable.

However, there are cases where encapsulation doesn't make any sense to me, allow me to demonstrate using a simple C# class:

public class Person
{
    public int Age { get; private set; } // makes sense, the setter is isolated
    public string Name { get; private set; } // same story
    public string ZipCode { get; set; } // doesn't make sense
    public string Country { get; set; } // doesn't make sense either

    public string City // also makes sense
    {
        get { /*some logic that gets the city based on zip code and country */ }
        private set;
    }
}

My issue here is that, according to good OOP practices, variables without any special rules, must also have separate accessors and mutators, but why should they if all you do anyway is set and get data to and from them?

In the case of Age and Name it makes sense to encapsulate it, because the setter is private, you can't mutate it outside the scope of the class, likewise with the City field, that has a special getter, that gets the data based on special rules.

What difference does it make if I wrap ZipCode and Country in a property or not? I can fully access and mutate the variables in either case.

Could someone clarify this?

2
  • 1
    Have a look at Jon Skeet's article, it lists some important reasons why that is being done.
    – phant0m
    May 21, 2014 at 11:40
  • It's too bad this question was closed as a duplicate, since objects which encapsulate containers are often a special case. If an object is specified to do everything a bunch of fields could do (including assigning arbitrary values to fields in arbitrary order, without side-effects, and having every read request yield the last value written), I would say regard the exposure of public fields as a good way to make that expectation clear.
    – supercat
    Feb 3, 2016 at 21:22

4 Answers 4

4

You're right - there's no point in using properties when fields will do (F# uses similar techniques with Records, and you could similarly use Structs in C#). If you're worried about runtime performance though, it will never be an issue (the performance impact is negligible compared to other bottlenecks in any system).

As others have said though, encapsulation is about future flexibility and maintenance of your software. The more dependencies you have on your class, the more likely it is that it will need to change at some point. When it does change, it could break a lot of the dependencies which use it.

In general though, the reason for encapsulation is to hide your implementation. For example, you might discover after writing your initial code that it makes more sense to store your data in a dictionary (I know you wouldn't normally expect that, but a similar thing happens in WPF and other frameworks, so it just might). If you have provided Properties instead of fields, it is easy to change that implementation without breaking any of your dependencies. In face, you are then free to change anything in your class without having to worry about the dependencies on it.

If you're using Visual Studio, it usually only makes sense to use properties anyway, as the Code Snippets "prop" and "propg" do all the typing for you.

1
  • I feel like such a noob for not knowing prop and propg, but thanks for the more in-depth answer May 21, 2014 at 11:51
5

It often happens that variables with no special rules, end up with special rules. If that happens you don't want to rewrite the code another time to use setters and getters, you can do it at the beginning, and if any rules changed you can simply change the implementation of the setter/getter.

That said, I know several cases were getters/setters are not usually needed, namely vector3/4 classes in game development, they often don't have setters/getters, they don't have any rules nor they will ever have as far as they represent the mathematical vector.

Regarding any perfomance hit, it's negligible in most of the applications anyway, unless you are doing a very performance critical application such as a game or a simulation. That said; languages like C++ tend to trivially inline these functions, eliminating any function call overhead.

5
  • But doesn't it add unnecessary overhead to wrap everything that doesn't need it in methods? May 21, 2014 at 11:18
  • @ElectricCoffee No, in most of the applications anyway, unless you are doing a very performance critical application such as a game or a simulation they don't add any significant overhead, that said; languages like C++ tend to trivially inline these functions, eliminating any function call overhead.
    – concept3d
    May 21, 2014 at 11:22
  • So basically, if I know I'm not gonna add any special rules, I can just leave the property out? Or should I keep it for the sake of consistency? May 21, 2014 at 11:24
  • 1
    @ElectricCoffee I have given the vector example, it is a well known example. In other situations you might want to use a setter/getter since in any serious application new rules tend to pop up later in development. I'd say use a setter/getter.
    – concept3d
    May 21, 2014 at 11:27
  • 1
    @ElectricCoffee a good rule of thumb is to always use them, unless you're sure you won't ever need them in the future (which should be rare), AND there's a critical performance requirement (which is rare in many environments). Software engineering considerations generally trump (premature?) optimisation, until proven otherwise.
    – Daniel B
    May 21, 2014 at 13:32
2

(Code examples are in Java since I'm not familiar with C#).

Another point I'd like to mention, is that sometimes the implementation of how you store the data changes. And when that happens, you don't want the client code to break.

For example, you might store data in an array. With no encapsulation, the code that needs this data would access the array directly. For example, class.array[8].

But what if you want to change the way the data is stored, to an ArrayList for example? All of the client code gets broken.

With encapsulation, you'd create a getter in the first place:

public int getValue(int i){
    return array[i];
}

Any classes that need to get data would do this: class.getValue(8).

And when the data structure changes from an array to an ArrayList, you only have change the getter, without breaking all of the client code:

public int getValue(int i){
    return list.get(i);
}

All of the client code stays the same: class.getValue(8).

This is an example of how encapsulation gives you flexibility to change the internal implementation of a class without worrying it'll ripple and break other things.

0

The main advantage of being able to change implementation without affecting dependents was already pointed in the other answers, but I would like to point out another advantage - uniformity. There is value in having all your "data slots" being accessed the same way.

While it looks like public fields and properties in C# are accessed the same way(objectReference.FieldOrProperty), it's different in reflection. To get the public fields you use Type.GetFields() and to get the properties you use Type.GetProperties().

Using both types as public data slots will force reflection code to deal with both of them, which will make it more complex. Therefore many libraries that need to map data slots(e.g. ORMs, serializers) choose to only deal with properties - which are more flexible.

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