12

Here are some arguments for properties and my counter-arguments:

Easier to use than writing getter and setter methods

Getter and setter method pairs are a code smell. Making it easier to write these is like making it easier to fail a math test by using a Scantron form and filling in all 'C's. Objects that contain only state, for persistence, shouldn't be using getters/setters and should be creating immutable objects at the time of persistence.

What is important to a consumer of an object is what it does, not how it does it. Its behavior is what it does; its state is how it does it. If you find yourself caring about an object's state (except for persistence, though this also breaks OO), you're simply not doing OOP and losing out on its advantages.

They give a rough indication of performance to consumers

This is something that could change in the future, for any given property. Suppose in release 1.0, accessing PropertyX simply returns a field. In release 1.5, if the field is null, PropertyX uses the Null Object pattern to create a new null object. In release 2.0, the field is getting further validated by the getter method in PropertyX.

As the property gets more and more complex, the performance indication of using a property seems less and less truthful.

They're better than public fields

This is true. But so are methods.

They represent a fundamentally different aspect of an object than a method, and all consumers of the object should care about this

Are you sure that both of the above statements are true?

They're easier to type, man

Sure, typing myObject.Length is easier than typing myObject.Length(), but couldn't that be fixed with a little syntactic sugar?


Why use methods instead of properties?

  • No performance guarantees. The API will remain truthful even if the method gets more complex. The consumer will need to profile their code if they are running in to performance issues, and not rely on word-of-API.

  • Less for the consumer to think about. Does this property have a setter? A method sure doesn't.

  • The consumer is thinking from a proper OOP mindset. As a consumer of an API, I am interested in interacting with an object's behavior. When I see properties in the API, it looks a lot like state. In fact, if the properties do too much, they shouldn't even be properties, so really, properties in an API ARE state as they appear to consumers.

  • The programmer of the API will think more deeply about methods with return values, and avoid modifying the object's state in such methods, if possible. Separation of commands from queries should be enforced wherever possible.


So I ask you, why use properties instead of methods? Most of the points on MSDN are code smells in and of themselves, and don't belong in either properties or methods.

(These thoughts came to me after thinking about CQS.)

xofz
  • 345
  • 1
  • 2
  • 10

10 Answers10

46

Why is it "methods against properties"? A method does something. A property is, well, a member of an object. They're totally different things, although two kinds of methods commonly written - getters and setters - correspond to properties. Since comparing properties with methods in general is not meaningful, I'll assume you meant to talk about getters/setters.

Getter and setter method pairs are a code smell.

Not necessarily, I'd argue, but either way this isn't a matter of getters/setters vs. properties but a matter of whether either should be used. Also note that you can e.g. leave out the setX part just like you can make read-only properties.

What is important to a consumer of an object is what it does, not how it does it. Its behavior is what it does; its state is how it does it. If you find yourself caring about an object's state (except for persistence, though this also breaks OO), you're simply not doing OOP and losing out on its advantages.

A highly questionable attitude. If the GUI wants to output data held by a DataStuffManagerImpl, it needs to get that number from it somehow (and no, cramming half of the application into the widget class is not an option).

As the property gets more and more complex, the performance indication of using a property seems less and less truthful.

[Methods have] No performance guarantees. The API will remain truthful even if the method gets more complex. The consumer will need to profile their code if they are running in to performance issues, and not rely on word-of-API.

In almost all cases, all the validation logic etc. is still effectively O(1), or otherwise negible in cost. If not, perhaps you've gone too far and it's time for a change. And a getX() method is usually treated as cheap as well!

Sure, typing myObject.Length is easier than typing myObject.Length(), but couldn't that be fixed with a little syntactic sugar?

Properties are that syntactic sugar.

Less for the consumer to think about. Does this property have a setter? A method sure doesn't.

"Is there a setter for this getter?" Same difference.

The programmer of the API will think more deeply about methods with return values, and avoid modifying the object's state in such methods, if possible. Separation of commands from queries should be enforced wherever possible.

I'm not sure what you're trying to tell us here. For properties, there's an even stronger unwritten law not to cause side effects.

19

Getter and setter method pairs are a code smell.

That is a faulty assumption and completely incorrect. Get/Set methods are a way to encapsulate a data member and are in no way a "code smell". I really hate the way some people throw around the term "code smell", but anyway...

This is something that could change in the future, for any given property. Suppose in release 1.0, accessing PropertyX simply returns a field. In release 1.5, if the field is null, PropertyX uses the Null Object pattern to create a new null object. In release 2.0, the field is getting further validated by the getter method in PropertyX.

As the property gets more and more complex, the performance indication of using a property seems less and less truthful.

Sounds like a poorly designed API, I don't see how that is the fault of property syntax.

Properties in C# were simply syntactic sugar for a very common pattern that made our lives as programmers a bit easier. However, these days, if you want to use data binding you "must" use properties, so they are now a bit more than syntactic sugar. I guess I really just don't agree with any of your points at all and I don't understand why you dislike a language feature that directly supports a common pattern.

Ed Swangren
  • 2,757
10

Your premise is wrong.

Properties are in no way a contract to performance or internal implementation or whatever.
Properties are special methods pairs, that semantically represent an attribute, if you will. And thus the only contract is, that a property behave as you would expect an attribute to behave.
If I ask for an object's color, I don't make assumtions whether it is obtained by a plain field access, or whether it is calculated just in time.
The whole point is, to have the ability to expose the behaviour of an attribute by using methods, while it is transparent to the consumer of the interface, whether you're using a field or accessors.

