2

I've heard that variables should be declared as close to the point that they're used as possible. However, I've also heard that member variables should be used to describe something that is a characteristic of a class.

I find that these two pieces of advice sometimes conflict. For example, say I have a class the parses JSON using the jackson library. Would the jackson parser object I create in order for the class to be able to parse JSON be considered a "characteristic" of the class? Without the parser object my class can't do what it was designed to do.

However, I only really use the parser object in my main parsing function-- as such, I could just create a local version there rather than giving it class wide scope.

Perhaps that example was a bit contrived, but hopefully it conveys the gist of my question. What exactly constitutes a "characteristic" of a class?

  • 5
    Is it used in more than one place in the class? If it is, it's a member and not a local. Is it used in a method but nowhere else? It's a local. – Robert Harvey Aug 8 '16 at 23:41
  • 3
    If your class doesn't have a well-defined set of characteristics, then it's probably not really a class / object, and is actually a set of functions. For example, I don't see why a JSON parser class would need to have any variables or functions that aren't static. It makes sense to create a car object from a Car class, but it doesn't make sense to create multiple jsonParsers from a JsonParser class. They're not things - parsing is something you do. – gardenhead Aug 8 '16 at 23:52
  • @Adam I recommend reading questions on this site about SRP. While it is technically a different topic than your question, that would provide some valuable insight about class and function responsibility. – user22815 Aug 9 '16 at 0:00
  • 1
    To expand on what some others are is saying, consider the object's lifetime. Now consider the object's member's lifetimes. If these are not the same or very similar, then some members that have (substantially) shorter lifetimes than the instance as a whole, and that is an indicator that there are different responsibilities going on, which might indicate splitting the class (or using a local). This guideline can help you look into when you have something that isn't as cohesive as a unit as indicated by their co-location. – Erik Eidt Aug 9 '16 at 1:01
  • What's the name of the class? – Tulains Córdova Aug 9 '16 at 11:49
6

member variables should be used to describe something that is a characteristic of a class

Yes and no. Guidelines like these should not be taken too far, since it may quickly turn into pointless philosophically discussions about what actually constitute "a characteristic of a class". I think the rule is useful as a quick sanity check: If a field cannot be said to be a characteristic of a class then it probably should not be a field, or it should be a field in a different class. But the reverse is not true. Even if something could be considered a characteristic of a class it does not follow it should be a field.

You always want to reduce the number of fields, so if something could be either a field or a local, you want it as a local - regardless of the above rule. So if your parser can be a local it should.

3

For your example above (the JSON parser), here are some thoughts. You can extend these to other use cases, hopefully.

You're right that the parser itself isn't intutively a member of the class. So you could instantiate it locally wherever you need it. However, this does have two issues:

  1. you could have the need to inject this into the class for testing purposes - so perhaps it's easier to make it a member and populate it via the constructor?
  2. it may take a long time to initialise, in which case creating one instance and referencing that would be faster, and being a member would be more practical.

At this point you have members of the class which intuitively make up the class (e.g. x and y coordinates for a Point class) and supporting members (e.g. the parser above). I wouldn't normally worry about this.

You could reinforce the division, perhaps, by making the class derive from an interface that provides methods referencing the members (e.g. getX(), getY(), but no parser getter. You don't need to get the parser, I would suggest).

But my gut feel is that I wouldn't worry. The internals of your class are really internal. I don't like getters since I want to tell a class to do something - not pull the members out and do it myself. Note that you may want to change the internals of the class, and your interface will remain the same. Consequently the class members are there to support the implementation that you favour to make the class do what you want as effectively/efficiently as you need.

  • Isn't it just as easy to inject the parser into the method? DI isn't just for ctors & properties. – RubberDuck Aug 10 '16 at 0:32
  • You could do. But do you want the caller of a method to know that it needs something like that ? I'd perhaps regard that as an implementation detail that clients of the object don't really want to know (i.e. so you can construct with it but then users don't need to know). As ever, it depends on your particular circumstance – Brian Agnew Aug 10 '16 at 8:40
2

In layman's terms:

  • Members are cosidered part of the state of a class
  • A class is considered cohesive when its methods access the class' state
  • If parser will only be used in the parser function, you might as well pass it as a parameter.
  • If you want to change the parser during the lifetime of the class via injecting it with a setParser method, then it should be a member variable and part of the class' state.
1

To expand on what some others are is saying, consider the object's lifetime. Now consider the object's member's lifetimes.

If these are not the same or very similar, then some members that have (substantially) shorter lifetimes than the instance as a whole.

That is an indicator that there are different responsibilities going on, which might indicate splitting the class (or using a local variable instead of a member variable).

This guideline can help you look into when you have something that isn't as cohesive as a unit as indicated by their co-location (within the same class).

0

I've also heard that member variables should be used to describe something that is a characteristic of a class.

Have you tried to find this definition?

If that parser is logically stateless and completely encapsulated then making it a field is practically a performance optimisation. Making it a local is a memory optimisation.

Best OOP definition is here: http://www.paulgraham.com/reesoo.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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