Porting Dojo Stateful to C#
I'm the sole Dojo advocate in our group so instead of introducing dojo directly I chose to introduce Stateful via a C# port.What is Stateful?
It is a observable data repository as this code shows:
var state = new Stateful(null);
var tokens = new List();
state.SetValue("user/age", 1.23);
state.Watch("user/name",
(d) => Console.WriteLine("username: {0}", d));
state.Watch(tokens, "user/age",
(d) => Console.WriteLine("age: {0}", d));
state.SetValue("user/name", "MyUserName");
state.SetValue("user/age", 4.56);
state.Unwatch(tokens);
The output when running the above code is:
age: 1.23
username: MyUserName
age: 4.56
The first age (1.23) displays because the value already exists when the Watch is registered. Stateful is a place to store data as well as a place to look for data and be notified of changes to that data.
Why use Stateful?
When writing a user interface you must hook into the control events before you can do anything useful. For example, you are notified that a button was clicked via a click event. You respond to that click via a click event handler. As the product grows the number of UI controls increases as does the number of event handlers. In my experience the code in these handlers becomes complex rather quickly. WinForms places event handler code in a single code-behind file so it would be nice if that code was easy to read -- if it expressed what was desired instead of what to do. Stateful facilitates this decoupling of UI controls and event handlers.Instead of writing code like this:
void loginToolStripMenuItem_Click(object sender, EventArgs e)
{
Login();
}
You express your intentions via a topic ("login@show"):
void loginToolStripMenuItem_Click(object sender, EventArgs e)
{
state.Publish("login@show");
}
And place the actual implementation elsewhere:
topics.Subscribe("login@show", (sender, e) =>
{
Login();
});
What does
Publish and Subscribe do?My implementation of Stateful is built on top of PubSub, a C# port of
dojo.Publish and dojo.Subscribe. The Publish method is similar to a SetValue without actually persisting the value. In the sample above a value isn't even provided; the Publish("login@show") is used to signal an event and the Subscribe handles the event.
Conclusion
Decoupling the UI from the business logic has known advantages. The MVC pattern describes why and how to do this. Dojo does this using Publish, Subscribe and Stateful. I've found the dojo implementation compelling enough to warrant porting to C# for use in WinForms development.Links
http://dojotoolkit.org/reference-guide/dojo/Stateful.htmlhttp://dojotoolkit.org/reference-guide/dojo/publish.html
http://dojotoolkit.org/reference-guide/dojo/subscribe.html
http://msdn.microsoft.com/en-us/library/ff649643.aspx
http://www.sitepen.com/blog/2010/05/04/consistent-interaction-with-stateful-objects-in-dojo/
http://doughays.dojotoolkit.org/dojomvc/
There's always room for abuse; notice how a requirement to show the login dialog when a login fails sneaks into the what should be a statement declaring a login@failure (a handler would then publish login@show, though publishing subscribers gets tough to debug):
ReplyDeleteif (elist.Any(n => n is LoginException))
{
topics.Publish("login@show", false);
}