The Model

Entities taking the Model role are responsible for holding the running state
and business functionality of the application, either as a whole or as the part
that is relevant to that specific MVC Triad, as either data (stored values) or
activity (routines computing relevant data). They define the protagonists of
the application’s domain, their mechanism of operation and cooperation. Model
objects can represent, for example,

  • An interface to a database, filesystem, low level driver, hardware machine
  • Access to a computational backend.
  • Proxies for a remote service
  • A representation of business entities such as weather forecast in a
    specific area, people’s details in a phonebook, tracks information in a
    music CD, student grades
  • In some designs, graphical state of the GUI, such as selected items, or
    the X-axis scale of a plot.
  • A running process.

When implemented, a Model can go from a dictionary-like of key/value pairs to a
complex network of objects with well defined interfaces. Regardless of the
implementation, Models in Traditional MVC must provide the following three
services:

Querying: to inquire about their current state, either represented by
high-level domain objects (Object Oriented approach), or through an IO
layer of routines providing access to the data (Data Oriented approach). In the
Object Oriented approach, the Model objects generally represents an
identifiable part of the domain of your application, and provide access to data
through a well-defined object-oriented interface. The Model can also perform
computation, generally of information derived or associated to the main data it
represents. In the Data Oriented approach, the routines “speak the domain
language” and have high-level semantics to access the data, generally from a
data storage (e.g. disk).

Altering: to modify the current state. The Model interface provides set
methods or routines to modify its state. The Model performs consistency
checks about the data it handles, enforcing fundamental integrity: for example,
it can raise an exception or ignore the passed data if a method
setCurrentTemperature is called passing a string instead of a float, or a
method setLength is called with a negative value.

Notifying: to inform interested parties that a change has occurred in its
state. The Model allows interested objects to register themselves for
notifications. When a change occurs, these objects will be notified of this
fact and can act accordingly, normally by synchronizing themselves against the
Model’s new contents.

Model objects should provide core application functionality through a clear and
self-documented interface, exposing what can be done with the program’s state.
To operate, they can depend only on other Model objects or other components of
the application that don’t involve presentation, like an IO layer. The
relationship among Model objects is that of a strong dependency.

On the other hand, a Model should not contain nor be dependent for its
functionality on any graphical entity, nor contain formatting/visual logic for
presentation (e.g. logic to make a negative value represented in red, or logic
to present the date in US vs. ISO representation). Model objects should be
completely unaware of how user interaction is handled by the application they
live in, and should have a weak dependency toward its listeners via the
notification generic interface.

For data modification, all the Model does is to process incoming requests in
the form of method calls. Normally these requests are performed by
Controllers, but a Model can also change due to requests from other subsystems
(for example, a network layer), from another Model component or because it is
monitoring a backend (e.g. a database, or a filesystem) and the monitored
entity changes. The only entities never allowed to issue a change request to
the Model are the Views.

The Model should enforce integrity of the data, but it does not necessarily
enforce validity: data might be correct (for example, integers for min/max
values) but overall invalid for computation (for example, if min > max). While
integrity should be enforced, storing invalid data can be acceptable: depending
on the application, invalid data may be marked as such in the Model by the part
of the code that detects the invalidity, so that the View can represent it (for
example, with a red font); An invalid state might be needed as a stepstone to
reach a valid state at the end of a set of changes done by the User via the UI.

With the above guidelines and restrictions in place, the resulting
implementation is robust, flexible and testable: Views and Controllers are the
components that change the most as the application evolves, and a Model that is
agnostic to these changes is easier to code and maintain. The Model can be
tested independently from the rest of the application, and it opens itself to
scripting, allowing the User to change the Model programmatically instead of
through the GUI.

Not all Model objects are the same. We can generally distinguish three subclassifications
of the Model layer:

  1. - Service Model (Domain Model): the actual part of the Model that describes the
  2. business rules and objects.
  3. - Data access: responsible for serialization and deserialization of the
  4. Service Model objects and persistence.
  5. - Value Objects: data objects with particular characteristics so that
  6. their equivalence depends on their value, rather than their identity.

Keeping the application functionality fully supported by the model allows scriptability.
The Model can be modified programmatically with a script that replaces the user interaction.