0

We are trying to implement the MVP pattern. Because it requires quite a lot of code just to have a functioning view, we try to use inheritance as much as possible. As I am pretty new to Java, I don't know exactly if I'm doing it right:

So, I started with a very simple Interface which all the views will implement (and the `getName`` method will be used for breadcrumb Feature):

public interface IView {    
    public String getName();
}

On top of that, I built a BaseView which will be used for most views:

public interface IBaseView extends IView {
    public void addListener(IBaseViewListener l);   

    interface IBaseViewListener {
        void viewEntered(Long id);
    }
}

And the implementation

public class BaseView extends CustomComponent implements View, IBaseView{
    private String name = "";
    private List<IBaseViewListener> listeners;

    public BaseView(String name) {
            this.name = name;
            listeners = new ArrayList<IBaseViewListener>();
            buildLayout();
    }

    @Override
    public void addListener(IBaseViewListener l) {
            listeners.add(l);
    }

    protected void buildLayout() {
            this.setId("base_view");
            // initialize layout....
    }

    @Override
    public void enter(ViewChangeEvent event) {
            for (IBaseViewListener l : listeners) {
                    l.viewEntered(id);
            }
    }

    @Override
    public String getName() {
            return name;
    }

}

And last we have a ScaffoldingView which will be used for some views (mainly for mocking):

public interface IScaffoldingView extends IBaseView{

    public void showTable(AbstractComponent t);

    interface IScaffoldingViewListener extends IBaseViewListener {
            void itemSelected(DataBaseObject selectedObject);
    }
}

And the implementation:

public class ScaffoldingView extends BaseView implements IScaffoldingView{

    private AbstractComponent table = null;

    public ScaffoldingView(String name) {
        super(name);
    }

    @Override
    protected void buildLayout() {
        // here is a lot more code...
    }

    public void showTable(AbstractComponent t) {
        // here is a lot of code...
    }

}

First of all: - Does that approach make any sense? especially the access modifiers. I'm totally weak when it Comes to polymorphism :(

  • I am very unsure about the handling of the EventListeners. For example: In the constructor of the BaseView, I am implementing the addListener function.

Now, in the ScaffoldingView's, there will be a specialized IScaffoldingViewListener. Will the super class (BaseView) addListener() method be able to handle These IScaffoldingViewListeners?

edit: Sorry, I forgot to mention that View and CustomComponent are some classes of a 3rd Party Framework (Vaadin) which we use and which offer the enter Event in which we call the eventListeners (Presenter).

netik
  • 1,736
  • 4
  • 22
  • 45
  • `IBaseView` and `BaseView` plus `IScaffoldingView` and `ScaffoldingView` seem to have a 1-to-1 relationship, not being an expert at polymorphism myself, I'm wondering what is the benefit? – glend May 28 '15 at 13:54
  • Sorry, probably there isn't any polymorphism at all. My goal is that I do not have to write the code of the BaseView (like adding the EventListeners, the Enter method, etc. in all of our views. – netik May 28 '15 at 13:57

1 Answers1

1

First, declaring an interface inside another interface is not quite clean, obscures the code quite a bit.

Second, about BaseView which extends CustomComponent, and implements IView and IBaseView, first a small detail, if it implements IBaseView, you do not need to implement IView, as IBaseView already extends IView, but the bigger issue i see is:

If you have a somewhere in some class, a method with an IBaseView as a parameter, but inside that function you expect to be able to use the overrided methods from CustomComponent, you won't be able to, you'll only have the methods declared on IBaseView.

If you wanted to use the CustomComponent methods, you'd had to do a cast inside that method, but that is not clean and a source of bugs, because if in the future, you add more classes that implement IBaseView but do not extend CustomComponent, that function will throw exceptions complaining about casting.

Also, about the ScaffoldingView, if you are going to use it only for mocking purposes in tests and you are extending the IBaseView behaviour, with more methods, if you test a method that has an IBaseView as parameter, you have the same exact situation as before, the method you are testing will not be aware of the IScaffoldingView declared methods, and then it won't use them, and your tests can't be trusted.

P.D.: if you are interested in learning about abstractions and inheritance design, i'd recomend you to check S.O.L.I.D. principles, there's a lot of literature in the web about those.

Edit: Response to your comment

First you need to ask yourself without thinking about internal details or implementations or testing or anything else, what are the behaviour my Views have? are they all behaving the same way? do i have different types of views or not really? Once you answer these questions and got an idea of what is going on, you'll have what it will need to design the interface hierarchy, and thats what is going to be exposed to the rest of the system.

You can (optionally) have abstract classes that derive from those interfaces, where you can provide some initialization, defaults, but, do not go further in offering more functionality than the interface offers, you can have some extra methods, but only for internal use.

And then you can derive the actual implementation of the views from the interface or the intermediate abstract classes if you have defined any.

Just think of this as a black box, in which the only thing you can see are the input and output interfaces, everything else that is going inside that box, the rest of the system doesn't and shouldn't need to know about.

Can't really give you specific solution because i'm not aware of the needs of your application.

saljuama
  • 2,906
  • 1
  • 20
  • 42
  • Thanks a lot for your answer. I see the issues you mentioned. Is there any solution to it, or any design pattern that has been proven useful when using inheritance in the MVP pattern? – netik May 29 '15 at 19:36
  • Tried to extend my answer on how to proceed, right now don't know any specific pattern that could fit your case, just explained the very basics from design perspective. Btw, found this, you should take a look: http://stackoverflow.com/questions/14544504/composition-vs-inheritance-in-mvp – saljuama May 30 '15 at 08:06