About me

Michael L Perry

Improving Enterprises

Principal Consultant

@michaellperry

User login

Michael L Perry's blog

Delegates vs. Lambdas

What is the difference between these two lines of code?

bool anyNegative = numbers.Any(n => n < 0);

Vs.

bool anyNegative = numbers.Any(delegate(int n)
{
    return n < 0;
});

On the face of it, not much. These two lines do exactly the same thing. Yet there is an important difference.

The code inside of the lambda is an expression. The code inside of the delegate is a statement.

Expressions vs. statements

An expression computes a value, whereas a statement performs an action. In the above code, that action is to “return” a value. But the action could have been to change state. And therein lies the danger.

The order in which statements are executed is important. This is especially true if those statements change state. An assignment changes the state of a variable. A statement performed before the assignment sees the old value. A statement performed afterward sees the new value.

int m = 2;
Console.WriteLine(m);
m = 3;
Console.WriteLine(m);

Expressions, on the other hand, can be executed in any order, provided that they don’t change state. In the following code, it doesn’t matter if the program calculates x squared or y squared first. It will get the same answer because neither calculation changes state.

double x = 4.0;
double y = 3.0;
double h = Math.Sqrt(x * x + y * y);

Some expressions change state. For example, though the ++ operator increments a variable, it can be used as an expression. Also, a method called as part of an expression might in fact have some mutating side-effect. But in general, if we intend to change state, we will usually use a statement.

Delegates are commands; lambdas are queries

In Object-Oriented Software Construction, Bertrand Meyer defined a principle called “Command-Query Separation”. This principle encourages us to separate code that modifies state from code that computes values. A method that modifies state is a command, and should return void. A method that computes a value is a query, and should have no mutating side-effects.

If we follow this principle, then it will be difficult for us to write an expression that mutates state. If we avoid operators like ++ within our expressions, and we can’t call a void method, then we can safely assume that an expression is non-mutating. If our intent was to mutate state, we would have written a statement.

So if delegates contain statements, and the intent of a statement is to mutate state, then all delegates should be commands. Conversely, if lambdas contain expressions, and expressions can’t mutate state, then all lambdas should be queries.

To make your intention clear, use lambdas to compute values, and delegates to make changes.

public ICommand Delete
{
    get
    {
        return MakeCommand
            .When(() => _selected != null)
            .Do(delegate
            {
                _selected.Delete();
            });
    }
}


Correspondence on Android

Correspondence_AndroidBuilding an Android app that stands out from the Marketplace crowd is not easy. The experience has to be worth talking about. And the app needs to give people a reason to share. If the app is unresponsive or frustrating, people aren’t going to use it. And if it doesn’t connect people, they aren’t compelled to talk about it.

Correspondence is a collaboration framework. It solves the technical problems related to building mobile apps that connect people. It provides local storage on the device, synchronization across devices, push notifications, and UI updates.

And now Correspondence is available on Android.

Build compelling collaborative experiences

Most of the apps that you find in the Android Marketplace are single-player games or single-user utilities. They store one person’s data on one device, and are designed for one user to enjoy. They are experience silos.

Mobile web applications, on the other hand, let users share information with one another. But they come with a cost. Most of them don’t store personal information locally, so you have to sign in to the server every time you use the app. And when you have a slow or intermittent data connection, the experience can suffer.

To make your app stand out from the Marketplace crowd, make it collaborative. A collaborative app lets users share information like a web app, but it also stores personal information on the device. Users get the advantage of a quick response regardless of the data connection, since all of the data that they have shared with others is stored locally. But they also get the advantage of being able to connect with their friends, since the collaborative application tears down the silos.

Phones are collaborative devices. An app should be a collaborative experience.

Focus on the client; we’ll handle the server

If you were to develop a collaborative application using traditional stacks, you would have to build a server-side database. Then you would build an API to access that database, probably using REST endpoints and JSON serialization. You would find a host, deploy the database and the code, and perhaps install an SSL certificate for secure communications. And whenever you add a features to your app, you’ll need to migrate the database and redeploy the code.

Correspondence is different. It is a single, application-agnostic server. It is schemaless, so there are no database scripts to deploy. And it has a single publish/subscribe API that can be used for any type of information. All you do is sign up for an API key, and build your app.

Download the project from GitHub. Follow the provided instructions to set up an Eclipse workspace and build the HoneyDo List example application.



Provable Code course on Pluralsight

Please check out my Provable Code course on Pluralsight. If you are not yet a Pluralsight subscriber, go ahead and sign up for 200 free minutes. You won’t be able to get through the whole course on that, but it will be enough for you to decide whether to subscribe.



You’re Invited publish subscribe

