Concepts
The following sections give a brief overview of the design concepts (patterns) the SAF is based on. In order to take full advantage of the classes and functionalities the SAF provides, the developer should have a good knowledge of these concepts.
MVVM design pattern - Separation of concerns
The basic idea of the MVVM pattern is to separate the logic that can be activated in a view, from its appearance and to separate the data the logic is based on, is separated from the logic and the view. Thus, following the MVVM pattern, the implementation of a visual component in an application consists of three parts:
- Model: The model is the domain model of the data which is presented in the view.
- View: The view is the visual element of the application, for example a window, a page, a tab item or any other kind of control. Using WPF, the view is defined in xaml and ideally its code behind is free of logic and data.
- ViewModel: The ViewModel holds the data objects which are stored in the model and presented in some kind in the view. The ViewModel is the connection between the view and the data model and in this way it implements all the logic to change and update the data presented in the view and stored in the model.
Managed Extensibility Framework - Inverse of control / dependency injection paradigm
The Managed Extensibility Framework (MEF) is a part of the Microsoft .NET Framework, with types primarily in the System.ComponentModel.Composition namespace. It is a composition layer for .NET that improves the flexibility, maintainability and testability of large applications. MEF can be used for third-party plugin extensibility, or it can bring the benefits of a loosely-coupled plugin-like architecture to regular applications. MEF is shipped with .NET 4.0. Imagine a large application that must provide support for extensibility. Furthermore, this application has to include a potentially large number of smaller components, and is responsible for creating and running them. The simplest approach to the problem is to include the components as source code in your application, and call them directly from your code. This has a number of obvious drawbacks. Most importantly, you cannot add new components without modifying the source code, a restriction that might be acceptable in, for example, a Web application, but is unworkable in a client application. Instead of this explicit registration of available components, MEF provides a way to discover them implicitly, via composition. A MEF component, called a part, declaratively specifies both its dependencies (known as imports) and what capabilities (known as exports) it makes available. When a part is created, the MEF composition engine satisfies its imports with what is available from other parts. The SAF uses MEF and furthermore relies on the fact that the software developers which use the SAF also take into account the advantage of MEF. Thus, the SAF provides tools to automatically setup the composition container for WPF applications with all parts the SAF provides. In addition, the SAF offers a class, called ServiceFactory to easily import SAF components that are exported into the CompositionContainer
An introduction to the concept and usage of MEF can be found on the following site http://msdn.microsoft.com/en-us/library/dd460648.aspx
Repository and UnitOfWork pattern
The SAF provides base classes to implement data access on the following two design patterns, the Repository pattern and the UnitOfWork pattern which are now described in brief.
-
Repository pattern: Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
A system with a complex domain model often benefits from a layer that isolates domain objects from details of the database access code. In such systems it can be worthwhile to build another layer of abstraction over the mapping layer where query construction code is concentrated. This becomes more important when there are a large number of domain classes or heavy querying. In these cases particularly, adding this layer helps minimize duplicate query logic. A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
-
Unit of work pattern: Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
When data is pulled in and out of a database, it's important to keep track of what you've changed; otherwise, that data won't be written back into the database. Similarly new objects have to be inserted when they are created and removed when they are deleted. When the database updates with each change to the object model, this can lead to lots of very small database calls, which ends up being very slow. Furthermore it requires an open transaction for the whole interaction, which is impractical for business transaction that spans multiple requests. A Unit of Work keeps track of every change during a business transaction that can affect the database. When the transaction is done, it figures out everything that needs to be done to update the database as a result of the transaction.