Managing State in CAB Smart Clients

Some time ago I posted about the interesting features of CAB State. I asserted that it was a useful way to compose and maintain client state and express your model (as in the Model-View-Presenter trinity). I changed my mind about this some time ago, and, no, I’m not feeling architectural guilt1.

Moving right along…

The State Bag Stuff in CAB is Evil

WorkItem.State, Presenter<T>.State… that’s what I’m talking about here. That and the StateChanged attribute. These are features that seem convenient on the surface; a consistent means of keeping and tracking state in your smart clients. Finally a solution to all of our smart client state management problems.

No. No, no, no… It is evil. Evil I tell you!

If you’re relying on the state dictionary you’re essentially giving back the benefit of strong typing. You’ve just lost the benefit of strong typing as soon as you throw something into a name-value collection (dictionary). You’re constantly casting objects you throw into the state back leading to ugly and convoluted code.

State in CAB is confusing. You expect it to dependency inject down the WorkItem tree, but it doesn’t. There are also some questionable WorkItem-lifecycle related things with the StateChanged attribute. Namely, it doesn’t fire predictably when you’re looking to add everything to a WorkItem you need to and just run.

The use of the State features encourages bad WorkItem programming. Keep in mind that the WorkItem is only a “container” (dependency injection container). Once state gets involved you’ll find your WorkItem Controller (we’re all using these, right?!) growing in size and scope. I want the Controller to be as lean-and-mean as possible. I want it to focus solely on setting up the scenario, adding my views/services/whatnot to the DI container, and handling events for orchestrating messages between views (in a multi-view/composite-view WorkItem scenario). That’s it… the single responsibility principle for WorkItems.

The Power of Explicit Intention Compels You

My proposal is simple: factor state management responsibilities into the appropriate CAB assets. WorkItems, Views, Presenters, and Services serve specific roles in CAB. Why not give each a specific, cooperative responsibility in the state management lifecycle? Let’s take a look and break it down…

(Click the image for a clearer copy of this sequence diagram)

1. The client code first creates a Startup Object and then sets up a ControlledWorkItem<T>. It calls the overloaded Run method of the WorkItem’s controller class and feeds the StartupObject in as a parameter.

2. Inside the Run method overload of your ControlledWorkItem<T> create a View that takes the same Startup Object in its constructor. This View will implement an interface that defines a get property that allows the Presenter to access the Startup Object. Add this view to the WorkItem’s SmartPart collection. (Note: if you prefer you could implement a setter or method in the Presenter to shove the StartupObject in from the View).

3. The View will build up the presenter via ObjectBuilder and the [CreateNew] attribute. After the View is loaded, the Presenter will obtain references to various additional services that gather additional state using the values in the Startup Object to call methods on CAB Services.

4. The presenter gets the “Starter Object” from the View (remember, originally passed in by the WorkItem Controller) and call into services to get additional required state. If you have a composite view (a view containing other views) have them do the same thing: presenter gets data from service(s), shoves said data into view(s)…

5. The CAB service is the gateway, facade, or layer supertype that allows access to the state owned by whatever lives under those services: Web Services, legacy systems, databases, domain models, etc. Put your Enterprise Library caching and entity mapping or transformation code in these services along with any features toward making getting at the state more performant and/or reliable. You may want to publish events with the CAB Event Broker in these services that indicate that the state has changed. As far as EventPublication scope goes, remember that it’s totally fine to have services that live at a certain level in your WorkItem hierarchy. Also these kind of events will (typically) be okay to go global with; you’ll want to notify everybody. Consider using an EventArgs<T> to pass enough information to determine if the event applies to the situation.

Missing Pieces

Clearly this approach isn’t an automated end-to-end state management framework (beware of things calling themselves that, IMHO). It’s more of a practice for managing state that requires application by an individual developer. One of the thing the state features of CAB promise is the ability to dehydrate and rehydrate your workitems. So you can call something like WorkItem.Save() and the state bag will persist to a configured location.

If you dig a little into CAB, you’ll notice that this functionality is implemented as a CAB service. I’d recommend that you, sure, take a look at that, but implement your own CAB service (a “foundational service”) if you really need to save state on the client between application instances. Of course you should question that need relentlessly. It is a cool feature, but how many smart clients really need it? (Yes, I know that it is a legitimate need at times). If you require this is it because you’re going offline? If not, I’d suggest you implement draft storage and resume logic in the server layers of your application and database.

You have to remember that CAB is a different beast than the Smart Client Offline Application Block or the User Interface Application Block. It addresses the need to create composite, plug-in style UIs. Therein lies it’s strengths… so, let’s use the good parts; there are certainly lots of those!

