Thursday, May 29, 2008

Workflow Runtime Manager - Streamlined Launching

If you've read Bruce Bukavics's "Pro WF - Windows Workflow in .NET 3.0", you may have seen some code for a Workflow Runtime Manager that wraps common steps to managing your Workflow Runtime such as launching workflows, adding services, retrieving output parameters and capturing exceptions from a workflow instance.

I expanded upon Bruce's implementation in two simple yet useful ways.  First, I created an interface from it.  I know, that's revolutionary! and nobody else would have ever though of that!  *cough*  *cough*  Anyway, that's not the point of this post.  I just needed to state that because I'm about to show you a clipping of the interface derived from Bruce's implementation.

public interface IWorkflowRuntimeManager
{
	...
	WorkflowInstanceWrapper StartWorkflow(Type workflowType, Dictionary<string, object> parameters);
	...
}

The problem with this is that I still have to set up that dictionary of parameters.  And what if I want to launch this workflow from multiple locations in my code?  I have to reinvent the wheel each time.  And how do I ensure that everyone is supplying the correct set of input parameters and they're named the same?  That's easy!  With the addition of another interface.

using System;
using System.Collections.Generic;

namespace Ipc.Framework.Workflow.Hosting
{
	/// <summary>
	///		Provides an interface for starting a workflow using
	///		<see cref="IWorkflowRuntimeManager"/>
	/// </summary>
	public interface IWorkflowStartInfo
	{
		/// <summary>
		///		The type of workflow that the <see cref="IWorkflowRuntimeManager"/>
		///		implementation should create and launch.
		/// </summary>
		Type WorkflowType { get; }

		/// <summary>
		///		The dictionary of parameters to feed to the new workflow instance.
		/// </summary>
		Dictionary<string, object> Parameters { get; }
	}
}

This interface basically describes how to build a key to start the car.  I simply write a class that implements this interface for each workflow defined in my project.  See an example implementation below.

public class HelpDeskCaseWorkflowStartInfo : IWorkflowStartInfo
{
	private const string PARAM_CASEID = "CaseId";

	private readonly Dictionary<string, object> _parameters;

	public HelpDeskCaseWorkflowStartInfo(int caseId)
	{
		_parameters = new Dictionary<string, object>();

		_parameters.Add(PARAM_CASEID, caseId);
	}

	#region IWorkflowStartInfo Members

	public Type WorkflowType
	{
		get { return typeof (HelpDeskCaseWorkflow); }
	}

	public Dictionary<string, object> Parameters
	{
		get { return _parameters; }
	}

	#endregion
}

And for the final step, let's expand the IWorkflowRuntimeManager interface as shown below.  The two functions accomplish the same task, but the second method allows compile-time binding of parameters wherever it is used (you just have to do the work to make sure that the parameter names you use in the implementation are correct).

public interface IWorkflowRuntimeManager
{
	...
	WorkflowInstanceWrapper StartWorkflow(Type workflowType, Dictionary<string, object> parameters);

	WorkflowInstanceWrapper StartWorkflow(IWorkflowStartInfo startInfo);
	...
}

Submit this story to DotNetKicks

Friday, May 23, 2008

Workflow Foundation Anatomy

One of my confusions that I ran into when I first started working with Microsoft's Windows Workflow Foundation (WF) was how the WF was structured.  A lot of words were being thrown at me such as Workflow Runtime, Workflow Instance, Core Services, Local Services, and Host Application.  The book that I was reading to learn WF did a piss-poor job explaining these.  Hopefully I can explain them in a way that may help you if you've run into the same problem.

Host Application

This one is fairly straight forward.  This is the application (Windows application, web application, web service, Windows service, etc) that creates and launches the workflow instances.  This is the guy that winds up the robot and lets it go.

iStock_000005521539XSmall

Workflow Runtime

This one is a little more tricky to describe, but the name basically does say it all again.  This is the runtime environment that the workflow instances run in.  The instances are created using the Workflow Runtime and the Workflow Runtime is the guy doing all of the work executing the instances.  The Workflow Runtime is the box that the robot operates in.  The Host Application will use the same box for all the robots doing similar tasks.

