SharePoint OOTB deployment functionalities are quite limited, and as developers we always end up filling the gaps ourselves. You might need to write code to clean up Web Part galleries, deploy resource files, or update Web.Config files (perhaps to register an Http Module), basically do some extra stuff to have a complete solution deployment (or retraction), and most of the time you end up writing a Feature receiver class to undergo a task on Feature installed, activated, deactivating or uninstalling event handlers.
When writing a Feature event receiver class, you might be tempted to write all your code in a single Feature event receiver, or assign additional responsibilities to your existing Feature event receiver class. Maybe it’s not even temptation; when you think about it, the only thing you have to change is the Feature event receiver assembly that the Feature manifest is pointing to, and doing so might seem to make sense. But it definitely violates one of the most important principles of software development (a.k.a. Computer Science), the Single-Responsibility Principle (SRP), which states that, “there should never be more than one reason for a class to change”. Tom DeMarco mentioned SRP in his book, Structured Analysis and Systems Specification, back in 1979, and till now I've tended to break it ;). Ok, I wasn’t even born then, but it says:
“…every object should have a single responsibility, and that all its services should be narrowly aligned with that responsibility.“
Why is it important to separate responsibilities into separate classes?
Extracts from http://www.objectmentor.com/resources/articles/srp.pdf, a chapter just about SRP:
“…Because each responsibility is an axis of change... If a class assumes more than one responsibility, then there will be more than one reason for it to change. If a class has more than one responsibility, then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’ ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed...”
All right, taking SRP into consideration, I decided to have the different set of functions I needed to execute in different Feature receivers. But wait a minute! You cannot have multiple Feature event receivers for a single Feature. How about we have a main Feature manifest that is pointing to a main Feature event receiver, and list down all the other Feature event receiver classes as Feature properties. When the main Feature event receiver goes through its life cycle, it will instantiate and execute the other Feature event receiver classes, per event (you have to write custom code to instantiate and execute the other Features). It sounds like a feasible solution, but it also sounds bizarre to me to have Feature event receiver classes with no actual Feature definition. Ok, instead, let me have a hidden Feature definition for each Feature event receiver class, and have activation dependencies on the main Feature. That way, there is no need for you to broadcast the main Feature’s life cycle events to the other ones yourself, because SharePoint will take care of that through Feature activation dependency (If you're undergoing tasks on Feature installed or Uninstalling then there is no need to have activation dependency; the feature definitions would just need to be referred in the solution manifest file so they can just be installed and removed). Also, you will be able to have isolated test cases for the other Feature event receiver classes without really making a lot of changes because they have their own Feature manifest file that you can use (ok, it might not be a big deal).
It should look something like this:
Main Feature Manifest file
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id=" 8B44F613-6040-4777-AE4F-16D56AB26D19"
Title="Main Feature"
Description="A visible Feature that the end-user going to activate and deactivate"
Version="1.0.0.0"
Scope="WebApplication"
Hidden="false"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ActivationDependencies>
<ActivationDependency
FeatureId="528DD2D9-DC76-45a1-8E2F-DFC57B4CC226" />
<ActivationDependency
FeatureId="7C5BEB3F-2129-4e12-BADB-22763FBF6758" />
<ActivationDependency
FeatureId="E4E20B37-13EC-44cd-9BB1-6514F1AA311F" />
</ActivationDependencies>
</Feature>
Dependent Feature Manifest file
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="528DD2D9-DC76-45a1-8E2F-DFC57B4CC226"
Title="Dependent Feature"
Description="Hidden dependent Feature with its own Feature receiver, and activate/deactivated when the main Feature is"
Version="1.0.0.0"
Scope="WebApplication"
Hidden="true"
ReceiverAssembly="[Feature receiver assembly name here]"
ReceiverClass="[Feature receiver class here]"
xmlns="http://schemas.microsoft.com/sharepoint/">
</Feature>
I agree that it takes a little extra work to have a separate Feature receiver class and Feature manifest file for each dependent Feature, but for the sake of SRP and Tom DeMarco, I think it is totally worth it. Even though the Single-Responsibility Principle is the simplest principle of all, in most situations it is kind of hard to identify SRP violations. Keeping in mind to work under the circumstances which best suit your own needs, know that having a separate Feature event receiver class for each set of functions at least reduces complexity so that others know where to look into an organized complexity.
To SRP,
NaT
Posted
Nov 12 2008, 05:11 PM
by
Natnael K. Gebremariam