Thursday, July 28, 2011

Hansen8 Developers Group Meeting II



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.html
http://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/







Wednesday, July 27, 2011

Hansen8 Developers Group Meeting I

Event Sourcing
In this meeting Russell introduced us to Martin Fowler and the concept of Event Sourcing.

Martin Fowler seems to focus on code refactoring, design patterns and automated testing.

Event Sourcing can be summarized as the process of recording changes to an application state as a sequence of events.

Russell walked us through a code example which demonstrated a book being added to a library, borrowed and returned. The process started with the creation of a session factory and event handler registration. The session is to ensure the operation was fully successful, similar to a database transaction. The handlers were to do any extra business logic, similar to database triggers.
In this example the session was opened
  a book is created
  a book is added to a book repository
The session was closed

Because a BookStateHandler was already registered with the DomainEvents it is called when the session is committed.

In this case the event contain book attributes. This is similar to (sender, e) where e contains all the meaningful parameters to avoid changing the signature. Before calling Append to queue the event, the Book constructor calls Apply. Apply copies the BookRegistered event arguments into the Book object, similar to an UPDATE statement.

At this point the event is in the queue and the book object is fully initialized. The only thing left is to commit the changes via session.SubmitChanges().

The commit process results in publishing (invoking) the queued events. The actual implementation was bogus, I would have liked to seen something maintenance free:


if (@event is BookRegistered)
DomainEvents.Raise((BookRegistered)@event);
if (@event is Event_Sourcing.BookRegistered.BookLent)
DomainEvents.Raise((Event_Sourcing.BookRegistered.BookLent)@event);
if (@event is Event_Sourcing.BookRegistered.BookReturned)
DomainEvents.Raise((Event_Sourcing.BookRegistered.BookReturned)@event);


The BookRegistered handler adds the event arguments to a book state query collection. This is not the same as the event queue. It is a data repository containing the current state of the book object. It could be DataTable with the book represented with a DataRow.

My Thoughts
There is a strong decoupling between the entity (Book), the event arguments (BookRegistered) and the captured state of the book (BookState). In this example the decoupling introduces much redundancy. Notice the duplicate members across these three classes:


 public Book(BookId id, string title, string isbn)
 {
  this.id = id;
  var @event = new BookRegistered(id, title, isbn);
  Apply(@event);
  Append(@event);
 }

 public BookRegistered(BookId id, string title, string isbn)
 {
  Id = id;
  Title = title;
  Isbn = isbn;
 }

 public class BookState
 {
  public BookId Id { get; set; }
  public string Title { get; set; }
  public bool Lent { get; set; }
 }

I would have liked an explanation as to why Book, BookRegistered, BookState did not all reference a fourth object which actually defines the Id, Title and Lent status. I can speculate that it is because in larger projects there becomes a divergence in attribute space among these three classes.

Conclusion
Event Sourcing as presented in the example showed straight-forward transactional code with the details pushed into the event handlers. The book event history and the book state were maintained separately. Based on the definition of Event Sourcing I presume the events would be persisted to permanent storage before allowing the transaction to complete. Likewise I presume the state might be periodically persisted with a replay identifier to avoid parsing the entire event history to recreate the book state.

Additional Thoughts
In this simple example it would be possible to parse the event history backwards until the book state is fully realized. The additional logic may likely result in a performance gain when recreating the state but is likely too complex for real-world object. Simpler to persist.

Wednesday, July 13, 2011

Code for working with CSV files (CREATE and SELECT):

void Main()
{
 System.Data.Common.DbProviderFactories.GetFactoryClasses().Dump();
 var f = System.Data.Common.DbProviderFactories.GetFactory("System.Data.Odbc");
 var csTemplate = "Driver={{Microsoft Text Driver (*.txt; *.csv)}};Dbq={0};Extensions=asc,csv,tab,txt;";
 var cs = string.Format(csTemplate, @"C:\Users\calix\AppData\Roaming\CSV\");
 var ds = new DataSet();
 var c = f.CreateCommand();
 c.Connection = f.CreateConnection();
 c.Connection.ConnectionString = cs;
 var adapter = f.CreateDataAdapter();
 c.CommandType = CommandType.Text;
 c.CommandText = "SELECT * FROM [csv2.txt]";
 adapter.SelectCommand = c;
 adapter.Fill(ds);
 ds.Dump(); 
 c.CommandText = "CREATE TABLE T1.TXT (F1 CHAR(10))";
 c.Connection.Open();
 c.ExecuteNonQuery();
 c.Connection.Close();
}