The Runtime does a good job isolating the Host Application from the Workflow Instances.  If any Workflow Instance bombs, the Runtime reports it to the Host Application through an event.  Anything that happens to an instance gets reported through events.  So if an instance completes, terminates, aborts, etc., it is reported to the Host Application via an event.  So the robots in the box can't hurt you when they explode because the box is pretty strong and contain the blast.

Workflow Instance

Ok, I've already been throwing this one around a bit, but I'm sure that you get this one already.  If I have a Workflow defined that takes in a set of input A and does an action B, when I need to fire off an execution of this workflow, I create an instance and give him to the Workflow Runtime to execute.  This instance of the workflow is the Workflow Instance (complicated isn't it?).  The Workflow Instance is the robot.

Core and Local Services

Ok, this is where my robot analogy begins to get a little more complicated.  It is important to note here that the Core Services and Local Services are actually an Inversion of Control.  Figuring this out helped me understand the Core and Local Services.

Local Services

Local Services are kind of like the code behind a web service.  A Local Service is nothing more than a class that implements an interface that has the 'ExternalDataExchangeAttribute' applied to it.  A Workflow can call a method on a Local Service using the 'CallExternalMethodActivity'.  The Local Services are loaded into the Workflow Runtime when the Runtime is first being initialized.  The WF provides a way to configure a Workflow Runtime via the application configuration file, so these Local Services can be swapped out after the application has been deployed and thus change how the application can function.  To use the robot analogy, Local Services are basically port holes in the box that the robots can put items in and possibly get items back.  Maybe there is one port hole that the robot can put a chunk of gold in and get gold coins back.  Or maybe the robots just deposit the gold in a port hole and don't get anything back.

For a real-life example, take a banking system.  I may have a Local Service that has functions defined for it such as CreateAccount, CloseAccount, DepositMoney, WithDrawMoney and GetBalance.  My Workflow can now use that Local Service via the interface that it implements (remember, the interface must have the 'ExternalDataExchangeAttribute' applied to it).  And after I've compiled and deployed my application to my test environment, I may want to switch out that Local Service with another one for testing (so that it doesn't hit against live data).  All I have to do is change my application configuration file and run the application again.  So instead of using MyCompany.MyApp.BankingSystem, I'm using MyCompany.MyApp.Testing.BankingSystem.

Core Services

Core Services are even more tricky.  Core Services are software components for the Workflow Runtime written into WF.  They provide functionality such as Workflow Persistence and Tracking (among others).  These are add-on functionality components that you can use to enhance your Workflow experience.  The persistence service gives the Workflow Runtime the ability to save it's running state, including the running state of the Workflow Instances, to a SQL Server database in order to suspend and resume the Workflow Runtime and its Workflow Instances.  The tracking service allows you to track a Workflow Instances so you can watch its progress.  In the robot analogy, since the box (the Workflow Runtime) is basically a black box and I can't actually see the robots, I use the Tracking service to watch what they are doing.  I can hook that up to my Host Application and it's basically a monitor on the side of the box that I can watch any given robot and what it is working on.  Or maybe, it's a unit that records all of the robot's activities (the Persistence service) so if I need to power down the box for the night, the robots can pick up tomorrow where they left off.

 

Note: In order to use the Core and Local Services, any input or output in those service or Workflow parameters must use Serializable objects.

Another Note: When using Local Services, objects are serialized, passed to the Local Service and passed back as a serialized object.  This means that the object going in is not going to be the same instance as the one coming back.  So if you have a Local Service that modifies an object, you're going to need to pass that object back.

Submit this story to DotNetKicks

Thursday, May 22, 2008

Unit Testing Switch Statements

A standard practice of mine when using switch statements with enum values is to throw a NotImplementedException on the default case.  This is so that when I add a new enum value, the function will bomb if I didn't account for that value in one of the switch statements.

