Now there's one more layer that's not officially part of the MVVM pattern,
but is often used with MVVM to further separate
concerns and avoid duplicate code.
That's the client services layer.
Client services encapsulate any shared logic that spans more than one ViewModel.
This could be utility code, data access code, security services, and so on.
So this layer logically sits underneath the ViewModels and
can allow the ViewModels to remain decoupled from things
that may change over time,
such as your data access strategy, as well as any functionality that's
needed in more than one ViewModel. A common form of client service is
one that insulates the ViewModel from the specific data access strategy
based on the repository pattern.
For example,
your app may start out as a simple two‑tier application that talks directly
to the database to get and update the data for your model.
But then you decide to support a more distributed scenario,
and you need to change things so the client makes
web service calls to get its data.
If you have the code that reads and writes the data encapsulated in the
client service, the ViewModel and View should not have to change at all when
this change is made. All the changes would be encapsulated in the
implementation details of the client repository.
Additionally,
as part of reading and writing the data to whatever back end you have, a
repository can also act as a client‑side in‑memory cache for data that
does not change frequently on the back end,
such as lookup lists. It can also cache transient changes made
by the client that have not been persisted to the back end yet,
even if you navigate off the current View or ViewModel that
first managed those changes.
So the MVVM pattern forms a layered architecture for the client side.
The model objects are produced by the client services layer and can be used,
exposed, or wrapped by the ViewModel layer.
The View gains access to the data exposed by the
ViewModel through data bindings.