Here is an implementation of "compound storages" in CPSSkins (this concerns the CPSSkins AJAX toolkit only so it also applies to Zope3 in general, or to any other server that can handle JSON requests and responses).

First of all, this is a great step towards simplifying the development of AJAX applications since it provides a complete abstraction between the model and the storage. The development model gets shifted from writing code in _javascript_ that moves data around places to defining a consistent data model. It is not necessarily easier unless one is used to creating application by first creating a model as opposed to starting by creating skins.

A data model needs some form of storage. There are many types of storages (persistent, volatile, with synchronous access, with asynchronous access, fast, slow, with low latency, with high latency...).
An AJAX application needs different types of storages to manipulate data locally, to store the results of some user action on a server, to provide temporary persistence for instance when editing a document, ... There isn't one type storage that is best suited for everything.
In the CPSSkins AJAX toolkit, there are three types of base storages available: the RAM storage, the local storage (cookie-based), and the remote storage (that uses accessors to get and set data via a remote server, e.g. Zope3).

A problem that occurs in the MVC model when many types of storages are available is that since a given view (a widget) can only observe a single model,  all the data will have to be stored in the same place and in the same way unless there is an indirection between the model and the storage(s).

The "compound storage" makes it possible to combine several models to set their respective storages in common. The "compound storage" is similar to a RAID controller: it uses several storages to create what looks like a single storage, also it dispatches the I/O to the different storages.

In the current implementation, the storages communicate with the compound storage and the compound storage communicates with the model using a simple event system (publish-subscribe with a extra message).

When some data gets stored in a given storage, an event is sent to the subscribers (e.g. the compound storage). The event then gets propagated to the model which relays the event to the view(s) which in turn get updated. This is completely event-driven, so no "user-space" controller is involved. The advantage is that it can occur asynchronously.

The compound storage defines a list of partitions. Each partition corresponds to the storage associated to a given model. The data stored in a model is accessed according to a schema which means that storages are protected against data corruption (such as changing the type of a field, or adding an unknown field).

There is a lot of complexity in the toolkit implementation, but this is as much complexity that gets hidden from the application: the controller simply needs to set data in the model it doesn't have to know anything about ajax.requests or cookies. I've started writing a simple live chat application, and all in all the entire application code consists in about 40 lines of code in zope3 and in a 3Kb page template.

The model definition can be created TTW, since the data is represented in JSON data structures, it involves no _javascript_. The only part that is _javascript_-heavy is the part that renders the widget, but there will be widget libraries.

The animation:

The toolkit code:

The code in Zope3:

The page template:

Here is the text seen in the animation:

CPSSkins: storage adapters

A storage adapter can be specified in the model definition to describe how the model will access the data.

There are 4 types of storages available:

  • RAM
  • Local (stores the data in cookies)
  • Remote (accesses a remote server)
  • Compound (a combination of several storages)

RAM storage

In a RAM storage the data is entirely stored in the client's memory. The server is never accessed. There is no data persistence.

Local storage

In a local storage the data is stored in a cookie on the client. The server is never accessed. There is data persistence as long as the cookie does not expire.

Remote storage

In this example the data is stored on the server inside the session. This provides some persistence which means that the page can be reloaded or the user can leave and return to the page and the current data will be restored.

An extra delay has been added when retrieving and when storing data to simulate network or database latency. Calls are made asynchronously which means that the browser can load the page entirely before the data is retrieved.

The user input is validated before the data is getting stored.

Finally the view gets refreshed when the model is updated.

Compound storage

A compound storage is created by combining the storages of different models.

In this example there are two storages:

  • A RAM storage for setting the status message on the client's side.
  • A remote storage for saving the answer and for setting the status message from the server's side.

Both storages are combined into a unique compound storage.

Hence the view (input box widget) still observes a unique model. The status message can be written to both by the client and by the server and the view will be automatically updated.

Zope3-dev mailing list
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com

Reply via email to