Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Getters and Setters should and shouldn't do [duplicate]

Possible Duplicate:
Convention question: When do you use a Getter/Setter function rather than using a Property

I've run into a lot of differing opinions on Getters and Setters lately, so I figured I should make it into it's own question.

A previous question of mine received an immediate comment (later deleted) that stated setters shouldn't have any side effects, and a SetProperty method would be a better choice.

Indeed, this seems to be Microsoft's opinion as well. However, their properties often raise events, such as Resized when a form's Width or Height property is set. OwenP also states "you shouldn't let a property throw exceptions, properties shouldn't have side effects, order shouldn't matter, and properties should return relatively quickly."

Yet Michael Stum states that exceptions should be thrown while validating data within a setter. If your setter doesn't throw an exception, how could you effectively validate data, as so many of the answers to this question suggest?

What about when you need to raise an event, like nearly all of Microsoft's Control's do? Aren't you then at the mercy of whomever subscribed to your event? If their handler performs a massive amount of information, or throws an error itself, what happens to your setter?

Finally, what about lazy loading within the getter? This too could violate the previous guidelines.

What is acceptable to place in a getter or setter, and what should be kept in only accessor methods?

Edit:

From another article in the MSDN:

The get and set methods are generally no different from other methods. They can perform any program logic, throw exceptions, be overridden, and be declared with any modifiers allowed by the programming language. Note, however, that properties can also be static. If a property is static, there are limitations on what the get and set methods can do. See your programming language reference for details.

like image 568
dlras2 Avatar asked May 25 '10 20:05

dlras2


People also ask

What are the common mistakes made when implementing getters and setters?

Following are the most common mistakes made by Java developers when implementing getters and setters in Java. The correct method is also mentioned along with each of them to know how such mistakes can be avoided. Mistake 1: Use of less restricted scope while declaring variables. 1.

What are getters and setters in Java?

Getters and Setters in Java Explained Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.

How do you write getters and setters in C++?

By convention, getters start with the word "get" and setters with the word "set", followed by a variable name. In both cases the first letter of the variable's name is capitalized:

Why do we need the getter method in JavaScript?

This is because since the getter method directly returns the reference of the internal variable data, the outside code can now obtain this reference and make changes to the internal object.


2 Answers

My view:

  1. If a setter or getter is expected to be expensive, don't make it a property, make it a method.

  2. If setting a property triggers events due to changes, this is fine. How else would you allow listeners to be notified of changes? However, you may want to offer a BeginInit/EndInit pair to suppress events until all changes are made. Normally, it is the responsibility of the event handler to return promptly, but if you really can't trust it to do so, then you may wish to signal the event in another thread.

  3. If setting a property throws exceptions on invalid values, it's also fine. This is a reasonable way to signal the problem when the value is completely wrong. In other cases, you set a bunch of properties and then call a method that uses them to do something, such as make a connection. This would allow holding off validation and error-handling until the properties are used, so the properties would not need to throw anything.

  4. Accessing a property may have side-effects so long as they aren't unexpected and don't matter. This means a JIT instantiation in a getter is fine. Likewise, setting a dirty flag for the instance whenever a change is made is just fine, as it setting a related property, such as a different format for the same value.

  5. If it does something as opposed to just accessing a value, it should be a method. Method are verbs, so creating a connection would be done by the OpenConnection() method, not a Connection property. A Connection property would be used to retrieve the connection in use, or to bind the instance to another connection.

edit - added 5, changed 2 and 3

like image 81
Steven Sudit Avatar answered Oct 03 '22 09:10

Steven Sudit


I agree with the idea that getters/settings shouldn't have side effects, but I would say that they shouldn't have non-obvious side effects.

As far as throwing exceptions, if you are setting a property to an invalid value (in a very basic sense), then validation exceptions are fine. However, if the setter is running whole series of complicated business rule validation, or trying to go off and update other objects, or any other thing that may cause an exception, then that is bad. But this problem is not really an issue with the exception itself, but rather that the setter is going off and secretly performing a lot of functionlity that the caller would not (or should not) expect.

The same with events. If a setter is throwing an event saying that "this property changed", then it's OK, because that's an obvious side effect. But if it's firing off some other custom event so cause some hidden chuck of code to execute in another part of a system, it's bad.

This is the same reason that I avoid lazy-loading in getters. Indeed, they can make things easier a lot of the time, but they can make things a more confusing some of the time, because there always ends up being convoluted logic around exactly when you want the child objects loaded. It's usually just one more line of code to explicitly load the child objects when you are populating the parent object, and it can avoid a lot of confusion about the object state. But this aspect can get very subjective, and a lot of it depends on the situation.

like image 43
Mike Mooney Avatar answered Oct 03 '22 09:10

Mike Mooney