The reason for using Correspondence was to make it easy to share data between the phone and the web. Here's a few unit tests that show how the web subscribes to data published on the phone.



You’re Invited Correspondence model

In this video, I create the Correspondence model for the You're Invited application, and start a set of unit tests. The templates start off with a working model, and I just tweak it to create the app I need.



You’re Invited Windows Phone 7 app

A couple of months ago, my friends and I started a Windows Phone 7 application called You're Invited. It took first prize at the contest, but we didn't actually complete it. This weekend, I'm going to finish it up so we can get it in the Marketplace.



MyCon: Web and Windows Phone template for conferences

If you are organizing a conference and need to build a web site for you attendees, feel free to use this template. If you want to give conference-goers a Windows Phone 7 application to organize their schedule, this template is yours.

MyCon is an ASP .NET MVC, Silverlight, and Windows Phone application that you can customize to run your own conference web site and mobile app. The code is free and open source. You just cover your own hosting.

The web site

Your conference web site lists your speakers, complete with photo and bio. Click on a speaker’s name to see all of the sessions that they are presenting.

image  image

Or break down sessions by track or by schedule. Please see the demo site.

The Windows Phone app

Your attendees will use their Windows Phones to manage their own schedule. They can browse sessions by time slot, speaker, or track, and can even search.

Schedule  Tracks  Search

The scheduling app

Use the Silverlight application to enter speaker, session, and schedule data. Everything you enter is synchronized to the web site and the phone app.

Conference

How to use the template

It’s easy to use the template. Simply fork the git repository and start making your changes. Here are the changes you need to make to the web app.

  1. Create a database in SQL Express called “MyCon”. The application will initialize it for you. If you don’t use SQL Express, edit the connection string in web.config.
  2. Enter a Conference ID in CommonSettings.cs. Just run the application and it will generate a new ID for you.
  3. Enter your own content in Views/Home/Index.cshtml and Views/Sponsors/Index.cshtml.
  4. Add your own banner to Views/Shares/_Layout.cshtml.
  5. Deploy the web application to AppHarbor, Azure or your own hosting provider. If you use AppHarbor, choose the SQL Server add-on.
  6. Run the Silverlight 4 application to create your session schedule.

And here are the changes you need to make in the Windows Phone app.

    1. Replace the images (ApplicationIcon.png, Background.png, and SplashScreen.png).
    2. Change the settings in WMAppManifest.xml (generate a new GUID for ProductID, set the Title, Author, Description, and Publisher).

Once you are ready to publish, you can pre-load the conference schedule so attendees don’t have to download it when they first use the app.

  1. Run the Capture desktop application.
  2. Copy the binary files that it generates from C:\Users\user\AppData\Roaming\FacetedWorlds\MyCon to the Data folder in the WP7 project.

If you change the schedule after you publish, don’t worry. The app will automatically download the updates.

Give back

You are free to use this template for any purpose. If you love it, there are many ways that you can give back.

  • Make a suggestion on how to improve the template.
  • Send me a git pull request on improvements that you have already made.
  • Tweet a link to this page (copy me @michaellperry).
  • Help someone else set up their conference app.
  • Include the “Powered by Correspondence” logo on your app’s splash screen.

image



Exclusive end dates

exclusive-endHere are some recurring patterns I see in software solutions:

  1. This offer is available from January 1 through March 31.
  2. Our fiscal year is from May 1 through April 30.
  3. Log all events from 12:00 am to 11:59:59 pm in this file.

They all have one thing in common. They specify an expiration data inclusively. Usually, this just makes things hard. Sometimes it leads to real problems.

Azure 2012

John Petersen wrote up a good summary of the leap day Azure outage. In it, he explains clearly why the simple solution of AddYears(1) is not enough. Azure experienced an outage because one certificate was valid through February 28, 2012, while the next was valid starting March 1, 2012. The code failed to account for leap day. As John explains, simply using proper date logic instead of string manipulation will still not account for the extra day.

Tiny gaps

Code that checks for times between 12:00 am and 11:59:59 pm fails to account for the last second of the day. I’ve seen people include milliseconds in that check. While this fills in the gap to the precision of the clock, it makes a bold assumption. Times are often stored using floating-point values, which are subject to round-off error. You are assuming that you will always round into the valid range instead of out to the tiny gap.

Consecutive ranges

Whenever software needs to handle a date or time range, it’s usually because something else is going to happen in the next consecutive range. We could be starting the next fiscal year, rolling over to the next log file, or enabling the next certificate.

When ranges are specified using inclusive end times, the start time for the next consecutive range is not equal to the end time of the previous one. At a minimum, this makes the calculation of consecutive ranges more complex than it needs to be. You need to add or subtract a day, a second, or a millisecond, based on the precision of your clock. At worst, this allows for gaps. They might be tiny. Or they might be a complete leap-day.

