Get Rid of That Code Smell – Attributes

In this post I will show you why using attribute accessors is a code smell in most of the cases. This is a very convenient feature of Ruby but you should only consider using it if you’re implementing a data-like objects which expose, well, data to other parts of your system. A good example is an Active Record object which exposes its attributes. Another good example could be an object which wraps a response from a remote API and through attribute readers gives you access to data returned in that response. Probably every other use case should be considered as a code smell.

Detecting Attribute Smell

It’s pretty easy to find the attribute smell in your code. Just grep for usage of attr_* in your classes. Pelusa does that for you. Reek can also detect this smell although this check is turned off by default.

Here’s an attribute class which you can instantiate with a name and set its reader visibility. This is an actual piece of code that we used to have in Virtus. The information about reader visibility needed to be public. Initially we had a public attr_reader for the reader_visibility instance variable that was set in the constructor. It was an easy and convenient solution. The related piece of code looked like that:

Now in other places we were using the value of reader_visibility so we had pieces of code like this:

This means that we had an instance variable exposed to the other objects which were relying on its value. This was a mistake and definitely a code smell.

Removing Attribute Smell

You probably know how to get rid of that smell, right? We should simply implement a predicate method and this is exactly what was done:

This is much better because of two reasons. First of all we hide the private state of an object behind a public predicate method which is simply cleaner. Secondly if, for some reason, the logic for calculating the value of reader_visibility becomes more complex we will simply implement that in the predicate method. Well, it’s probably not going to be the case here but you get the idea.

What about “Tell, Don’t Ask”?

This rule is also related to the attribute smell. Whenever you rely on an object’s attribute to make a decision what to do next – you’re violating “Tell, Don’t Ask” and you’re introducing the attribute smell. Here’s a quick example:

This subtle difference is important because the library object should know how to deal with an empty books array and it should not be a concern “outside” of the library object. We also rely on the books property which indicates the attribute smell.

Summing Up

As you can see the attribute smell is easy to find and fix. The important thing to remember is that when you rely on the internal state of the objects you make future refactorings very difficult. So just don’t do that. Objects should expose as little information about their internal state as possible. Make things publicly visible only if you’re certain it’s really really needed. Rely on API that your objects provide instead of their internal state. This will make your life much easier.

In the next post we’ll deal with the “Control Couple” smell.

  • Ben

    There’s definitely an argument to be made that referencing your ivars all over your class is a smell too. I like wrapping them in private readers. Message sending is important even internally.

    • http://solnic.eu/ solnic

      Good point. I do that too.

  • hugoestr

    After thinking for a while on your post, there is another advantage of avoiding the use of attributes: when assigned to complex objects, you leak out the object’s methods, breaking Demeter’s. Our code becomes brittle and hard to refactor.

  • http://lucapette.com Luca Pette

    Nice. I have the feeling I’m going to enjoy this series a lot ;)

  • Seban

    Nice article. By the way pelusa. Pelusa says me that i should not use more than 3 ivars. Can you aso explain why it is important?
    My second question. I have a method to deal with my ivar. When I test it how should I check that it really do something with this instance variable? On one side I don’t wan to have ivar getter only for test something, on other side I don’t want to do instance_variable_get bla bla bla.  

    • http://solnic.eu/ solnic

      ivar limit will be covered in the post about “Large Class” smell, so stay tuned :)

      Regarding your second question – you shouldn’t be testing internal state of an object so I’d say this test is simply not needed.

  • http://codigoergosum.com Balint Erdi

    So following ‘Tell Don’t Ask’ would it be possible to get rid of public_reader? somehow?

    • http://solnic.eu/ solnic

      Ha! I was expecting that question :)

      No, not really – in Virtus we need a way to *find*  all publicly available model attributes that’s why we need a method that would tell us if an attribute is public. See here: https://github.com/solnic/virtus/blob/master/lib/virtus/instance_methods.rb#L84-86

  • http://drogomir.com/blog Piotr Sarnacki

    Really cool post, thanks for sharing. That reminds me of a challenge that Gregory Moeck mentioned on twitter the other day, something like: “Try to not use getters and setters at all and see how it changes your code design”

  • panthomakos

    Just a short while back I wrote an article about this exact same concept with relation to ActiveRecord and finders. Exposing internal attributes is bad. It’s convenient to use but makes refactoring so much harder in the long run.

    http://ablogaboutcode.com/2012/03/22/respect-the-active-record/

  • http://mwilden.blogspot.com Mark Wilden

    In general, I agree that attributes (including getter/setters) are a code smell.

    A point on terminology: A “code smell” is not a bad thing in itself. A code smell is the canary in the coal mine that alerts you to a *potential* problem. It’s not correct to say something is a “code smell in most of the cases”. Using attributes is a code smell in *all* of the cases. In many of those cases, it’s a problem that should be fixed.

    The other point is about doing the simplest thing that could possibly work. “if, for some reason, the logic for calculating the value of reader_visibility
    becomes more complex we will simply implement that in the predicate
    method. Well, it’s probably not going to be the case here but you get
    the idea.” The ability to do something later is not necessarily a good reason for doing something now. Ruby makes this easy. You can start with a simple attr_accessor, and build those out to full-blown methods when and if necessary.

    • http://solnic.eu/ solnic

      Thanks, you’re right – I didn’t put it correctly. What I meant was that using attributes is problematic in many cases :)

      Regarding the example with reader_visibility – it was actually the simplest thing that could work because we could remove referencing the value of reader_visibility in other places in the code base and use public_reader? instead which actually *was simpler*. Hence the refactor.

      • http://mwilden.blogspot.com Mark Wilden

        And to be clear in my turn, I do agree with the reader_visibility refactoring, but because it’s more intentional now rather than because it might help later.