Is It Really That Wrong Not Using Setters and Getters

Is it really that wrong not using setters and getters?

The main problem with not using property accessors is that if you find out you ever need to change a field to a property later on – to make it a computed property in a subclass, for instance – you’ll break clients of your API. For a published library, this would be unacceptable; for an internal one, just quite a lot of work fixing things.

For private code or small apps, it could be feasible to just wing it. An IDE (or text editor) will let you generate accessor boilerplate and hide it using code folding. This arguably makes using getters and setters mechanically fairly easy.

Note that some programming languages have features to synthesise the default field+getter+setter – Ruby does it via metaprogramming, C# has auto-implemented properties. And Python sidesteps the issue completely by letting you override attribute access, letting you encapsulate the attribute in the subclass that needs it instead of having to bother with it up front. (This is the approach I like best.)

Getters and Setters are bad OO design?

Getters or setters by themselves are not bad OO design.

What is bad is coding practice which includes a getter AND a setter for EVERY single member automatically, whether that getter/setter is needed or not (coupled with making members public which should not be public) - because this basically exposes class's implementation to outside world violating the information hiding/abstraction. Sometimes this is done automatically by IDE, which means such practice is significantly more widespread than it's hoped for.

Why use getters and setters/accessors?

There are actually many good reasons to consider using accessors rather than directly exposing fields of a class - beyond just the argument of encapsulation and making future changes easier.

Here are the some of the reasons I am aware of:

  • Encapsulation of behavior associated with getting or setting the property - this allows additional functionality (like validation) to be added more easily later.
  • Hiding the internal representation of the property while exposing a property using an alternative representation.
  • Insulating your public interface from change - allowing the public interface to remain constant while the implementation changes without affecting existing consumers.
  • Controlling the lifetime and memory management (disposal) semantics of the property - particularly important in non-managed memory environments (like C++ or Objective-C).
  • Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages.
  • Improved interoperability with libraries that are designed to operate against property getter/setters - Mocking, Serialization, and WPF come to mind.
  • Allowing inheritors to change the semantics of how the property behaves and is exposed by overriding the getter/setter methods.
  • Allowing the getter/setter to be passed around as lambda expressions rather than values.
  • Getters and setters can allow different access levels - for example the get may be public, but the set could be protected.

Are getters and setters poor design? Contradictory advice seen

There is also the point of view that most of the time, using setters still breaks encapsulation by allowing you to set values that are meaningless. As a very obvious example, if you have a score counter on the game that only ever goes up, instead of

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

it should be

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

This is perhaps a bit of a facile example. What I'm trying to say is that discussing getter/setters vs public fields often obscures bigger problems with objects manipulating each others' internal state in an intimate manner and hence being too closely coupled.

The idea is to make methods that directly do things you want to do. An example would be how to set enemies' "alive" status. You might be tempted to have a setAlive(boolean alive) method. Instead you should have:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

The reason for this is that if you change the implementation that things no longer have an "alive" boolean but rather a "hit points" value, you can change that around without breaking the contract of the two methods you wrote earlier:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

Should I or should I not use getter and setter methods?

Because if the implementation of how the value is set changes (to a db), you don't have to change the callers. Another example is that you may need to do some checking on the value before setting it.

Having a method lets you intercept the setting/getting of that variable, doing it when it doesn't seem like you need it makes your code more change friendly.

Property getters

Languages like C# and recent versions of JavaScript allow you to intercept property reading and writing, so you can just use properties in languages that support it.

Object watchers

Some languages allow you to intercept the reading/setting of all JavaScript's Object.watch, or inaccessible properties with PHP's __get. This allows you to implements getters and setters but you get a performance hit because of the overhead they create for every property access. This answer talks about other problems with getters and setters. Best practice: PHP Magic Methods __set and __get

Getters and Setters are OK, but...

Just making boilerplate getters and setters is better, but is almost as bad as public properties. If anybody can change your object's state (specially with multiple properties), it won't be well encapsulated. http://cspray.github.io/2012/05/13/stop-calling-them-getters-setters.html

Should I use getters and setters in constructors?

You should not call getters and setters from the constructor.

A constructor constructs the specific class in which it is defined. It is its job to initialise the fields because - well - nothing else will.

