views:

92

answers:

1

I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.

The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:

class PostViewHelper {
    private $postModel;

    public function __construct(PostModel $postModel) {
         $this->postModel = $postModel;
    }

    public function title() {
         return $this->postModel->getTitle();
    }
}

In my template (view) file this could be called like this:

<h1><?php echo $this->post->title(); ?></h1>

So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:

public function title() {
    return $this->filter($this->postModel->getTitle());
}

I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.

+3  A: 

I didn't find the blog post you referenced very interesting or insightful.

What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.

That said, I'd suggest taking your Decorator pattern and running with it.

interface PostInterface
{
    public function title();
}

class PostModel implements PostInterface
{
    public function title()
    {
        return $this->title;
    }
}

class PostViewHelper implements PostInterface
{
    public function __construct(PostInterface $post)
    {
        $this->post = $post;
    }

    public function title()
    {
        return $this->post->title();
    }
}

class PostFilter implements PostInterface
{
    public function __construct(PostInterface $post)
    {
        $this->post = $post;
    }

    public function title()
    {
        return $this->filter($this->post->title());
    }

    protected function filter($str)
    {
        return "FILTERED:$str";
    }
}

You'd simply use whatever DI framework you have to build this object graph like so:

$post = new PostFilter(new PostViewHelper($model)));

I often use this approach when building complex nested objects.

One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.

interface PostInterface
{
    /**
     * Minimal interface. This is the accessor
     * for the unique ID of this Post.
     */
    public function getId();
}


class SomeDecoratedPost implements PostInterface
{
    public function __construct(PostInterface $post)
    {
        $this->_post = $post;
    }

    public function getId()
    {
        return $this->_post->getId();
    }

    /**
     * The following magic functions proxy all 
     * calls back to the decorated Post
     */
    public function __call($name, $arguments)
    {
        return call_user_func_array(array($this->_post, $name), $arguments);
    }

    public function __get($name)
    {
        return $this->_post->get($name);
    }

    public function __set($name, $value)
    {
        $this->_post->__set($name, $value);
    }

    public function __isset($name)
    {
        return $this->_post->__isset($name);
    }

    public function __unset($name)
    {
        $this->_post->__unset($name);
    }
}

With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.

hobodave
Thanks for answering hobodave. There are however some things I don't understand. 1) it doesn't seem to address the issue of getting the filters in 2) I don't understand why the model needs to implement the interface that the viewHelper implements. If that's the contract/api the view can use I could just as well pass in the model directly.So I don't see how your answer addresses the problem I'd like to see solved, and what you make of the presenting-the-model-to-the-view-part doesn't seem convincing to me.
koen
@koen: 1) "getting them in?" I assume you are referring to constructing your object graph. This would be done by you manually, or using whatever Factory object or DI framework you use. You haven't provided any information as to how your DI framework works; thus, lacking psychic abilities, I can't show you how to do that.
hobodave
@koen: 2) That's what a Decorator is. The PostInterface is used by objects to say, "Hey, I chirp, walk, talk, and act just like a Post - so treat me like one." It also allows for using the interface in typehinting as shown by your constructors. You wouldn't want to pass a FooObject to your PostViewHelper constructor, that's why you use the PostInterface type hint.
hobodave
I suggest the following resource: http://www.slideshare.net/weierophinney/architecting-your-models
hobodave
1) It actually doesn't matter what I use for it as it doesn't make a difference for the question. The question is not how to technically get them in. It's how to design the objects according to the newable/injectable distinction set out in that blog article. The model is a newable. Your implementation suggests that viewHelper is a newable too (could indeed be), and the filter is also one. Sorry if I confused you by my answer. Note: after typing reply to 2) I maybe can use the filterAdapter approach, but I still think that how you put the model in the viewHelper is unwanted.
koen
2) I don't think the decorator pattern is any good here. In this case it couples what I want to decouple. The viewHelper should hide the model from the view, I think we agree on that. It hides the model from the view so the model can vary while keeping the api stable. If both model and viewHelper implement the same interface a change in the modelInterface is reflected by a change in the viewHelperInterface (since both implement the same interface). So there is no 'hiding the models implementation'. We need more comment room here and better discussion possibilities.
koen
@koen: I don't see the need to abstract the model API behind a proxy/bridge so that the view can use it. In MVC the View uses the public API of the Model; that is the standard and accepted behavior. If your model is so volatile as to require an abstraction layer, then it is not well designed. The only changes I tend to make to my models is to add new accessors/behaviors, or to modify the internals of existing ones. Neither of these require any need to change my view, unless I wish to use the new methods. Your approach would require the same.
hobodave
There are many implementations of MVC. A reason to decouple the model and the view through the use of a viewHelper is that it is not desirable to depend on the inner workings of the model. If the view 'getX' from the model it does depend on that. Getters are to be avoided when it queries for state. The view is a boundary of the program so getters are unavoidable but we can decouple this from the model. Another reason is that the viewHelper is a good candidate for the responsibility of adding output filters through events. I think this is better discussed in another topic though.
koen
Actually, I also don't agree when you say 'In MVC the View uses the public API of the Model; that is the standard and accepted behavior'. But as I said, maybe better to leave that to another topic.
koen