MVVMCS – Model, View, View Model, Controller, Services - the outcome of combining the aspects of different models of MVC: MVC, MVVM, MVCS
About this article
Below you will find an extract of best practices related to MVC in the Daymo approach drawn from different sources, Design Patterns and frameworks. The main goal is to find and offer you the best and most optimal way of coding both simple and complex projects.
You will find very basic examples and summaries on benefits and possible pitfalls.
Some basic assumptions on coding
But before we start, let’s focus briefly on the basic assumptions we took on Daymo and coding.
We assume that:
- Every project is different and comes with different demands on structure and approaches to solve problems
- Change is inherent to building an application. Your code and your application is a growing and changing entity as your project and time progresses.
- Restructuring and refactoring will recurringly happen along the way. At several stages in your development, you will restructure the way your code is organized. Including the places where you execute specific procedures.
The following five aspects are therefore key to Daymo:
- Separation of Responsibilities - A way to define what belongs where, based on what it does.
- Promoting- and Demoting code – A way to refactor you code to get clearer project structures.
- Model Driven design - Using the data model to tell your views what to do and how to respond.
- Event Driven design – Using events to tell “something” that “something” has happened “somewhere else”.
- Parameter Driven design – Using parameters and Composition instead of creating Custom Classes to distinct and create Objects of the same type with different types of behavior.
Apart from that:
- Use Strong Typing for variables and return types of functions – It will help you greatly when building your application and re-factoring and restructuring your code
The core goal of Daymo
The core goal of all below is to provide you with a structure that will:
- Simplify your software design.
- Reduce dependencies in your code and application.
- Increase the stability of your application (make it unbreakable).
- Make your code easier to refactor.
- Reduce Boilerplate code as you will only do what is necessary for the project and also find easier ways to re-use code
- Reduction of Classes, Code and Files as you create objects with specific behaviors via Parameters and Composition (Parameter Driven Design) and can address (self protected) objects directly instead of via layers of mediators and managers.
It is understandable that Daymo might approach things different from what you have been using and doing before and also might break some approaches which are considered to be “best practices”. Frameworks, for instance, invite you to think, look and work in one specific direction, solving problems in a very specific way to that Framework. So it might also bring you:
- Stress and frustration from learning a new approach which might be alien to you.
- Resistance from doing things you have been tought to be “wrong”.
- New insights into stuff you took for granted before.
.
MVC, MVVM and MVCS
There are many different opinions on how MVC should and could be implemented. Each of them add their own value and neither of them is the ultimate solution. To understand the basics of MVC I went back to the original definition by Steve Burback here and also to this one quoting an unfindable paper by Dean Helman.
MVC
The Model, View, Controller pattern
The MVC pattern is the most common. It stands for “Model”, “View” and “Controller”. Below you will find each more closer defined.
According to the definition of Dean Helman, the MVC pattern originates from this flow:
[User] Input –> Processing –> Output
Controller –> Model –> View
As you will read in the quotes and the next chapter, the Model is more than storing and providing data alone. The Model also contains all your application logic, including classes to process data and execute business logic. Quoting quotes from Dean Helmans Objective Toolkit Pro whitepaper:
a model encapsulates more than just data and functions that operate on it. A model is meant to serve as a computational approximation or abstraction of some real world process or system. It captures not only the state of a process or system, but how the system works.
MVVM – adding the “View Model”
The Model, View, View Model pattern
When using the MVC pattern, you will find you have two types of “Models”:
- Dealing with View Specific data (the View Model)
- Dealing with a lot of processes and things that eventually will produce data to be presented or rendered in your View (The Model)
The MVVM pattern makes this Separation of Responsibilities easier. You will see in the “Combining best practices” below how we recommend you to apply the MVVM pattern with MVC in flex. MVVM is credited to John Gossman.
MVCS – adding Services
The Model, View, Controller, Services pattern
As an application is also loading and storing data from and to external data sources, the MVC-pattern has been extended with “Services”.
Services are called to to specifically that: accepting, loading and storing any type of data from any type of external source. MVCS is apparently intorduced to the (Flex) community in 2006 by Joel Berkovitz
Combining the best practices
Huh? 3-Tier!
Looking at the structure that emerges here, by combining MVC, MVVM and MVCS, you will find many parallels with the 3-Tier approach which consists of:
- The Presentation Layer / Tier – Represented here in the User Interface Domain.
- The Business Layer / Tier – Represented here in the Application Logic Domain.
- The Data Layer / Tier – Represented here in the Services Domain.
(MVC – according to WikiPedia – is an older structure than the 3-Tier approach. Where 3-Tier emerged in the 1990′s, MVC originates from the late 1970′s.)
Handling this setup according to Daymo
With Daymo you make a distinction between User Interface specific and Application Logic specific domains.
The Application Logic Domain is Data- and Business Logic Centered and contains all the code required to run the Application. This includes generic View States and Application States but excludes View-specific code.
The User Interface Domain is View Centered and contains all the View-specific code. The Views will therefore instantiate the Controllers and the View Model Objects
A View Object instantiates the View Model Object and the Controller Object.
A View Model Object connects to the Application Model and Application Logic via an Object Request on an Object in the Application Model. This request is a Static Function on the Object itself.
A Controller observes the View and deals with events happening in the View, to update the View Model Object.
Services are invoked from the Application Model Domain.
We will go into the different aspects of this setup later in this document.
.
The Model
The most common description of the Model and it’s role is like this (from Wikipedia):
The model is used to manage information and notify observers when that information changes. The model is the domain-specific representation of the data upon which the application operates. Domain logic adds meaning to raw data (for example, calculating whether today is the user’s birthday, or the totals, taxes, and shipping charges for shopping cart items). When a model changes its state, it notifies its associated views so they can be refreshed.
The problem is: how do you translate this to anything? Based on the description above we deal with data, information management and notifying observers when things changes in the model, but nothing clear about where to put “the smart stuff” and how to organize, categorize and name that stuff. Searching further, I came to this definition of the Model on OOtips (accredited to Dean Helman):
[The model is used] to manage information and notify observers when that information changes. [...] It contains only data and functionality that are related by a common purpose [...]. If you need to model two groups of unrelated data and functionality, you create two separate models.
[...] a model encapsulates more than just data and functions that operate on it. A model is meant to serve as a computational approximation or abstraction of some real world process or system. It captures not only the state of a process or system, but how the system works. This makes it very easy to use real-world modeling techniques in defining your models. For example, you could define a model that bridges your computational back-end with your GUI front-end. In this scenario, the model wraps and abstracts the functionality of a computation engine or hardware system and acts as a liaison requesting the real services of the system it models.
The Model in brief:
- Represents a real world process or system
- Captures the state of a process or system and how that system works
- Manages information
- Notifies observers when information changes
- Contains data and functionality
- The data and functionality are related by a common purpose
- You can have multiple models – unrelated functionality and data are placed in a separate model
Now each of these are pointers, giving you an idea where to look for what. The purpose of the next part is to make some practical sens out of this and put it into something you can code. To do that, let’s state some more definitions first.
Model Objects
As the Model is the sum of all parts, we choose to refer to the Model parts in general as Model Objects.
Separation of responsibilities
When you look at classes inside the model, the most common are the Value Object, the Object, the Manager and the Handler. Let’s put them in line.
- The Value Object (VO) – The Value Object is completely stupid. Its only function is to contain data.
- The View Model Object (VMO) - The View Model Object is directly related to the View.
- The Object – The Object is your generic all purpose thing and a bit smarter than the VO. It holds data like the Value Object and is able to perform specific simple actions.
- The Handler (HND) – The Handler is created to perform or “handle” specific but simple actions, like loading files, sending data to the server, and parsing data from one format to another.
- The Manager (MGR) – The Manager is created to deal with the more complex issues. It usually deals with multiple issues from multiple sources, managing them using specific rules. Managers use and (can) contain the Business Logic and uses the Business Rules of your application.
Promoting and Demoting your code
Let us assume that in most cases you start with an Object. This Object has some internal logic and performs specific actions. When that internal logic grows, you might want to start separating it into different logic blocks.
Code Promotion and Code Demotion is just another way to say:
- “This part of code does more things or smarter things than should happen in this specific Class”
- “We should extract this specific part / these specific variables and place it in a separate class”.
- Promoting your code
A promotion means that the code moves one or more steps up the ladder. So code inside your Object that is more than – let’s say – 10 lines, does smart stuff or handles specific things and shows ambitions to grow even more, will become a Handler or Manager.
- Demoting your code
When you are only storing values inside an Object and it turns out to have no intelligence at all, you demote the Object to become a Value Object.
Handlers
The Handler can be split up into separate parts, doing very specific things. In practice you will find:
- The Parser – Parsing data from one data-format or data-structure to another.
- The IOhandler, which can be split into:
- The (Data) Loader - Loading data from a server or device
- The (Data) Submitter – Sending data to a server or device
- The Verifyer – Veryfying data and variables based on Rules or Business Rules
- The Wrapper or Adapter – Adding extra functionalities and handles to an object, to make it complient to your specific needs
- The Controller – Doing very specific stuff based on user actions and user interactions
- The View State Engine – Doing very specific stuff with the View, based on internal and external settings and values.
- Utilities – Doing very generic but time-saving stuff which you can re-use in any project. Like: validating e-mail addresses, cleaning up objects, copying values from one object to another and so on.
Managers
Managers can be split into different levels of management in your applicaton:
- Managing Items – Dealing with the low level parts in your application, making sure everything is done right.
- Managing Views - Dealing with what is visible and hidden, kept persistent or treated as disposable items (thrown away once used)
- Managing Application Parts – Dealing with a very specific part of the application, like “The 2D drawing area” of an paint-application
- Managing the Application – Managing the overall flow of interactions
Static functions on Managers
Managers are there for other parts of the application to be used. To avoid Object Instantiation Dependency, Daymo promotes to use Static Functions on Managers so that you can directly ask a Manager to perform a specific task without having to care where or by whom it is instantiated
Application Models and View Models
As stated before, a Model is the sum of all parts. In the case of coding, these parts are Objects. Looking at an application you will find Objects dealing with Application Logic and Objects (in your Model) dealing with Views.
Based on the best practices of MVVM (Model, View, View Model) we recommend to create View Models to deal with the data in your View and communicate to other Objects in whatever Model there is: to store and request data.
Once you start doing that, the Objects in your Model start to form (at least) two camps:
- View Model Objects – Dealing with your View and requesting data from and sending data to other Objects in your Model
- Other Objects – Dealing with other stuff like: the logic of your application, handling things, managing objects and application parts, etcetera.
This is where the Application Model and the View Model concept starts.
The Application Model
The Application Model contains all the logic and Objects that run and manage your application. This includes:
- Managers – Doing smart things and executing Business Rules
- Handlers – Handling specific processes
- Generic Objects - Doing and handling very simple things and storing information about the objects they represent
- Value Objects – Containing only data
- Business Logic – Dealing with the more complex decisions related to the application
- Business Rules – Offering a simple way to find out whether something complies to specific rules
- Services – Getting data from- and submitting data to- some external source.
- Application States - Telling you what is where and telling your Views to respond
This excludes:
- Controllers
- View-specific Models or View-specific Value Objects
- View-specific View States
The View Model
The View Model contains all the Classes that deal with and store View-specific data.
This includes:
- View Managers – Managing Views and View states according to business rules
- View Handlers – Handling specific things for specific views
- View Value Objects – Containing View specific data
- View-specific View States – Telling the View what to show and hide
This excludes:
- View Objects – Being represented in either State Machines or Controllers
- The Controller - Dealing with user input and user interaction
Object Requests – Connecting from a View Model to the Application Model
And more neutral:
There is no strong binding between objects in the Application Model and the View Model. They are two separate worlds without any direct knowledge to each other, except for the knowledge (by the View Model Object) of the existence of specific Classes with specific handles (comparable to an API) in the Application Model.
Basic rules of thumb:
- The View Model connects to the Application Model via an Object Request.
- The Application Model never connects to the View Model.
- The Object Request is done via a Static Function in the Object in the Application Model.
To connect to any Data Source or Service in the Application Model in most cases a Static Function is used directly on the Class.
// We need an instantion of an object in the Application Model var myInstance:AppModelObject=AppModelObject.getObject();
getObject can be either a provider of:
- A Singleton Instance – Being the same object anywhere.
- A Multiton Instance – Being a specific object based on an input variable.
- A new Object – Created on request.
- A Recycled object – coming from the recycle bin of that object.
We never assume anything about the returned Object from the perspective of the View Model. We fully trust that the provider knows what it is doing when providing either a Singleton, Multiton, new Object or Recycled object.
You might choose to be more specific in calling the Object Provider. The call will then look something like this:
// We need an instantion of an object in the Application Model var myInstance:AppModelObject=AppModelObject.getAppModelObject();
The markup of the Object Provider
The Object Provider is something you create yourself, in your own Classes. Below you find four examples of an Object Provider.
The principle in Daymo is to cal the Object Provider function call “getObject”. getObject is a Static Function and looks like this:
// For a singleton public static function getObject(): MyObject { if(_instance==null) { _instance=new MyObject(); } return _instance; } // For a multiton public static function getObject( objectKey:<some type> ):MyObject { var myObject:MyObject=_myDictionary[objectKey]; if(myObject==null) { myObject=new MyObject(); _myDictionary[objectKey]=myObject; } return myObject; } // For an Object public static function getObject():MyObject { return new MyObject(); } // For a Recycled Object pubic static function getObject():MyObject { var myObject:MyObject; // Get from recyclebin if(_recycleBin.length>0) { myObject = _recycleBin.pop(); } // Or create new one else { myObject=new MyObject(); } }
Benefits:
- Direct but Protected Access to onbjects in the Application Model – Each Object in the Application Model implementing this approach is directly accessible, in a protected manner, so that you can not break the application by accedentily instantiating an object the wrong way.
- Internal Object management – The Provider of the Object Instances is also the manager of the rules related to the type of instantiation (singelton, multiton, recycled, new).
- Simplified Object management / No Object Management Dependencies – There is no need to manage the Object Instantiation on other places in your application (other than in the Object Provider itself).
- Agnostic code – Your code only needs to know how to get the object. How it is managed is dealt with somewhere else.
Critiques:
- Diverts from Flex Approach – This approach to get objects from the Application Model diverts from the Flex Approach and is structurally different from other frameworks.
.
The View
The View contains all visible elements, like Buttons, Lists and Text fields.
In Daymo the View is stupid. It contains no code, except for the bare basics you need to instantiate the Controller and the View Model Object.
Building the View
Phase 1: building what you need – In Flex you will normally start building your View code inside the MXML of your View. There is nothing wrong with that. Your code might look like this:
<mc:Canvas>
<mx:formatter id="myFormatter" />
<mx:Button click="onClick(event)" label="my Button" formatter="myFormatter"/>
<mx:DataGrid dataProvider="{myProvider}" filterFunction="{onListItemFilter(data)}"/>
<script>
<![CDATA[
[Bindable]
var myProvider:ArrayCollection;
// This can be moved to a Controller
private function onClick(event:MouseEvent)
{
// Do Something
}
// This can be move to a State Machine
private function setState(state:String)
{
// Hide, show or move something in the View
}
// This can be moved to an Handler class
private function onListItemFilter(object:SomeValueObject):Boolean
{
// Check if this item complies to conditions // Returns false if not
}
]]>
</script>
</mx:Canvas>
Phase 2: evaluating your MXML code – Basic rule of thumb: When you have more than 30 lines of code and/or your code takes more real estate than your screen provides, it is time to start separating it from the MXML.
Phase 3: Separating Responsibilities – When you look at the code in your View it usually either:
- Does someting with something else, based on events triggered by the User – This is moved into a Controller.
- Handles something of something inside your View, like running through data in a list to filter stuff – This is moved into a Handler.
- Influences the State of your View (hiding, showing or moving stuff), based on something happening somewhere inside or outside your View – This is moved into a State Machine.
- Formats something in your View, like colors of elements and specific notations of (telephone) numbers – This is moved into a Formatter.
Each of the Objects from these Classes are instantiated by the View. The reference to the View is Injected when the specific object is Instantiated.
<mc:Canvas creationComplete="init()"> <mx:Button label="my Button"/> <mx:DataGrid dataProvider="{viewModel.myProvider}" /> <script> <![CDATA[ var viewModel:MyViewNameVM; var controller:MyViewNameController; var handler:MyViewNameHandler; var stateMachine:MyVieNameStateMachine; var formatter:SomeSpecificFormatter; private function init() { // viewModel uses the Bindable options of Flex to signal changes viewModel = new MyViewNameVM( this ); // The Controller will internally attach Event // Listeners to buttens and what have you controller = new MyViewNameController( this ); // The Handler will deal with filters on lists and other // stuff that needs "handled" handler = new MyViewNameHandler( this ); // The state-machine will deals with making items visible and invisible // Based on specific rules stateMachine = new MyStateMachine( this ); // The Formatter attaches formatters to specific objects formatter = new SomeSpecificFormatter( this ); } ]]> </script> </mx:Canvas>
Phase 4: generalize your code – It might be that for each form you have in your project, the data is collected and sent in exactly the same way. This might lead to a generic function that looks at the display list of your form, picks out all the objects of a specific type and collects and structures the data in such a way that you can send it directly to the Server. The key questions for generalization are:
- Did I already do something like this somewhere else? – If so, you are very likely repeating a pattern that can be generalized.
- Can I make this into something that is re-usable? – This is the tough one. Very likely: yes.
- Is it worth the effort? – If your generalized code is only useable on two places in your code and you will never need it again, you might consider leaving things as they are.
Instantiating your View Model Objects, Controllers and Handlers
As we already gave an example of a cleaned up View, below you will only find the <script> part, as shown above.
<script>
<![CDATA[
var viewModel:MyViewNameVM;
var controller:MyViewNameController;
var handler:MyViewNameHandler;
var stateMachine:MyVieNameStateMachine;
var formatter:SomeSpecificFormatter;
// Called "oncreationComplete"
private function init()
{
// viewModel uses the Bindable options of Flex to signal changes
viewModel = new MyViewNameVMO( this );
// The Controller will internally attach Event // Listeners to buttens and what have you
controller = new MyViewNameController( this );
// The Handler will deal with filters on lists and other // stuff that needs "handled"
handler = new MyViewNameHandler( this );
// The state-machine will dela with making items visible and invisible
stateMachine = new MyStateMachine( this );
// The Formatter attaches formatters to specific objects
formatter = new SomeSpecificFormatter( this );
}
]]>
</script>
All the View-specific classes share the same name as the View. This makes referring and code-organizing a lot easier as your editor very likely has code-completion and other ways to help you while typing.
Motivation behind- and benefits of this approach
Even though Flex allows you to write code in your Views, this is not really recommendable. You are basically doing the same thing people used to do in HTML: mixing presentation stuff with coding stuff. While this is OK for small projects, your integrated code becomes less and less maintainable as your project grows.
The biggest pitfalls you can avoid by externalizing your code are:
- Code repetition – It is easy and also very tempting to make quick builds by Copy & Paste the code you already made throughout your application. However, when you change your approach, this might also lead to
- Code clutter – As the complexity of your View grows, so does the amount of functions and procedures. By Separation of Responsibilities and externalization you cut your code into clear parts which are stored in a clear place.
The main benefits are:
- Clear separation of responsiblity – Your code is broken up into clear modules, each with a clear purpose and function
- Easier to refactor – As your code is externalized, functionalities in your View can be changed or extended by using and adding other Classes.
- More inviting and stimulating to generalize your code – When you start externalizing your code, you also (very likely) automatically start to seen new ways to do things smarter and more efficient. For instance: when you do the same thing on multiple places, with only slight changes in the code, it might suddenly become rewarding to generalize those parts, so that one function and one method is doing it all for everyone. This also helps you big time when you need to refactor those specific parts.
.
The Controller
The controller deals with all events on the view, induced by the user. It retrieves data from the View and passes this to the View Model Object. It can also retrieve data from the View Model Object.
In Daymo, the Controller is separated from the MXML code.
Registering Events
Although Flex provides a simple and clean way to attach Events to any object in the View, Events are best attached from the Controller, using ActionScript.
// Attaching an Event to an object in the View myView.myButton.adEventListener(MouseEvent.MOUSE_UP, onMouseUp)
This seems retarded at first when you are used to the simple event dispatchers in MXML, but starts making sense when the same pattern is repeated for any button in your View.
Registering Events with a Handler Object
When you find that code is repeating, you might want to bundle the repetitive code. For instance: on mouse over the object receives a glow, on mouse-out the glow dissappears.
// HANDLER OBJECT public class mouseGlowHandler implements IMouseHandler { // Function to deal with repetative actions public function addObjectMouseHandler( object:UIComponent ) { // Add eventlisteners to the object object.addEventListener( MouseEvent.MOUSE_OVER, onMouseOver ) object.addEventListener( MouseEvent.MOUSE_OUT, onMouseOut ) } // Handle the events private function onMouseOver( event:MouseEvent ) { // Do something } private function onMouseOut( event:MouseEvent ) { // Do something else } }
Applying the Handler Object to the buttons
// Instantiate the Handler Object private var handler:IMouseHandler=new mouseGlowHandler(); // Apply to objects handler.addObjectMouseHandler( this.buttonOne ); handler.addObjectMouseHandler( this.buttonTwo ); handler.addObjectMouseHandler( this.buttonThree );
.
The Services
[Text to be written]




Posted on July 1, 2010
0