3

I have the following code in PHP:

abstract class AlgorithmOnArray {

    public function runOn($array) {
        $this->setup(); 
        foreach ($array as $item) {
           $this->processItem();
        }
        $this->cleanup(); 
    }

    public abstract function processItem();

    public function cleanup() { }
    public function setup() { }
}

My question is regarding this notion I have here of having empty but implemented methods for cleanup and setup. The idea here is that while normally I'd have them as abstract, I also want classes which extend the AlgorithmOnArray class to be able to fallback to a default implementation.

The question here is whether this is deemed a reasonable thing to do or should I strictly say that these methods also need to be abstract to force child algorithms to implement them?

4
  • 1
    What do you mean by "reasonable?" Terms like "best practice" and "reasonable" are too vague to respond to specifically, and at the end of the day the "goodness" of a technique is judged by how well it meets your specific requirements. Oct 4, 2017 at 15:20
  • @RobertHarvey I guess my biggest concern here is whether or not this is considered to be any known anti-pattern I'm not aware of. Here's the thing that I'm a bit nervous about, those two methods offer absolutely nothing to this specific class.
    – apokryfos
    Oct 4, 2017 at 15:35
  • If you override cleanup() in the derived class, and call runOn() from the derived class, won't runOn() still call the cleanup function here, where it has no implementation? Oct 4, 2017 at 16:16
  • @RobertHarvey no, PHP has no specific "override" keyword like e.g. Java or C# has. All functions are assumed virtual and any function with the same name in a child class is assumed to be an override.
    – apokryfos
    Oct 4, 2017 at 16:36

1 Answer 1

5

There are two major reasons for implementing functions in the base class, like setup() and cleanup().

The first is to reduce duplicate code, including NO-OP code, as you have here. If there is no requirement for an subclass to implement setup() or cleanup(), then it will be common for developers to simply drop in an identical copy of the functions as shown here. It's better for the base class to just do it and leave the subclasses to do their work. The subclasses will be easier to write and cleaner as a result. (It isn't hard to come up with subclasses that would not need those two functions.)

The second is to allow for future enhancements to the base class. Let's say you add a feature to the base class that needs some setup and cleanup -- threading, maybe. If I'm writing a subclass that has no need for setup() and cleanup(), then I'll leave them out, and the new threading versions from the base class will run, as expected. If I do write one, then I'll write it like this:

class MyAlgo extends AlgorithmOnArray {
  public function setup() {
    parent::setup();
    // my setup stuff
  }
}

When the base class adds the threading feature, mine won't break the application by bypassing the base version. The class docs should encourage this pattern as developers are sometimes lazy and will omit the call to the parent class if they know it is a no-op. If it is declared abstract, they must omit it.

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.