57

This question is subjective but I was just curious how most programmers approach this. The sample below is in pseudo-C# but this should apply to Java, C++, and other OOP languages as well.

Anyway, when writing helper methods in my classes, I tend to declare them as static and just pass the fields if the helper method needs them. For example, given the code below, I prefer to use Method Call #2.

class Foo
{
  Bar _bar;

  public void DoSomethingWithBar()
  {
    // Method Call #1.
    DoSomethingWithBarImpl();

    // Method Call #2.
    DoSomethingWithBarImpl(_bar);
  }

  private void DoSomethingWithBarImpl()
  {
    _bar.DoSomething();
  }

  private static void DoSomethingWithBarImpl(Bar bar)
  {
    bar.DoSomething();
  }
}

My reason for doing this is that it makes it clear (to my eyes at least) that the helper method has a possible side-effect on other objects - even without reading its implementation. I find that I can quickly grok methods that use this practice and thus help me in debugging things.

Which do you prefer to do in your own code and what are your reasons for doing so?

Ilian
  • 673

4 Answers4

24

This really depends. If the values your helpers operate on are primitives, then static methods are a good choice, as Péter pointed out.

If they are complex, then SOLID applies, more specifically the S, the I and the D.

Example:

class CookieJar {
      function takeCookies(count:Int):Array<Cookie> { ... }
      function countCookies():Int { ... }
      function ressuplyCookies(cookies:Array<Cookie>
      ... // lot of stuff we don't care about now
}

class CookieFan {
      function getHunger():Float;
      function eatCookies(cookies:Array<Cookie>):Smile { ... }
}

class OurHouse {
      var jake:CookieFan;
      var jane:CookieFan;
      var cookies:CookieJar;
      function makeEveryBodyAsHappyAsPossible():Void {
           //perform a lot of operations on jake, jane and the cookies
      }
      public function cookieTime():Void {
           makeEveryBodyAsHappyAsPossible();
      }
}

This would be about your problem. You can make makeEveryBodyAsHappyAsPossible a static method, that will take in the necessary parameters. Another option is:

interface CookieDistributor {
    function distributeCookies(to:Array<CookieFan>):Array<Smile>;
}
class HappynessMaximizingDistributor implements CookieDistributor {
    var jar:CookieJar;
    function distributeCookies(to:Array<CookieFan>):Array<Smile> {
         //put the logic of makeEveryBodyAsHappyAsPossible here
    }
}
//and make a change here
class OurHouse {
      var jake:CookieFan;
      var jane:CookieFan;
      var cookies:CookieDistributor;

      public function cookieTime():Void {
           cookies.distributeCookies([jake, jane]);
      }
}

Now OurHouse need not know about the intricacies of cookie distribution rules. It must only now an object, which implements a rule. The implementation is abstracted away into an object, who's sole responsibility is to apply the rule. This object can be tested in isolation. OurHouse can be tested with using a mere mock of the CookieDistributor. And you can easily decide to change cookie distribution rules.

However, take care that you don't overdo it. For example having a complex system of 30 classes act as the implementation of CookieDistributor, where each class merely fulfills a tiny task, doesn't really make sense. My interpretation of the SRP is that it doesn't only dictate that each class may only have one responsibility, but also that a single responsibility should be carried out by a single class.

In the case of primitives or objects you use like primitives (for example objects representing points in space, matrices or something), static helper classes make a lot of sense. If you have the choice, and it really makes sense, then you might actually consider adding a method to the class representing the data, e.g. it's sensible for a Point to have an add method. Again, don't overdo it.

So depending on your problem, there are different ways to go about it.

back2dos
  • 30,140
21

It is a well known idiom to declare methods of utility classes static, so such classes need never be instantiated. Following this idiom makes your code easier to understand, which is a good thing.

There is a serious limitation to this approach though: such methods / classes can't be easily mocked (although AFAIK at least for C# there are mocking frameworks which can achieve even this, but they aren't commonplace and at least some of them are commercial). So if a helper method has any external dependency (e.g. a DB) which makes it - thus its callers - hard to unit test, it is better to declare it non-static. This allows dependency injection, thus making the method's callers easier to unit test.

Update

Clarification: the above talks about utility classes, which contain only low level helper methods and (typically) no state. Helper methods inside stateful non-utility classes are a different issue; apologies for misinterpreting the OP.

In this case, I sense a code smell: a method of class A which operates primarily on an instance of class B may actually have a better place in class B. But if I decide to keep it where it is, I prefer option 1, as it is simpler and easier to read.

4

Which do you prefer to do in your own code

I prefer #1 (this->DoSomethingWithBarImpl();), unless of course the helper method does not need access to the instance's data/implementation static t_image OpenDefaultImage().

and what are your reasons for doing so?

public interface and private implementation and members are separate. programs would be far more difficult to read if i opted for #2. with #1, i always have the members and instance available. compared to many OO based implementations, i tend to use a lot of encapsualtion, and very few members per class. as far as side effects - i am ok with that, there is often state validation which extends the dependencies (e.g. arguments one would need to pass).

#1 is much simpler to read, maintain, and has good performance traits. of course, there will be cases where you can share an implementation:

static void ValidateImage(const t_image& image);
void validateImages() const {
    ValidateImage(this->innerImage());
    ValidateImage(this->outerImage());
}

If #2 were a good common solution (e.g. the default) in a codebase, I would be concerned about the structure of the design: are the classes doing too much? is there not enough encapsulation or not enough reuse? is the abstraction level high enough?

lastly, #2 seems redundant if you are using OO languages where mutation is supported (e.g. a const method).

justin
  • 2,033
0

It is simple: if you don't need polymorphism (you are not implementing an interface), use static method, otherwise use instance method.