Client-side MV* - Should the model have a save method?

angularjs, ember.js, javascript, knockout.js, model-view-controller

Solution

It depends on the pattern (and not at all opinion based imo).

Your first example: A domain object having a `.save` method is called an ActiveRecord (also see here).

Your second example: A mapper between the data mapping and domain layers is called a Repository (also see here)

Active Record pattern

Quoting Fowler:

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.

The ActiveRecord pattern generally excels at prototyping, and is a good idea sometimes in very small applications where there exists a 1-1 mapping between objects and DB rows. Generally, you want to separate the logic of persisting an object and the logic of an actual domain object, since they are inherently different responsibilities.

This is one of the simplest ways to logically handle the persistence of data.

For example, this is what Backbone models and collections do with their `sync()` method. Which causes them to persist to the server. It's often the reason you see larger Backbone applications not use `sync()` altogether in favor of implementing their own adapters. After all, in the Backbone world it forces a 1-1 mapping between your REST API and your domain objects, effectively making your domain objects and data transfer objects the same which can grow hard to maintain as your application grows.

Repository Pattern

Quoting Fowler again:

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

A repository is generally a better design pattern for larger applications since it removes the persistence logic from your domain object, so it does better separation of concerns.

Implementation wise, a repository usually looks like this:

However, to its users a repository might look like:

As any abstraction, another object for a responsibility has some overhead, however - as an app grows it starts to pay off. If you create a `$resource` with Angular and wrap it in a service that maps these objects from the db query to your domain objects (your data mapper) and then query that service like a collection - that's a repository for you.

Problem

So this is a generic pattern question but one I have been going back and forth with for some time. Should a model have a save method in MV*? I often jump back and forth between Knockout, Ember, and sometimes even Angular but one of the persistent questions I always have is should the model have a save method on it's class or prototype that knows how to save changes to reduce dependencies around the application on services (aka the model has a service for saving that all of the other view models / controllers inherit by knowing about the model) or should there be a service that each of the view models / controllers depend on that has a specific method for saving changes to the object? Example JavaScript pseudo-code ``` var person = new Model.Person(); person.name = 'Bill'; person.save(); ``` vs ``` var personService = require('services/person.service'); var person = new Model.Person(); person.name = 'Bill'; personService.save(person); ``` Both accomplish the same purpose of saving the person but in Example 1 the view model / controller doesn't know about the service or how it is implemented only that if you want to change a person, you save it. In example two obviously we have to know about not only the way to save it but how the save is implemented. Please read this before you answer - I realize that this is an opinion-based question but if you can back up your opinion with facts it will be factual, so please have references to back up any claims so that this is not closed as 'Primarily opinion based'

Original source