Take the following example.  I have an enum called MyValues.  I've recently added Value3.  All the unit tests that I've written for my method MyClass.DoSomething pass, so I'm done... Right?  Wrong!  My switch statement doesn't explicitly use the new value and it should.  The unit test technically passes because no exception is thrown, but I wanted it to do something with that value, but instead it did nothing.

public enum MyValues
{
	Value1,
	Value2,
	Value3 //	Added to support feature #123
}

public static class MyClass
{
	public static void DoSomething(MyValues myValue)
	{
		switch (myValue)
		{
			case MyValues.Value1:
				System.Console.WriteLine("Did first action.");
				break;
			case MyValues.Value2:
				System.Console.WriteLine("Did second action.");
				break;
		}
	}
}

[NUnit.Framework.TestFixture]
public class MyClass_Tester
{
	[NUnit.Framework.Test]
	public void DoSomething_Test01()
	{
		MyClass.DoSomething(MyValues.Value1);
	}

	[NUnit.Framework.Test]
	public void DoSomething_Test02()
	{
		MyClass.DoSomething(MyValues.Value2);
	}

	[NUnit.Framework.Test]
	public void DoSomething_Test03()
	{
		MyClass.DoSomething(MyValues.Value3);
	}
}

Ok, let's go ahead and change that switch statement to now throw an exception on the default case.

switch (myValue)
{
	case MyValues.Value1:
		System.Console.WriteLine("Did first action.");
		break;
	case MyValues.Value2:
		System.Console.WriteLine("Did second action.");
		break;
	default:
		throw new System.NotImplementedException(
			string.Format("The switch statement does not have an implementation for the MyValues value {0}.", myValue));
}

Now my unit test DoSomething_Test03() fails and I realize that I haven't accounted for MyValues.Value3 in MyClass.DoSomething.

switch (myValue)
{
	case MyValues.Value1:
		System.Console.WriteLine("Did first action.");
		break;
	case MyValues.Value2:
		System.Console.WriteLine("Did second action.");
		break;
	case MyValues.Value3:
		System.Console.WriteLine("Did third action.");
		break;
	default:
		throw new System.NotImplementedException(
			string.Format("The switch statement does not have an implementation for the MyValues value {0}.", myValue));
}

But I still haven't figured out how to test the default case in unit tests.  This means I do not have 100% code coverage.  It's a moot point as the default case is a simple throw statement, but I really want to achieve 100% code coverage on this class.  For this, I'm modifying the DoSomething method to employ a Design-By-Contract class (find the code here) to check the enum values  So now my code looks like this.

public static class MyClass
{
	public static void DoSomething(MyValues myValue)
	{
		Check.Require(myValue == MyValues.Value1 || 
			myValue == MyValues.Value2 || 
			myValue == MyValues.Value3);

		switch (myValue)
		{
			case MyValues.Value1:
				System.Console.WriteLine("Did first action.");
				break;
			case MyValues.Value2:
				System.Console.WriteLine("Did second action.");
				break;
			case MyValues.Value3:
				System.Console.WriteLine("Did third action.");
				break;
		}
	}
}

Now I can achieve 100% code coverage.  And you'll notice, I no longer need the default case since I've already listed the enum values that I support in the function at the very top of the function.  If I wrote my unit test better to automatically just test every value of that enum without me having to explicitly define a test for each enum value, then I could switch that Check.Require to Check.Invariant and then that check won't even occur during production execution (as long as you don't have the DBC_CHECK_INVARIANT conditional compilation symbol defined in your Release configuration).  I can do this because I know that the unit tests will catch any enum values I don't support.

Submit this story to DotNetKicks

Wednesday, May 21, 2008

Ninja Level Code Coverage

At my old job, I and another developer embarked on writing a .NET assembly that offered low level functions into the system that our company developed.  One of our goals was to unit test the heck out of the assembly since it was so low level.  That assembly had to be as bug free as possible and when a change was made, we needed a way to try to ensure, without a huge effort on QA's side, that nothing would break.

