N-tier development is not a new methodology. I remember learning about it in 200-level courses back in 2000, and I used it in ASP.NET development before I jumped on the SharePoint bandwagon. However, one of the things I’ve noticed over the years as a SharePoint developer is that most project development is done in the SharePoint object’s code behind or a few helper classes. This isn’t always the case —sometimes the solution isn’t complex enough to warrant a tiered approach (i.e. a single Event Receiver). But a recent project highlighted the power behind N-tiered architecture.
The client has a custom solution that they provide as a service: A master document (Microsoft Word) is split into section documents (also Word) by a project manager. Each section is assigned to a person to be modified in Word (the client also provides a Word plug-in for this modification). Once the sections are properly marked up, the master document is recreated from the sections. We were brought in to implement this solution in SharePoint 2010.
Our team consisted of our lead, another developer and myself. The solution started with all the code being in a single Visual Studio project. This project contained several different types of SharePoint objects. For the purpose of this post we’re going to focus on the workflows, custom activities, two content types and two web parts. I will reference them all by their object name as shown in Figure 1 below.
However, after evaluating the solution early on, we decided to extract the Data and Business Layers to consolidate redundant logic. For example, the SectionDocumentApprovalState (a State Workflow) uses the MergeSectionsAndGenerateDocuments custom activity. The procedures done inside this activity are also executed in the PostMergeAction2 web part (and the majority of these procedures are in PostMergeAction1).
Instead of having the exact same code in three places, the layers were extracted into a second Visual Studio project (see below, Figure 2). The design for this project was what I would classify as a typical three-tier application: Data Layer, Business Layer, and Presentation/SharePoint Object Layer.
Data Layer
The Data Layer for this project consisted of a single class: WebServiceInteractions. It pulled data from, or manipulated data with, the client’s custom WCF services. The methods return byte arrays or proprietary response objects that the Business Layer object will manipulate. It made sense to make only a single class in this layer because this was the only data external to SharePoint and was needed in multiple SharePoint artifacts.
[pullquote]By extracting this layer, the client can now consume this library in other platforms. It can become the backbone of a range of products because of this architecture. [/pullquote]By extracting this layer, there were a couple of benefits. First, the client can now consume this library in other platforms. It can become the backbone of a range of products because of this architecture. And if the WCF services change, it’s much easier to modify a single method than search through several objects that utilize the same service. This actually happened during the development process as the client changed the response from a byte array to one of the proprietary response objects. While this change actually required more than just editing this layer, the changes in the Business Layer were minimal.
Business Layer
The Business Layer was more complex. The client’s solution is based around the creation of Projects. Each project consists of multiple types of documents, so we created Project and ProjectFileBase classes. The Project class houses all the public methods accessed by the presentation layer since it’s the root object to the solution. The ProjectFileBase class is an abstract class that is inherited by the nine document-based classes that represent the various document types that make up the project. One of the properties in this class is the SPListItem object of the file in the library which allows for the needed interaction with the associated fields for value updates.
The other nine document type classes are used to classify the different types of documents and they provide Create and Load methods. A few are required for others to be created, so they have additional methods to create those documents. This creates a natural null reference check as the parent document has to be instantiated before the child documents can be created.
Much like the Data Layer, this design makes maintenance easier and allows for use outside of SharePoint. In addition, the Business Layer can be expanded as the product grows with little effort to avoid affecting the existing functionality. This is really important in development, as a developer doesn’t need to be troubleshooting working code that is suddenly broken because of the attempted upgrades. Finally, the upgrades can be made here without having to upgrade the Presentation Layer so the project plan can be split across multiple sprints or even entire projects.
Presentation Layer
The Presentation Layer is made up of several SharePoint objects. The root of which are the six Content Types for most of the various documents in a project. The MasterDocumentApproval workflow is associated to the MasterDocument type and the SectionDocumentApprovalState workflow is associated to the SectionDocument type. These workflows perform the business processes upon which the solution is founded. A master document is broken off into section documents where users can perform some manual tasks. Each of these sections, when checked-in or when the task on it is completed, is merged back into the master document. Once the merge is complete, additional functions, handled by the WCF services, are performed on the modified master document. Once all the sections are complete, the master document can be approved and the project is complete.
While the workflows perform these processes through the custom activities I built, another team member built out two pages and a web part. The web part performs the merge. One of the pages performs the merge and one of the post-merge actions, while the other does this and the final post-merge action. This is where the architecture really comes together.
In Figure 3, there are three methods that are in the Project class that would perform the merge and the post-merge actions. Since merge is a dependency of both post-merge actions and the first action is a dependency for the second, there’s cascading call logic so changes to any one of the methods will be updated downstream. When it comes to the custom activities and pages, this becomes really simple.
For example, Figure 4 shows all the code needed in the custom activity to do all of these processes. To perform all three actions, almost 100 lines of code would have to be written in two locations (one page and the workflow activity), not to mention the other page and Web Part that would have a subset of those 100 lines. These four objects would need to be updated with changes to the merge or post-merge action one parts every time. Now, the methods in Figure 3 are updated in a single location, and that’s all the change that’s necessary. Maintenance time is a fraction of what it would be if everything was contained in the Presentation Layer.
Conclusion
The simplicity of the Presentation Layer was worth the architectural change alone for this project. The client now has a design structure that will be easy for them to maintain, thus allowing them to deliver new functionality to their clients faster.
N-tier development has a place in SharePoint. Give consideration to this methodology if you intend to provide the same actions in multiple locations across a solution or the environment. It could also be useful if there is a plan to surface the same data across multiple solutions. (For example, SharePoint provides an excellent option in the Business Connectivity Service which allows integration of external Line of Business data.)
N-tier development in SharePoint will not only save time and money maintaining the environment, but it will also provide a cleaner way of growing the features as additional requirements arise. Spending this extra time early in the design process will pay dividends as the product matures.