—-

1 Architectural guilt: only feel it when being self-indulgent in your design. In any case, move on quickly. Consider Emerson’s classic quote, “a foolish consistency is the hobgoblin of little minds.” Anyway, architectural guilt, another post for a rainy day…

[tags].NET, Smart Clients, SCSF, CAB, State Management[/tags]

The Geek Squad

Some members of our team decided to dress up as The Geek Squad for Halloween. Pretty funny, actually. From left to right: Rik, Dan, Dick, Tony, Chris and Paul. I flew in to Syracuse today (with costume) but my bag (with costume in it) got mistakenly routed to Sarasota, Florida, so I didn’t make the cut…

 

[tags]Culture, Geek Squad, Shops, Team[/tags]

Model, Layer, and Don’t Distribute!

Ted Neward has a new article series on MSDN on “Pragmatic Architecture”. It’s not technical concept but it’s an important distinction he re-iterates. Read it here. Anyway, great stuff as usual…

A corollary to the layers vs. tiers distinction that Ted makes is Martin Fowler’s “First Rule of Distributed Object Design”:

Don’t distribute your objects.

Seems like a rash statement. Of course what is meant is that you should only distribute when you are forced to. This is a key reason I like Domain Driven Design (DDD).

In DDD, you start with the conceptual model. Get your business logic, objects of the “Domain Model” right. Only worry about the infrastructure elements such as distribution and persistence when the model is closing in. Pragmatic.

Model first. Layer second. Tiers last…

Current (and next generation) tools such as NHibernate, CSLA, Entity Framework, w/ LINQ, etc.), WCF, or whatever-your-tastes ease the disciple required with the “problem first”, pragmatic approach. Put another way: the pragmatic beliefs of YAGNI[1], simplicity, and anti-BDUF[2] become easier when your tools and platform provide the “default architecture” that takes care of infrastructure.

—-

[1] YAGNI - “You ain’t gonna need it.”
[2] BDUF - “Big design up-front.”

One Talk Down…

Just finished my first talk at the NYC .NET Developer’s Group. Went pretty well… I think… feedback anyone? Excellent, challenging questions. I was up against the Mets, so the group was smaller than usual, but it was still a good turnout and the people there seemed pretty into CAB/SCSF and the whole software factories thing.

Here’s the link to the resources page I mentioned in the talk. You can download the deck/code from there, plus there’s a bunch of extra links. I will try to add to this over the weekend. Be sure to check back! I’m scheduled to do the talk at least one more time (maybe more), so I plan on revamping the resources page as I get feedback.

Thank you for your time if you’re reading this post and were there. Thanks again to Bill, Steve, & Andrew for the opportunity. If you have suggestions, criticism or feedback-in-general, I’d love an email or comment!

ObjectBuilder DI Example

Brad Wilson has posted the sample code from his talk on dependency injection at the patterns & practices summit last week on CodePlex. ObjectBuilder is a foundational part of CAB, Enterprise Library, etc.

For the uninitiated: ObjectBuilder is a meta-framework for building dependency injection frameworks. The sample code (right here) illustrates how one may build a lightweight DI framework.

Software Factories Talk

What follows are (rough) notes from Jack Greenfield’s talk about software factories at the patterns & practices summit 2006 at the Microsoft campus I just attended. I managed to catch Jack in the hall and talk to him on the way out. It was good to hear that they’re at the point of working on factory schemas (aka “factories of factories”) and are working through some of the versioning.

He had some pragmatic tips toward working with the current technology around factories. Specifically developing relationships between viewpoints and versioning. I asked him, also, about very vertical domain specific languages (e.g. a language for insurance policies). His advice was to treat DSLs as a specific tool for specific situations. In that highly vertical domain, a DSL might not be the best angle (the old “my only tool is a hammer syndrome”). So that’s an area where frameworks/patterns/recipes/guidance and the other elements of factories used to “40%-ify” a viewpoint (insurance claims) come into play. At any rate, my confidence is pretty high that the factories approach has legs and is moving along…

Back to the notes. I’ve read the book, and Jack’s presentation was largely an introduction to the concept of factories, so my notes tend to be the finer points that struck me. Also, did I mention rough?

—-

Augmented reality, augmented development… knowledge is locked up in books. You almost want the Stirling notion of “specs”. That is, when you’re looking at a problem it would be ideal to be presented or prompted with the knowledge…

40/60? If 40% of the requirements in a given solution domain were common, “we’d be in good shape” toward delivering solutions successfully.

The gaming industry has “gaming engines” that each developer customizes to meet the needs of her specific game. Why isn’t there an analog in the business applications space?

Factories of factories… you can build large factories by integrating smaller factories (implicit to this: that represent specific viewpoints in the software factories schema). So — factories are easy to integrate with other factories.

“Think about the Dell website.” Mass-customization is a key motivation in software factories. Requirements through choice not customer-directed expression.

Guidance in Context, Model Driven Development, Software Product Lines

Packaging is a “very important precursor” to the realization of a software factory.

TOGAF - The Open Group Architecture Framework

“Rectangular frameworks” (e.g. Zachman) cannot express relationships between “cells”. A software factory schema is composed of viewpoints and relationships between viewpoints. Relationships permit interesting services such as navigation and generation. They also add to the overall richness of a factory solution’s metadata.

See article in Architecture Journal.
Currently working on “a cut of the Web Services Software Factory” who’s schema expresses 15-20 viewpoints. Going to provide “two or three” domain specific language tools within this schema.

Product lines: harvest-adapt-apply-harvest… rinse and repeat…

Composing factories by gathering viewpoints, IEEE-1471.

So Long MVP

A while back, Martin Fowler decided to retire (at least from his world) the Model View Presenter pattern. Specifically he’s split it into two new patterns called Supervising Presenter and Passive View.

Those familiar with MVP as applied to the CAB world (especially if you’ve seen the Smart Client Software Factory), will recognize Passive View as the pattern called MVP. There’s no data-binding in the reference implementations.

Supervising Presenter is more accommodating toward data-binding, which is good as it’s often times a very desirable thing to do (grids, etc.) I think it’ll become even more desirable with in the WPF world…

The view interface in this scenario would define events (or methods) which are often already implemented by your underlying technology — in the case of System.Windows.Forms.Form’s & System.Web.UI.Page’s “Load” event. The presenter defines handlers for these events which can easily be wired in its setter dependency for the view interface, e.g.

public class MyPresenter
{
private IMyView _view;

public IMyView View
{
set
{
_view = value;
_view.Load += OnViewLoad;
}
}

public void OnViewLoad(object sender, EventArgs e)
{
//.. do business logic, act on the view, etc.
}

}

public interface IMyView
{
event EventHandler Load;
event EventHandler Save;
}

A slight departure from the normal MVP style of handling the event in the view and calling back to a corresponding method in the presenter (although I guess more-or-less the same effect). I’d favor this approach when using third party controls to reduce coupling… e.g. keep the event delegates simple EventHandlers. Of course, there’s nothing preventing one from using this model: calling back to a presenter method from an event handler defined in the view.

The point with Supervising Presenter is that only the business logic is handled by the presenter. We assume the underlying databinding goes to plan. So if we want to color a specific databound textbox (say), we put that logic (choosing the color based on values present in the model) inside the presenter… and test it.

Here’s a complete code sample covering Supervising Presenter from Phil Haack. Note he doesn’t use an interface. Not my preferred approach; reuse aside, a view interface makes mocking easier. I, like Phil, am not a big believer in reusable presenters (e.g. same presenter for ASP.NET and Smart Client). If you’re looking for reuse in this way, I think you really have to question just why it is that you’re duplicating your UI for two platforms. Sometimes there is a case for this (think Outlook/OWA), but I think it’s fairly rare… at least in my experience. If you need reuse better to factor back into your business/services layers.

—-

Martin Fowler
Retirement note for Model View Presenter
Supervising Presenter & Passive View

Weird Project Codenames

At this point in my career I’ve encountered or been responsible for some interesting codename conventions applied to computing clusters or projects. I thought we could share…

The Daily Scrum at The Black LodgeAt Xclaim, we (okay I) started naming our projects after various Twin Peaks characters (yeah, I’m one of those people) . So we had “The ARM” and “BOB”. “Man from Another Place” turned out to be just a little too abstruse. To be fair these projects had real-world analogs. So BOB stood for “book-of-business” and the ARM stood for “accounts receivable module”… at least officially anyway. The plan was to go on to Laura, Cooper, and — my personal favorite — Audrey.

At a previous gig the enterprise Unix boxes were named after monsters in the Godzilla universe: “Rodan”, “Mothra”, “Hydra”, etc. At yet another job the Unix machines were named after various synonyms for the word Dictator. I’m having a hard time remembering but the machine names “Despot” and “Warlord” spring to mind. A picture into the mind of your typical Unix administrator of the time!

This same shop named their Netware file server cluster after the cast of Gilligan’s Island.

What weird-ass codenames have you come across?