iStock_000005249766XSmall We therefore needed to make sure that we had as much code coverage as possible.  Code coverage is simply the lines of code actually executed during the unit tests.  Now 100% code coverage, while it means that every single line of code has been executed, does not by any means mean your code is bug-free.  Code coverage does not take into account code you didn't write.  For example if I have a function Add(int a, int b) that returns an integer and my method just does 'return a+b;', I've got a huge bug if a+b > Int.MaxValue.  I could have had 100% code coverage and still missed that bug.

So while having 100% code coverage does not mean a great deal towards the quality of your unit testing, having 10% code coverage is a horrible level of code coverage.  In the past, we had unit tested some projects and eventually fallen behind on testing certain classes, or didn't employ test-driven development (TDD), etc. and we found we had about 20-30% coverage.  If you do not employ TDD, 20-30% is probably the best you're going to do (unless you are an amazing developer and can write completely testable code without even thinking about it).  With this project though, we did employ TDD and we achieved about 80% code coverage.  Most of that remaining 20% was untestable code because it interacted with the database through SQL command objects or with system APIs.

Let me clarify my definition of "untestable".  When I write unit tests, anything that interacts with another system or the environment is considered untestable.  Unit tests should really be environment independent.  Anything that requires a specific setup on the environment or a specific system could mean that the next developer is not able to run the unit tests on their system.  For example, if code interacts with SQL Server, what happens when the next developer does not have access to that server or the server is down?  Then the tests fail.  If possible, we will substitute one dependency for an equivalent, move versatile dependency.  When testing our nHibernate mapping files, we use SQLite because nothing needs to be installed and this unit test can run on any environment.

With a project I am working on right now, web services that our customers use to interact with our system, we need a heavy amount of unit testing as well.  We do not want a change on our side to force our customers to change on their side as well.  This requires them to spend money and until they change their code, there is a potential for their application to either break or cause invalid in our system (depending on the change and how it is implemented).

So I've been working hard on writing the library assembly for these web services using TDD and employing any techniques I can to streamline development, increase testability, leave the code easy to read and develop, etc.  I am using Spring.NET to help me do this.  I am using their Dependency Injection (DI) functionality of their Inversion of Control (IoC) container as well as their Aspect-Oriented Programming (AOP) components.  Lastly, I used a Design-By-Contract to assist in validating parameter arguments.

Using the DI, my classes already are stripped of their hard dependencies making them easier to test.  Using the AOP, I've simplified the code in my services classes by removing things such as authentication, logging and exception handling.  Each one of these aspects can be tested independently of the service class.  By not having them mixed in with the actual service execution code, the unit tests for the service code have less paths to test so less unit tests that need to be written.  In addition to this, as I was developing the library assembly, I stayed mindful of what code would be untestable and coded around that pulling those pieces of code out into their own classes.

