|
|
Michael L Perry's blog
Submitted by Michael L Perry on Sat, 03/16/2013 - 17:46
This weekend I spoke at Cowtown Code Camp. I showed a demo of Correspondence, and built an app called "I Like Tunes". I built the app for Windows Phone and Windows 8 simultaneously, all the while showing how these two versions of the app talk to each other.
Please download the slides and code.
Submitted by Michael L Perry on Thu, 03/14/2013 - 14:34
Google Reader will be retired on July 1, 2013. This leaves a vacuum in the application landscape. Many of the best reader applications on various platforms have used Google Reader as a back end. There are several RSS readers that are not backed by Google, but these applications lack an important feature: the Continuous Client. When you use an RSS reader on one device, it doesn’t know about the posts you’ve already read on a different device. Google Reader solved that problem, because it was a common back end for multiple clients.
Correspondence
To fill this vacuum, I am starting an open source project to build an RSS reader back end on Correspondence. Correspondence is a client library and a cloud service for building occasionally-connected applications. Correspondence applications work off-line. They store data locally so that it is immediately accessible and updatable without a network. They also publish data to the cloud, so that it can be shared across devices and across individuals.
Correspondence is the perfect platform for a continuous RSS reader client. People want to be able to consume posts while off-line. They want the application to know which posts they have read. And they want the application to publish that to the cloud so that they get a continuous experience when they pick up another device.
Correspondence currently supports all Microsoft client stacks. For this project, we will begin by focusing on Windows Phone, Windows 8, and ASP.NET MVC. In the near future, Correspondence will be ported to Android and iOS via Xamarin, and will have JavaScript binding for rich web clients. Work has already begun on a native Android implementation of Correspondence. A native Objective-C implementation for iOS will begin in the future.
So eventually, we will be able to deploy the RSS reader application natively to any client, and provide a rich web-based experience as a fall-back.
Join me
Please watch the project on GitHub. Once there’s a basic project structure in place, you can fork it and help me out with pull requests. I’ve created an AgileZen board for keeping track of work items. If you want to participate in a more material manner, please send me an email (Michael at this domain) or tweet (Michael L Perry on Twitter) and I’ll add you to the board.
The clients will be launched in their respective stores as free apps. My intention is not to produce revenue on the reader apps themselves, but to promote Correspondence as a platform.
Please help me to support the folks that Google has left behind.
Submitted by Michael L Perry on Mon, 02/18/2013 - 18:48
To develop applications for Windows 8, you need to obtain a developer license. This is not the same as the Windows Store registration that allows you to publish applications. You don’t pay for this license. This is just a token that lets you run applications on your own machine. This license expires every 30 days, so you need to renew it often.
As you develop your app, it pays to frequently run on lower-powered hardware. Develop on a full-powered PC, but deploy to a surface RT or other ARM device periodically to test. To do this, you need to renew your developer license on the RT device as well.
On your full development machine, Visual Studio will prompt you to renew your license when you open your project. But on an ARM device, you don’t have Visual Studio. To renew the license, you have to run the following PowerShell command as an administrator:
Show-WindowsDeveloperLicenseRegistration
This will display a login page where you enter your Microsoft ID credentials. You won’t be charged. You will just get a new license that is good for 30 days of development and testing.
Since you need to do this frequently, you’ll want to create a shortcut that you can launch from the start screen. Here’s how you do that.
Create a PowerShell script
Create a folder called c:\Scripts. Create a text file in that folder called “DeveloperLicense.ps1”. Add the command above to the text file. You can do this by running the following from the command line:
mkdir c:\Scripts
echo Show-WindowsDeveloperLicenseRegistration > c:\Scripts\DeveloperLicense.ps1
Create a shortcut
Then create a shortcut in that same folder. You do that by right-clicking and selecting “New”, “Shortcut”. Set the target to the following:
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe c:\Scripts\DeveloperLicense.ps1
Name this shortcut “Renew Developer License”. Right-click the new shortcut, edit the properties, click Advanced, and set it to run as administrator.
Set the execution policy
Finally, before you can run this license for the first time, you need to set the execution policy. Open a PowerShell command prompt as an administrator. To do this, pull up the start screen, type “PowerShell”, right-click “Windows PowerShell”, and click “Run as administrator”. Then run this command:
Set-ExecutionPolicy Unrestricted
I should warn you that this opens your machine to running untrusted PowerShell scripts. Find out more about this setting at http://go.microsoft.com/fwlink/?LinkID=135170. Don’t do this lightly.
Finally, you can right-click on this shortcut and pin it to the start screen. Now you can easily tap the tile and login to renew your free Windows developer license.
Submitted by Michael L Perry on Wed, 02/13/2013 - 15:36
With my style of MVVM, you end up with several layers of view model, each one taking a reference to a different part of the model. The view model hierarchy mirrors the model hierarchy. When a view model lower in the hierarchy needs a new reference, I have to plumb that parameter through all of the constructors.
At least, I used to. Now I use a simple functional IoC pattern.
Hierarchy of view models
MyCon is a template for conference web sites and mobile applications. In the Windows 8 app, the sessions for the conference appear in a GridView, grouped by track. The GridView is data bound to the TracksViewModel. This view model exposes a collection property called Tracks. It is a collection of TrackViewModel. This view model in turn exposes a collection of SessionHeaderViewModel through a property called Items.
public class TracksViewModel
{
public IEnumerable<TrackViewModel> Tracks
{
get
{
return
from track in _synchronizationService.Conference.Tracks
orderby track.Name
select new TrackViewModel(track);
}
}
}
public class TrackViewModel
{
public IEnumerable<SessionHeaderViewModel> Items
{
get
{
return
from sessionPlace in _track.CurrentSessionPlaces
orderby sessionPlace.Place.PlaceTime.Start
select new SessionHeaderViewModel(sessionPlace);
}
}
}
Each view model constructor takes a reference to the part of the model that it represents. So the TracksViewModel takes a reference to the SynchronizationService – the top-level object that provides the reference to the Conference. The TrackViewModel references a Track. And the SessionHeaderViewModel references a SessionPlace – a model object that knows where and when a session will be given.
public class TracksViewModel
{
private readonly SynchronizationService _synchronizationService;
public TracksViewModel(SynchronizationService synchronizationService)
{
_synchronizationService = synchronizationService;
}
}
public class TrackViewModel
{
private readonly Track _track;
public TrackViewModel(Track track)
{
_track = track;
}
}
public class SessionHeaderViewModel
{
private readonly SessionPlace _sessionPlace;
public SessionHeaderViewModel(SessionPlace sessionPlace)
{
_sessionPlace = sessionPlace;
}
}
Add a selection model
The application also has a SelectionModel. This class records which session is currently selected. The SessionHeaderViewModel needs to set a property on the SelectionModel when it has been clicked. So let’s add the SelectionModel reference to the SessionHeaderViewModel constructor.
public class SessionHeaderViewModel
{
private readonly SessionPlace _sessionPlace;
private readonly SelectionModel _selectionModel;
public SessionHeaderViewModel(SessionPlace sessionPlace)
{
_sessionPlace = sessionPlace;
_selectionModel = selectionModel;
}
}
After doing this, we have broken its parent view model – TrackViewModel. It needs to call the SessionHeaderViewModel constructor, so it needs to pass in the new parameter.
public class TrackViewModel
{
private readonly Track _track;
private readonly SelectionModel _selectionModel;
public TrackViewModel(Track track, SelectionModel selectionModel)
{
_track = track;
_selectionModel = selectionModel;
}
public IEnumerable<SessionHeaderViewModel> Items
{
get
{
return
from sessionPlace in _track.CurrentSessionPlaces
orderby sessionPlace.Place.PlaceTime.Start
select new SessionHeaderViewModel(sessionPlace, _selectionModel);
}
}
}
Now it takes the SelectionModel and passes it on through. But guess what. Now we’ve broken its parent – TracksViewModel. So again, we have to plumb the parameter through the parent.
public class TracksViewModel
{
private readonly SynchronizationService _synchronizationService;
private readonly SelectionModel _selectionModel;
public TracksViewModel(SynchronizationService synchronizationService, SelectionModel selectionModel)
{
_synchronizationService = synchronizationService;
_selectionModel = selectionModel;
}
public IEnumerable<TrackViewModel> Tracks
{
get
{
return
from track in _synchronizationService.Conference.Tracks
orderby track.Name
select new TrackViewModel(track, _selectionModel);
}
}
}
And so it goes with every constructor parameter I need to add. If a child view model needs to know about it, then the parent view model needs to provide it. And it bubbles up the hierarchy. Every level needs to know about all of these parameters, even if they don’t use them directly.
Functional IoC to the rescue
This looks like the sort of problem that an IoC container solves. IoC – Inversion of Control – is a pattern that takes construction and dependency management out of the hands of business objects, like view models. It places that responsibility in the hands of a container. The IoC container creates all of the business objects, so that they don’t have to create each other. And it figures out how to resolve their dependencies so that the intermediate objects don’t need to worry about it.
There are many great open source IoC containers available. One that would be particularly adept at solving this problem is AutoFac. But we’re not going to use AutoFac, or any other IoC container library. Instead, we are going to use a feature of the language: function closure.
Closure simply means that a function in C# will encapsulate any variables that are referenced within the function body. So we can declare a function that creates a SessionHeaderViewModel like so:
SelectionModel selectionModel = new SelectionModel();
Func<SessionPlace, SessionHeaderViewModel> newSessionHeaderViewModel = s =>
new SessionHeaderViewModel(s, selectionModel);
The variable selectionModel is declared outside of the scope of the lambda, but since it is referenced inside, that variable is encapsulated within the function. Anyone who calls the newSessionHeaderViewModel function will get back an object with that same SelectionModel reference.
Instead of letting the parent TrackViewModel call the SessionHeaderViewModel directly, we’ll just give it this function.
public class TrackViewModel
{
private readonly Track _track;
private readonly Func<SessionPlace, SessionHeaderViewModel> _newSessionHeaderViewModel;
public TrackViewModel(Track track, Func<SessionPlace, SessionHeaderViewModel> newSessionHeaderViewModel)
{
_track = track;
_newSessionHeaderViewModel = newSessionHeaderViewModel;
}
public IEnumerable<SessionHeaderViewModel> Items
{
get
{
return
from sessionPlace in _track.CurrentSessionPlaces
orderby sessionPlace.Place.PlaceTime.Start
select _newSessionHeaderViewModel(sessionPlace);
}
}
}
Continuing this trend upward, we’ll define a function that creates TrackViewModels. Again, we’ll use functional closure to encapsulate the parameters we need.
SelectionModel selectionModel = new SelectionModel();
Func<SessionPlace, SessionHeaderViewModel> newSessionHeaderViewModel = s =>
new SessionHeaderViewModel(s, selectionModel);
Func<Track, TrackViewModel> newTrackViewModel = t =>
new TrackViewModel(t, newSessionHeaderViewModel);
In this case, the newTrackViewModel function is encapsulating the newSessionHeaderViewModel function. So we change the TracksViewModel to use this function.
public class TracksViewModel
{
private readonly SynchronizationService _synchronizationService;
private readonly Func<Track, TrackViewModel> _newTrackViewModel;
public TracksViewModel(SynchronizationService synchronizationService, Func<Track, TrackViewModel> newTrackViewModel)
{
_synchronizationService = synchronizationService;
_newTrackViewModel = newTrackViewModel;
}
public IEnumerable<TrackViewModel> Tracks
{
get
{
return
from track in _synchronizationService.Conference.Tracks
orderby track.Name
select _newTrackViewModel(track);
}
}
}
A containerless container
All of the functions related to a given top-level view model need to be managed in the same scope. That is what allows those functions to be encapsulated into each other via closure. And so I like to declare a static class in my view model namespace called Container. This static class contains a static method that creates a top-level view model.
public static class Container
{
public static TracksViewModel CreateViewModel(
SelectionModel selectionModel,
SynchronizationService synchronizationService)
{
Func<SessionPlace, SessionHeaderViewModel> newSessionHeaderViewModel = s =>
new SessionHeaderViewModel(s, selectionModel);
Func<Track, TrackViewModel> newTrackViewModel = t =>
new TrackViewModel(t, newSessionHeaderViewModel);
return new TracksViewModel(synchronizationService, newTrackViewModel);
}
}
Then if I need to add a parameter to any of the view models in this hierarchy, I simply add that parameter to this function. It is encapsulated into the functions that need it. The view models that don’t need it do not need to change.
Without resorting to an IoC container library, I have defined a container that creates instances of view models. It manages the dependencies of each particular view model, so that the parent view models don’t have to. It does so simply by using the language feature of function closure.
You can see the complete source code at https://github.com/michaellperry/MyCon. Open the FacetedWorlds.MyCon project the WinRT folder.
Submitted by Michael L Perry on Thu, 01/24/2013 - 12:43
In “About Face”, Alan Cooper showed us how the Save command in most desktop programs forces users to change their conceptual model. The user has a model of how the domain works, and that model does not include things like memory and files. When an application provides a Save command, it forces the user to see the implementation detail that data on the disk can be different from the data in memory. This is an artificial boundary
This artificial boundary becomes increasingly visible when the user exits the program. If they haven’t hit that Save button, then they get a prompt. This prompt points out that the version of their document in memory is different than the one on disk. It “stops the proceedings with idiocy”. The user wanted to quit the program and move on to something else, but the idiot program interrupted them to satisfy its own implementation detail. That detail – the artificial boundary – is unimportant to the user.
Boundaries on the web
On the web, there is no Save command. Users make their changes, and those changes are naturally saved. The artificial boundary doesn’t exist … or does it?
The web actually has a much bigger artificial boundary: that between the browser and the server. The data that the user enters is not saved until they hit submit. Even then, there might be a network problem that prevents them from submitting the form. There might be an authentication step that they have to complete. And there is always the very real risk that the work that the user is trying to save won’t be there after they correct the problem or hit the Back button.
So we rely on AJAX to solve this problem. As the user enters data on the page, we can post back to the server. We don’t have to wait for them to click Submit. We don’t have to show them the artificial boundary, unless something goes wrong. Then, of course, all bets are off and we have to tell them that we failed to save their data.
Boundaries in code
The AJAX solution is a reasonable one. Unfortunately, it creates artificial boundaries within our code. For example, in an MVC application, we have one programming model for postback-style web pages, and another programming model for AJAX.
In a postback-style web page, we inject data into the page on the server using Razor. Then, when the user clicks Submit, we pull data back out of the page using the model binder.
But in an AJAX-style interaction, we can use neither of these. We send data to the client through a REST endpoint as JSON, and then receive it in a similar fashion. All of the data injection, binding, and DOM manipulation occurs in JavaScript rather than Razor.
This is an artificial boundary, too. It’s one that we have imposed upon ourselves. But this isn’t the way it has to be.
Recognizing boundaries
A boundary in software exists when the state on one side can differ from the state on the other. The document in memory can be different from the one on disk. The data in the browser can be different from the data on the server. Sometimes we can eliminate these boundaries. Sometimes these boundaries have to exist. But we must recognize them as accidental complexity – not essential to the problem that we are actually trying to solve.
When you see a view model with fields or auto properties, that is an artificial boundary that we can eliminate. Fields and auto properties can store data. That data can become different from its source. To eliminate this boundary, write get and set methods in your properties that reference the source directly. That’s what I’ve done with Update Controls.
When you see data on disk and in memory, that is another artificial boundary that we can eliminate. Let the in-memory cache be the only way to access the persisted data. Write through the cache so that you know it always represents the persisted data. That’s what I’ve done with Correspondence.
When you see two machines separated by a network, then there is an artificial boundary that we can’t eliminate. But at the very least, we could define a consistent, composable programming model that recognizes the boundary, yet doesn’t force you to code against it. This programming model should be Again, that’s what I’ve done with Correspondence.
In future posts, I will lay out the programming model that remains consistent across artificial boundaries, and eliminates them entirely when possible. I will show examples in client applications first. But eventually, I will apply these principals to web applications. The goal is to reduce defects by making all programming consistent and composable across boundaries.
Submitted by Michael L Perry on Fri, 12/28/2012 - 19:29
How often have you closed the lid to your laptop and put it in the bag, only to reach in an hour later and feel a nice toasty machine with a nearly dead battery?
Here’s a little program to solve that problem. I call it “No, Really!”.
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
for (;;)
{
DWORD sleep = GetTickCount();
SetSuspendState(false, false, true);
DWORD wake = GetTickCount();
if (wake-sleep > 30000)
break;
}
return 0;
}
Submitted by Michael L Perry on Sat, 12/08/2012 - 14:51
Distributed systems are constructed from different bounded contexts. These subsystems each have their own dialect of the ubiquitous language, and are owned by different teams. An enterprise service bus lets you integrate these bounded contexts using messages. Messages are a fantastic form of integration, because they tend to be small, complete, and temporally decoupled. But to effectively integrate using messages, you need to understand what kind of messages you can use.
Kinds of messages
A distributed system using a message-driven architecture will have three kinds of messages:
Each kind of message is intended to flow between bounded contexts in a certain way.
A command is a message that is intended to change the system in some way. Commands are sent asynchronously. They are sent durably. And they carry a complete payload. Commands are named as imperative verb phrases using words like “place” or “process”.
An order placed by a customer is an example of a command. The command carries with it all of the items that the customer wishes to order. There is no guarantee that the command will be successful, but there is a guarantee that it will be processed. We can make this guarantee by adhering to the rules of durability. The command will be received, it will be processed, and it will not be duplicated. We just can’t make any guarantees about the outcome of the command. It may result in the order being shipped. Or it may result in a refund and an apologetic email.
A query is a message that makes no change to the system. Instead, it returns results. Queries are sent synchronously. They are not sent durably. And they carry a specification. Queries are named as imperative verb phrases using words like “get”, “check”, or “list”.
For example, a customer can query for the status of a previously submitted order. The query doesn’t change anything. It is safe to query the status again and again. Because of this, queries don’t have to be sent durably. The payload of the query is a set of criteria for the desired results. These criteria collectively are called a specification. In the case of an order status query, the specification could be nothing more than the order ID.
An event is a notification message that is multi-cast to several interested parties. Events are sent asynchronously. They are sent durably. And they carry a complete payload. what distinguishes an event from a command is the fact that the sender does not have any particular intent for the subsequent change to the system. An event is named as a past tense verb phrase.
The fulfillment system will notify any interested party when an order ships. It multi-casts the order shipped event asynchronously to all subscribers. It must send these messages durably, because they may have a downstream impact on the system. The event contains all of the information that a subscriber might need. This includes the contents of the order, information about the customer, and tracking information for the shipment. The publisher has no way of knowing which pieces of information will be important to the subscribers, so it has to send everything.
Dependencies among bounded contexts
One of the best features of an enterprise service bus is the way that it manages dependencies among bounded contexts. The dependencies in an ESB do not necessarily flow in the same direction as the information. The direction of the dependency is determined by the system that defines it. It is not determined by the direction in which the information flows.
Commands are defined by the information consumer. The producer sends the message to the consumer. The sender intends to make a certain change to a system. It needs to express that intent using the language of the consumer. Senders take a dependency on consumers. They know the data types defined by the command handler, as well as the address of the handler.
Queries are defined by the information producer. The consumer calls an RPC to request information from the producer. The caller provides a specification using the language of the producer. The producer will respond using data types that it has defined. Even though the information is flowing back toward the consumer, the direction of dependency is toward the producer.
Events are defined by the information producer. The consumer subscribes to events from the producer. The subscriber makes the request using the language of the publisher. The subscriber knows the address of the publisher, not the other way around. The publisher will multi-cast events using its own data types. So even though the data is flowing toward the subscriber, the dependency is toward the publisher.
By decoupling the direction of dependency from the direction of information flow, an enterprise service bus lets information flow in many directions without forming circular dependencies. The dependency direction is best optimized for collaboration among bounded contexts created by different teams, hosted on different hardware, and deployed on different schedules. The ESB manages those dependencies and keeps the information flowing.
For more information about CQRS, durability, and enterprise service busses, please watch CQRS Theory and Practice on Pluralsight.
Submitted by Michael L Perry on Mon, 10/29/2012 - 12:12
In a system using the CQRS pattern, the client will typically send command messages to a queue. A handler will pull messages from that queue for asynchronous processing.
When we take this approach, we have to be sure not to violate the client’s trust. If they send us a command, and know that we have received it, they should expect that it will eventually be processed. Furthermore, if they send us a command, and don’t know whether we received it (because they got a network failure), then they should feel safe to re-send the command.
These are durability guarantees. We guarantee that the message was persisted. If the server reboots before it can handle the message, the message won’t be lost. The message is not removed from persistent storage until it is processed. And if the client sends a duplicate, the handler recognizes it and does not duplicate the results.
MSMQ command queue
If you are using MSMQ for the commands, you don’t get the durability guarantees for free. The default behavior of MSMQ is optimized for performance. Durability has a cost. To get it, use the following options:
- Recoverable messages
- Transactional queues
- Private local queues
As C# developers, we have our own definition for public and private. These definitions do not apply to MSMQ. Private local queues are managed just at the machine level. A public queue is managed by Active Directory. Because we are using this queue as an inbox for a known command handler, private queues are the simpler option.
When the command handler first starts up, it needs to check whether the queue exists. If not, it should create it. Use the overload that takes an extra boolean parameter so that you can specify this to be a transactional queue.
_path = @".\private$\" + queueName;
if (!MessageQueue.Exists(_path))
{
MessageQueue.Create(_path,
transactional: true);
} To send a message to a transactional queue, you have to be in a transaction. Create a TransactionScope to begin the transaction. Use the Send overload that takes a MessageQueueTransactionType so that you can tell MSMQ to participate in that transaction. And always remember to call Complete on your transaction scope when it’s done. If you forget any of these steps, you will find that your message is silently dropped, and never makes it to the queue.
We want to send recoverable messages to the queue. Recoverable messages are persisted. Non-recoverable messages are kept in memory. If the machine reboots before the handler removes them from the queue, non-recoverable messages are lost. Set the Recoverable property to “true” before sending.
using (var scope = new TransactionScope())
{
using (var queue = new MessageQueue(_path))
{
queue.DefaultPropertiesToSend
.Recoverable = true;
queue.Send(message,
MessageQueueTransactionType.Automatic);
}
scope.Complete();
} The receiver must also create a TransactionScope to receive from a transactional queue. It should enlist its database connection in this same transaction. That way the removal from the queue and the commit to the database are performed atomically. If the message is not processed, it is not removed from the queue.
Because we are using this transaction scope for database operations, be sure to set the isolation level to ReadCommitted. By default the isolation level is Serializable, which is usually far too paranoid. Again, use the MessageQueueTransactionType to enlist in the active transaction, and remember to call Complete.
using (var scope = new TransactionScope(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = IsolationLevel
.ReadCommitted
}))
{
using (var queue = new MessageQueue(_path))
{
var msmqMessage = queue.Receive(
MessageQueueTransactionType.Automatic);
message = (T)msmqMessage.Body;
HandleMessage(message);
scope.Complete();
}
} By using MSMQ in this way, you can guarantee that the message is persisted, and that it is not removed from persistent storage until it is processed. But this does not guarantee that duplicates are recognized. For that, we need to follow some simple guidelines.
Duplicate messages
If the client sends a command, and a network exception occurs, then the client doesn’t know whether message made it into the queue. It has no choice but to retry. It is up to the server to detect duplicates and handle them appropriately. To make sure we don’t duplicate, follow these guidelines:
- Client-generated identifier
- Check for the outcome
- Nod and smile
To detect duplicates, the server needs a way to uniquely identify commands. Because the duplication originates on the client, the unique identifier must as well. include a Guid command ID with every message.
public class PlaceOrder
{
public Guid OrderId { get; set; }
...
} When the handler has processed the message – whether it was successful or not – it should store an outcome. Make sure that outcome includes the command identifier. Then, when the next message comes in, you can simply check for an outcome having the same ID.
You might be tempted to throw an exception when you detect a duplicate. Doing so only confuses the issue. The best thing to do is nod and smile.
The client has already sent the original message, gotten an error, and sent the duplicate. They should not get an error after having successfully sent a message. What would the client do in response to that exception? The answer is the same as if they received no exception: move on. So don’t throw an exception to the client. Just nod and smile.
It’s better to just check for duplicates in the handler, after the client has already moved on. If you find an outcome for this command, then you know that the message is a duplicate. Just short-circuit the handler.
if (_pickListService.GetPickLists(message.OrderId)
.Any())
return; These guidelines will help you to create services that uphold the durability guarantees. If the client knows that you have received the message, then they know that you have already persisted it. If the power goes out, their command won’t be lost. Furthermore, they know that you won’t drop the message until it has been handled. And finally, if they have to send you a duplicate in order to know that you’ve received it, they can rest assured that you won’t duplicate the results.
Submitted by Michael L Perry on Thu, 10/18/2012 - 10:37
Greg Young and Udi Dahan have documented a pattern that they found worked well in large-scale distributed systems. They called this pattern Command Query Responsibility Segregation, or CQRS. This pattern is based on the principal of Command Query Separation, or CQS, which is described in Bertrand Meyer’s Object-Oriented Software Construction. It seeks to scale read-heavy components separately from write-heavy components. In order to achieve that scale, the responsibilities for processing write-heavy commands had to be segregated from the responsibility of processing read-heavy queries.
Command Query Separation
The underlying principal of Command Query Separation tells us that a method should either change the state of the system, or return results. A method should not do both. It is very difficult to reason about the behavior of a software system if it changes state whenever you observe it. The methods that change state are commands. The methods that return results are queries.
It is very easy for a user of the API to recognize commands and queries. Commands declare their return type as “void”. Queries have a non-void return type. This also makes it easy to spot the calls in code. The code will be doing something with the results of queries.
Have you ever seen code that ignores the return value of a method call? The caller probably made a mistake. It’s very difficult to see that mistake in the written code, since you can’t see that the method returns a value. If the method obeyed the principal of Command Query Separation, then it either wouldn’t have any effect on the system, or it wouldn’t have a return value to ignore. Either way, the caller wouldn’t be able to make that mistake.
When code follows the principal of Command Query Separation, callers are encouraged to organize their code in three sections. The first section gathers information by executing queries. The second section makes a decision based on that information. And the third section records the decision by calling a command.
There can be many calls to different objects to get the information the caller needs. These calls can occur in any order. Since the calls have no side-effects, they can be easily reordered. New calls can be inserted with no change in correctness.
There is usually just one command issued at the end of this kind of sequence. Chains of commands open the possibility for corruption and inconsistencies due to partial successes. It is much easier to maintain code in which each command leaves the system in a consistent state. A subsequent sequence of operations can read that state and issue the next command.
This kind of structure is much easier to reason about. In the gather information section, we can rewrite the calls just as we would a mathematical equation. We can apply the commutative and associative properties, because the order in which we execute queries has no effect on their results. There is only one state change in the entire sequence, and that always occurs at the end.
Command Query Responsibility Segregation
The CQRS pattern has a much different goal than it’s predecessor, the CQS principal. The goal of CQRS is to scale reads differently than writes.
Many of the systems that we build are read-heavy. We tend to read data much more often and in much higher quantity than we write it. You can actually calculate a ratio for any given system. Take a typical record. It will be written once. How many times will it be read? How many times will it be aggregated to produce a report? How many times will it be shared with the other users of the system? In most systems, it is not surprising to find that the average record is read hundreds or thousands of times. So the ratio of reads to writes is easily two to three orders of magnitude, in most business systems.
Given the read-heavy nature of business systems, when they come under load, it makes sense to scale up the number of resources dedicated to servicing reads. However, if those same resources are responsible for writes, then those resources are wasted. Worse, those resources can put heavier write load on the system, compete with the reads, and counteract the benefit of scaling up in the first place.
Where CQS separates commands from queries at the method level, CQRS separates them at the component level. Some components are responsible for commands – writes – and others are responsible for queries – reads. To scale out a read-heavy business system, you can allocate more resources just to the read components.
CQRS in practice
Consider this WCF contract.
[ServiceContract]
public interface IFulfillmentService
{
[OperationContract]
Confirmation PlaceOrder(Order order);
} This method does not obey the CQS principal. It is changing the state of the system, and returning a result. Hidden inside of this result is a tracking number. This result is quite expensive. To process an order and get a tracking number, the fulfillment system needs to:
- Locate inventory
- Allocate that inventory to this order
- Determine the shipment method
- Allocate space on a pallet
- Obtain a tracking number from the carrier
Because this is returned from a method, all of these steps must be performed synchronously. The caller will have to wait while those steps are performed before they know that their order has even been submitted.
The first step in correcting this problem is to define two methods: a command and a query.
[ServiceContract]
public interface IFulfillmentService
{
[OperationContract]
void PlaceOrder(Order order);
[OperationContract]
Confirmation CheckOrderStatus(Guid orderId);
} Now the service can return immediately after storing the incoming order. It doesn’t have to go through all of the steps before letting the caller know that the order was received. The caller can come back later and check the status of the order by executing a query.
The next step will be to move the processing of that command to a different component. We will see how to do that in the next article.
For the complete example, please download the code from the PharmaNet repository on GitHub. Look at the Fulfillment solution for this service.
Submitted by Michael L Perry on Tue, 09/25/2012 - 15:37
When a Correspondence application starts up, it doesn’t need to immediately load data from storage. It can complete its data binding and render an empty view. Then, when the data is loaded, it can update the view. This results in quicker load times and more responsive applications. But it also means that you sometimes have to take one extra step to ensure the value of a property or result of a query.
Delayed load for more fluid UI
Let’s start with a simple model. An individual is identified by their anonymous Windows Live ID. The user can change their name. Here’s the model:
fact Individual {
key:
string anonymousId;
mutable:
publish string name;
} We’ll inject the individual into a view model. From there, we expose the name property for data binding.
public class MainViewModel
{
private Individual _individual;
public MainViewModel(Individual individual)
{
_individual = individual;
}
public string Name
{
get { return _individual.Name; }
set { _individual.Name = value; }
}
} When the application starts up, Correspondence won’t wait for the name to load from storage before displaying the view. It will just return a null during the initial data binding. After the name has loaded asynchronously, it will fire property changed and update the view.
When the user enters a new name, the property setter asynchronously starts the process of writing the new value. It returns before that process is finished so that the UI can be more responsive. When dealing with data binding and user interaction, this behavior is beneficial. The UI renders more quickly and fluidly, even if the data fills in just a fraction of a second later.
Delayed load is not so good for code
But when dealing with code, this behavior is unexpected. For example:
_flynn.FavoriteColor = "Blue";
// It's still blank.
Assert.AreEqual(null, _flynn.FavoriteColor.Value); If I’ve never read the property before, it will return null. It will start loading the value asynchronously, but by then my code has already moved on. It won’t respond to a PropertyChanged notification when the value finishes loading.
Ensure that a property is loaded
You don’t want the UI to wait for the value to finish loading. That would just cause stutter. But you do want code to wait. So in code, you should call the “Ensure()” method. Ensure will block until the property has finished loading.
_flynn.FavoriteColor = "Blue";
// Ensure that the value is loaded.
Assert.AreEqual("Blue", _flynn.FavoriteColor.Ensure().Value); Ensure that query results are loaded
Ensure also works with queries. By default, a query will return an empty collection while the result loads asynchronously. But when you need to make a decision based on the results of a query, you need to Ensure that they’ve finished loading.
TaskList taskList = individual.TaskLists.Ensure().FirstOrDefault();
if (taskList == null)
taskList = individual.CreateTaskList();
Task task = taskList.AddTask(); Without the call to Ensure, this code will create a new task list every time the application starts.
Because Ensure blocks, do not call it in a view model property getter. You don’t want to block the UI. But it is perfectly valid in a view model property setter. The user has already performed an action, and they won’t perceive the momentary pause while the query or property loads. It’s also appropriate to use in background code that is not related to the view model at all. If you use Ensure in the right places, you can have the consistent behavior that code needs while still getting the responsive UI that the user desires.
|