Back in the days as I wasn’t a Node.js developer yet, we used to have our MVC models implemented in a server side language such as Ruby (as in Ruby on Rails) and once again on the client side in JavaScript. In our newest project as we decided to use Node for our backend and was discussing on wether to use AngularJS or React for the frontend, I voted for React because I thought we don’t need to implement yet another MVC system (such as Angular) on the frontend. The rationale was to share the models on both server and client side and use a lightweight library (such as React) just for the view.
In the following I suggest a simple approach enabling the models to be shared both on the server and client side. The only assumption is that Node is used in the backend and JavaScript in the frontend.
Models
The models are inspired by Rails’ Active Record Models. Each model contains a list of properties and a set of validators. The basic stub (without specific implementation) is as follows:
Upon initiation the default
values merge with data
and from now on data
is the object representing the serialized version of the model and which can be exchanged between client and server as a JSON object.
validates
can be used in the constructor of any subclassing model to attach validators to specific properties. Next section elaborates on the concept of validators.
Validators
A class implementing the isValid(value) -> boolean
is considered a validator:
Validators can be attached to properties of a model and are invoked upon setting the value of that property by calling the set
method of the model. The BaseModel
maintains a mapping of property name to an array of validators.
The advantage of embedding validators inside a model is that you can use it both on server side (e.g. just before persisting data in a database) and the front end (e.g. just before submitting a form).
Serializing and Deserializing
Since the data exchange between the frontend and backend is succeeded in JSON format and both ends are written in JavaScript, the (de)serializing is done at little to no cost.
As mentioned earlier the data
object of any model corresponds to the serialized version of that model. Deserializing simply consists of instantiating an object of that model with the serialized data
.
The serialize
method of the BaseClass
can be overwritten if property values need to be manipulated before transmission.
An Example
Consider we want to model a nuclear plant:
The BooleanValidator
can be something like: