I am working on a Rails application which employs a classic MVC as its fundamental structure. In that structure the controller is supposed to be responsible for "which view to render when".

Now after reading a design pattern book I learned about design patterns and, inspired, started looking for ways to use them to improve the code quality. A couple of months ago I started writing code which renders a collection of books (not really, I'm just simplifying here). Each book is a ruby class instance, and has a 'type' property. Depending on the type property, books look drastically different from one another (whole different view partials are used for different books). Now I had a choice of having something like an if statement in my controller or view, choosing what partial to render for each book, or to associate a partial with the book type property directly (which is more like a strategy pattern, I think). The second way seemed much better as it got rid of all if statements, so that's what I went for. I simply did something like render books in the view and each book rendered correctly based on type.

All seemed beautiful, however. Now I started thinking whether this is against mvc model. The way the code is written now, the controller is not deciding anything about how to render a particular book. Confirming my fear of potential weirdness, the designers I work with brought up to my attention that they usually only look at the rails 'views' layer (they are responsible for writing html structure). Before they could easily follow what partial was rendered for each book, as before all logic was in the view in a form of easily read if statements. Now to find out which partial renders for which type of book they have to go all the way into the model layer. Feels wrong to have them go there.

Did I do the wrong thing by putting the 'which partial to render' logic into the model?

有帮助吗?

解决方案

The MVC design pattern does not specify the mechanics involved in choosing which view to render. Both ways are "MVC".

If you are rendering a collection of books, the controller renders a single view responsible for rendering a collection of books.

If the controller renders a single book, it needs to render a single view for a single book.

They are two different views.

The real problem to solve is where the logic of deciding which view to render based on book type should live. If you put this logic in the model, then it certainly is portable and reusable. You can put it in a view too. I think the Principal of Least Astonishment provides the best guidance here.

Where do you or your teammates expect to find this logic?

Put it there, and don't worry so much about "violating" the MVC design pattern, because it really doesn't tell you where to put this logic. The MVC design pattern is primarily about Separation of Concerns. If the logic for handling user interaction is separate from the logic of rendering the view, which is separate from the data and business logic, then you are following the MVC design pattern.

Beyond that, architect your code so you don't get a migraine every day before going home and you can isolate changes in your code base, instead of being forced to make sweeping changes for simple refactoring jobs.

其他提示

I think you did a great job by identifying that you could get rid of the if statements by using polymorphism. No matter if this adheres to the MVC adaption of Rails or not. According to Martin Fowler the MVC pattern is by far the most misquoted pattern anyway. One of the problems iOS developers run into these days ist called the Massive View Controller problem. Which means they put all possible code into the view controller. You are on the right track to move the presentation code into separate classes. Although the model might not be the right place to put it. Probably you come up with a separate class for this. Martin Fowlers page about GUI Architecture (https://martinfowler.com/eaaDev/) is probably a great site for you to explore next.

Yes, this goes against MVC design, but don't make the mistake of forcing a paradigm. MVC was probably a decent design back when applications were still primarily exclusively installed on the client computer. Nowadays, it is a bit outdated, and while that's not to say you shouldn't take an example from this, you should be using it as a stepping stone for buliding your own application and not the holy grail of program architectures.

I'm not a Rails programmer, but I do happen to like how they approach the problem. It elegantly places the logic in the view rather than the controller. You should reserve the controller for circumstances where it wouldn't really be appropriate for a particular view.

And while getting rid of the if statements doesn't necessarily mean it's an improvement, it probably is just the same, as it eliminates possible pathways in your program and simplifies it in the process.

许可以下: CC-BY-SA归因
scroll top