Friday, October 07, 2005

Design vs Deadline

One of the most controversial topics between programmers is the discussion of "design vs getting things done". It takes place on many different levels, from the low-level data-access strategy (DataSets vs Typed Objects), to the higher-level architectural descisions of reusability, extensibility, etc.

The good thing about Microsoft .NET is (IMO) that for the first time - using Microsoft technologies - you can now sort of combine both. .NET allows you to create fully-fledged object-oriented, event-based, strongly-typed applications, which - from a design point of view - are infinitely much better constructed than most VB6 applications. Make no mistakes though, even in .NET its completely possible to write crappy applications, and unfortunately it gets done a lot.

The situation gets even more complicated when you add a product to the mix, lets take - as an example - SharePoint? ;)Sharepoint allows you to extend its out-of-the-box functionality with Webparts, which are really just a specific kind of Asp.Net user controls. Problem is, Sharepoint has its own logic, which makes a number of 'normal' sound design principles more problematic (client-side validation using Validators being one).

Again though, with a little effort, it is possible to create a well-structured application even in Sharepoint. As an example, in a recent project, we needed to create a webpart, which would, when the user put the page in Design Mode, automatically display a fairly complex user administration part. This admin part would then manipulate those values and have to pesist them as properties in the WebPart.

Now, speaking in design terms, two obvious choices presented itself.

1. Implement the functionality in the WebPart itself, resulting in a flat less-complex structure, but also quite quickly leading to spaghetti code, especially if the desired functionality is moderately complex. Plus, from a design POV, the level of abstraction is practically zero, which will not encourage reuse and/or extensions of the webpart.

2. Create a series of ASP.NET user controls, and use LoadControl on the top-level user control to add him to the control collection of the webpart. Its elegant, its sound design-wise, but it does raise the problem, how do we communicate between the 'layers'. Its the classic circular reference problem, webpart needs to know about user control to create it, and user control needs to know about webpart to give some information back to it. Circular references are solveable usually, but even if it was solved it would still leave you with a user control who somehow knows he'll be included in a webpart, which is again Bad Design.

So whats the solution then? Any experienced control builder in .NET will now be screaming it. *Events* of course. That wonderful mechanism, IMO one of the better features of .NET alltogether, that allows us to decouple layers from one another and create true plug-and-play usercontrols.

So, you set up the following situation:

- Webpart creates UserControl through LoadControl
MyCustomControl myControl = (MyCustomControl) Page.LoadControl("MyCustomControl.ascx");

- Webpart subscribes to the OnDataChanged event from the UserControl
myControl.OnDataChanged += new MyDataEventHandler( myControl_OnDataChanged );

- Webpart adds control to his own control collection
pnl = new Panel();
pnl.Controls.Add(myControl);
Controls.Add(pnl);

- Something happens in the control, and it raises the OnDataChanged event. Thats all the control needs to do, no 'upper references' needed.
private void changeButton_Click(object sender, System.EventArgs e)
{
if ( OnDataChanged != null )
{
OnDataChanged (sender, new MyDataEventArgs(e));
}
}
- The webpart receives notification of the event and does whatever it needs to do with it.
private void myControl_OnDataChanged(object sender, MyDataEventArgs args)
{
// do something useful
}

Thats all there is to it, the beauty of it is that you now have a user control which can be easily re-used in another webpart, or in another usercontrol or even directly in an aspx page.
Of course, there are a few SharePoint gotchas that even good design can't solve, but we'll leave those for another time ;)

No comments: