質問

This is an architectural / design question that just came to my mind when comparing current MVC practices in PHP with component based development in Javascript.

My question is:

Why doesn't the view (or parts of the view) define what data should be used to display it?

It seems to be common practice in MVC Frameworks to let the controller define what data the view needs. For me this creates unnecessarily coupling between the controller and the view.

When the view library has the possibility to call functions (twig for example) which retrieve the needed data structures, why wouldn't that be preferred? The controller would only have to know which root view to render and parts of the view would then work with the model to read the necessary data to render itself. I see following advantages:

  • Controllers get simpler as they don't aggregate the data before rendering the view
  • Unused data structures passed to the view would occur a lot less
  • Re-using parts of the view (templates) would also be easier as they aren't dependent on the controller to render anymore

Obviously when changing data the logic would stay in the controller, but I'm referring only to reading data to display the UI. Certain data (e.g. after submitting a form) would still have to be passed to the view by the controller, but most of it could be put into independently renderable components.

Do you see any disadvantages to this approach? Have you already tried something similiar to this with an MVC Framework?

役に立ちましたか?

解決

Views in MVC are supposed to be dumb. They should be little more than the templates that take data and format the data for in a consumable way. The change you suggest would certainly work, but there will be some downsides:

  • View now has more than one responsibility. It must fetch its data and format its data. Violates SRP.
  • View cannot be reused with different data. This makes testing more difficult. Ideally you can unit test your view by passing in data and checking the HTML.
  • Alternate views that use the same data must reimplement the same logic. For example if you want XML, HTML, and JSON outputs from a controller, each of those views would have the same logic for fetching the same data. It's better for the controller to fetch the data and pass it to the appropriate view.
  • Switching to client-side app is easier when controller holds the logic. If you want to move your view to the browser, you need the controller to do the data aggregation for you for performance reasons. It's not feasible to make many HTTP requests from the client to fetch all the data.

... this creates unnecessarily coupling between the controller and the view

Yes, the controller is coupled to the view in some way, but it should be loose-coupling that allows you to test the controller without testing the view. In PHP you can use interfaces to achieve a nice loosely-coupled relationship between controller and view:

interface iUserView {
    public function render($user);
}

class HtmlUserView implements iUserView {
    public function render($user) {
        return <<<HTML
          <html>
             <body><h1>{$user->name}</h1>
             </body>
          </html>
HTML;
    }
}

// Could implement a JSON version of the view, or an alternate HTML view
class JsonUserView implements iUserView {
    public function render($user) { ... }
}

class UserController {
    public function __construct(iUserView $userView) {
        $this->userView = $userView;
    }

    public function getUser($userId) {
        $user = // get user by $userId
        $this->userView.render($user);
    }
}
ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top