I'm curious about your thoughts on this subject that we have discussed with the people around me. Especially at the architectural stage, in which layer is the most optimal and efficient way to use the messages to be given to the end user (for example, your update was successful, you had an error while adding a file). When starting a project, at which layer should I handle these situations, should I manage them with a database, or is there a newer and more popular way? Also, should I manage these messages in aspect-oriented programming way? Thank you for sharing your thoughts and answers.
-
1I have the feeling the question is too broad. It seems to imply that the n-tier property is what matters, and leaves out many details that could affect the answer you get.– edalorzoCommented Oct 12, 2021 at 0:38
-
2I agree with edalorzo on this one. You're asking "abstract" questions as though you were speaking of "any" project – but, of course, you never are. No real-world projects are ever "abstract." When starting a project, "dive straight for the details, so that you'll be sure to find and then classify them." Once you're sure that you have done that, you can confidently begin to build "architectural abstractions."– Mike RobinsonCommented Oct 12, 2021 at 2:52
-
Answers can vary depending on what you mean by “tier”, the nature of the application and its final users. For example, messages from the backend tier (e.g. an HTTP API) are rarely intended for the end user. Most of the backend errors are API errors, intended for the programmers doing the integration, not for the end users of the system. Errors are subject to interpretation by clients and could be handled in different ways (e.g. retry, alternative flow). If frontend and backend teams are separate making the backend deal with i18n might have implications in how the software is built, etc., etc.– edalorzoCommented Oct 12, 2021 at 14:27
3 Answers
Conventional wisdom is to deal with user messages only within the "presentation layer". Conventional wisdom is wrong.
Let's be pragmatical and deal with things where it most makes sense. If your project is a user facing application, whether through remote "API" calls, or through an actual web interface, there is no reason to abstract it away from being a user facing application. That is, you could deal with users where ever you like.
If you deal with it only in the user-facing part, that might work for a static and very limited set of circumstances. You would have to return "codes" from every other place and deal with those meanings in the presentation layer. As soon as there are many of those messages, or even "parameters" for those messages, you will have a difficult time managing it.
And then you'll have to maintain that. Every time you have to add or change a message, add a new parameter, etc. you'll have to change multiple layers. It'll be a mess.
Instead, you could just make i18n and notifying the user of something a "cross-cutting concern", if you're thinking in "layers". Just have it available everywhere and then you can use it anywhere. Much easier, simpler, more pragmatical and more maintainable.
I'm not talking about AOP, but to simply have an interface with some abstract notions of sending localized user notifications. Have that passed "down" to any and every components that need it.
Standard disclaimer: I don't know your exact requirements. This solution may or may not apply to your project.
-
Actually, that's exactly what I wanted to hear. First of all, thank you for your answer @Robert, we don't have a project at the moment, but since we had a lot of discussions about this subject recently, I wanted to hear different opinions.– mtulunCommented Oct 12, 2021 at 13:36
The actual messages that are communicated with the user should come from the Presentation layer/tier. That is the only layer that should have to deal with things like internationalization (give the message to the user in their own language) or the way the user interaction works (a simple text console, a graphical interface or maybe a speech interface).
The other layers and tiers should provide enough information to the Presentation layer that it is able to construct the correct message for the user. Some of that information might be in the form of human-readable strings, but it should not be confused with the actual message to the user.
Messages you send to the user are generally about the domain rules. Most of the time you will have 2 or 3 types of messages : Confirmation, Error or Warning messages.
In a N-Tier architecture
:
The Confirmation messages are sent after everything went good, i.e a new inserted record. And should be send in the
UI-Tier
The Error or Warning messages are wrapped in exceptions as, your
Business-Tier
rules should be managed within custom exceptions. i.e :if(person.getAge() < 18) { throw InvalidAgeException("The age of the person is under 18"); }
The message you send to the user have to be clear and adapted to the domain.
In case you have a Rest API
, your message should be a customized Json
message adapted to the HTTP Code
returned values such as :
- 200 for Success
- 400-404 for Bad user inputs or Business Rules
- 500 for Internal server errors