21

According to Refactoring to Patterns:

When a class is trying to do too much, it often shows up as too many instance variables. When a class has too many instance variables, duplicated code cannot be far behind.

How does having too many instance variables lead to duplicate code?

1
  • 2
    Simply put: n boolean variables for example create an internal state space of 2^n. More often than not though your object does not have that many observable states, but because you crammed all that state into a single object, internally you still have to handle them all.
    – biziclop
    Commented Dec 2, 2015 at 19:32

4 Answers 4

26

Having too many instance variables is not directly related to duplicate code, or vice versa. This statement, in this generality, is false. One can throw two separate classes with no duplicate code into one class - that produces a new class with unseparated responsibilities and too many instance variables, but still no duplicate code.

But when you find a class with too many responsibilites in real world legacy code, chances are high the programmer who wrote it did not care for clean code or SOLID principles (at least, not at the time when he wrote that code), so its not unlikely you will find other code smells like duplicate code in there.

For example, the "copy-paste reuse" anti-pattern is often applied by copying an old method and making some slight modifications to it, without proper refactoring. Sometimes, to make this work, one has to duplicate a member variable and modify that variable a little bit, too. This might result in a class with too many instance variables (more precise: too many very similar looking instance variables). In such a situation, the similar instance variables maybe an indicator for repeated code elsewhere in the class. However, as you noted, this is an artificial example, and I would not conclude a general rule from it.

12

Too many instance variables means too much state. Too much state leads to duplicated code that is only slightly different for each of the states.

This is classic single concrete class doing too many things that should be sub-classes or compositions.

Find a few classes that have too many instance variables, you will see they maintain way too much state and have lots of duplicated code paths that are only slightly specialized for each case, but so convoluted that they can not be broken apart into reusable methods. This is one of the biggests sources of side effects as well.

There is at least one exception to this that does not fall into this category and is an easy way to remediate this. Immutableobjects do not have this problem, because they are a fixed state, there is not any chances for convoluted state management or side effects.

9

The statement you cite is meant to be seen in a specific context.

According to my experience, I cannot confirm that "many instance variables in general indicate duplicated code". Also, note that this belongs to the "code smells", and there are allegedly contradicting smells. Have a look here:

http://c2.com/cgi/wiki?CodeSmell

Amusingly, you will find "too many instance variables" is as good a code smell as "too few instance variables".

But there are problems with instance variables, be it too few or too many:

  1. Every instance variable may mean some kind of status of the object. Stati always need a careful treatment. You must ensure that you have covered all possible combinations of stati in order to avoid unexpected behavior. You must always clearly now: which status does my object have right now? From this angle, a lot of instance variables may indicated that the class has become unmaintainable. It may also indicate that a class does too many jobs, as it needs so many stati.

  2. Every instance variable requires you to keep oversight, which methods alter the variable in what way. So, suddenly, you don't know any longer all the cooks that are cooking. One of them, programmed tiredly at late night, will spoil your soup. Again: too many of such variables will lead to code difficult to penetrate.

  3. The other side: too few instance variables may cause that many methods must handle their information with too much work and with too much parameters. You feel this, if you are giving to many of your methods a certain equal parameter, and all methods do somehow a very similar thing with this parameter. In that situation, your code will start to bloat. You will end up scrolling many screens up and down in order to get some simple things together. Here, a refactoring may help: introduce one instance variable and one clear entrance to it. Then, free all the methods.

  4. Last but not least: If many instance variables of a class have their setter and getter each, then it may indicate that other classes don't use this first class the right way. There is a discussion about "Why getters and setters are evil". The idea in short is, if a class Rectangleoffers some getX(), and dozens of other classes use rectangle.getX(), then you are writing code that is not robust against the "ripple effect" (how far around is a code change influencing other code). Simply ask what happens if you change the type from int to double? According to this discussion, many of the rectangle.getX() calls should in fact better be calls like rectanlge.calculateThisThingForMe(). So, very indirectly, duplicated code could emerge from many instance variables, as many classes around use many getters and setters doing very similar things, i.e. copied things, that should better be moved inside the class.

Many or few instance variables remains a permanent trade off, altering both ways while the software is growing.

1
  • The R-to-P quote is too general which is why I like this answer. My take away is: if we expose enough properties a client can, and will, take those and write it's own version of a given functionality - #4 above. The problem can go as deep as the object composition - see #2: I see this too often in our code. (a) "why didn't they use the <whatever> class (to corral some of this unorganized state)?" or (b) "Why didn't they make a new class? I can't keep track of it all." And sure enough we have several classes internally duplicating functionality for lack of a coherent class.
    – radarbob
    Commented Dec 2, 2015 at 18:15
7

Simply put: poor separation of concerns within code, leads to code that is not modular, leads to poor reuse, leads to duplicated code.

If you never try to repeat functionality, you won't get duplicated code, and many instance variables, will not be a problem.

If you do try to repeat functionality, then monolithic code, which isn't modular, cannot be reused. It does too much and can only do what it does. To do something similar, but not the same, it's "easier" to cut and paste, rather than to break up the monolithic code. Experiences programmers know that duplicated code is the road to hell.

So whilst many instance variable itself isn't the root cause of the problem it is a strong "smell" that the problem is coming.

The language "cannot be far behind" is weaker than saying "must surely follow" so the author is not claiming it must happen but will eventually happen; if you need to reuse functionality but cannot as the code isn't modular.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.