The result?  I have about 75% code coverage already (the remaining 25% is a combination of untestable code, code that will eventually be removed as it is no longer needed and method stubs that haven't been developed yet and for now just return generic data for UI testing).  The interesting effect of my development process I noticed is that  every single class had either 0% code coverage or 100% code coverage..  So the 0% tested classes were classes that were not developed yet or were untestable code.  A quick glance at those classes and I noticed that all of the untestable classes were very minimalistic (about 3 - 10 lines of actual code per class).  These classes can easily be checked by two developers to determine if there are any bug potentials in them and most likely will be fully tested in a simple, manual QA test.

I have to admit, I thought that was really cool.  I used to think just having high code coverage was exciting.  But then seeing that every single class has either 0% or 100% code coverage, that definitely tops the cake (at least until I can achieve 100% code coverage on an entire assembly).

Submit this story to DotNetKicks

Tuesday, May 20, 2008

Dependency Injection

A while back a colleague of mine sent me a link to a Wikipedia article about a design pattern called Inversion of Control (IoC).  He also told me about a framework called Spring.NET that is apparently very popular (as well as other similar frameworks that extend the .NET Framework in an attempt to make building enterprise level applications easier).  In reading up on Spring.NET, I also came across a methodology called Aspect Oriented Programming (AOP) and a technique called Dependency Injection (DI).  After getting to fully know these design patterns, techniques and methodologies (oh my!), I feel like I've been living under a rock not knowing about them.

Let's talk about Dependency Injection first.  This is a specific form of IoC.  This technique allows the user application to swap out functional pieces of the application thus changing how the application runs.  Instead of a software component creating or retrieving it's own dependencies, it asks the user layer for it's dependencies.

Quick example: I have an AccountManager class in a banking program.  The AccountManager class interacts with the persistent data via the BankDb class.  Pretty typical.  The AccountManager class depends on the BankDb class and knows how to instantiate this class on it's own.  However, if we employ DI, we would modify the AccountManager class to take in a IBankDb class on instantiation.  Then when we instantiate the AccountManager class in the interface layer, we can supply the BankDb (which implements IBankDb) and the AccountManager no longer needs to know how to create that instance on it's own because it will be spoon-fed this object.iStock_000004289321XSmall

But wait!  We're not done.  Now we employ the help of the Spring.NET framework to do the DI for us.  We can now define in XML configuration files (such as the application configuration file) what class should be passed in to the AccountManager class when we instantiate the AccountManager.  Instead of hard-coding a BankDb object into the constructor, we retrieve the IBankDb object to use from the Spring.NET IoC container.  The Spring.NET IoC container is configured using the XML configuration files.

Ok, so what exactly do we have?

We have an AccountManager who doesn't care what object it uses to interact with the persistent data as long as it's an object that implements IBankDb.  And we also have an application that is able to dynamically load which object to pass into the AccountManager via the application configuration file.

How does this benefit us?

Well first, you can now fully unit test the AccountManager class (as long as IBankDb is it's only dependency).  You can use a framework such as Rhino Mocks or NMock to mock the IBankDb in order to help you fully unit test the AccountManager class.

Second, what if the person that needs to write the actual BankDb hasn't written it yet and you're not able to write it yourself because you don't have the appropriate access to write that code?  Well, you can write your own mock BankDb class that does enough for you to test your interface and when the actual BankDb class is created, you simply change a configuration file instead of your code.

Another example of the second benefit is in a web service.  Say you now have a web service that uses the AccountManager class.  You now want to create a development set of web services that allow consumers of the web services to develop their applications without hitting the live data but acts the same in all other aspects.  You can use the same exact AccountManager class, but now supply it a different BankDb class using just a configuration file change.  (By the way, Spring.NET has a way of dynamically generating .NET web services, so you don't even need to actually create another .asmx file - it's all done through the web.config).

Can't we accomplish the same thing by swapping the BankDb object via code?

Yes.  Using Spring.NET to do your DI vs. code is really your call.  This call is roughly equivalent to choosing C# over VB.NET, or Pepsi over Coca Cola.  There are arguments for either choice but at the end of the day, they both accomplish the same thing.  The only advice I can offer there is to go with what your comfortable with.  Spring.NET configuration files do have their headaches involved, but being able to change the functionality of the application without recompiling your application is pretty cool and sometimes handy.

Another example before I let you go.  I recently developed some web services.  I made three projects: The web service project, a .NET library and a Windows application to test the web service.  I relied on Spring.NET to do all of my DI.  The web services consume local services (code run directly from the library - not Windows services) to accomplish their tasks.  The tester application is written such that by commenting out one line and un-commenting another in the application configuration file, I can switch the tester application between using the production web services, using the development web services and using the local services without recompiling the application.  When the Windows app is using the local services, it is using the same exact Spring.NET configuration files that the web services do (thus injecting the dependencies the exact same way the web services would).  So I can test the local services and work out the bugs, then switch over to the web services (confident that the local services will work the same for them as it did for the Windows app) and do a great deal less testing on the web services.

If you've never looked at IoC, DI or Spring.NET (or equivalent frameworks), I encourage you to do so.  There can be a learning curve involved in figuring out when to and when not to use these, but I'm sure that you'll be able to figure out when those times are.

Submit this story to DotNetKicks