INTRODUCTION

This is a series:
- Managing Risks in Sharepoint 1 - Aligning the Environments
- Managing Risks in Sharepoint 2 - User Permissions

In the previous articles I've discussed about aligning the environments and ensuring user permissions. In this opportunity I would like to discuss more on the development side of things in terms of how you should structure your project, etc.

When writing custom code for Sharepoint (be it web-parts, custom controls, etc), there is a chance for developers to use third party DLLs. Not only that, you may actually download the whole third party's WSPs. In this article, I will discuss how we should develop our code including how we should manage third party DLLs and solutions. Once again, please also share your experience.

I've been in a project where no one actually knows what version of the code deployed in Production is. Even the third party DLLs/controls, when I tried to get latest version from vendor's website, they actually appear to be a different version than the ones deployed in Prod.

What's even worse is, I've tried "Get Latest" from Visual Source Safe hoping that I downloaded the right code, but it's actually not! The previous developer has managed to modify the code only on his local machine (and disconnected it from VSS) and deploy it straight away to Prod without re-checking the code back in. The machine that this developer was using was wiped out because he was only a temporary contractor. So then we had to use Reflector to open the DLL in Prod and made necessary changes in VSS.

Having all these experience, I think it's important to discuss how we can minimize development and deployment risks.

Managing Risks in Sharepoint 3 - Solutions and Features Deployment

Whenever I do Sharepoint customization project, I will always go down the Solutions and Features Deployment path. I've discussed about this in my other development articles. I know it can be a more complicated process than just doing everything straight from the GUI but it will save us time later on maintaining it. And in fact, throughout my experience, it can minimize the risk of deploying/storing incorrect version of code. There are things that we have to get right though but let me explain more.

We're minimizing risks (and not removing risks, there are always risks) when:

1. Our deployment document is tight

The very first step to minimize development risk is to get our deployment document tight. Make sure that we write down what we're developing and what we're planning to deploy and also where to get the deployment files from. This information includes (and not limited to):
- The custom solutions we're developing
- Shared DLLs/assemblies that we reference within our project
- Third party DLLs/assemblies that we reference within our project
- Third party WSP/features that we may deploy

I normally come up with two documents for every deployment: Deployment Manual and Release Manual.

The Deployment Manual document contains information on HOW TO DEPLOY the code (it will mention the stsadm command to perform, etc). Imagine if you're purchasing Microsoft Word, there is a help manual on how to install ie (ie. double click on the exe, follow the prompts, etc). That's exactly it.

The Release Manual document contains HOW TO GET the code to deploy. This document will be for internal use only. It will mention something like "Get Latest from VSS on the such and such node, open in Visual Studio and click Build" or "Go to http://thirdpartywebsite.com/Downloads and download Version 3.0 of ControlX", etc.

If we can get these documents produced every time we do deployment then everyone will have the knowledge on what is actually deployed in Production and where to get the files from. This way, we have minimized deployment risks.

2. We structure our TFS/VSS correctly 

I've mentioned to you above that there was a developer who disconnected from VSS and start modifying the code directly then deploy that code to Prod without re-adding back to VSS. His reason was he needed to make a small change to current production code and didn't want to create a new branch in VSS because the current code in VSS has already got new functionalities and it will confuse the team later on if he created too many nodes of the same code (it actually confuses everyone afterwards anyway). In VSS we don't have such a good merging system unfortunately, but in TFS we do and using the merging functionality of TFS, it can help us handling the typical scenario above. I normally structure my TFS like this (for every project):

Project Root
------ Development
------ Main
------ Production
---------- v1.0
---------- v1.1
---------- v1.2
etc

- I normally do the development in Development node then when it's ready for Iteration 1 testing, I branch to Main.
- I keep developing more and more functionalities in Development while the code from Main is tested by Testers/Project Managers.
- When the bug report comes, I fix the bugs in Main.
- I then merge from Main to Development so that Development now contains new functionalities plus bug fixes from Iteration 1 report.
- When I'm ready for Iteration 2 testing, I merge from Development back to Main so that now Main contains new functionalities and bug fixes and it's ready for Iteration 2 testing.
- The process repeats over and over again until it's ready for release.
- When it's ready for release to Production, I would branch from Main to Production -> Version node.

My Release Manual will then include information on how to build the code in Production/Version node and my Deployment Manual will then include information on how to deploy the built code. After I do this, I'm pretty comfortable that I've now captured all information about a particular release including what version of code is currently in Prod, etc.

When I need to do another major release, I will create a new branch under Production with a new Version number and I will update my Release Manual and Deployment Manual. You can find this TFS structure in Microsoft's website. I found by structuring my TFS right, I minimize my development and deployment risks and it's pretty clear which node in TFS has the latest source, etc and I know exactly which part of the Production branch is currently in Prod.

Going back to VSS, since it doesn't have any merging capabilities, labelling would be the way to go. With VSS it's a bit tricky to create versions of the code and I don't think it's possible to perform Dev, Main, Prod branch/merge as TFS.

3. Our customization code ALWAYS lives in Visual Studio and Source Control and always strong-name your assemblies

I will ALWAYS deploy Sharepoint customizations using Features and Solutions because it means that all Sharepoint customizations I'm developing live in source control application which then makes it easier to maintain and share. Please read my Development Best Practice articles. Customization code includes:
- My code
- Third party code
- Third party images, CSS, javascripts
- etc that is not Sharepoint OOTB

Strong naming your assemblies is always a good practice even when you're doing development with general .NET application. Sharepoint makes a huge use of assemblies in GAC and you can only deploy your DLLs in GAC if they're strong named (including third parties'). What's interesting is, not all third party assemblies are strong-named. Therefore, ensure that you strong name all assemblies that need to be deployed to your farm including third parties'.

To strong-name third party assemblies:
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/35930958-9775-4e56-bd38-0362d124ffc4

4. Always guard your code from memory-leaks

Whenever you reference SPSite and SPWeb instance ALWAYS guard them with "using" statement from memory leaks. For example:

using(SPSite site = new SPSite(http://url/))
{
       using(SPWeb web = site.OpenWeb())
       {

       }
}

There are exceptions though:

If you're referencing SPWeb, SPSite or RootWeb from SPContext.Current, do NOT dispose or you'll get an error. The following code does NOT have memory leaks anyway:

SPWeb web = SPContext.Current.Web; --> GOOD
SPSite site = web.Site; --> GOOD
SPWeb rootWeb = web.Site.RootWeb; --> GOOD

Use SPDisposeCheck tool (http://blogs.msdn.com/sharepoint/archive/2008/11/12/announcing-spdisposecheck-tool-for-sharepoint-developers.aspx) to check for memory leaks within your custom assemblies.

5. Always check that you're NOT deploying ANY of Microsoft's DLL (such as Search DLL, etc)

When you're adding a reference to Microsoft.Sharepoint.dll in Visual Studio, it's going to add reference to Microsoft.Sharepoint.Search.dll.

If you're adding reference to Microsoft.Sharepoint.Publishing.dll, it's going to add reference to Microsoft.Office.Server.Search.dll, Microsoft.Sharepoint.Portal.SingleSignOn.dll and ssocli.dll.

Make sure you REMOVE all of them from your WSP (if they're included by your automated built commands such as STSDEV, WSPBuilder, etc) otherwise your farm will break because these DLLs are overridden by update patches in the future and if you deploy them, Sharepoint will get confused in terms of which version to use.

 

CONCLUSION

They're so far the things that I will be aware of when doing Sharepoint development and deployment. Please share your thoughts.

Tommy