This is my dissertation paper in which I present an approach towards developing interactive applications and propose a way this can be accomplished in a clean and maintainable way.
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Interactive Applications in .NET
1. INTERACTIVE
APPLICATIONS IN .NET
Master of Software Engineering
AUTHOR
ANDREI FANGLI
SCIENTIFIC COORDINATOR
DR. IOAN LAZĂR
JUNE 2016
"BABEȘ-BOLYAI" UNIVERSITY, FACULTY OF MATHEMATICS AND COMPUTER SCIENCE
2. Interactive Applications in .NET - Table of Contents
Table of Contents
1. Applications Today................................................................................................................................................3
2. Asynchronous Programming.............................................................................................................................5
3. Architectural Approach..................................................................................................................................... 11
3.1. Model-View-ViewModel......................................................................................................................... 14
3.2. Defining the Context: Observable Domain Objects ..................................................................... 15
3.3. Asynchronous Model ............................................................................................................................... 17
3.4. Validation...................................................................................................................................................... 20
3.5. Visual State Manager ............................................................................................................................... 23
4. Implementing the Machine............................................................................................................................. 25
4.1. Reactive Extensions................................................................................................................................... 31
5. Conclusions........................................................................................................................................................... 32
6. References ............................................................................................................................................................. 33
3. Interactive Applications in .NET - Applications Today
3
1. Applications Today
A few years back, the number of applications available to the general public was rather small
compared to their number today. Most of them were huge, enterprise level, applications that serve
the needs of a company, after all, who is paying for all that effort? Developing software was harder,
resources were limited and sometimes difficult to come by even though the Internet was generally
available.
As years went by and developer tools got rich and richer, more people jumped on the boat of
software development. Creating software is still hard, but not as hard as it was 10 years ago.
Making a desktop application by one self is a tiring effort as it requires a lot of features to even
compete with the software already available. Not to mention user interaction.
When tablets and smartphones came out, it was a first sign that there will be a boom in the
numbers of developers. Once Software Development Kits came available for creating applications
for various mobile platforms the trigger was pulled, and the explosion happened. There are
literally tons of mobile applications. Anyone with little knowledge about writing code can
download one of these Software Developments Kits and are already writing their application.
Having virtual stores, in contrast to classic desktop applications, for mobile applications is a bonus
as it offers a degree of security, a user is not going to any site to download free software, it is the
official store for a mobile platform. Nothing should get in there without proper verification.
These stores do not require from the application that is being published to be complex, in fact
any simple application can make its way to the store without much problem. There are some that
simply keep the score for a game of cards, some that just store one list where a user can only add
and remove items to it.
Tablets and smartphones are not meant for heavy duty computations; they are accessories that
fit in pockets or really small bags. They are meant to be useful in most if not all situations. Some
people spent some of their time with their friends playing card games, how useful it is having the
phone keep the score rather than memorizing it? How useful is it to have a “to-do” list on a phone
than instead of a piece of paper for which one also needs a pen to be able to write on?
Tablets and smartphones have a lot of small and simple applications. This is the perfect
environment for a single person to write an application that ends up being used by a lot of people.
Tools available today make it really easy to write such applications, there are hundreds of libraries
available that help in solving specific problems, there are a lot of Q&A sites, blogs and books that
can aid just about anyone to create their own application. [1]
This boom in software developers is both beneficial and somewhat damaging. Besides the risk to
security as scam applications that somehow get past store verification and get published there is
also the risk of bad software. Not as in ill-intended applications that drain battery or do some
other damaging action on purpose. It is easy to write bad code, too easy. One can write all their
4. Interactive Applications in .NET - Applications Today
4
logic in the code-behind of a page without using a single await statement. Besides having a bulk
of non-reusable code that cannot be even tested automatically, it does not have a rich user
experience. The user needs to wait for the application to finish whatever it is processing, or rather
wait until the web service the mobile application has invoked returns as the phone itself should
not do any heavy duty operations. [1]
Applications today must be responsive! The user is in charge of their phone, not the other way
around. Any mobile application that is not responsive sits on the same shelf with broken
applications. The developer must take into consideration that at any point in time there may be
an incoming call or the user simply needs to do something else with their phone. At any point in
time the application must be ready to respond to what the user wants.
Practically, it is impossible to respond in the exact same instant, it may be damaging to do so as
an interrupt right in the middle of a write operation could corrupt the file that is being saved. [2]
On the other hand, everything is from the perspective of the user. A small delay since the user has
tapped the cancel button until it actually happens is acceptable. It is difficult, if not impossible, for
a human being to tell whether the device responded exactly when the button was tapped or a few
hundred milliseconds later.
In order to be able to handle multiple events, or at least apparently handle them, one needs to
consider parallel programming or asynchronous programming. Parallel programming comes with
its own trouble of synchronization and multiple worker threads, joining threads and so on.
Asynchronous programming, on the other hand, may be the best fit for allowing developers to
create rich user interfaces.
Asynchronous programming does not necessarily mean to move all computation on a separate
thread so the user interface thread is free to receive other events and interact with the user. If
small chunks of code are executed in a sequence in such a way that a tap event or an income
phone call may come between them and eventually changing how the remaining chunks of code
in the sequence are executed, then it is possible to give the impression that the application is
doing multiple things in parallel when in fact it is doing little bits of more things giving the
impression of parallel execution. [2]
As long as there is visual feedback and the users are free to interact with the application and with
their phone they will not tell the difference. Probably they do not even care about what is beneath
the interface as long as the application does the job. One way to make rich user interfaces and
responsive applications without all the synchronization issues that parallel programming may
bring is through the use of asynchronous programming.
5. Interactive Applications in .NET - Asynchronous Programming
5
2. Asynchronous Programming
In conventional programming, in order to stop a long running method from blocking the caller of
that method one would create a new thread and have it execute the long running method. One
issue with this approach is signaling when the operation has completed in order to make
necessary user interface updates, but also make use of the result of the operation. [2]
In asynchronous programming, parallelism does not happen outside of the operation, but rather
inside. Parallelism is initiated inside the long running method only if it is necessary. [2]
This promotes encapsulation since there is no need to know whether a method is long running or
not in order to use a separate thread. If the user interface freezes because a method takes too
much time to complete, the optimization happens within the method. Responsibility falls on the
implementer to refine their code, not on the user.
There is still the issue of signaling completion. Whenever an operation completes, regardless of
whether it is synchronous or asynchronous, it is a must to have some way of knowing when it
completed.
Typically, asynchronous methods do not block the caller. They return control to them before doing
any actual work. In order to either know when the operation completed or have a continuation to
that operation, asynchronous methods either return an object that can be used in that way or take
a callback that will be called when the operation completes. [2]
The initial approach in .NET was to use callbacks for continuations. Operations that could be
executed asynchronously, such as reading from a stream, have a BeginX/EndX pair of methods for
the corresponding X method, which was synchronous. For instance, the asynchronous pair of
methods for Read are BeginRead/EndRead. BeginRead would take a callback, among other
parameters that are also available for the synchronous Read version, that was executed once the
operation has completed. The method returned an object implementing IAsyncResult that has to
be used as parameter when calling EndRead. [2]
In some cases, it would be possible to have the callback executed right away since most, if not all,
stream implementations use a buffer behind the scenes. If the buffer already had the necessary
data that was requested for an asynchronous read, the callback would have been invoked right
away with the result. On the other hand, if the buffer did not already have the necessary
information, it would load into the buffer on a different thread and only afterwards it would invoke
the callback.
This is one of the advantages of asynchronous programming, sometimes the code is not executed
on a different thread because it is not always necessary. Forcing parallel execution by moving the
actual method invocation to a different thread cannot yield such advantages unless the entire
method is decoupled.
6. Interactive Applications in .NET - Asynchronous Programming
6
One of the issues with the callback approach is that it promotes unreadable code that is also hard
to maintain or extend. For instance, asynchronously making a request to a web service will require
a callback for continuation. If the call is successful, responds with HTTP status code 201 - Created,
then another call needs to be made to a different web service. The second call happens insides
the callback. If the second request fails, responds with HTTP status code 400 – Bad request, then
the first request to the web service needs to be undone which will turn out to be another
asynchronous call, with another callback.
How would this be written in a synchronous fashion? Make the first request, if the response has
status code 201 then proceed with second request, if that is unsuccessful then undo the first one.
The code ends up really easy to read even if the actual requests are not extracted into separate
methods.
How would the code change when another web service needs to be called when the undo fails?
For the asynchronous approach it would mean another callback, while for the synchronous
approach is just another if with another line of code. Easy to test, easy to extend.
In .NET callbacks are provided through parameters of delegate type. Parameters of this type, or
event handlers, accept anonymous methods or lambda expression. As with functional
programming, when using lambda expressions, one can create closures over certain objects thus
when passing a callback to a BeginX method, one can use a lambda expression, instead of an
ordinary method, and inside it to close some of the variables. This is extremely useful, but it also
blocks any kind of method extraction from the callback unless code is made less readable. [2]
There is no doubt that the callback approach has its benefits, most notably the fact that there is
no need for an actual signaling mechanism as it is certain that the callback is executed only after
the asynchronous operation has completed. However, this approach promotes code that is hard
to read, hard to maintain. [2]
The issue of handling exceptions does not need exemplification. The try… catch statement already
makes code less friendly to eyes, but the real problem is resource management.
With the callback approach one needs to manually dispose the resources they use since the using
statement does not split into lambda expressions. Resources need to be created outside of the
callback and disposed when they are no longer necessary, no matter what! This is a critical as an
exception can be thrown either when calling the BeginX method, either in the callback if the
asynchronous operation fails. Resource disposal needs to happen in either case! [2]
Resources that require manual handling implement the IDisposable interface. Usually these types
also define a finalizer to ensure that the resource is safely deallocated even when Dispose is not
called. Relying on the finalizer to actually deallocate resources yields memory issues as the
Common Language Runtime has a generational garbage collection system. Objects that will have
their finalizers invoked will be promoted to at least generation 1, if the next garbage collection
does not include generation 1 then these objects will get promoted to generation 2! To actually
7. Interactive Applications in .NET - Asynchronous Programming
7
reclaim the memory occupied by generation 2 objects the entire memory used by the application
needs to be cleaned. [2]
Exception management is a big problem alongside readability with the callback approach.
There are more issues with this approach, however it is clear that writing code having this in mind
is not exactly that easy and there are too many things that could go wrong, now there are
alternatives to this approach which solve most of the problems.
Tasks symbolize a unit of work that may not have completed but can be used to either block until
it has completed, enlist continuations for when the operation has completed thus blocking is
avoided but the callback issue returns or await them in C# asynchronous methods. [2]
Tasks were introduced in .NET 4; they represent an abstract concept that enables high level parallel
programming. Threads are primitive structures on which other parallel concepts are built on, they
do not easily enable fine-grained parallelism. It is difficult to compose little parallel operations
using threads in contrast to Tasks. A Task is literally a delegate that gets executed on one thread
or another depending on the task scheduler. [2]
Tasks can be easily composed using operations such as WhenAll or WhenAny as the result of
either of these methods is another Task. It is easy to write code that executes in parallel that at
some point some operations need to wait on each other to complete before the overall operation
can continue. [2]
Since C# 5.0, the language has support for asynchronous programming. Developers are no longer
required to make a big effort into writing asynchronous code. The async and await keywords have
been introduced, any method decorated with async must either return a Task or void. The await
keyword can be used on methods that return a Task. [2]
One of the great advantages of async and wait is that it enables developers to write code that
looks like synchronous code, but in fact it is asynchronous. All of the actual splitting and plumbing
is done by the compiler behind the scenes. [2]
Having language support is very important as it is a standard approach to this style of
programming in the respective language, but also makes these concepts generally available
directly in the language rather than some third party library. Plus, it is far less likely to have bugs
in what the compiler translates than a third library would.
Back to the web services example. Writing code synchronously it would look something like the
snippet bellow:
if (Request1().StatusCode == 201)
if (Request2().Failed)
UndoRequest1();
8. Interactive Applications in .NET - Asynchronous Programming
8
Really simple, however to invoke web services requires a number of steps that could take enough
to make a user interface freeze. First is the DNS1
lookup, then it’s the actual connection, serializing
the request and sending it over Internet. Afterwards the service processes the request and
responds.
It is possible that the service invoked to take a bit to load, or the web host is too busy processing
other requests and our request would eventually end up in a timeout. This is one example where
code should be written in an asynchronously in an effort to keep the user interface responsive.
Using the async and await is really simple and straight forward:
if ((await Request1Async()).StatusCode == 201)
if ((await Request2Async()).Failed)
await UndoRequest1Async();
It does not seem to have changed much, however there are more implications than what it may
seem.
When the compiler encounters an await it splits the method in two. From a high point of view,
everything before the await is extracted into one method and everything after it goes to another
method. To make the link between the two, the compiler uses the awaiter that is returned by
calling GetAwaiter on a Task to subscribe a continuation. When the awaited operation completes
then the continuation will be executed which will contain the remainder of the asynchronous
operation. [2]
The method transformation that the compiler applies to an async decorated method do not
change much from the initial approach with callbacks, the great advantage is that the compiler is
generating the necessary callbacks rather than the developer. This reduces the likely hood of
introducing bugs and also enable some of the code C# features, such as conditionals, loops, try..
catch and using statements. [2]
Since the method is split into multiple, there is the problem of maintaining method state. Variables
and parameters that were either defined or provided inside an asynchronous method must be
available throughout the method regardless of whether the compiler decides to split the method.
Besides just splitting the asynchronous method after await statements, the compiler actually
transforms each async decorated method into a state machine. Parameters and variables are
stored as the context of the state machine which is encapsulated inside an object of type Task
which is returned by the async decorated method. When then asynchronous method completes
then the returned task transitions to either RanToCompletion, Faulted or Canceled states. [2]
Since the transformations done to an async method are somewhat similar to what a developer
would write using the callback approach, one needs to ask. Where does the code actually execute?
1
DNS stands for Domain Name System. The overall principle of the system is to associate names to IP
addresses so it would be easier for human beings to memorize the location of a web site.
9. Interactive Applications in .NET - Asynchronous Programming
9
Is it a thread from the thread pool? Is it always a new thread created by the task scheduler? Where
does code actually execute? This is an important issue because all graphical user interfaces that
can be written with .NET (Windows Forms, Windows Presentation Foundation) or WindowsRT have
a dedicated thread (UI Thread), for interacting with any user interface components. Changes to
the user interface and events from their controls are all executed on the UI Thread, any attempt
to change the user interface from a different thread ends with an exception. [2]
The way most user interfaces work is that they implement a producer-consumer pattern where
the consumer is the UI Thread and a producer can be anything. A click on a button, an event from
the operating system and so on. As events happen, their handlers, which are nothing else than
callbacks, are posted in an execution queue where they may be prioritized. The UI Thread is
constantly inspecting this queue and when an item is available it removes it from the queue it and
executes in on the UI Thread. [2]
All tasks are scheduled by a task scheduler which behind the scenes uses a Synchronization Context
to actually marshal the code. When a task is awaited, the awaiter actually captures the current
Synchronization Context to subscribe the remained of the method. [2]
If necessary, one can implement their own Synchronization Context and have full control over how
tasks are actually executed. Each thread can have at most one Synchronization Context set, if there
is none set then the default is used which actually relies on the thread pool to carry out the actual
execution. [2]
All graphical user interfaces that can be programmed through .NET or WindowsRT set a specialized
Synchronization Context for the UI Thread. The respective instance can be obtained and passed
down to view models, controllers or other types of objects as a means to marshal code unto the
UI Thread. It is already known that this is how async and await does it. [2]
Whenever an async method is awaited whose execution was initiated on the UI Thread, usually
the click event handler of a button or within the Execute method for a command to which a button
is bound to, the continuation is posted to the specialized Synchronization Context which relies on
the UI Thread to carry our actual execution. Eventually, continuations end up on the UI Thread and
the user interface can be safely updated. [2]
Writing responsive user interfaces means to have visual feedback for whatever the user does or
for whatever event happens under the hood. If a long running operation is started, it may entirely
run on the UI thread, but that does not necessarily mean waiting for the long operation to finish
until any event is handled.
The beauty of asynchronous programming in C# is that async methods are actually fragmented
into smaller pieces where each is scheduled one at a time. This fragmentation allows for other
events to be pushed unto the UI Thread execution queue in between the smaller pieces and
respond accordingly to those events and in time.
10. Interactive Applications in .NET - Asynchronous Programming
10
One can carry out all their work on the UI Thread alone. If the code is written well it may seem to
the user that the application actually runs multiple jobs in parallel. In truth it does not execute
anything in parallel, it just does one little bit of multiple tasks at a time.
Regardless of whether there is some real parallelism behind, the user interface stays responsive.
The user can constantly interact with the application and based on its current state it may be able
to carry out some operations and not others.
While it all may seem fine with asynchronous methods in C#, there are a few subtle side effects
that async methods have. [3]
One of them are the fake awaits. It is possible for an async method to actually complete
synchronously and return an already completed task. For instance, the snippet bellow relies on a
cache to fetch data faster: [3]
public async Task<string> GetMessageAsync()
{
if (IsMessageCached())
return messageFromCache;
var message = await someService.GetANewMessageAsync();
Cache(message);
return message;
}
If the message is cached, then it is fetched from there and the async method completes
synchronously. On the other hand, if this is the first time the method is called, it is most likely that
the message is not cached, thus the call to GetANewMessageAsync is made. Depending on what
happens inside the awaited method the GetMessageAsync may return with a Task that is not yet
completed. The same principle is applied recursively. [3]
An async method will return prior to actually finishing when it will find a real await. These happen
when a task that executes on a different thread is actually returned or when a call to Task.Yield()
is awaited. The latter does nothing special. It simply forces the compiler to actually split the
method in two having the side effect of having the async method actually return control to the
caller when the call to Task.Yield() is made. This is a safe way of ensuring that the async method
will always return control to the caller before it actually finishes. [2]
One last topic to cover when it comes to asynchronous programming is cancellation. Like in most
other platforms, cancellation is signaled. The operation that is being canceled has to check, from
time to time, whether a cancellation has been signaled. [2]
Cancellation is requested to a task through a CancellationToken. One can use
CancellationTokenSource which exposes a token that can be passed to one or more tasks. To signal
a cancellation request one must call the Cancel method on the CancellationTokenSource which in
turn will mark the token with cancellation requested. [2]
11. Interactive Applications in .NET - Architectural Approach
11
3. Architectural Approach
While asynchronous programming can be beneficial to writing interactive applications, they are
only part of the solution. In order to have a rich user interface it must also be updated constantly
to show both available options depending on what the application is doing at that point, but also
what information is available and whether new information is being retrieved from somewhere.
Things such as progress bars, fade and other kind of animations make the user experience more
pleasing, if a list of items just pops up without a smooth fade in animation the application will
seem less user friendly.
Starting with Windows Presentation Foundation and now also in WindowsRT, one can make use of
the already available tools to write rich user interface applications. Controls already come with
their own bag of animations which make the application pleasing, since they are out of the box it
is likely to encounter the same animation as other applications and even what the operating
system is using. This helps with the look and feel as just navigating through such an application
will already make it familiar and inviting. [4]
One critical part to writing good applications is how they are structured. For quite some time, user
interfaces build with Visual Studio, either Windows Presentation Foundation for Windows Desktop,
or WindowsRT for mobile platforms, use XAML to describe them. [4]
XAML stands for eXtensible Application Markup Language, it is a derivative of XML2
and enables
developers to create user interfaces, and not only, in a declarative meaner. Every XAML file is
bound to a concrete class, the code within that class is referred to as code-behind. [4]
Clearly, C# code will not go into the XAML file. On the other hand, in the code-behind class one
can access anything that was defined in the corresponding XAML file. This is one of the reasons
why the code-behind exists, to cover for anything that cannot be made through XAML, such as
enabling or disabling buttons based on some event, handling button clicks and so on.
This is where asynchronous programming comes into play. One can write an asynchronous event
handler for handling what happens when, for instance, the user fills a form and clicks the save
button. Right when the event handler starts, the button is available in the code behind and thus
it can be disabled during the save operation. The save operation itself is asynchronous thus it is
awaited, there is no telling how long it will take but during that time the button is disabled. When
the save operation completes the button is enabled and the user is free to add another item.
If the handler were to be synchronous, there would be no need to disable and enable the save
button, but because of the compiler fragments the async methods, it is possible that the user to
click the save button while the operation is being carried out and have the event handler executed
once again before the first call is finished (see figure 1).
2
XML stands for eXtensible Markup Language. It was first introduced to help transfer data between
applications.
12. Interactive Applications in .NET - Architectural Approach
12
FIGURE 1: SYNCHRONOUS VS ASYNCHRONOUS EVENT HANDLERS
Synchronous
UI Thread
1st
button click
<<event handler>>
SaveButton_Click
2nd
button click
<<event handler>>
SaveButton_Click
Asynchronous
UI Thread
1st
button click
<<event handler>>
SaveButton_Click
2nd
button click
<<event handler>>
SaveButton_Click
The synchronous way is simple and straight forward, however it may lead the user interface to
freeze which leads to a very poor user experience. The asynchronous way illustrates both a
problem and a feature.
As it can be seen in figure 1, using asynchronous event handlers may lead to overlapping
execution. It is possible to have multiple handlers in progress at the same, clearly it could lead to
some problems if a user is allowed to save the same entity twice at the same time. Because of this,
as previously mentioned, the developer must take extra steps in the code behind to ensure that
the save button is unavailable while the associated action is being executed.
On the other hand, other buttons may become available. For instance, while the application is
saving an entity it could be possible to cancel that operation. Having a synchronous approach,
clearly that cannot happen as easily as it can with an asynchronous approach. Imagine that instead
of the second button click it would be a cancel button click event. That would signal the save
operation to cancel which may either lead to actually cancelling the operation, or the cancellation
to fail. It is possible that the user to click right the cancel button right when the entity was saved,
thus canceling the operation means actually deleting the entity.
Working with the code-behind is just one, less promoted way, to respond to events. XAML
encourages binding controls to various properties in order to both provide data to them but also
respond to events such as button clicks. [4]
13. Interactive Applications in .NET - Architectural Approach
13
Data binding encourages separation of concerns, usually an object providing data and commands
through properties is used as a binding source for a view. The binding source can raise specific
events in order to inform the user interface to update itself. [4]
The data source to which a control binds to may expose a number of properties, this is usually the
case, which themselves become binding sources.
Observer is a behavioral design pattern implies that an object, referred to as the subject, maintains
a list of different objects, whose concrete type is unknown, referred to as observers. Whenever the
subject changes it is responsible with notifying all observers about that change. [5]
In .NET, the observer pattern is implemented using events which themselves are implemented
using delegates. A delegate is a reference to a function. Through a delegate one can invoke a
method that an object exposes, or not, as well as a static method. [2]
It is possible to have an event handler, which is basically a method subscribed to an event, that is
actually a private method. Events in .NET do not require the observer to implement any specific
interface but rather have either a method with a specific signature or an adapter for it. Anonymous
methods or lambda expressions can be used to subscribe to a method and actually have them
call a private method of an object. The lambda expression is actually a closure around the instance
whose method will be called. [2]
User interface controls, not just Windows Presentation Foundation and WindowsRT ones, Windows
Forms as well, rely on INotifyPropertyChanged interface in order to be notified whether the binding
source has changed. It is not mandatory to implement this interface, an object that does not
implement it can still be bound to, but the respective control will not receive update notifications
and thus it will not update. [4]
INotifyPropertyChanged exposes just one event, PropertyChanged which relies on the
PropertyChangedEventHandler delegate. Most event handlers require a method with two
parameters, an object which refers to the initiator of the event, the subject and an instance of
EventArgs or one of its derivatives. In this case, when the event is raised a specialized EventArgs is
sent which informs which property has changed through its PropertyName property. [4]
Besides binding to data, views can also bind to commands. Command is a behavioral design
pattern in which an object encapsulates the invocation to an operation. [5]
In order to successfully bind to a command, a binding source needs to implement the ICommand
interface. This interface exposes two operations, CanExecute(object) and Execute(object) alongside
an event, CanExecuteChanged. [4]
Basically, the object implementing this interface needs to be both a command and a subject. This
is done in order to avoid pooling the CanExecute(object) method, when there is a chance that the
result of the respective method to have changed, the CanExecuteChanged event is raised. This will
14. Interactive Applications in .NET - Architectural Approach
14
make controls call CanExecute(object). Based on the result, the button becomes available or
disabled. When a user clicks on a button, the Execute(object) method is called.
The object parameter which is required by both methods is a value that can be optionally specified
when binding to a command. This is useful for commands like navigating to a page. It page
number itself does not have to be encapsulated inside the command object, but can be provided
as a parameter. However useful, any change on the command parameter that is signaled to the
user interface through the PropertyChanged event will not initiate a call to CanExecute(object)!
3.1.Model-View-ViewModel
Separating views from business logic enhances code reusability but also testability. It is easy to
test whether an object has the desired behavior when it can be passed input that would normally
come from the user and see what it outputs.
For application where the user interaction needs to be rich, there is need for an intermediary layer
between the view and the business layer in order to properly handle the logic behind a view. [6]
The Model-View-ViewModel is an architectural pattern focusing on separating the view and its
logic from the business models of the application in an effort to separate concerns and thus obtain
more granular, maintainable, testable and reusable code. [4]
All data is provided to the view by the view model and all requests from the user are forwarded to
the view model. The view model itself relies on a model, which can be a data model or any business
object, to retrieve data and operate on (see Figure 2).
FIGURE 2: MODEL-VIEW-VIEWMODEL OVERVIEW
ViewModel
<<binding>> <<property changed notifications>>
Model
View
<<provides data>><<changes>>
In this case, the view model is the binding source of the view. It provides both data and commands.
This can lead to a lot of code duplication, for every model there should be a view model or
something similar, as well as ending up with classes having multiple responsibilities. There are
exceptions to the Single Responsibility Principal, but data and behavior should not be mixed
together in the same class. [7]
15. Interactive Applications in .NET - Architectural Approach
15
3.2.Defining the Context: Observable Domain Objects
In Domain Driven Design, it is proposed to model the business layer around the domain for which
the application is being implemented. While doing this, the model should be constantly presented
and approved by domain experts in an effort to reduce the risk of misunderstanding and also help
create a ubiquitous language. [8]
There is more to Domain Driven Design than the above paragraph, but this paper focuses on
describing an approach towards creating interactive applications in a clean and reliable way. This
has an impact towards how certain concepts in Domain Driven Design are affected.
The domain layer should contain only classes that are either entities, values or domain services.
Entities are objects that have a thread of life in some way. For instance, in an application which
manages movies, it is important that when a user is reading about a movie to be the same movie
that the administrator introduced. Usually when changing one of the properties of an entity, it is
not a new entity but the same one. [8]
Value objects, on the other hand, are simple values. For instance, the length of a movie is a value
as it is not important whether the value is created each time a movie is being loaded from the
database or not. It can be stored as the number of minutes the movie lasts and when it is retrieved
from the database a TimeSpan is created from that value. The difference between a value and an
entity is that values should be immutable, when one wants to change a property of a value or the
value itself, it is a new value rather than the same one with an update. [8]
So far only data structures have been covered. There are more complex applications in which the
software must perform an action that is domain specific. One of the most common examples is
changing the currency of a sum. Accountants have a formula for how to transfer a sum from one
currency to another besides the currency transfer rate and the source sum. It is likely that after a
transfer the resulting sum needs to be rounded. The entire logic of transferring a sum from one
currency to another is implemented in a domain service since these actually model operations on
data rather than data itself. [8]
Going strict by definitions, it would mean to have a number of types that model the domain in
the business logic layer. A number of view models, a considerable part of them will map one-to-
one with domain objects, that expose both data and behavior through commands for a view to
bind to. Last but not least, a number of repositories for managing entities in a storage.
The mapping between the business model and their respective view models can be done through
an Anticorruption Layer [8]. But what would the view model wrapping the domain object do
anyway? It would only expose the same properties as the model does only that the view model is
observable. This is a direct violation of Don’t Repeat Yourself principle.
Besides duplicating code, there is also the issue of circular references. The domain model is
implemented however the business demands, if it demands circular references then there will be
such associations. When working with references, which is mostly the case in .NET and other
16. Interactive Applications in .NET - Architectural Approach
16
platforms, one must think of the relationships between objects as a graph, for what it truly is, and
not as a tree, which is only a subset of all possible cases.
How would the Anticorruption Layer fair with circular references? Extra checks would need to be
set in place in order to avoid infinite loops or StackOverflowExceptions. That means a greater
performance cost, more time spent until actual data is shown on the user interface. Writing view
models for each domain model by hand rather than have a tool to generate them means more
time spent by a developer on less engaging matters. Creating a tool to generate view models
would seem like an appropriate challenge for a developer, but either approach needs to deal with
the circular reference issue. Some sort of cache needs to be implemented in order to properly
map the domain object graph to the view model object graph. [9]
Last but not least, one could write a generic class that wraps an object and through reflection it
automatically generates other view models for the wrapped object with a few exceptions such as
strings, integers and other data types considered to be primitives. This approach eliminates
intellisense completely as properties are implicit, not explicitly defined on the view model class.
Any approach taken either increases development costs or end up in eliminating very useful
features offered by the integrated development environment. The price needs to match the reward
or this is a very bad deal.
What if, the domain objects were themselves observable? What if, one could bind directly to them
without any intermediary? If there is any circular reference between them, it is already set when it
gets to the view. There is not duplicate code and there is no time wasted in doing so.
In order to be able to bind to an object and automatically have the user interface updated when
one of their properties change one must only implement INotifyPropertyChanged which exposes
only one event. The entire subscriber list is managed by the delegate which is used to implement
the event. All that is required is to raise the respective event when a property is being set.
This is a very small price to pay when implementing domain entities and values for what is
obtained in return. To ease development, one can offer a base implementation of
INotifyPropertyChanged and simply derive all observable objects from there. The base
implementation would provide a protected method for raising the respective event taking a string
parameter which will resemble the property name that has changed.
17. Interactive Applications in .NET - Architectural Approach
17
3.3.Asynchronous Model
When domain objects become observable one can easily bind the user interface controls to them.
Even view models themselves can subscribe to their events in order to carry out different
operations. For instance, when the property of an entity changes it would be required to validate
the updated entity. If there are any errors an observable collection of errors would be updated
and thus any control that has bound to it will automatically display them.
All user interface controls rely on objects that implement INotifyPropertyChanged and
INotifyCollectionChanged interfaces to update themselves. They both only expose events for
notifying when the subject has changed. Both the ObservableCollection<T> and
ReadOnlyObservableCollection<T> are types present in .NET framework that implement these
interfaces and they should be used to speed development. [4]
One important aspect of software development besides data is behavior. Software is mostly about
behavior; it is mostly about doing something over a dataset.
Interactive application demand that the user has constant visual feedback, even when the
application is busy carrying out a request, there is a progress ring or something that informs the
user that something is going on and may have some progress updates.
When a user navigates to a view where they can edit an entity, typically, it means that a form is
displayed with a number of input controls, when the user hits save there is a validation of the data
that has been introduced. If the data is valid then the entity is saved, otherwise a list of error is
shown. The user experience is poor in this case. Whenever a user wants to see whether their input
is valid, they need to click on save.
From a behavioral point of view, the view is going through several states. It starts off in the editing
state where the user is free to provide input. When the save button is clicked, the view actually
first transitions into a validating state and depending on the outcome of the validation it either
transitions into a saving state or transitions to an invalid state.
If the application were to be implemented synchronously, which offers a lesser user experience,
all these states are implicit and the view does not require any kind of modeling since the sequence
of transitions is quite simple with two possible outcomes.
On the other hand, if the application is written using asynchronous programming in an effort to
provide a rich user experience, then having an implicit state machine may prove confusing and
less maintainable. After a developer would investigate a bit the view, it would most likely become
clear that there is a state machine at play even though it is implicit. [10]
As the view transitions from one state to another the user interface needs to update. Some actions
can be performed while in a state but cannot be performed while in another. [10]
It is clear that there is need to model the state machine behind a view, but how does it fit with the
View-Model-ViewModel pattern? The data has already been isolated from view models, leaving
18. Interactive Applications in .NET - Architectural Approach
18
them open only to resembling behavior. Where better place would there be to implement a state
machine? After all they are used to model behavior in software systems. [11]
A Mealy Machine is a finite-state machine that uses both its input and its current state to determine
its output. They can be used to model asynchronous reactive processes and, as with most if not
all finite state machine models, it focuses on observable inputs and outputs. [12]
In case of a view model which is an implementation of a Mealy Machine, further referred to as an
interactive view model, operates based on a context which resembles the input and sometimes
even the output as properties of an object may be set by the view model. [12]
Depending on its current state and context, the interactive view model may transition to one state
or another. If, for instance, the operation that is being carried out is a save operation then the
output of the machine is the successful storage of the entity. [12]
Commands that are exposed by an interactive view model can be bound to states that it defines.
When an interactive view model transitions from one state to another, the commands it exposes
automatically update. In other words, they raise the CanExecuteChanged event which in turn will
make the control that has bound to the respective command call CanExecute(object) method. The
method itself encapsulates the logic for verifying whether the command is bound to the current
state of the interactive view model or not.
An interactive view model should always expose a state, even if it is a state that is used to expose
that behind the scenes, an operation is actually performed. When an operation finishes,
depending on what requests have been received in the meantime and the context of the machine,
the interactive view model will make another transition.
It becomes obvious that states can be grouped into two main categories. Action states and quiet
states. Actions states are states in which the interactive view model is carrying out a request. It is
executing an asynchronous operation.
Quiet states, on the other hand, are the typical states in which the interactive view model exposes
some commands that are available to the user. In these states, the application is quietly waiting
for user input.
Initially, an interactive view model can be in either an action state or a quiet state, but whenever it
enters an action state it should eventually transition to a quiet state unless an endless loop of
operations is carried out. This is just a guide line, there are exceptions.
For instance, a pooling loop can be implemented using action states. There is a pooling state in
which information is being fetched and presented to the user, and afterwards there is a waiting
state. The interactive view model will stay in the waiting state for a fixed period of time and
afterwards will transition back into the pooling state. The waiting state it actually is an
asynchronous operation that is implemented using Task.Delay(int) or Task.Delay(TimeSpan).
19. Interactive Applications in .NET - Architectural Approach
19
Even though it may seem simple, one must take into account that it is possible that the fetch to
fail due to losing Internet connection or a timeout on the other end. For situations such as these,
the application can have a number of attempts to fetching data. If they all fail, then the interactive
view model should transition to a quiet state where the user is asked for further instructions.
If action states perform that actual operation, then what would a command really do? This is really
simple. The commands that are exposed by an interactive view model actually resemble transition
triggers for the view model that exposes them. Furthermore, the command can be bound to
specific interactive view model states which will make them available based on the current state
of the interactive view model that exposes them.
When a command is invoked it will actually trigger a transition inside the interactive view model
which in turn will update other commands and also start the desired operation. Any button that
was bound to a command exposed by the same interactive view model will get an update. The
will become available or disabled with respect to the current state of the interactive view model.
Another issue, which was previously raised, is overlapping asynchronous operations. If a command
is actually a transition trigger, then what would happen if the interactive view model is currently
in an action state and a command that triggers a transition is invoked? Regardless of what initiates
the transition, whilst in an action state, an interactive view model cannot transition to any other
state. Any attempt to do so will result in an InvalidOperationException. The interactive view model
can carry out one operation at the time, this does not block signaling cancellations and it does
not block making changes to its context. When the context has changes, the interactive view
model must react accordingly.
Blocking transition requests while in an action state, in certain situations, forces the developer to
find a work around this restriction that would only end up in code duplication. For instance, when
the interactive view model is in the validating state and a change to its context occurs by user
interaction, the interactive view model should automatically cancel the validation and start over
as the data is currently validating is already outdated.
To answer to this strictness, the interactive view model allows queuing transition requests. When
a transition is queued the interactive view model will perform the transition if it is in a quiet state,
if not then it will transition as soon as it enters a quiet state.
The queueing mechanism resolves the validation problem, and probably others as well. If the
interactive view model is already validating, then queueing another transition to the validating
state seems appropriate as the same operation needs to be carried out all over again.
Since action states resemble actual operations, it does not make sense to have an external event
dictate how many times the interactive view model needs to queue state transitions. The response
to the event is that the interactive view model will transition to the desired state at some point in
the future if not immediately. If a request to queue a transition matches the last in the queue, then
20. Interactive Applications in .NET - Architectural Approach
20
it is ignored. By this, if there are multiple changes to the context, thus multiple transition queue
requests, there will only be at most one queued transition request towards the validating state.
Clarifying thus far, the initial approach towards Model-View-ViewModel was to have a view model
that provides properties for both data and commands that a view could bind to. In an effort to
decrease costs and make code more reusable, the view models no longer expose data directly
through its properties, but rather expose a context property which refers to an actual domain
object. The view model implements a Mealy state machine behind the scenes in an effort to model
its behavior in an explicit and clean way. Commands exposed by the interactive view model are
actually triggers to transitioning to one state or another. These triggers can also queue transitions.
3.4.Validation
Thus far only data and behavior has been covered. One important thing within software
applications is validation. Validation is the act through which a set of data is checked in order to
determine whether it conforms to a number of rules.
Validation can be of multiple forms such as user input validation, schema validation, whether a
product meets the requirements of a user and so on.
Previously it was presented that domain objects should contain only data and that they should
also be observable so they could be used directly by a view in an effort to avoid duplicate code
and reduce the responsibilities of a view model. Continuing with the same idea, where should
validation take place? More specifically, where should user input validation take place.
A common way used through web applications built with ASP.NET MVC is to annotate models
with various attributes, such as RequiredAttribute or EmailAddressAttribute which can be used to
validate an e-mail address, that specify what kind of validation should be carried out on them.
In case the attributes do not suffice, one can always implement ValidationAttribute and perform
any custom validation that is required for a property, in case there is a requirement for which
multiple properties must be involved or the value of one property determines the validity of
another then one must implement IValidatableObject interface and provide custom validation in
the implementation.
This approach eliminates any layer dedicated for validation, however it imposes that the model
itself should validate itself or at least specify what makes it valid. Both validation and data
representation fall unto one class. [6]
Besides, the same models can be used with an Object-Relational Mapping framework, such as
Entity Framework, in an effort to simplify queries and data storage. The same class may end up
being responsible for representing data, validating that data at a given point in time and also
specify how it is stored in a relational data base. [9]
As previously said, validation is of multiple kinds and they are treated differently. For instance,
user input validation is a kind of validation that results in collection of error messages, preferably
21. Interactive Applications in .NET - Architectural Approach
21
localized so they can be displayed in multiple languages, which is then displayed to the user.
Schema validation where a given object is stored to a data store, any store not just relational, does
not return a collection of error but throws exceptions. If a given object does not conform to the
database schema, then there is most likely a programmatic error. Throwing an exception is the
reasonable thing to do as it signals an abnormal situation.
Constraints come from multiple sides, domain constraints are set by domain experts which also
have a big part to play in developing the domain model. [8]
There are also schema constraints, such as how many characters can a string contain, whether a
field is an integer or a real number, a Boolean value and so on. Schema constraints are only set at
the storage level, they may bring some restrictions to the domain model itself and the two may
also overlap. When the two do not overlap it is better to bring domain constraints into the schema
constraints only if they do not impact performance.
Having this in mind, it is time to reflect this on the design thus far. Moving validation outside of
the model itself means that there is a new component having this responsibility. The view model
cannot be used to also contain domain validation as it is already responsible with managing a
state machine. [11]
The validation component will be responsible with validating a given domain object and providing
a list of errors where the error message is preferably localizable. This increases reusability as the
same type of object can be validated from multiple perspectives. There can be multiple validators
that validate the same kind of object but having different logic encapsulated within them.
Through this approach the domain objects can be used, as they are, by repositories. When
retrieving an object from a repository one can always execute the validator in an effort to ensure
that whatever the repository retrieved is valid from the point of view of the domain.
Besides, data representation is separated from its validation. It is true that there is a dependency
relation from the latter towards the former, however having them separated increases testability.
One can write unit tests just for domain validation logic without having to change the domain
model representation.
Wrapping it up, after analyzing a few alternatives that seem to be paying off the initial Model-
View-ViewModel approach has changed slightly (see figure 3).
22. Interactive Applications in .NET - Architectural Approach
22
FIGURE 3 DECOUPLED MODEL-VIEW-VIEWMODEL
ViewModel
<<binding>>
<<property changed notifications>>
Model
View
<<provides data>>
<<changes>>
<<property changed notifications>>
Validator <<validates>>
<<uses>>
<<binding>>
Clearly, there are more dependencies this way, however the initial approach did not take into
account multiple aspects of an application.
There are two binding sources now for the view, the view model and the model itself. The former
provides commands, which encapsulate behavior, to the view while the latter provides data to the
view. In case of the model, there is also the possibility of two-way binding as user input needs to
make its way to the model so it can be validated.
Notice that there is no association between the view and the validator. It falls under the
responsibility of the view model to validate the model; however, this behavior is delegated to a
validator class which provides the view model with a collection of errors. The view model simply
exposes this collection as an observable one thus the view will be automatically notified when it
changes. Validation should be triggered automatically when a change to the model is made, such
changes mainly happen through user interaction as the model is mainly updated through a two-
way binding.
Thus far, the overall architectural approach is decoupled, behavior is separated from data
structures. The classes representing data may be reusable as they only provide a number of
properties with specific data types and nothing else. Validation logic is testable and any change
in the respective logic does not affect the domain model, unless the latter was designed wrong in
the first place.
The view model represents a state machine containing quiet and action states. Commands, which
are provided by the view model, are bound to specific states making the available in some states
and not in others. The view automatically enables and disables buttons based on the availability
of the command they are bound to. [11]
23. Interactive Applications in .NET - Architectural Approach
23
3.5.Visual State Manager
So far, the only user interface interaction that was presented was enabling and disabling buttons
through a command. That is hardly an interactive application as there is a lot more to this kind of
applications than buttons.
On the other hand, the part that was presented thus far is critical to a functioning application.
Besides having a rich user interface, it is important to have functional software and most
importantly to be able to write it with ease and at speed.
Rich user interfaces have nice animations; controls update their visual aspect depending on what
the application is doing in the back or whether the device on which the application runs is turned
or moved.
Animations have been a difficult thing to do since there is not always support from the underlying
framework for them. Starting with XAML this has changed. Both Windows Presentation Foundation
and WindowsRT have built-in support for animations and even offer a handful of predefined
animations for the developer to use.
A control may define for itself and contained controls a number of visual states. Each visual state
is contained in a visual state group. A control may be in at most one visual state in each group.
This means that the control may be in multiple visual states at the same time, but only at most
one per visual state group.
For instance, a number of controls define a visual state group for the orientation of the device. For
each possible orientation, landscape or portrait, the visual state group contains visual states. When
the user rotates the device, the visual state is updated and thus the visual aspect of the control is
updated. Depending on the type of control they may display more information, or they may just
expand to fit the available space after it was updated through the device rotation.
Each visual state contains a set of instructions on how the control should transition to the
respective visual state. It contains a declarative description for animations. Start values may be
specified, but if omitted the current values of the respective property are used. This is useful as
this allows the visual state to practically be able to transition smoothly from any other visual state.
If, for instance in the middle of an animation another visual state transition is triggered, then the
currently executing animation is stopped and the one specified by the latest visual state transition
is started. Since start values can be omitted, the animation can still execute smoothly without
having controls having sudden visual changes which are unpleasing.
The entire visual state definition and transition is done through the Visual State Manager. This
class is responsible for housing visual states for each control and making visual state transitions
available to the developer in code-behind.
Since the view model transitions from one state to another depending on what it is
asynchronously doing behind the scenes, the view needs to update itself the same way. The view
24. Interactive Applications in .NET - Architectural Approach
24
model is always in a state, there is no such thing as “transitioning”. The view model exposes its
current state through a State property. Whenever the state changes a PropertyChanged event is
fired by the view model so the view is notified of the changed.
For each view model state, the view may define for itself visual states. When the view model
changes its state, the view will transition to the visual state having the same name. Visual states
contain specifications for how the control, or contained controls, should animate for this change.
This makes them perfect for adjusting any visual aspect to illustrate that the application is working
behind the scenes.
Besides having buttons enable and disable when a view model transitions from one state to
another, the view can now properly adapt to this change and update any control on the interface
to illustrate the change.
For instance, when the view model transitions to the saving state, the view may fade out all user
input controls and fade in a process ring which shows that the application is currently saving the
entity. When the view model completes the save, it will transition to the editing state while the
view will fade out the process ring as the application is no longer processing and fade back in the
user input controls.
Figure 4 illustrates a simple interaction using a sequence diagram. [13]
FIGURE 4 SIMPLE INTERACTION
:UI saveCommand :TriggerCommand :EntityViewModel :Repository
Execute(null)
TransitionToAsync("Saving")
<<event>>PropertyChanged("State")
SaveAsync(entity)
<<event>>PropertyChanged("State")
<<tap>>
save
<<visual state transition>>
<<visual state transition>>
25. Interactive Applications in .NET - Implementing the Machine
25
4. Implementing the Machine
Thus far there was mostly, if not only, design ideas. How would the ideas presented previously
would actually be implemented? Is it even feasible?
Starting with one of the most critical parts of the library, implementing INotifyPropertyChanged.
Binding relies on it in order to update the content of a control. Since the interface only exposes
one event, PropertyChanged, it is relatively easy to provide a default implementation.
One of the goals of the default implementation is to simplify how the event is raised. As with
all .NET events, raising one requires to invoke the backing delegate of the event with both the
initiator of the event, referred to as sender, and an EventArgs, or one of its derivatives.
For the PropertyChanged event the argument is represented by PropertyChangedEventArgs. To
create one such instance one must provide the property name that has changed. This makes it
relatively easy to abstract. The default implementation should expose a protected method that
takes as argument the name of the property. The method itself constructs the
PropertyChangedEventArgs instance and uses it to properly raise the event.
Since the method is protected, the only way to access it from a different class is through
inheritance, this solve the problem regarding the sender of the event as the initiator is the instance
itself. Using the this keyword and the property name parameter the method has all the information
required to raise the event accordingly.
Providing the name of the property as a hardcoded string may yield problems when renaming
them. The rename function within Visual Studio does not change hardcoded strings that contain
the same value. If a property is renamed, then all places where it would be used to raise the
PropertyChanged event also need to be updated.
To solve this problem one can use the nameof operator available with C# 6.0, in case of using an
older version for various reasons, one can use the CallerMemberNameAttribute and have the
compiler fill in the property name automatically.
Having a base implementation that makes it easy to notify upon property changes makes it ideal
for a candidate for a base class to domain objects. Since they should be observable such that
controls can be bound directly to them they should all derive from the default
INotifyPropertyChanged implementation.
Calling the protected method with the property name to notify that it has changed leads to a lot
of copy and paste code which tends to become less challenging. If this becomes an issue or a lot
of unit tests need to be written in order to test whether the event is raised with the appropriate
property name, there are a few alternatives to remedy this.
If unit tests become a problem, then one can write a generic unit test class and rely on reflection
to test each and every public property that when it is updated the PropertyChanged event is raised
with the appropriate property name.
26. Interactive Applications in .NET - Implementing the Machine
26
If calling a method in each property becomes problematic then one can rely on Aspect Oriented
Programming and use PostSharp, or any other tool, to have INotifyPropertyChanged automatically
implemented by all types matching a pattern, such as all classes that are in a specific namespace.
This technique will speed development time a little, but all the observable behavior that is required
will be provided out of the box by any domain object without any additional code.
Besides domain objects, there is the interactive view model. Any derivative of the
InteractiveViewModel class should be able to define a number of action states in which the view
model processes something.
Each action state actually maps to a method that can be either synchronous, for quick operations,
or asynchronous. The view model can be in exactly one state at a time which is either a quiet state
or an action state. The name of the state is resembled through a string which allows it to be just
about any value except null.
Within the view model constructor, the user needs to make sure to transition to an initial state. If
the state of the view model is queried before it actually transitions to one the State property
accessor will throw an InvalidOperationException as the view model was not properly initialized.
At any given point, action states can be created using a string as the name of the state, state
names are case insensitive, and an associated method that performs the actual action. For
reliability, it is best that all action states are created in the constructor, this will ensure that all
action states are defined when the instance is made available.
When an interactive view model transitions to a state which was previously marked as an action
state, the mapped method is executed. Before actually invoking the method the state of the
interactive view model is updated in the same sequence and not at a later point in time. This
means that when calling TransitionToAsync, the view model will update its state accordingly before
returning control to the caller.
Figure 5 contains a sequence diagram illustrating the interaction happening when transition from
one state to another. [13]
The method starts by checking whether the state that the interactive view model should transition
to is an action state. If that is the case, then the state is updated and all subscribers to the
PropertyChanged event are notified of the change. The first callbacks that get executed are those
that subscribed to the event and only after that the callback mapped to the action state is
executed! This is very important as the user interface can be informed of the transition before
actual execution is performed thus it can be updated accordingly.
Each method mapped to an action state must have one parameter of type ActionContext which
represents the context in which the action is being executed. One can query the action context to
determine the source state from which the interactive view model transitions and use it to
determine the next state. Before the mapped method or callback completes, it must provide the
name of the next state the interactive view model should transition.
27. Interactive Applications in .NET - Implementing the Machine
27
Instead of mapping the destination state of an action state when it is created it is provided by the
callback to the view model after it has executed. This offers great flexibility as based on what
happens within the action state the interactive view model can transition to one state in some
cases and to a different state in other cases.
At the end the state of the view model is updated with the latest state name returned through the
ActionContext instance, in case there were any action states, or the state which was initially
provided as parameter to the TransitionToAsync method.
One important note is that an action state is not constrained to the kind of destination state it
must provide. An action state may have as destination another action state which will result in a
chaining of actions. All these transitions are visible to the interface and depending on the currently
executing action the visual state may alter how controls are displayed.
FIGURE 5 TRANSITIONTOASYNC INTERACTION
:InteractiveViewModel
TransitionToAsync(state)
viewModelState:
ViewModelState
while
[TryGetActionState(state, out viewModelState)]
Property Changed
Subscriber
actionContext:
ActionContext
<<create>>
<<set>>State := state
NotifyPropertyChanged("State")
<<notify>>
<<await>>Execute(actionContext)
<<awaitable Task>>
<<set>>NextState := nextState
<<continuation>>
state := <<get>>NextState
<<set>>State := state
NotifyPropertyChanged("State")
<<notify>>
<<task completion
notification>>
One of the constraints that is not illustrated in the diagram in Figure 5 is that while an interactive
view model is in an action state, any attempt to call the TransitionToAsync method will end in an
28. Interactive Applications in .NET - Implementing the Machine
28
exception. In order for the interactive view model to transition to an action state it must either be
in a quiet state or the action state itself to be in initial state of the view model.
Since an interactive view model cannot be triggered to transition from one state to another while
in an action state it would be useful to be able to queue transition requests.
Behind the scenes, the view model stores the task which resembles the asynchronous execution
of the last transition. To be able to queue transition requests one would need to await the previous
transition task and only then make the request for the next transition.
Note that the task returned by TransitionToAsync only completes when the interactive view model
reaches a quiet state! This behavior needs to be maintained even for queued transition request.
When calling EnqueueTransitionToAsync the method should return a task that will complete only
when the transition towards the enqueued has completed. Figure 6 illustrates this.
FIGURE 6 ENQUEUING TRANSITIONS
interactiveViewModel:
InteractiveViewModel
EnqueueTransitionToAsync(state)
<<await current transition>>
<<await>>TransitionToAsync(state)
<<task completion
notification>>
Most, if not all, applications have to do with user input. Thus far the interactive view model is only
concerned about implementing the asynchronous model through a state machine. This is ideal
for a base class for interactive view models as the entire logic of transitioning and queueing
transition requests is all in one class and that class has no other responsibility. [11]
This increases code reuse and reliability as the InteractiveViewModel class has only one
responsibility which can be thoroughly analyzed and tested.
The next step is extending the class to work within a data context. Previously it was mentioned
that domain objects themselves should be observable and that they should be the data context
in which a view model operates.
While this may seem easy at first, there is a catch. When working with user input one must always
validate that input. The rule still applies to interactive view models. The class containing the core
29. Interactive Applications in .NET - Implementing the Machine
29
functionality cannot be simply derived and have an extra property holding the data context. The
derivative must provide a way that alongside data, validation errors are also provided.
XAML allows to specify the data context of a control through the DataContext property. Any
binding expression made on the respective control will look at the object set through the
DataContext property if a source is not specified. The intellisense is smart enough to know this
meaning that once a DataContext is set one can use auto complete to browse through the list of
available properties to bind to.
Since there is only one DataContext property, in order to provide both data and validation errors
to a control in order to bind to them, they must be packed into one object and the respective
instance to be used as the DataContext of data bound controls.
The type of the object housing both data and context is called ViewModelContext. It is not prefixed
with “Interactive” since it may be used in other view models that are not interactive. It contains a
reference to an object (it can be an object but as discussed previously, it would make sense to be
a domain object) and a reference to a read only observable collection containing items of type
ValidationError. ValidationResult from ComponentModel is not portable.
The ViewModelContext class is generic as the object containing data can be of various types, even
though binding would work even if the type of the property used in binding is of type object, it
would be best to not limit intellisense where there is no reason to do so.
The InteractiveViewModel which operates with a data context receives on the constructor a data
object, which is generic, and provides to the ViewModelContext the same object and a read only
observable collection proxy to a usual observable collection. This is to restrict the ability to edit
the list of errors from outside the view model. [14]
The observable collection of errors and the data object are exposed as protected properties which
makes them only available to derivatives. This way, any interactive view model is able to manage
the list of errors in their own way.
Figure 7 illustrates the static structure of the components using class diagrams. [13]
30. Interactive Applications in .NET - Implementing the Machine
30
FIGURE 7 STATIC STRUCTURE
InteractiveViewModel
#CreateActionState(name : string, action : Action<ActionStateContext>)
#TransitionToAsync(name : string) : Task
#TransitionToAsync(name : string, parameter : object) : Task
#EnqueueTransitionToAsync(name : string) : Task
#EnqueueTransitionToAsync(name : string, parameter : object) : Task
#BindCommand(command : ICommand, states : string[*]) : ICommand
#GetTransitionCommand(state : string) : ICommand
#GetEnqueuingTransitionCommand(state : string) : ICommand
#GetTransitionCommand(state : string, errorHandler : Action<ErrorContext>) : ICommand
#GetEnqueuingTransitionCommand(state : string, errorHandler : Action<ErrorContext>) : ICommand
#CreateActionState(name : string, asyncCancellableAction : Func<ActionStateContext, CancellationToken, Task>)
#CreateActionState(name : string, asyncAction : Func<ActionStateContext, Task>)
TDataModel
InteractiveViewModel
+<<create>>(dataModel : TDataModel)
#<<get>>DataModel : TDataModel TDataModel
ViewModelContext
+<<get>>DataModel : TDataModel
ValidationError
+<<get>>Message : string
+<<get>>MemberName : string
#Errors : ObservableCollection<ValidationError>*
+Errors : ReadOnlyObservableCollection<ValidationError>
*
+Context1
ErrorContext
+<<get>>CanTransition : bool
+<<get, set>>NextState : string
+<<get>>FaultState : string
+<<get>>IsCancelled : bool
/+<<get>>Exception : Exception
+<<get>>AggregateException : AggregateException
InteractiveViewModel1
ActionStateContext
+<<get>>Parameter : object
+<<get>>NextState : string
InteractiveViewModel1
+<<get>>PreviousState : string
As it can be noted, there is an ErrorContext class. Commands have no returning type (void) thus
they cannot be awaited but can be asynchronous methods. In order to be able to handle errors
that may happen during the execution of a trigger command, an error handler callback can be
31. Interactive Applications in .NET - Implementing the Machine
31
provided to the GetTransitionCommand method. This method creates a command that when
executed it will trigger a transition towards the state given as parameter to the method. If the
method execution fails in an exception, cancellation is also reported as exception, then the
provided handler is used to remedy the situation and stop the application from crashing.
Within the error handler one can check whether the exception that occurred was actually a
completed cancellation or if something bad actually happened. Based on its logic, the error
handler instructs the interactive view model to what state it should transition.
The BindCommand method simply wraps the provided command into a proxy which allows the
command to be made available only when the interactive view model is in one of the bound states.
Ultimately it is up to the wrapped command to tell whether it is truly available in a bound state or
not through its CanExecute method. [14]
4.1.Reactive Extensions
Reactive Extensions is a library which also helps in developing interactive applications, however
they do not rely on INotifyPropertyChanged interface, but more on IObservable and IObserver
interfaces. Sadly, controls on the user interface do not respond to notifications from objects
implementing these interfaces, however Reactive Extensions make use of observable collections.
One can use this library to create asynchronous data flows using collections and queries. This is
particularly useful at the view model level as data which is provided by the user can be used to
filter collections asynchronously. The application will show results as they become available and
not all at once.
The approach presented in this paper does not cover data queries and how they should load on
the user interface, however with Reactive Extensions one can bind the two and achieve a rich user
experience with ease. The two can complement each other and neither is a replacement for the
other.
32. Interactive Applications in .NET - Conclusions
32
5. Conclusions
This paper has presented an architectural approach towards developing applications in general,
but more centered around being able to create rich user interfaces with tools that are already
available.
The originality of this work is illustrated through the implementation of a library that blends in
with the .NET Framework and can be easily integrated, even partially, in any application. The library
uses abstractions provided by the underlying framework without introducing any new ones that
require workarounds in certain scenarios.
The library itself is an extension of the framework not only using its abstractions but also
promoting language features available in both C# and Visual Basic .NET, the library bridges
concepts and tools in an effort to ease the creation of applications that provide a rich user
experience by using asynchronous programming and eliminating data races that tend to happen
in applications that use worker threads instead.
33. Interactive Applications in .NET - References
33
6. References
[1] R. C. Martin, The Clean Coder: A Code of Conduct for Professional Programmers, 1st ed.,
Prentice Hall, 2011.
[2] J. Albahari and B. Albahari, C# 5.0 in a Nutshell: The Definitive Reference, 5th ed., O'Reilly,
2012.
[3] A. Davies, Async in C# 5.0, 1st ed., O'Reilly Media, 2012.
[4] J. Smith, "Patterns - WPF Apps With The Model-View-ViewModel Design Pattern," MSDN
Magazine, vol. 24, no. 2, pp. 72-83, February 2009.
[5] E. Gamma, R. Helm, R. Johnson and J. Vlissides, Design Patterns: Elements of Reusable
Object-Oriented Software, Pearson Education, 1994.
[6] Microsoft Patterns & Practices Team, Microsoft® Application Architecture Guide (Patterns
& Practices), 2nd ed., Microsoft Press, 2009.
[7] R. C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship, 1st ed., Prentice Hall,
2008.
[8] E. Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software, Addison
Wesley, 2003.
[9] V. Vernon, Implementing Domain-Driven Design, 1st ed., Addison-Wesley Professional,
2013.
[10] E. Burris, Programming in the Large with Design Patterns, 1st ed., Pretty Print Press, 2012.
[11] V.-S. Tarquin, "MVVM - WPF Commanding with the State Machine Pattern," MSDN Magazine,
vol. 29, no. 11, pp. 58-61, November 2014.
[12] G. H. Mealy, "A Method for Synthesizing Sequential Circuits," Bell System Technical Journal,
p. 34: 5, September 1955.
[13] R. Miles and K. Hamilton, Learning UML 2.0, O'Reilly, 2006.
[14] E. Freeman, B. Bates, K. Sierra and E. Robson, Head First Design Patterns, 1st ed., O'Reilly
Media, 2004.