Yesterday I ran into a problem trying to figure out where to localize error messages.
We are using a MVP (Model View Presenter) pattern for our web based application. I was working on refactoring some code to move the business logic which handled the parsing of a file out of the view layer and down into the model.
When my file parsing class encounters errors it needs to be able to send those errors back up to the view to be displayed to the user.
Since there could be multiple errors and we don’t necessarily want to stop parsing the file if we hit an error, we need a way to batch up those errors to be sent up to the presenter to give to the view.
It is easy enough to come up with a list of strings of error messages until you consider the problem of localization.
Should the file parser really need to know anything about localization? Should it even really deal with error message strings?
IErrorMessage to the rescue
Once I came across the solution it was obvious to me.
Why not have the error message localize itself? In fact, why not give the message the data it needs that is specific to that instance and let it construct itself?
It turns out to be a very clean solution. The responsibilities are clearly separated. Let’s take a look at the new flow.
- Presenter hands a data source to the file parser to parse.
- Parser begins parsing the file.
- When parser encounters an error, it creates a new typed error message which implements IErrorMessage.
- The list of error messages is returned to the presenter.
- The presenter loops through the list of error messages asking each one for its generated message. (The presenter doesn’t know anything about localization here).
- The error messages use their internal data and localization to generate a localized error message for the presenter.
- The presenter passes the generated strings to the view.
Why all the hoopla?
Why not just localize the strings inside the file parser?
Ideally we don’t want either the presenter or the parser to have to know anything about generating strings from bits of data and localizing those strings.
By doing this, we make the software easier to maintain and debug, since only one thing is happening in one place.
Want to change how the file is parsed? Look in the file parser; error messages still handle generating their string representations, without you having to know how.
Want to change how an error message creates its string representation? Just look at that error message class.
Not even the presenter needs to know about how error messages are formatted or generated, it just needs to know that it has some errors and it can tell the errors to give it a string representation.