Inclusive start, exclusive end

The simplest solution is to specify date ranges with an inclusive start and an exclusive end. In mathematics, this is written as “[)”, as in “[5/1/2011, 5/1/2012)”. In code, it’s just >= and <. This has the advantages of simplifying consecutive range calculations and filling the gaps.

The beginning of the next consecutive range is equal to the end of the current one. You don’t have to think about it. There is no need to add or subtract days. You don’t need to know the precision of your clock.

There is no gap between < and >=. These operators are opposites. If you compare two values - even floating-point values - with one, you will always get the opposite answer as you would with the other. It is unambiguous which side of the line a value falls, as long as one side is inclusive and the other is exclusive.

People don’t usually think in terms of exclusive ends. If you read “Sale ends Saturday” only to find that items were full price Saturday morning, you’d be upset. So translate exclusive ends into inclusive ones when you present them to the user. But always store and calculate date ranges with inclusive start dates and exclusive end dates.



KnockoutCS

KnockoutJS is a JavaScript dependency tracking library that enables MVVM in the browser. I took the syntax and simplicity of KnockoutJS and ported it to C#. Thus was born KnockoutCS.

Simple data binding

Like any pattern, MVVM is not appropriate in all situations. Sometimes an application is just too simple for an MVVM framework. But at what point do you make the switch? KnockoutCS fits into the gap between Hello World and Composite Enterprise Application.

Start by defining a data model. Use virtual properties to give KnockoutCS the ability to insert its dependency tracking hooks.

   1: public class Model
   2: {
   3:     public virtual string FirstName { get; set; }
   4:     public virtual string LastName { get; set; }
   5: }

When you construct this model, use the KO.NewObservable method. Then use KO.ApplyBindings to bind it to your view.

   1: private void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     Model model = KO.NewObservable<Model>();
   4:     DataContext = KO.ApplyBindings(model, new { });
   5: }

You now have INotifyPropertyChanged behavior injected into your model. This is your basic Hello World starting point.

Computed properties

That little anonymous object “new { }” is your gateway to more interesting behavior. Insert a computed property using the KO.Computed method.

   1: private void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     Model model = KO.NewObservable<Model>();
   4:     DataContext = KO.ApplyBindings(model, new
   5:     {
   6:         FullName = KO.Computed(() => model.FirstName + " " + model.LastName)
   7:     });
   8: }

Now you can data bind to the computed property. It will automatically update (and fire PropertyChanged) when one of its observable properties changes.

Queries

Any data model is going to have a collection. Declare these as properties of type IList. There is no need to make these virtual.

   1: public class Parent
   2: {
   3:     public IList<Child> Children { get; set; }
   4: }

Then when you bind the model, you can inject a computed property using a linq query.

   1: private void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     Parent parent = KO.NewObservable<Parent>();
   4:     DataContext = KO.ApplyBindings(parent, new
   5:     {
   6:         Children = KO.Computed(() =>
   7:             from child in parent.Children
   8:             orderby child.Age
   9:             select new ChildSummary(child)
  10:         )
  11:     });
  12: }

This query will depend not only upon the source collection, but also upon any observable properties used to order or filter it.

Commands

When you data bind to the Command property of a button, you provide a delegate that will be called when that button is clicked. And you can also provide a lambda that dictates when that button is enabled.

   1: private void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     PhoneBook phoneBook = KO.NewObservable<PhoneBook>();
   4:     PhoneBookSelection selection = KO.NewObservable<PhoneBookSelection>();
   5:     DataContext = KO.ApplyBindings(phoneBook, new
   6:     {
   7:         DeletePerson = KO.Command(() =>
   8:         {
   9:             phoneBook.People.Remove(selection.SelectedPerson);
  10:             selection.SelectedPerson = null;
  11:         }, () => selection.SelectedPerson != null
  12:         )
  13:     });
  14: }

Since this lambda references the property of an observable, the button will enable and disable as the user changes that property.

There is more to KnockoutCS. Try it out and see if you like it. Right now it only works for Silverlight 5, but I can easily port it to Silverlight 4 or the full WPF stack. I’m still working out how to port it to Windows Phone and WinRT.



Historical Modeling makes offline data analysis easy

Because I built my Windows Phone application using Historical Modeling, I have been able to easily export user data to an analytical database. This is giving me insight into the way the application is used, and will lead to an improved user experience.

The HoneyDo List historical model

The HoneyDo List Windows Phone application was built using Correspondence, a collaboration framework based on the principle of Historical Modeling. Historical Modeling captures a history of facts, each one a decision made by a user. HoneyDo List defines facts like:

  • List – the user has create a task list
  • List__name – the user has updated the name of the task list
  • Task – the user has added a task to a list
  • TaskComplete – the user has completed a task
  • TaskCompleteUndo – the user has unchecked a task

