views:

66

answers:

2

So..I intend to use a Model View Presenter(the "passive" mode, in which the UI is pretty dumb and sends all the events to the Presenter, and the Presenter takes care of dealing with the Model) to glue my domain's business logic and the UI.

My question is how should my Presenter look like. Is this what I want?

public class TicTacToeGamePresenter
{
    private readonly ITicTacToeView view;
    private readonly PlayerController model;

    public TicTacToeGamePresenter(ITicTacToeView view) {
        this.view = view;
    }

    ...
}

Should I by constructor injection pass the instance of the intended ITicTacToeView? This would allow me to use this TicTacToeGamePresenter class with Forms, WPF, WebForms, etc. I would only have to make sure my View implements the ITicTacToeView interface.

Or should I just instantiate the kind of concrete classes I intend to use directly and just have a parameterless constructor? This seems kinda pointless, but I had to ask :( .

I currently have the ITicTacToeView interface defined as:

public interface ITicTacToePassiveView
{
    event EventHandler<EventArgs<Point>> ButtonClicked;
    void PlayerOPlayed(Point location);
    void PlayerXPlayed(Point location);
    void EnableStartButton();
    void DisableStartButton();
}

One more thing. When coding the constructor of TicTacToeGamePresenter I ended up with this:

public TicTacToeGamePresenter(ITicTacToePassiveView view)
{
    this.view = view;

    IGameLogicAnaliser gameLogicAnaliser = new GameLogicAnaliser();
    IPlayer playerO = new Player(gameLogicAnaliser);
    IPlayer playerX = new Player(gameLogicAnaliser);

    Game game = new Game(playerO, playerX);

    this.playerOModel = new PlayerController(playerO, game);
    this.playerXModel = new PlayerController(playerX, game);
}

Now, after looking to the code I reckon that maybe it'd be better to have this' class dependencies be made more explicit by giving the "class above" the responsability of class instantiation:

    public TicTacToeGamePresenter(ITicTacToePassiveView view, IPlayer playerO, IPlayer playerX, Game game, PlayerController playerOModel, PlayerController playerXModel)
    {
        this.view = view;
        this.playerO = playerO;
        this.playerX = playerX;
        this.game = game;
        this.playerOModel = playerOModel;
        this.playerXModel = playerXModel;
    }

Which one would be better? Thanks

+1  A: 

I would go with your first option : using the constructor to inject the view into the presenter as it will allow you to support different types of UI provided they all implement the interface.

Also, from a unit testing perspective, your life will be much simpler as any mock class implementing that interface can be used for your testing

EDIT: Added code sample from how WCSF does it WCSF uses dependency injection and every view has a property for the presenter that is injected into the view. This works just as well and there is no need for the constructor approach but this will need a public View property exposed.

[CreateNew]
public DefaultViewPresenter Presenter
{
    set
    {
        this._presenter = value;
        this._presenter.View = this;
    }
}
InSane
+1  A: 

I don't think you have much choice BUT to use constructor (or parameter) injection.

At runtime, your view will already be instantiated when its presenter first instantiates; if you create the view in the presenter, then you'll be working with a separate instance of your view, and none of the events you'll expect will be handled.


If you're using an IoC container to create your presenter, I'd favor the second approach to your constructor. If you're not, then you're asking your view to instantiate IPlayers, PlayerControllers and Games on behalf of the presenter, and it probably shouldn't know how to do that. Take a look here for some discussion on why you'd want to use an IoC container.

Jeremy Frey
I'll eventually start using IoC containers. But right now I have already a lot of things that I have to learn and are causing enough havoc by themselves.
devoured elysium
Btw, that post you linked seems nice.
devoured elysium
One more question, you said that "At runtime, your view will already be instantiated when its presenter first instantiates; if you create the view in the presenter, then you'll be working with a separate instance of your view, and none of the events you'll expect will be handled.". Couldn't I just instantiate the View in the Presenter? That way the View would only be instantiated AFTER the Presenter. Or am I missing something?
devoured elysium
When the presenter is handling interactions, instantiating views, and returning instances of those views, then you have MVC, not MVP. Assuming ASP.NET Webforms, MVP doesn't allow you to short-circuit the first step of requesting a View (a page).
Jeremy Frey
Let's try to make this straight. In MVP, both the View and the Model are shielded from each other, having the Presenter between them, handling all interactions, right? In MVC that is not true, as the View can see the model.
devoured elysium
Not entirely true - in both MVC and MVP the view can see the model, but both shouldn't be touching it directly. In MVC, user actions are handled via the controller, which makes changes to the model, and updates the view accordingly (or returns an entirely new view). In MVP, user actions are still handled by the view, but the view immediately defers this to the presenter, who determines the best way of updating the model.
Jeremy Frey