This is a question I’ve to-and-fro’d with for a while, and searched for and found nothing on: what’re the accepted practices surrounding duplicating domain models in Javascript for a web application, when using a framework like Backbone or Knockout?
Given a web application of a non-trivial size with a set of domain models on the server side, should we duplicate these models in the web application (see the example at the bottom)? Or should we use the dynamic nature to load these models from the server?
To my mind, the arguments for duplicating the models are in easing validation of fields, ensuring that fields that expected to be present are in fact present etc. My approach is to treat the client-side code like an almost separate application, doing trivial things itself and only relying on the server for data and complex operations (which require data the client-side doesn’t have). I think treating the client-side code like this is akin to separation between entities from an ORM and the models used with the view in the UI layer: they may have the same fields and relate to the same domain concept, but they’re distinct things.
On the other hand, it seems to me that duplicating these models on the server side is a clear violation of DRY and likely to lead to differing results on the client- and server-side (where one piece gets updated but the other doesn’t). To avoid this violation of DRY we can simply use Javascripts dynamism to get the field names and data from the server as and when they’re neeed.
So: are there any accepted guidelines around when (and when not) to repeat yourself in these situations? Or this a purely subjective thing, based on the project and developer(s)?
Example
Server-side model
class M
{
int A
DateTime B
int C
int D = (A*C)
double SomeComplexCalculation = ServiceLayer.Call();
}
Client-side model
function M(){
this.A = ko.observable();
this.B = ko.observable();
this.C = ko.observable();
this.D = function() { return A() * C(); }
this.SomeComplexCalculation = ko.observalbe();
return this;
}l
M.GetComplexValue = function(){
this.SomeComplexCalculation(Ajax.CallBackToServer());
};
I realise this question is quite similar to this one, but I think this is more about almost wholly untying the web application from the server, where that question is about doing this only in the case of complex calculation.
2
I think good design patterns and a framework like Breeze can help you out. Don’t repeat the domain model on the client again, leave it on the server but use Breeze to pull the model to the client.
Here is a great example of using breezejs with the repository and unit of work patterns.
https://github.com/yagopv/DurandalAuth
The domain model is kept on the server and breeze reads the metadata and creates the entities locally from the server. I think this is a great solution to your problem. You get local entity framework type access locally via JS and you can keep your model on the server. I think it strikes a good balance of the issues you brought up in your question.
2
Your actual question is kinda more general so it’s hard to answer, but your form validation example is a little bit more specific, so I will try to stick with that one.
As you said you should always be DRY, as much as possible. That’s a good thing to keep in mind as a developer. However you should distinguish between the things that they are similar and you should avoid repeating them with the things that they does similar things, but they have different Purposes.
Let’s get to your form validation example. The purpose of your validation code on the server is to make sure that you have the user’s email address for example to put into the database. So as it’s a must for your registration process to have the email address of the user, you’re checking that during the registration process.
But what is the purpose of your client-side JavaScript code? Yes, it does the validation on the email input field, but the whole idea is: To check if the user has already entered their email address, if not show them an alert BEFORE sending it to the server! So the purpose of your client-side form validation is to stop sending useless data to the server and show an error message after a few seconds to resend the application form again. Why? because it’s annoying for users. Now do you think you should keep your form validation function only on the server? No, because they have different purposes.
The purpose of the form validation on the client-side is not I can’t trust users, let’s check it out, but it’s more of a UX thing where you’re trying to avoid communicate with server just to get the validation error message; However the purpose of the form validation on the server-side is that I can’t trust the users, let’s see what they’re asking me to do, and a User can be an API request as well — without any human-user on the client-side.
If you look at it like this, your form validation example would be totally fine, without making you feel WET.
Regarding your actual question, don’t try to keep everything on the server or everything on the client; It really depends to the task. Let say if I need to parse a big-big CSV file for the user and I have only a hundred users on the website and I know that I have mobile users, then I can parse that file on the server and then output a proper easy-to-digest markup to the client. However if I have millions of users, then I’d try to parse the file on their machines — using their web-browsers to use their processing power to avoid burning out our server. So the the parsing functionality could be either on the server or client, whatever makes more sense.
However if you’re not sure where to keep your things, then I’d say keep them on the server and then serve the results to the users — avoid duplicated code on both server and client.
1