Although the names of some of these facts are nouns, it is important to remember that these are not entities or objects. They are facts that capture the creation of these objects. By convention, we just drop the verb “Create” because it would get very wordy and confusing.

The relationships among these facts form a tree.

Model

Each of the arrows points to a predecessor of a fact. Think of this like a foreign key relationship. The red arrows are special. They indicate that the successor is published to its predecessor. Anybody subscribing to a List will see all of the related facts. This is what makes Correspondence a good collaboration framework.

The analytical database

My task was to analyze how the app was being used, so I can decide what features should be in the next version. The historical model captures a history of facts. This history is a detailed account of application usage. All I needed to do was to mine this data.

Correspondence was designed to make it easy to synchronize data across different data stores. Each client points to a distribution node, which publishes facts so that the clients can subscribe to the ones they care about. It has built-in support for several storage mechanisms, including isolated storage on the phone and SQL Server on the desktop. My first step in constructing an analytical database was to plug in the SQL Server storage mechanism and point it at the distribution node.

The SQL database that Correspondence creates is not suitable for data mining. It stores all facts in a single table, regardless of type. All of the fields are serialized to a binary column within that table. It is impossible to query such a structure for any useful analytics.

image

So the next step was to design a separate database with an application-specific schema. This database has separate tables for lists and tasks.

image

The data loader

The final step was to populate the analytical database from the historical database. This is where things really got fun.

Take a look at each of the facts in the historical model. It is a record of a decision that the user made. We can turn each fact into an insert, update, or delete operation. This is what the user would have done had they been working directly against the analytical database. We just write a method that maps each fact to the appropriate SQL.

   1: public void Transform(CorrespondenceFact nextFact, FactID nextFactId, Func<CorrespondenceFact, FactID> idOfFact)
   2: {
   3:     using (var session = new Session(_connectionString))
   4:     {
   5:         session.BeginTransaction();
   6:         if (nextFact is List)
   7:         {
   8:             Console.WriteLine(String.Format("Insert list {0}", nextFactId.key));
   9:             InsertList(session, nextFactId.key);
  10:         }
  11:         if (nextFact is List__name)
  12:         {
  13:             List__name listName = nextFact as List__name;
  14:             Console.WriteLine(String.Format("Update list name {0} {1}", idOfFact(listName.List).key, listName.Value));
  15:             UpdateList(session, idOfFact(listName.List).key, listName.Value);
  16:         }
  17:         //...
  18:         UpdateTimestamp(session, nextFactId);
  19:         session.Commit();
  20:     }
  21:     LastFactId = nextFactId;
  22: }
  23:  
  24: private static void InsertList(Session session, long listId)
  25: {
  26:     session.Command.CommandType = CommandType.Text;
  27:     session.Command.CommandText = "INSERT INTO List (ListId) VALUES (@ListId)";
  28:     session.ClearParameters();
  29:     session.AddParameter("@ListId", listId);
  30:     session.Command.ExecuteNonQuery();
  31: }
  32:  
  33: private static void UpdateList(Session session, long listId, string listName)
  34: {
  35:     session.Command.CommandType = CommandType.Text;
  36:     session.Command.CommandText = "UPDATE List SET ListName = @ListName WHERE ListId = @ListId";
  37:     session.ClearParameters();
  38:     session.AddParameter("@ListId", listId);
  39:     session.AddParameter("@ListName", listName);
  40:     session.Command.ExecuteNonQuery();
  41: }

The analytical database keeps the ID of the last fact that it processed. It updates this ID with each change. Both of these database operations are performed within the same transaction, so there is no danger of missing or duplicating a fact. It’s like using a transactional queue without the overhead of the distributed transaction coordinator.

The analytical database uses fact IDs as primary keys, rather than defining its own auto increment key. For the foreign key relationships to be valid, the parent record must be inserted before the child. Fortunately, Correspondence ensures that this is always the case. Predecessors are always handled before their successors.

Future analysis

Now that I have HoneyDo List data loaded into an analytical database, I can see exactly how people are using the system. I have a few features planned, and I will get those deployed to the Marketplace very soon. When the new version is out there, I’m sure that I will come up with more analytics to capture. For example, how many people are sharing lists with their family? How frequently does the average user add a task, or mark it completed? As I come up with new analytics, I will need to modify the database. After each modification, I’ll simply drop all of the data and replay it from the historical model.

Historical modeling has made it easy for me to separate the analytics from the collaborative application. The app doesn’t have to operate against the analytical database. But I can see the data as if it did, because I can tap into the history and replay it offline.