tags:

views:

141

answers:

4

Hello!

Before rendering into a view model should be formatted:

  1. multilingual data localized;
  2. date, time values formatted;
  3. numbers formatted.

Who performs all this formatting - Controller or View?

Am I right that all the formatting is performed by the Controller which creates so called ViewModel containing only formatted values and sends this ViewModel to the View?

Thanks in advance!

+1  A: 

All that stuff seems like presentation layer logic, so personally I think it should go in the view.

ETA:

I wouldn't advocate for having the view call service layer objects in the general sense, but for localization I think it makes sense.

For example, lets say you have lots of static text on your pages that you have tokenized and stored in a database in various localized forms. I don't think it would make sense for the controller to have to lookup and put all those text tokens in the model. Even though a text token lookup is technically a "service layer" operation, I still think it makes sense for the view to call that service directly via some utility class rather than having the controller do it.

Eric Petroelje
Then we should provide view with additional data like "User locale" and view must know how to localize strings according to the locale and so on. Isn't it too much for a view?
Andrey
@Andrey - I think JonoW's answer sums up how to handle the string localization issue pretty nicely.
Eric Petroelje
Please take a look at my comment. JonoW offers strongly coupled model where both controller and view use the same service. I don't see the difference between controller and view then.
Andrey
+2  A: 

Eric Petroelje is right, but I would build helper a class(es) to get localised content/dates etc, because localisation isn't always in the views, e.g. sending emails with localised content. I would have something like LocalisationHelper.GetString("MyKey"), or LocalisationHelper.GetDate(Date.Now), where the LocalisationHelper knows the users current locale (maybe from Session).

Then use this directly in the views where possible:

<%= Html.Encode(LocalisationHelper.GetDate(Date.Now)) %>
JonoW
That seems to break MVC concept as your view actually uses "Localization service" i.e. behaves like controller.
Andrey
LocalisationHelper isn't a service, it would just be a formatter to make your view code neater. It's simply formatting the data that your Controller is giving to your View.
JonoW
@JonoW I cannot agree with you, because LocalisationHelper knows about user session. It means that it is stateful - so it isn't just a static helper but a real service. If it wasn't you should provide it with Locale parameter.
Andrey
Problem is Andrey, if you do all your formatting in the Controller, nearly all your model properties will have to be strings, as opposed to ints, DateTimes, which makes your model weaker. Passing in a Locale parameter is fine, but where would you get the value from?
JonoW
I think it is worth to get the locale in the Controller by calling"String locale = i18nService.getLocale();"and then pass both the model and the locale to the view. Then the View can just render the model using static methods like:"I18nHelper.getLocalizedValue(multilingualString, locale);"
Andrey
Yeah that works
JonoW
+1  A: 

The view is responsible for this not the controller.

To explain I need to elaborate a bit about what the "view" is:

In both web-based and traditional GUI MVC patterns, the View is responsible for the external representation of whatever parts of the model that are shown. If that means "formatting" data from the model then so be it.

The controller shouldn't format the data - because the controller is responsible for doing things to the model based on events/commands coming in from the outside world. The controller doesn't have anything to do with rendering the output.

Example:

I want to display a shopping cart with several order lines:

  • Adding things to the cart causes the controller to change what's in the cart model.
  • Changing my locale causes the controller to change a setting in the user model to indicate preferred locale.
  • Whenever the cart is displayed, the view has to ask the model for the order lines and decide how to display that - maybe doing locale-sensitive work.
  • The same customer could ask to see the shopping cart in multiple different currencies. That just means changing what it looks like in the view. It's still the same shopping cart for the same customer with the same things in it.
  • If this is a web-app made from web template pages, you might embed code to pull in localized messages e.g. <%= message_renderer.text(:insufficient_funds) %>. In this case the "message_renderer" and the template file are both part of the view.

Views aren't necessarily just web-based templates. In some Java-based frameworks for example, we put "view objects" into a velocity template. Those view objects are linked back to objects in the model, but they also perform on-demand rendering and formatting behaviour. Those are part of the view although they're not just a template.

