A while ago, I read about a political study that was done back in the 1950s. In it, researchers followed a set of people undergoing a career change and tested their political views before and after the change. People who were going from blue-collar jobs to white-collar jobs tended to become more conservative after a while. People who went from white-collar jobs to blue-collar jobs tended to become more liberal. Where you sit influences your perspective.
What does this have to do with programming? Well, let's try something out.
How do you feel about this Java code?
public class GlazeObject implements Renderable {
private ClassStore store = new DefaultClassStore();
private Formatter formatter = new DefaultFormatter();
public void setStore(ClassStore store) {
this.store = store;
}
public void setFormatter(Formatter formatter) {
this.formatter = formatter;
}
public void render()
…
}
}
Do the setters bother you?
Okay, how do you feel about this Ruby code?
class GlazeObject def initialize @store = DefaultStore.new @formatter = DefaultFormatter.new end def render ... end endFeel any different?
The fact of the matter, is that they both offer the same level of access protection. In the Ruby class, you can open up GlazeObject at any time, even hundreds of lines after its declaration, and make its variables accessible:
class GlazeObject attr_accessor :store end def do_something o = GlazeObject.new o.store = TerribleBadMaliciousStore.new ... endYet, you won’t find too many Ruby developers who are freaked out by this. You will, however, find Java developers who don’t like the setters. And, odder still, you will find people who program in Java and Ruby who will insist that setters are evil and blithely ignore the fact that they always have all the access that they would have with a setter by default in Ruby.
The only explanation that I have for this is that we are biased by our languages. When we see that a level of protection is available in a language, we feel an obligation to use it. When it's not there, we don't seem to notice it. Where you sit influences your perspective.

Comments (10)
Java developers prefer to avoid setters in favor of immutably. Final fields enable the compiler to verify that the field is set once and only once. They also make concurrency easier to reason about. Instead of looking for Ruby developers who are "freaked out" by it's lack of equivalent functionality, you should look for developers who don't use Ruby at all for reasons like this.
Posted by Bob Lee | December 7, 2007 5:02 PM
I'm not sure this is bias. Rather, it might illustrate the role of convention in programming language culture.
The presence of public setter methods in the Java object advertises them as intentional parts of the class' interface, and the absence of an attr_accessor in the ruby version advertises that mutators are not part of that interface. That is, in addition to the technical function of these methods, there is a social function ("If you want to mutate these members, please do so, and here is how..."). While the ruby class trusts its clients to add attribute accessors, it doesn't make any promises its clients, and in fact it (perhaps too politely) implies that such code may be a bad idea.
Code that depends on the render() method is code that the provider of the class is promising to support. Code that depends on @store is on thinner ice.
Posted by Joe Bowers | December 7, 2007 5:13 PM
If you'd prefer to keep the Ruby class from being opened up later on, you can always freeze it.
GlazeObject.freeze
# This will now fail
class GlazeObject
attr_accessor :store
end
# TypeError: can't modify frozen class/module
Posted by Dave Hoover | December 8, 2007 6:47 AM
How, exactly can you "not like" Java setters? If they are defined, then class supports pluggable ClassStore and Formatter implementations. Presumably, those can be switched on-the-fly!
(If you did not want that you a) would put "final" on the private variables b) would not provide setters.)
Now ruby is different matter. The contract is not enforced by language at all.
Posted by wx | December 8, 2007 7:35 AM
Bob Lee, it's true that some Java developers favor immutability with final, but not all of them. Joshua Bloch's call "final is the new private" is relatively recent. Personally, I like immutability too, but I have this feeling that when you say that you should do always X whenever you do Y, it's time to change the language or change your language. I like OCaml's take on mutability. Immutability is the default and mutability is explicit.
Posted by Michael Feathers | December 8, 2007 8:05 AM
Joe Bowers, yes, I was hoping someone would bring that up. The setter carries information.. it is telling people why the author intended. I wish we recognized the social function of access control a bit more.
Regardless, there's been a long standing bias against setters in OO. It eased up a bit with EJB (making the sign of the cross) and dependency injection.
Posted by Michael Feathers | December 8, 2007 8:10 AM
David, I agree, you can use freeze, but really, how many people do?
I do have people argue with me about opening up access to classes for testing, and it seems that a lot of it is motivated by expectations that they have due to the capability of their languages.
It is odd. There are some coding styles in static languages that definitely put people off.
Case in point.. I often tell C++ and Java teams to open up access to their singletons to make them mockable for testing. Over the past few years it's gotten better, but in the early days, the arguments were wild.
Posted by Michael Feathers | December 8, 2007 8:16 AM
wx, some people do argue against setters, particularly people in the immutability or "more encapsulation is better" camps.
Posted by Michael Feathers | December 8, 2007 8:17 AM
Michael, you're right that most people don't use freeze. I think that's a cultural thing. In Ruby, we tend to give people the benefit of the doubt and assume they know what they're doing. If they want to open up a class, we assume they have a good reason for doing so. In Java, we tend to use the language's features to protect ourselves from other developers. Both tendencies have their costs and risks.
I think that mentioning Class#freeze is important for people coming from a culture like Java's where they might feel nervous about Ruby's open classes.
Posted by Dave Hoover | December 8, 2007 9:42 AM
I think the other thing to keep in mind here is what we originally intended by creating set methods. We're trying to hide the internals of what's going on within the object when you are actually setting something - there may be side effects that we are shielding the client from needing to know about. I think everybody has gotten a horrible taste in their mouths due the whole EJB get/set mess, but really, I the original OO intention behind get/set methods has been lost/forgotten/abandoned.
Posted by Jason Brown | December 9, 2007 12:42 AM