Design patterns are important to write maintainable and reusable code. A pattern is a reusable solution that can be applied to commonly occurring problems in software design — in our case — writing Chrome packaged apps. We recommend that developers decouple the app into a series of independent components following the MVC pattern.
MVC is composed of three components:
Model is where the application’s data objects are stored. The model doesn’t know anything about views and controllers. When a model changes, typically it will notify its observers that a change has occurred.
To understand this further, let’s use the Todo list app, a simple, one page web app that tracks your task list.
The model here represents attributes associated with each todo item such as description and status. When a new todo item is created, it is stored in an instance of the model.
For example, in the above todo list web app, you can create a view that nicely presents the list of todo items to your users. Users can also enter a new todo item through some input format; however, the view doesn’t know how to update the model because that’s the controller’s job.
The controller is the decision maker and the glue between the model and view. The controller updates the view when the model changes. It also adds event listeners to the view and updates the model when the user manipulates the view.
In the todo list web app, when the user checks an item as completed, the click is forwarded to the controller. The controller modifies the model to mark item as completed. If the data needs to be persistent, it also makes an async save to the server. In rich client-side web app development such as Chrome packaged apps, keeping the data persistent in local storage is also crucial. In this case, the controller also handles saving the data to the client-side storage such as FileSystem API.
There are a few variations of the MVC design pattern such as MVP (Model–View–Presenter) and MVVP(Model–View–ViewModel). Even with the so called MVC design pattern itself, there is some variation between the traditional MVC pattern vs the modern interpretation in various programming languages. For example, some MVC–based frameworks will have the view observe the changes in the models while others will let the controller handle the view update. This article is not focused on the comparison of various implementations but rather on the separation–of–concerns and it's importance in writing modern web apps.
To summarize, the MVC pattern brings modularity to application developers and it enables:
There are many different ways of implementing persistence with an MVC framework, each with different trade–offs. When writing Chrome packaged apps, choose the frameworks with MVC and persistence patterns that feel natural to you and fit you application needs.
Popular in both server–side frameworks like Ruby on Rails, and client-side frameworks like Backbone.js and ember.js, the ActiveRecord pattern places the responsibility for persistence on the model itself and is typically implemented via JSON API.
A slightly different take from having a model handle the persistence is to introduce a separate concept of Store and Adapter API. Store, Model and Adapter (in some frameworks it is called Proxy) work hand by hand. Store is the repository that holds the loaded models, and it also provides functions such as creating, querying and filtering the model instances contained within it.
An adapter, or a proxy, receives the requests from a store and translates them into appropriate actions to take against your persistent data layer (such as JSON API). This is interesting in the modern web app design because you often interact with more than one persistent data layer such as a remote server and browser’s local storage. Chrome package apps provides both Chrome Storage API and HTML 5 fileSystem API for client side storage.
In this pattern, the controller holds a reference to both the model and a datastore and is responsible for keeping the model persisted. The controller responds to lifecycle events like Load, Save, Delete, and issues commands to the datastore to fetch or update the model.
In some patterns, there is a supervising controller responsible for navigating between one MVC and another. The AppController decides, for example, that a ‘Back’ button moves the client from an editing screen (which contains MVC widgets/formats), to a settings screen.
In the AppController pattern, the AppController responds to events and changes the app’s current screen by issuing a call to the datastore to load any models needed and constructing all of the matching views and controllers for that screen.
MVC is crucial to designing Chrome packaged apps. We recommend the following CSP–Compliant MVC frameworks for writing secure and scalable Chrome packaged apps: