In my view, if itās an intrinsic attribute of the model (like in the example, a full name is a characteristic of a person regardless of context), it should be defined in the model, to avoid duplication.
In Ember.js, controllers allow you to decorate your models with display logic. In general, your models will have properties that are saved to the server, while controllers will have properties that your app does not need to save to the server. http://emberjs.com/guides/controllers/
āfullNameā property is simply a decoration of the model and belongs in the controller. Maintaining a clear separation of concerns is what makes the structure of Ember so powerful.
As an example, think about the different ways you could implement fullName.
First Last
FIRST LAST
Last, First
Etc. Would each of those go in the model? You might only use one now, but what about two years from now? Data decorations are primarily concerned with the UI, so you generate and store them closer to the UI. It helps with change management.
In practice, they both function, and the wrong way is even quicker to develop. Code spends more time in maintenance than development though, so the best practice is to develop for easy maintenance.
@kylecoberly I tend to agree that ādata decorations primarily concerned with UI ā¦ (should be) stored close to the UIā, but I lean towards @funtusovās reasoning - I agree that in Ember the model is the best single, central place of reference, as a model may share many controllers.
I see Ember as a framework offering built strongly upon the concept of data models and therefore that the centricity of its data is of high importance.
And further, since these such values are not being pushed back to the server I canāt reasonably justify the performance or data integrity arguments.
IMO, the pattern is that model is a single source of TRUTH. A fullName is not truth, itās an opinion on how two pieces of truth should be combined. Itās entirely possible that this distinction is trivial to your application (or Discourse), or that āfullNameā is a well-enough understood computation that you have nothing to gain but performance by storing it in your model. Bottom-line, if you do this, absolutely no one on your team is going to call you a dummy, and youāre probably not going to lose a job if you answer this on an interview question.
Your original question was about patterns, and I would rules-lawyer about this absolutely being an anti-pattern. I want whatever is controlling my data to only care about what the lowest level of truth is. What fullName, or mailingAddress, or combinedSocial might be in my application could be completely different in someone elseās, or in mine a month from now, or in this page when I change how it works. This pattern allows you to have one version of fullName on one route, and a different one on another route. This is super-desirable when those routes are developed by different people who donāt talk to each other as much as they should.
Really, the entire philosophy of data design is based around some truly conspiratorial worries- āWhat if three middle names becomes the standard?ā or āWhat if global addresses become single integers?ā Good application design is impervious to these changes because of patterns.
In the brutally honest real-world, no one is going to use your application except you and maybe your client. Storing a computation in the model (why not the database!) is faster. So is denormalizing. Patterns will protect you from when the entire use-case shifts. Itās a 100% judgement call whether the pros outweigh the cons on that for you.
The pattern is to keep any opinionated, domain-specific data implementation away from persistence as much as possible. For me, that would include ember models.
All the data manipulation ideally should be managed by a Controller. That is its purpose. If you have some on your models and some on your controllers that could create an undesirable mess. I have personally experienced that and it created confusion. Remember, that models canāt access controllerās properties.
Mixins or object inheritance will help you to avoid repeating it in several controllers.
In regards to discourseās models, it would be interesting to hear from @eviltrout
This is one of those cases where I have to remind people that the Discourse code base is far from perfect! Itās gone through years of Ember updates and patterns and while we try to fix things as we go along, there are always things Iām unhappy with.
I believe computed properties are almost always the controllerās job. Going forward I am trying to make all models super lean and extend display logic to the controller layer.
Having said that, you can make good arguments for putting them in the model that I wouldnāt disagree with. Letās say itās a property that is expensive to calculate but you are going to show over and over again? I canāt honestly think of one off the top of my head, but that would be a good thing to put in a model as a CP for the caching.
Iām now satisfied that this is the most ideal way to assign reusable computed properties without assigning directly on either a Model or a Controller. Although itās fair that we all agree that properties may still be assigned directly to Controllers or Models if they are not be reusable or significant enough to afford caching respectively.
You probably donāt want multiple controllers handling the same model. You can have a dependency between controllers with needs or you can specify a controller in the route with controllerName.
You could have a currentUser controller, holding a user model, or your user routeās backing controller, which holds the user model How you structure this is more of a UI concern, and doesnāt always have to map 1:1.
Computed Properties could go in both models or controllers, they are very useful, for more than just decorating. There is no reason to constrain them to a specific layer. If they feel like they belong on a model, just put it there. Another big win is that now the user object has the full name property everywhere it is used instead of on a case-by-case basis per controller.