SharePoint Design Patterns: Entry 2

In the previous entry, we explored how to clean up our interaction with instances of SPSite, SPWeb, and SPList objects. Logically, the next scenario that we’d want to cover is working with the SPListItem that we get back from the list.

What does this look like? Usually something like this (we’ll use some sample code from our last entry):

By itself, this seems innocent enough, but the problem lies in the fact that it’s rarely so easy as returning simply one field value. Even if that were the case, the issue remains that these field name strings leak out across the codebase. Again, this is typically mitigated through the use of Constants or configuration settings, but it’s still messy code, IMO. Aside from that, it can be difficult to figure out which fields are valid for which lists. In general, it makes it hard for developers to figure out how to work with the existing code without good documentation.

Enter the Decorator pattern. The intent of Decorator, as described in Design Patterns, is as follows:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.

Basically, what we’d like to do is to make working with SPListItems more intuitive and more domain specific. Since we can’t subclass SPListItem (and even if we could I don’t think it would make sense to do so since it would also expose all of the properties and operations on the SPListItem), we’ll have to leverage the simplified version of the Decorator pattern to help us instead. Here is an example:

If nothing else, we now have a clean, domain specific way to access the SharePoint list item. Team members and new developers don’t have to guess which fields are valid for this items retrieved from this list; it would be hidden from them by the properties on the Proposal class instead. If you look at the code to determine the check-out user, you can see that we now also have a single location to encapsulate this parsing logic and any associated error handling we may want to add; other developers don’t need to duplicate this code when they use the list item.

It’s debatable whether you should use a constructor to initialize the instance, some sort of implicit conversion operation, or a static method like I’ve used here. I would rule out an implicit conversion operator since it may be hard for users to understand at first blush (i.e. XName and string). As for a “natural” constructor that takes the SPListItem instance? While it’s slightly more discoverable (XDocument.Parse() is pretty hard to find for new users), I feel like that’s a bit misleading and the intent isn’t clear, however, YMMV. Another possible improvement is to pull the abstraction up yet another level since many of the fields are common (like title and last modified by); this exercise is left to the reader ;-).

If we go back to our first example, we can now write this as:

That’s pretty cool. While this example is intentionally simple, you now have a nice object oriented way of working the the fields. In addition, you have a very logical place to put all of your domain specific operations on specific list item types (or should that be content types?). For example, it may make perfect sense to add a method here called CompressAndEmail(string recipientEmailAddress) which would compress the file contents of the proposal and email it to the specified recipient.

Admittedly, this still isn’t ideal since 1) we still have to deal with SPListItem on some level (“leakage”, if you will) and 2) what about the other side of this equation: updating the item? With regards to (1), we can simply hide this by adding a method to the ProposalsLibrary class as discussed in the previous entry:

Now our method looks like this instead:

That’s pretty awesome since it means that we can now remove all references to and knowledge of SharePoint from a whole layer of our application code.

Now onto point (2). For a moment, let’s say our proposals have properties called “Status” and “CustomerName”. From time to time, we may want to update these (from a source other than the web form, like through a custom web service call or if we have a batch process that runs on our SharePoint environment). One way we can handle this is by implementing the set operation on the properties which can be updated and a Save() method:

Nice. In doing this, we’ve basically hidden most knowledge of the SharePoint list item from the users of our object and framework. Downstream developers only need to know about the domain specific objects. It’s now far easier for a member of our team or a new developer to reuse this code and it cuts down on error prone duplication and leakage of field names across our codebase. We also now have a nice place to put field validation logic (for example, in the Save() method). If we wanted to, we can also add logic here (through some references to services or DAOs or something) to load additional metadata from external systems like databases.

If you want to get fancier, you could also add a dictionary keyed by string (internal field name) and with value type object and use that to hold your “set” properties until Save() is called. In the save, you’d simply iterate the keys and set the values then update, only changing the values that were actually set by the caller.

Updating the status of a proposal would go from looking like this:

To this instead:

It becomes even more compelling once we consider that in a real world implementation of an UpdateStatus() operation, it would probably involve checking to see if a user has the object checked out in the first place! This would make our first example explode into a giant mess of code while in our second one, it would be one line (or integrated into the Save() method which could throw a custom NotCheckedOutException or framework InvalidOperationException or try to check it out automatically).

All this with relatively little work involved. It’s better in every way: less nesting of code, much more readable and natural, less error prone, better discoverability, and more domain specific (and less SharePoint-centric). In the end, I think it dramatically improves usability and reuse of your SharePoint application code. It also leads to a nice, logical place to encapsulate much of the common, repetitive, and error prone code that would otherwise be littered among your application (or worse, UI) code.

In future installments, we’ll examine how flesh out the FindById() method on the ProposalsLibrary. We’ll also examine a GUI pattern to help promote reuse, improve tesatability, and cut down on duplication of business logic.

You may also like...

5 Responses

  1. Peter says:

    You may be interested to look at a similar open source project to abstract away SharePoint to allow better concentration of domain-specific coding: code.google.com/p/domaindrivensharepoint/ – not complete I think, but it’s going along the same path as you.

  2. Chuck says:

    Peter,

    Sounds awesome. The more that developers approach the SharePoint Issue in a quasi-domain driven way, the better!

    — Chuck

  3. Vitaly Baum says:

    item["Title"] – bad practice for built-in fields, see at this dict: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbuiltinfieldid_fields.aspx
    And more SharePoint practices you will read in http://spg.codeplex.com/

  4. Chuck says:

    Vitaly,

    That’s a good catch. Although in the case of "Title", it seems like it would be pretty consistent.

    The built in fields are definitely handy to mitigate discovery of some of the more obscure fields in SharePoint.

    Also, another good link πŸ™‚ I think the value is in the documentation and code samples. We need more of these to balance out the tons of quick-and-dirty examples on the web.

  1. October 10, 2010

    […] Design Patterns for SharePoint Part 2 […]