Monday, August 31, 2009

Simple MVP in ASP.NET

Model View Presenter (MVP)

The model:

public interface IEntity
{
SomeType SomeProperty1 { get; set;}
SomeOtherType SomeProperty2 { get; set;}
YetAnotherType SomeProperty3 { get; set;}
}



The interface (the view contract - insulates the presenter from the implementation):

public interface IEntityView
{
event EventHandler Init;
event EventHandler Load;
event EventHandler Unload;
IEntity Entity { get; set; }
bool Visible { get; }
}


The code behind (the view implementation):

public partial class EntityDisplayPage : Page, IEntityView
{
protected EntityDisplayPage()
: base()
{
new EntityPresenter(this); // wire the MVP pattern
}

#region IEntityView Members

public IEntity Entity { get; set; }

#endregion
}


The presenter (doesn't know the view implementation, manipulates it through the view contract defined as an interface):

public class EntityPresenter
{
public EntityPresenter(IEntityView view)
: base()
{
if (null == view)
throw new ArgumentNullException("view");
this.view = view;

this.View.Init += (sender, e) => { /* some business logic on init */ };
this.View.Load += (sender, e) =>
{
/* some business logic on load*/
this.View.Entity = GetEntityToDisplay();
};
this.View.Unload += (sender, e) => { /* some business logic on unload*/ };
}

private readonly IEntityView view;
public IEntityView View
{
get { return view; }
}
}


And that's how you get good separation through a simple MVP implementation in ASP.NET. I think it speaks for itself.

Tuesday, August 4, 2009

Embrace Your Technology

Recently, I was working with a fairly progressive client that was spending a lot of time working its internal architecture into an SOA solution. I was brought on in January as a consultant to build a greenfield application of modest complexity, but probably more complex than the apps they'd built internally to date. They placed several strict requirements on certain technological aspects of development, which I could easily handle. However, they did declare one that gave me some fits.

A few months before I arrived, their internal staff had started to develop a web service to centralize contact information for the entire agency. During the initial phases of my project, I was told that my app was to integrate with this new contact web service when in comes online in March. (Those of you with inter-team experience already know where I'm going.) March came and went; no contact web service. I kept hearing rumors of re-work from members of the team, which made me very nervous. My project manager (also a consultant) and I began to think of contingencies as this was probably going to bite us and delay our release. We were then told May; the web service would be up and running by May. May came and went. Our thoughts eventually turned entirely to "It's never going to be delivered. We're going to have to implement something ourselves to make our release date."

Our app was due to make it's initial production release the first of July. We had to have that contact piece to go live. But we had nothing. At the end of May, we decided to write our own and merge it with theirs later. I wrote our solution for contacts the following week and we moved into production the first week of July. Whew!

Sometime that month, they finally pushed their contact web service to production and I was able to begin integration with my app on July 30th. They were using an ASMX web service, so I figured that it'd be easy enough to create a proxy and adapt it to our solution. I silently thought to myself, "I bet I can have this integrated in just a couple days."

I was in for shock though. When I dug into the WSDL, I was both disgusted and astonished. The schema was flat. They were using SOAP to usher strings (and only strings) back and forth to the web service. The schema had no depth at all anywhere - everything was a string, a string that had to be parsed manually. If an operation returned person information, it returned a string which contained the information in XML form, but still a string that'd have to be parsed or accessed via XPath. There other issues that come about by having such a poorly defined schema. For example, if everything is a string, I can send anything I want to the service including the current version of Webster's dictionary or the New York City phone book. And oh yeah! I was delayed for this? It took them months and months to build this? Less than twenty-five operations, no schema... What were they doing all that time?

It's as if they intended to build a house, took as long as building a sky scraper and wound up with a tool shed. They decided to leverage a very powerful tool, an air nailer, but used it as a hammer. When they went to drive a nail, they turned the air nailer sideways and drove it with the side of the air nailer. In this way, not only did they negate the benefits of the air nailer, but they also endured a loss of productivity.

I had no doubt; this was going to be painful. To add some extra salt to the wound, some features my application needed were simply not implemented. So, on top of having to break it to my users that some of their favorite contact functions were going away, now I have to write custom parsing logic to extract information from the operations, rather than let .NET's out-of-the-box SOAP digestion handle if for me. Which is going to delay the whole process by days. I cringe when I think of parsing XML myself for any reason; especially when so many good people worked hard to write frameworks for SOAP and various other specifications so I wouldn't have to.

Thus, I plead to the masses, "Embrace Your Technology". It seems more and more commonplace that my clients not only fail to understand the technologies they choose, but choose technologies they don't understand. From ASP.NET to Oracle to Visual Studio to web services, they don't understand what these choices provide and end up misusing them negating the benefit. They stand up and claim "We're using SOAP web services!", but have no idea what that the specification does for them. They miss the benefits a specification provides by allowing them to leverage pre-established frameworks to forgo the normal rigmarole that other web service specifications impose on them, allowing them the ability to move on with more important development without writing custom XML parsing and operation security for invalid data.

I will contend that too many folks are content to acquire a technology without acquiring a book on the subject. Heaven forbid someone even try reading the book before acquiring the technology. This is so unfortunate as there are typically some really great minds on these technologies that share their expertise through writing books and whitepapers.

I'll take it a step further and sideways; I will contend that too many folks that barely need a firecracker acquire a nuclear bomb. Some acquire Oracle when a text file will suffice for the moment; even when an RDBMS is necessary, MySQL will do the trick before you bring in the heavy hitter. Remember, your real need is persistence of data, not the acquisition of Oracle. A good friend watched his startup fail because his colleagues spent their capital on Oracle rather than a prototype of their idea - a simple case of confusing needs.

So to all you hard-working folk out there, embrace the technology you choose and choose the technology you need. Perhaps, you'll deliver a functioning house on time.