Wednesday, December 30, 2009
Controlling Personal Projects with TDD/BDD
Though the conversation, we began to talk about an issue we were both sharing about our pet projects getting drawn out. While there are true reasons (i.e. time constraints being the most prevalent), the one that plagued us was the concept of scope creep. As a developer, we battle with scope creep during our day jobs (usually) but to experience such at home leads to only a single person to put the blame on; ourselves.
This really got me thinking and reflecting on my project and my own scope creep issues. I began to realize that every time I had scope creep, it was a spot where I hadn't written unit tests first. In many cases I focus on a test-first strategy of TDD; however, there are a few times when I get in the flow and just write the code. This works sometimes but the times in which I can identify as scope creep all fell into these moments. If I had stayed focus on a test-first strategy, would these moments of scope creep been prevented? Probably not; however, it would have probably allowed me to be more conscience of the decision and possibly move it to some form of feature list for another iteration.
I only use standard NUnit-based unit tests and haven't fully tried out writing specs associated with BDD. Using something like a full spec like BDD would have been able to control the feature list a bit better but, again, not fully prevent scope creep. Regardless of the method, staying focused on a test-first approach does have a habit of controlling and identifying scope creep. It's easier to finishing a single iteration and enhance/refactor than it is to always go with the flow and allow the scope to continue to grow.
Tuesday, December 22, 2009
Using MEF and Custom Configuration Sections
Up to this point, I've dove into some of the core fundamentals of using the Managed Extensibility Framework. Starting with this post, we're going to dive into how to apply it under certain circumstances. Some of the scenarios in the upcoming posts will focus on using MEF with different .Net technologies, applications that use MEF, or tricks in .Net that can assist when working with MEF. In this post, we'll start with this last category of scenarios by looking at how to utilize a custom configuration section defined in an assembly used as a MEF part and not located in the same directory as the executable. Using this method, it will allow even greater power to your application and freedom to the parts consumed by such.
Setting the Stage
For this post, we'll look at a simple code base we worked on earlier in the series which imported MEF parts from a separate assembly. Let's extend the code base by defining our simple custom configuration section from within the same assembly that define our external part. For simplicity sake, let's call the custom configuration section MEFCustomConfigSection. Below is the code for our custom configuration section:
1: public class MEFCustomConfigSection : ConfigurationSection
2: {
3: private static MEFCustomConfigSection settings = ConfigurationManager.GetSection("MEFCustomConfigSection") as MEFCustomConfigSection;
4:
5:
6: public static MEFCustomConfigSection Settings
7: {
8: get { return settings; }
9: }
10:
11: [ConfigurationProperty("message", IsRequired = true)]
12: public string Message
13: {
14: get { return this["message"].ToString(); }
15: set { this["message"] = value; }
16: }
17: }
This configuration section is very simple in that it only defines one property/attribute called Message. This property will contain a string value in which we'll be displaying on the screen when the application consumes our part.
Consuming Our Section
Now that our configuration section has been defining, let's go ahead and create the code to consume such. In previous examples, each of our parts had a property called HelpText that is used by the consuming application to display command line help documentation for each part. What we will do with this new part is using our configuration section's Message property to define what the value of the HelpText property should be. Thankfully, the code for this is extremely simple as shown below:
1: [Export("command", typeof(IHelp))]
2: public class CustomCommand : IHelp
3: {
4: public string CommandName
5: {
6: get { return "Custom"; }
7: }
8:
9: public string HelpText
10: {
11: get { return MEFCustomConfigSection.Settings.Message; }
12: }
13: }
Setting Up the Configuration File
Now that we have the custom configuration section created and code that needs it, we're now ready to update our consuming application's App.config file.
1: <configuration>
2: <configSections>
3: <section name="MEFCustomConfigSection"
4: type="MEFExample7.Commands.MEFCustomConfigSection, MEFExample7.Commands" />
5: </configSections>
6:
7: <MEFCustomConfigSection message="Hello From a Custom Section" />
8:
9: <runtime>
10: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
11: <probing privatePath="Plug-ins;" />
12: </assemblyBinding>
13: </runtime>
14: </configuration>
Setting up the custom configuration section is the same as any other configuration section that would need to be setup. We first define our section within the <configSections> node and then we're able to insert our section; however, what's that last section?
The <runtime> section in the above snippet is needed to tell .Net to scan the Plug-ins subdirectory for the assembly that contains our configuration section. There are two ways of doing this. The example above uses the <probing> node which is great for little examples like this; however, can lead to performance issues since it will scan all assemblies in the paths that are provided. Another issue with the <probing> node is that it doesn't provide a way for targeting specific, strongly named assemblies nor specific assembly versions. If you need stronger control of what assemblies gets loaded, you can use the <codeBase> node instead.
For more information on using the <probing> and <codeBase> nodes for loading assemblies this way, feel free to check out the following links:
NOTE: One final item I need to mention about using <probing>, it can only look in subdirectories of the location the executable is in. So if the assembly is in /bin, your path to probe for assemblies cannot be in a parent directory.
Once the configuration section is setup, and the Plug-ins directory is a child directory of the location of the executable, our new command is now displayed when the application runs.
Summary
In this post, we briefly looked at some things to be aware of when defining a custom configuration section from with in an assembly used as an external MEF part. In future posts, we'll be looking at other scenarios on using MEF including consuming parts written in F# by a C# application as well as take a look at an open source project that will soon be releasing a new version that uses MEF.
Resources
Tuesday, December 1, 2009
Managing Composition Through Lazy Loading Parts
So far in this post series, we've been looking at various aspects of working with MEF in the context of a single level of composition. One interesting thing about MEF is that its composition is recursive based on the assemblies and types identified in the catalogs within the container. What this means is that if one of our parts also has imports defined for parts of its own, the composition container will continue loading parts for the initial type as well as all parts loaded until no more parts are found or all imports are fulfilled. This is a really nice feature since it will ensure everything is ready for you once compose the initial type; however, this eager loading can greatly cause a performance issue if the parts are not constructed properly. In this post on our ongoing series about MEF, we'll look into the concept of parts of parts and how to apply lazy loading principles towards them.
Putting the Pieces of Pieces Together
To start this example off, we'll add to the code we last used in the fourth post of this series (Playing Nice with Other Assemblies using MEF Catalogs). In order to enhance the code to illustrate a part of parts, let's add a new field to our IHelp interface that will represent subcommands of our parts. Since we're going to assume that any of our commands could have multiple subcommands, let's make it of type IEnumerable<IHelp>. Since it's an enumeration of IHelp, the amount of embedding could be infinite in theory (which sounds like fun but maybe another time). After we update our IHelp interface and our current commands, let's mark only our ExampleCommand class to have its Subcommands property to be a MEF Import point as shown below.
IHelp.cs
1: public interface IHelp
2: {
3: string CommandName { get; }
4: string HelpText { get; }
5: IEnumerable<IHelp> Subcommands { get; set; }
6: }
ExampleCommand.cs
1: [Export("Commands", typeof(IHelp))]
2: public class ExampleCommand : IHelp
3: {
4: private string _helpText = "Lorem ipsum dolor sit amet, c ..." +
5: "Nulla molestie erat rhon ..." +
6: "amet dolor. Aliquam rhon ..." +
7: "vel est. Vestibulum et u ..." +
8: "id tellus. Fusce lectus ..."
9:
10: public string CommandName
11: {
12: get { return AppName + " Example1"; }
13: }
14:
15: public string HelpText
16: {
17: get { return _helpText; }
18: }
19:
20: [ImportMany("Subcommands", typeof(IHelp))]
21: public IEnumerable<IHelp> Subcommands { get; set; }
22:
23: [Import("AppName")]
24: public string AppName { get; set; }
25: }
With this done, let's modify our Program.cs code slightly as well. In order to ensure the we can infinitely loop through our subcommands, let's change our output information slightly by using recursion as shown below.
1: void Run()
2: {
3: Compose();
4:
5: OutputHelp(Commands, 0);
6: Console.ReadKey();
7: }
8:
9: private void OutputHelp(IEnumerable<IHelp> helpCommands, int padding)
10: {
11: foreach (var help in helpCommands)
12: {
13: Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help));
14:
15: if (help.Subcommands != null && help.Subcommands.Count() > 0)
16: {
17: OutputHelp(help.Subcommands, ++padding);
18: }
19: }
20: }
In the above code, we're passing our recursive function, OutputHelp, two parameters. The first parameter represent the collection of IHelp instances to be outputted to the screen while the second is to provide depth of the recursion. On line 13 of the snippet above we use this depth parameter to append our formatted command name with hyphens equal to the depth. Lastly, we check to see if the Subcommands collection has values and call our OutputHelp method again passing the collection and incrementing the depth.
Next, let's create a new class called ExampleSubcommand.cs. This will represent a subcommand for our ExampleCommand.cs class. Once our ExampleSubcommand is all set, we can run the application to see the following output.
In the above image, we can see our Subcommand being displayed after the Example1 command as expected. In addition, we've applied the hyphens prior to the command name to indicate the depth correctly. Alternatively, we could have added an export to our ExampleCommand class similar to that of our AppName property to send the "MEFExample6 Example1" down the tree as well.
Working with Lazing Parts
Now that we have our example prepped, it's time to see what we can do to optimize the code slightly through lazy loading. For those who may not be familiar with the concept, lazy loading ultimately means that you do not load the objects or data until they are needed. What this translates to is that when we call container.ComposeParts(this) in our Program.cs class, we want only our initial commands to be instantiated but not any subcommands it has in order to ensure only the objects that are currently being used are the ones currently in memory.
in order to accomplish lazy loading of exports in MEF, we need to use the System.Lazy<T> type in place of the contract type of our exports. This type (built into the MEF assembly for .Net 3.5) tells MEF to delay the instantiation of the value until it's actually called. This is exactly what we're looking for to prevent a full line of instances from being created as we compose our parts. Before we dive into the nuances of Lazy<T>, let's look at a simplified snippet below:
1: public class LazyExample
2: {
3: [Import()]
4: public System.Lazy<IHelp> command { get; set; }
5: }
In the above code, we created an example class called LazyExample which contains a singular import of type IHelp. Because we wanted to delay the instantiation of this instance, we changed the type from IHelp to System.Lazy<IHelp> and we are all set from a definition standpoint. While this looks easy, there are two things to be aware of when working with Lazy<T>.
- System.Lazy<T> requires you to grab instances of the underlying type using the Value property. In the example snippet above, we would need to call command.Value in order to get the instance of IHelp instead of just calling the command property like we've been doing up to this point.
- System.Lazy<T> is not a collection type. System.Lazy<T> does not implement nor inherit any class that implement IEnumerable<T>. What this means is that just wrapping Lazy<T> around your currently defined properties that are decorated with ImportMany() won't work. In order to apply lazy loading to collections of parts, you must change the type to IEnumerable<Lazy<IHelp>>, keeping inline with the above example. This means any looping within the collection must be item.Value now instead of just item.
Applying Lazy Loading to Our Exports
Since we now see how to apply lazy loading to our exports, let's modify our code to implement such. To do this, we'll need to modify our IHelp interface to change the Subcommands property we added to be of type IEnumerable<Lazy<IHelp>> and propagate such between the various parts. Next, we need to copy our recursive OutputHelp command to create a new method called OutputSubcommandHelp which will address the output. Once this is done, our code should look something like this:
IHelp.cs
1: public interface IHelp
2: {
3: string CommandName { get; }
4: string HelpText { get; }
5: IEnumerable<Lazy<IHelp>> Subcommands { get; set; }
6: }
ExampleCommand.cs
1: [ImportMany("Subcommands", typeof(IHelp))]
2: public IEnumerable<Lazy<IHelp>> Subcommands { get; set; }
Program.cs
1: [ImportMany("Commands", typeof(IHelp))]
2: public IEnumerable<IHelp> Commands { get; set; }
3:
4: [Export("AppName")]
5: public string AppName { get { return "MEFExample6"; } }
6:
7: void Run()
8: {
9: Compose();
10:
11: OutputHelp(Commands, 0);
12: Console.ReadKey();
13: }
14:
15: private void OutputHelp(IEnumerable<IHelp> helpCommands, int padding)
16: {
17: foreach (var help in helpCommands)
18: {
19: Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help));
20:
21: if (help.Subcommands != null && help.Subcommands.Count() > 0)
22: {
23: OutputSubcommandHelp(help.Subcommands, ++padding);
24: }
25: }
26: }
27:
28: private void OutputSubcommandHelp(IEnumerable<Lazy<IHelp>> helpCommands, int padding)
29: {
30: foreach (var help in helpCommands)
31: {
32: Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help.Value));
33:
34: if (help.Value.Subcommands != null && help.Value.Subcommands.Count() > 0)
35: {
36: OutputSubcommandHelp(help.Value.Subcommands, ++padding);
37: }
38: }
39: }
Adding Another Subcommand Layer
The last thing we will do in this example is to further extend the recursion tree by adding a new subcommand onto our current ExampleSubcommand. We'll call it ExampleSubcommand2 and give the contract a label of "Subcommands2". We'll decorate our ExampleSubcommand class to apply Import such into its own Subcommand collection and we'll run our application to see the following:
Summary:
Hopefully after this post you can see the benefits of lazy loading exports as well as how easy it is to implement such. Given the pattern that we have outlined above, the true depth can open a number of possibilities without over-utilizing our memory. In the next section, we're going to mix things up a bit by looking at what it may take to have an export be used to defined and interact with a custom configuration section while the assembly is not in the same directory as the calling assembly.