Having attributes (and actually hiding their implementation, as properties do opposed to fields) is a powerful declarative feature, that is the basis for having visual object inspectors and other automatic view generation, for data binding and many other useful things. And most importantly, it clearly transports this information for your fellow programmers as well.

back2dos
  • 30,140
7

The consumer is thinking from a proper OOP mindset. As a consumer of an API, I am interested in interacting with an object's behavior. When I see properties in the API, it looks a lot like state. In fact, if the properties do too much, they shouldn't even be properties, so really, properties in an API ARE state as they appear to consumers.

A property is supposed to be a state. If the underlying setter or getter code changes to add significantly to processing required to set or get the state then really it's no longer a property and you should replace it with methods. This is up to you as developer of the code.

Putting too much (how much is too much depends) code in a setter or getter is wrong, but just because it's possible is not a reason to throw out the pattern in all cases.

ChrisF
  • 38,948
  • 11
  • 127
  • 168
6

Another important reason in my book for using properties is that they can increase readability greatly.

account.setBalance(Account.getBalance()+deposit);

is plainly much less readable than

account.Balance += deposit;
apoorv020
  • 656
  • 5
  • 11
6

One thing you are missing, and I don't know if this is due to ignorance or if you're intentionally overlooking this detail, is that properties ARE methods.

When you use C#'s property syntax, the compiler quietly creates getter and setter methods with metadata that tells languages that understand properties as a first-class syntactical feature to treat them as such. That is, in fact, the syntactic sugar you're asking for. A few languages that can be run on the CLR don't completely hide this detail from you (Boo, if memory serves me, and some Lisp implementations), and you can call the getters and setters explicitly.

Properties occasionally have side-effects, like triggering change notification events (INotifyPropertyChanged, for example) or marking an instance of a class as dirty. This is where they have their real value, though creating them is a little more work (except in Boo, which has syntax-savvy macros).

Now, the broader question is whether getter and setter methods are, in fact, A Good Thing. There are clearly tradeoffs; if you have mutator methods, your code is inherently less parallelizable, because you now have to deal with thread synchronization issues. And it's quite possible that you'll risk violating the Law of Demeter using mutator methods (whether called properties or getter/setter methods; they are equivalent), because it's so darned convenient to do so.

But sometimes it's the right thing to do. Sometimes your problem is to grab data from some source, change it a little, present the updated data to the user, and save the changes. That idiom is well-served by properties. As Allen Holub's article says, just because getters and setters have problems doesn't mean you should never use them. (Parroting abstract Guruspeak considered harmful). Even when you follow the Class/Responsibilities/Collaborators approach, you still end up exposing either information or presentations of information to somebody; the point is to minimize the surface area of entanglement.

The upside of properties is that it's very easy to have another object take advantage of them. The downside of properties is that it's very easy to have another object take advantage of them, and you can't easily prevent that.

Object mutation makes sense at the controller layer, in, for example, an MVC architecture. That's your collaborator. Your view is also a collaborator, but it shouldn't directly be mutating your objects, because it has different responsibilities. Rolling presentation code into your business objects isn't necessarily the right way to avoid getters/setters either.

The equation changes a bit if you use functional, rather than pure OO, abstractions, which generally makes making copies of a "record" object with a couple of changes pretty trivial, though not free. And hey, If you're trying to get performance guarantees, properties are generally more predictable than lazy rebuilding an immutable collection.

JasonTrue
  • 9,041
4

You have almost the opposite religious viewpoint to me :)

When I moved from Delphi to Java the lack of properties was a huge affront to me. I was used to declaring a property and either pointing it directly to a private variable or writing a (protected) getter & setter then "plumbing" them to the property. This encapsulated the property and controlled how it should be accessed in a clear unambiguous way. You could have a read-only property that calculated the total when accessed and call it "Total" not "_getTotal()" or similar ballochs. It also meant that you could restrict access to properties by making them protected in the abstract base class then moving them to public or published in subclasses.

To me, properties are a more natural & expressive way of setting & getting the state of the object. Relying on unenforced coding conventions is more of a "code smell" than anything you're criticizing properties for. Also, as others have said, coming up with a badly designed use of properties and using its failings to try & dismiss the concept of properties in general is extremely bad form. It's possible that you've only seen bad use of properties & assume that's the way it is I suppose but you should do more research before becoming too dogmatic.

mcottle
  • 6,152
  • 2
  • 26
  • 27
1

One of the reasons properties were introduced in the Java Beans Framework was to allow integration with an IDE - you can drag those components to the IDE and edit the properties using property editors.

(back then they were only regular getters and setters - and were defined only by the naming convention - and this did indeed smell)

Today there are even more cases where properties are accessed and modified not through regular code - such as while debugging.

Ophir Yoktan
  • 387
  • 1
  • 11
1

One other angle -- they really came from VB. Remember, back in the dark days of the 20th century when .NET was conceived one major emphasis was it was an easy, drop-in replacement for VB so your VB programmers could just drag and drop things onto webforms. VB had properties so you needed to keep that feature for things to translate right.

Wyatt Barnett
  • 20,787
1

There are at least two purposes for properties:

  • They are conceptually identical to fields even if they're implemented differently. A getter should not change the state of the object and should have no side effects. A setter should only change the state in ways conceptually similar to modifying a field and not have other side effects.

  • They're syntactically identical to public (possibly read-only) fields. This means a public field can be changed to a property without breaking callers at the source level.

dsimcha
  • 17,284