It's a bit confusing with frameworks like ruby on rails and groovy on grails where they call the template the "view" - when a view is really more than just a template. Traditionally (in Smalltalk MVC and in Java's Swing) views are just code that can perform formatting, rendering and any other display-related behaviour.

cartoonfox
Thank you! But localization still causes issues for me. Your message_renderer looks like stateful domain service which knows about the user session (see also my comments below). Is it normal to call services from a view?
Andrey
It's not a service. It's a view object - and it will need to connect to model objects to get the right localised message although you can't see that from the fragment I used. I'm very suspicious of services because they're just chunks of globally visible functionality - nothing to do with MVC or object-oriented code!
cartoonfox
Well, you say that your View connects to the Model to get the user locale. If so why can't that View also "connect to the Model" to get the objects for viewing in this way - "repository.getBooks();"?Don't you see anything strange with this code? It seems that Controller is no more needed as your View can "connect to the Model". I think there is a mistake somewhere in your suggestions.
Andrey
This discussion is too abstract to be useful. I don't even know what platform/language you're using. I think there's some sort of misunderstanding here around you thinking that locales and locale-related data isn't part of the model. I can't imagine any reason why they wouldn't be. That's what I've done many times and it's worked just fine. Think of the model being "wrapped" in view objects and those objects could be different objects (or contain different objects) depending on the locale - or they could just do different behaviours by being different classes of view object... it depends!
cartoonfox
+1  A: 

Design Patterns 101.

Model is for storing data (usually database-backed).

View is for presenting the data (not manipulating it).

Controller is for manipulating the model and passing that to the view (choosing the right locale for instance would go here).

MVC doesn't necessarily mean you have 3 distinct classes, but rather 3 components or layers. These are abstract and don't necessarily have to be tied to one physical class. Inside your Controller layer, that can consist of any number of helper classes or whatever.

I agree with part of what cartoonfox is saying, everything is intertwined. For instance, if you develop a view for a shopping cart, but the model is containing birthday information, then it isn't going to work. It is simply a design pattern to help remove duplication of effort. When you have fewer variables and less noise, it is much easier to focus on what needs to be done and understand it very well.

I had a discussion with our team about using annotations to render forms on a web page. These annotations were placed in the model or entity class. You will often work directly with entity classes, so it eliminates quite a bit of overhead and duplication of effort if you put your annotations here. Because your annotations are placed directly on the model class, you cannot end up with a view for birthday information, it just isn't possible. In addition, by following patterns, you strip out the junk that doesn't add value to the end result. You simply write the business logic and close to nothing else.

Although the annotations were in the same class as the model layer, the presentation or view layer consisted of the annotations and the helper classes. It doesn't need to necessarily be distinct classes or boundaries.

Another example would be. I've worked on some PHP web "applications" in the past. I use applications because they were a monolithic block of code, more or less a single main method with all the logic in there (which is hardly a functional application).

If you don't abstract code into functions and simply use a single method, you will end up with a lot of duplication of effort. If you tried to understand that monolithic code block, you would be in for a heap of trouble (as was I, it was hard to learn what was going on, then I would find a similar block of code somewhere else and be dumbfounded why a few things were tweaked the way they were).

It can be done any way you want, but design patterns such as MVC help you simplify what you write in order to get it to work as well as more easily wrap your head around the solution. Another popular design pattern or approach is divide and conquer.

To answer your original questions:

In Java, localized data would be done transparently by the application. For instance, if you wanted US English locale support, you would create a properties file:

messages_en-US.properties

and then place all your US English content in there. Depending on how much content this may be, you might want to use a different approach.

For my application I have whole pages in a different language so what I do is this. My controller determines the client's locale or a best match. Then it chooses which view to display and passes the model (data) to the view.

If you need dynamic formatting for your date/times, then your controller is responsible for determining which one will be used. Then, your view is responsible for using that converter to format the value.

I'm using JBoss Seam so the MVC design pattern is still used, but more abstractly. I don't have actual 'controllers', but an interceptor which is responsible for handling a specific piece of functionality (determining the client's locale, then another for their date/time preference). My controllers that would be the equivalent of a Spring Controller are action components responsible for handling page actions.

Walter