1

I was reading an article earlier when I cam across the following quote from Alan Kay:

"Lots of so called object oriented languages have setters and when you have an setter on an object you turned it back into a data structure."

The article went on to imply that this was not best practice and could hurt applications you develop in the long run.

I'm a CompSci student with experience with C, Java, PHP, Ruby etc... so am fairly familiar with OOP as a concept and a practice, but am by no means an expert.

I guess what my question boils down to is this:

Is it semantically correct (and a matter of best practice) when writing OO programs, to access field values (with getters) and then Create new Objects based upon the modified values RATHER than using setter methods to simply adjust the field of that object.

Or if have a piece of wood, and I then carve some wood off of that original piece, should I model that as the same piece with less mass, or a new piece entirely.

Using setters appears to be more concise and Garbage collection would be an issue if you were creating so many objects so I am approaching this question from a theoretical, rather than practical, viewpoint.

Thanks in advance for your answers!

Community
  • 1
  • 1
Hugo Firth
  • 535
  • 5
  • 13
  • http://stackoverflow.com/questions/3511120/why-shouldnt-i-use-immutable-pojos-instead-of-javabeans and many others. You can search for "immutable" (which is a subset of "objects with no setters"). – assylias Apr 30 '12 at 12:37
  • Setters are merely one way to have mutability. For instance, consider an `Iterator` whose `next` first returns 0 and on each subsequent call returns the next natural number (like Python's `itertools.count`). No setter, yet the whole point is being mutable. –  Apr 30 '12 at 12:43
  • Thank you for this. I will read through some of the questions. Now that you mention it immutables were brought up with respect to Concurrent Programming. I understand that is possible - I would like to know the situations in which either is appropriate. I will read through questions for that term. So much to learn! – Hugo Firth Apr 30 '12 at 12:45
  • @assylias Yes, sorry I missed that. I removed you from the comment, instead I'd advise the asker so read and consider it. The question seems to mix the two concepts up. –  Apr 30 '12 at 12:46
  • Hugo, i have taken the liberty of adding an attribution of the quote you cite. At the risk of sliding into argument from authority, Alan Kay is a person whose opinions on object orientation deserve to be taken seriously! – Tom Anderson Apr 30 '12 at 13:32

7 Answers7

2

An object must have at least one of two types of responsibilities: behaviour and knowledge. Behaviour defines how the object reacts to events within its execution context, and knowledge defines what the object knows.

Behaviour is implemented as methods where the method names map onto the events that trigger reactions. Knowledge is implemented as getters that return values mapping to the knoweldge being queried.

Designed and implemented in this way, objects rarely need setters, as object states change only in reaction to external events. Having said this, one may implement an external event as a setter (e.g. car.setSpeed(...)), but usually a more suitable name should be sought (e.g. car.accelerateTo(...) and car.decelerateTo(...)).

  • This is the only answer here which correctly explains what Alan Kay was saying in the passage quoted above. It's not about mutable vs immutable, or setters vs public fields, it's about setters vs object-orientation. The fact that the tension between them is not widely understood today is an ongoing disaster. – Tom Anderson Apr 30 '12 at 13:30
  • I would upvote your comment, but that would be self-congratulation :-) Let's just say that I'm happy to finally meet someone on SO with the same view on object-technology. May I refer you to the most recent post on my blog at http://priscimon.com/blog which explains how one proceeds in modeling objects in terms of behaviour and knowledge? –  Apr 30 '12 at 13:37
1

It's a matter of design. The basic principle of OO is encapsulation. Suppose you have a Circle object. You could have a setter for the radius and a setter for the perimeter. But of course, since both are linked together, setting the perimeter should also change the radius, and setting the radius should also change the perimeter. If that's not the case, you indeed don't have an object anymore, but a simple data structure, without any encapsulation.

Now some objects are mutable, and some others are not. For example, a String or an Integer is immutable. Once it has a value, its value can't change. Concatenating a String to another one just creates a new String instance, without affecting any of the two original Strings. Immutable objects are easier to understand and use, because they only have one state. They also are inherently thread-safe. But they can lead to performance problems. For example, concatenating in a loop creates a whole lot of temporary String instances that consume memory and must be GC'ed. That's the reason why StringBuilder exists: it's basically a mutable String.

To conclude: there is no definitive answer, because it all depends on the kind of object, and the way it's used. In general, favor immutable objects over mutable ones. Favor less mutable objects over more mutable ones.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I had a suspicion that it would be a case of best practice but, as you described, depends on the semantics of the situation you are modelling. This answer combined with @assylias's links have helped me sort it out in my head. Thanks. – Hugo Firth Apr 30 '12 at 13:07
0

