Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to maximize code reuse while avoiding implementation inheritance and maintaining internalization

I am torn between several different OOP approaches to code reuse and code structure, and I cannot figure out the best option for my case.

Currently, I have a base class called 'Plot' (a piece of land) which handles the core functionality of a standard plot type and any other plot type. So I figured it would make sense to have any other Plot type that uses the core plot functionality to extend Plot. However, I am now realizing that there are many downfalls to this approach. Here is the current basic structure of my code (in java):

public class Plot {
    public void doStuff() {
        // Do stuff for Standard plot type
    }
}

public class EstatePlot extends Plot {
    @Override
    public void doStuff() {
        // Make sure we still handle the base functionality (code reuse)
        super.doStuff();
        
        // Make sure we also do stuff specific to the Estate plot type
    }
    
    public void extendedFunctionality() {
        // Do stuff that only applies to the Estate plot type
    }
}

I do not like this approach for several reasons.

  • There are cases where I need to override a method to provide more functionality, but I don't want to execute all of the code in the parent method. (ie: there is no control or precision to code reuse)
  • There is a strong coupling of functionality between classes. (ie: the base Plot class may have an undesired effect on any sub-classes behavior because they are tightly coupled. This is known as the fragile base-class problem)

More reasons why I think this approach is undesireable can be found here (http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html)

I thought about using Composition, but I realized that this was not a good option either because I still need to override functionality of the base Plot class.

So at this point, I know I should use interface inheritance over implementation inheritance. Perhaps I can make Plot an interface that defined the core functionality for all Plot Types (Standard, Estate, Etc.). Now this is where I am stuck because I am faced with the issue of code reuse. I do not want to implement the same standard functionality for all Plot types, so I thought about using a sort of procedure class (lets call it PlotHelper) that defined public static methods to handle a lot of the core functionality given a Plot object. Here is an example:

public interface Plot {
    public void doStuff();
}

public class StandardPlot implements Plot {

    @Override
    public void doStuff() {
        PlotHelper.handleStuff(this);
    }
}

public class EstatePlot implements Plot {
    @Override
    public void doStuff() {
        // Make sure we still handle the base functionality (code reuse)
        PlotHelper.handleStuff(this);
        
        // Make sure we also do stuff specific to the Estate plot type
    }
    
    public void extendedFunctionality() {
        // Do stuff that only applies to the Estate plot type
    }
}

public class PlotHelper {
    public static void handleStuff(Plot plot) {
        // Do stuff for Standard plot type
    }
}

My problem with this is that now the core functionality is no longer internalized. The bits and pieced of functionality that is now in the public static methods in PlotHelper used to be handled together in the base Plot class which meant more modular and internalized code.

So finally, now that you know where and why I am stuck, is there any preferred solution that avoids implementation inheritance and maintains internalization of type specific code? Or perhaps you can think of a completely different approach that would be great for this case.

Thanks for your time!

like image 496
Jon McPherson Avatar asked Oct 24 '14 14:10

Jon McPherson


2 Answers

Abstract classes allows you to implement a method (Code reusability) and declare abstract methods (Interface inheritance).

You can then implement a doStuff() method in your Plot abstract class and create an abstract method like doSpecificStuff() to be implemented in your PlotType.

public abstract class Plot {
    protected void doStuff(){
        //Implement general stuff for Plot
    };

    abstract void doSpecificStuff();
}

public class StandardPlot extends Plot {

    @Override
    public void doSpecificStuff() {
        // Make sure we still handle the base functionality (code reuse)
        doStuff(); //if needed. You can call standardPlot.doStuff() and then
                   //standardPlot.doSpecificStuff();

        // Make sure we also do stuff specific to the Estate plot type
    }

    public void extendedFunctionality() {
        // Do stuff that only applies to this plot type
    }
}

Abstract classes can't be instantiated tough, so you'll still need a StandardPlot class. Also declaring doStuff() as protected you ensure that the method is called only by Plot class and it's subclasses.

like image 90
Narmer Avatar answered Oct 13 '22 20:10

Narmer


Maybe Template Pattern would apply to you?

like image 45
lupus137 Avatar answered Oct 13 '22 21:10

lupus137