The only way to guarantee initialising the fields is to assign them. If you call a setter there is a chance it could be overridden and it might do something else. It might call a method in a sub-class which is not initialised yet.

Calling a getter is also a bad idea if you are just getting a field from the same class. If it has been declared in the super-class you might justify it; if you need to get data from the super-class in the sub-class, you will have to call the getter (unless it is protected). If you need to communicate data from a sub-class to the super-class during construction you should pass it as a parameter. But this is a different use-case to what you are describing and the sub-class would probably not have your own field corresponding to the getter anyway.

If you have any "special" initialisation code, put that in a separate private method and call it from both the constructor and the setter separately.

Public variables bad practice vs Getters and Setters functions?

First of all, a struct is completely equivalent to a class, but with the default member access being public rather than private.

Now, in Object Oriented Programming (OOP), it's not considered good practice to have public data members (variables), because that makes all your code dependent on the internals of the class, and thus breaking a primordial principle of OOP, and that is...

Holy and Sacred Encapsulation

Encapsulation is the coding philosophy that states that a class should englobe both data and the code that manages it in a single tight entity. That is, you don't access data directy, but rather you use methods from the class to manipulate such data. This has several design advantages, such as that you'll know that no code except the one inside the class may incorporate bugs with respect to the manipulation of such information.

Now, get()ers and set()ers, otherwise known as accessors, are a complete lie! With accessors, you're tricking yourself into thinking that you're respecting encapsulation, when you're rather breaking it! It adds bloat, unnecessary verbosity, bugs, and everything but encapsulation. Instead of having a class Person with unsigned getAge() and void setAge(unsigned), have it with a unsigned getAge() and a void incrementAge() or however you want to call it.

Now, to your question's core...

"Plain old" structs

Encapsulation is not always desired. Although you should (usually) not do this on header files (again, for at least some bit of encapsulation), you may create static plain old structs that are private to a single translation unit. My recommendation is to make them even "older" than they already are, i.e...

  • All data members are public.
  • No methods.
  • No constructors (except implicit ones).
  • Inheritance is always public, and only allowed from other plain old structs.
  • I repeat, don't put them on header files!

Now, another use for plain old structs is (ironically) metaprogrammatic exporting of constexpr data and types, otherwise known as modern-hardcore-template-metaprogramming-without-having-to-type-public-everywhere, for example...

template<bool B, typename T>
struct EnableIf {};

template<typename T>
struct EnableIf<true, T> {
typedef T type;
};

template<bool B, typename T>
using SFINAE = typename EnableIf<B, T>::Type;

Why are getter and setter method important in java?

The basic "private field with public getter and setter that do nothing but return or set the field" pattern is indeed completely pointless when it comes to encapsulation, except that it gives you a chance to change it later without changing the API.

So don't use that pattern unthinkingly. Carefully consider what operations you actually need.

The real point of getters and setters is that you should only use them where they are appropriate, and that they can do more than just get and set fields.

  • You can have only a getter. Then the property is read only. This should actually be the most common case.
  • You can have only a setter, making the property configurable, but communicating that nothing else should depend on its value
  • A getter can compute a value from several fields rather than return one field.
  • A getter can make a defensive copy
  • A getter can perform an expensive fetch operation lazily and use a field to cache the value
  • A setter can do sanity checks and throw IllegalArgumentException
  • A setter can notify listeners of changes to the value
  • You can have a setter that sets multiple fields together because they belong together conceptually. This doesn't adhere to the JavaBeans specification, so don't do it if you depend on frameworks or tools that expect JavaBeans. Otherwise, it's a useful option.

All of these things are implementation details that are hidden behind the simple "getter and setter" interface. That's what encapsulation is about.

Using getter / setter inside a class - good or bad practice?

It is more common to access the field directly. The value of a setFieldName method is more obvious for programmers using your code in other classes. With the implementation details hidden, they might not realize what ranges of values are acceptable, so keeping fields private and forcing other developers to go through a setter makes sense. But inside your own class, the case for using a setter is much weaker. If you look at the source for the java API you'll find that getter / setter methods are generally not used within a class.



Related Topics



Leave a reply



Submit