You are asking two questions:

1) Is it OK to have public fields in an object?

It is usually better from a maintenance/debugging perspective if you access fields of objects via methods for at least one reason: the method introduces a common entry for change to the field, and you can add custom logic to prevent invalid changes or update the invariant of the object to keep its state consistent with the requested change. If you have no internal state in the object, you don't need a method (but it's still advisable: it introduces a single breakpoint area for all accesses for debugging)

2) Should I use mutable or immutable objects?

Either approach is correct. Immutable objects allow easier reasoning on the code as you cannot modify the state of existing objects. OTOH you can end up with a lot more objects, so either will use more memory or the garbage collector will have more work. Mutable object offer the opposite advantages/disadvantages

Attila
  • 28,265
  • 3
  • 46
  • 55
  • I understand you're point about both approachs having points in their favour, however I am not specifically asking if it is OK to have public fields in an object. I almost never do (preferring getter methods) as I have been led to beleive that this is best practice. – Hugo Firth Apr 30 '12 at 13:04
0

In my opinion it all depends on whether you model the object in question as 'immutable'. This might make perfect sense depending on your model and in this case you should refrain from coding setter methods.

Generally speaking though, I find no reason for not using setters. Besides, you can find many languages (C#, AS3) which provide specialized syntax for defining setter methods.

biril
  • 1,975
  • 1
  • 19
  • 30
0

This completely depends on what you want to achieve. If you want to change the properties of an instance, you should use setter or similar methods (carveOutSomeWood()). If you need to have access to the previous version and want to generate a new instance, you can implement some sort of createCopy()/clone() method to create a copy and then apply carveOutSomeWood() to that new instance.

I would not reccommend creating a new instance by reading out properties of the old instance and creating it by yourself. The main reason (there might be others) is, that your class might change. You would then also have to change your creation of the new instance, as it is done outside of the class. If you simply use a createCopy() method it would be in the responsibility of the class to account for its changes.

You can also directly introduce an derive() method which creates a copy internally and applies some changes.

brimborium
  • 9,362
  • 9
  • 48
  • 76
0

setters can expose your inner implementation and cause some problems. if you set an object, and perform some actions based on the new assignment state, it might cause a problem if the assigned object is changed externally.

  • (1) Simply to circumvent, copy it (if it's mutable). (2) The whole point of going through getters and setters is to hide implementation details (up to and including wether there's a field that maps to this setter or the value is used otherwise). –  Apr 30 '12 at 12:48
0

Suppose some variable foo identifies a class object with some field bar, and presently foo.bar=5;. One would like for foo.bar to equal six. Your question is whether it is better to have foo continue to identify the same object, but change that object's bar to six, or whether it's better to have foo identify a new object which is just like the one it used to identify except that its bar field will equal 6. In cases where both approaches would be correct, modifying the field (whether directly or through a setFoo() call) is apt to be more efficient than creating the new object, and would thus be "better". Often, however, only one of the approaches will be correct; the other won't simply be "not as good"--it will be wrong.

The $50,000 question in determining which approach to use is what is supposed to be encapsulated by foo and the object identified thereby.

  • If foo holds a reference to a shared object, and other references to it use it to encapsulate the a state where "bar=5", then modifying bar would be wrong. The only correct approach is to create a new object, and change foo to identify that instead of the original.

  • If foo holds the only reference anywhere in the universe that identifies a particular object, then the creation of a new object or the modification of the existing object would be semantically equivalent, though as noted modifying the existing object is apt to be faster.

  • If foo identifies an object to which other references exist, and its purpose is to identify the object which is identified by those other references (effectively forming a connection with those other references), then changing foo to identify a different object would be wrong unless all references to that object are updated to identify the new object instead.

  • If field bar is final, or is otherwise protected against modification, then even if one holds the only reference to a particular object, there's no alternative but to create a new object and make foo identify it.

The second case and fourth cases are perhaps the most common; those could be handled by the principle "Don't create new objects needlessly" [in case 2, new object creation can be avoided; in case 4, it can't]. That principle will also easily handle case 3 [since it would encourage one do to the necessary thing]. The only problematic case from the perspective of that rule is the first. Even there, the key is recognizing that creation of the new object will be necessary if the reference is shared but is not intended to encapsulate identity.

I suspect one of the real reasons behind the popularity of immutable objects is that proper use of mutable objects requires knowing which references should encapsulate identity and which ones don't; use of immutable classes allows one to dodge such issues.

supercat
  • 77,689
  • 9
  • 166
  • 211