Skip to main content

Posts

Showing posts from February, 2012

Unit Testing Workflow Code Activities - Part 1

When I first started looking into Windows Workflow one of the first things that I liked about it was how it separated responsibilities. The workflow was responsible for handling the procedural logic with all it's conditional statements, etc. Whilst individual code activities could be written to handle the business logic processing; created in small easily re-usable components. To try and realise my original perception this series of blog posts will cover the unit testing of bespoke code activities; broken down into: Part One: Unit testing a code activity with a (generic) cast return type (this post)Part Two: Unit testing a code activity that assigns it's (multiple) output to "OutArguments" (Not yet written)So to make a start consider the following really basic code activity; it expects an InArgument<string> of "Input" and returns a string containing the processed output; in this case a reverse copy of the value held in "Input".namespace Ex…

Windows Workflow: Re-introducing old anti-patterns?

As part of my day job I've been experimenting with Windows Workflow in both modifying the existing TFS2010 build templates and as a way of controlling the process flow in our new suite of applications. On the most part I've been really impressed; when you sit in a process workshop watching the business users mapping the existing steps out on a white board (or even a wall) it is quickly apparent that showing them a similar flow should hold significant benefits. Gherkin goes some way towards creating a syntax/language that works for both technical and non-technical people, but it is a test language verifying the application is working as intended - you don't write the process itself in gherkin. We've also found (from experience) that gherkin has a reasonable learning curve for both technical and non-technical users; whilst most people seem to find it easy to relate to the visual element of workflow with little or no training.But as I opened I've been impressed for …

TFS2010: Publishing solution projects to their own directories

When looking to automate a TFS2010 build one of the first issues that most people seem to encounter is that all the binaries of each project in a solution end up in the same "bin" directory. The forum post TFS 2010 BUILD SERVER: Can not keep folder tree in the drop location ? details the solution; which is changes to both the CSPROJ file and the workflow template that is called by your build. Note: each CSPROJ file in your project needs to be updated as the workflow loops through the solution finding all the referenced projects.. The answer in the forum post has everything about what is needed but not why, which can be a bit confusing if you're just starting out with TFS / workflow. The image to the left is the section of the workflow that is changed. The workflow variable "OutputDirectory" is defined within the scope of "Compile and Test for configuration" (highlighted in green). The value of "outputDirectory" is assigned (highlighted i…

Improving “Boiler Plate” Data-Reader Code – Part 5

In this post we will extend the query functionality to handle stored procedures with parameters. To do this we need to create a new query type interface with an example implementation: public interfaceIDefineAStoredProcedureQuery : IQuery { string StoredProcName { get; } IList<SqlParameter> Parameters { get; } } public classGetCustomersByFirstName : IDefineAStoredProcedureQuery { public GetCustomersByFirstName(string firstName) { this.Parameters = newList<SqlParameter> { newSqlParameter("FirstName", firstName) }; } public string StoredProcName { get { return "GetCustomersByFirstName"; } } publicIList<SqlParameter> Parameters { get; private set; } } Now that we have the ability to create stored procedure queries we need something to handle them. To do this we need a concrete implementation of the interface "IHandleAQuery":public classStoredProcedureQueryHandler : IHandleAQuery { public void Assign(SqlCommand command, IQuery query) { var castQuery = query…

Improving “Boiler Plate” Data-Reader Code – Part 4

In part 3 we created a SQL repository object that took a populated instance of IQuery to select/return an enumerable list of objects. A limitation of the repository was that the query had to be text based, it couldn't handle stored procedures and/or parameters. By incorporating an abstract factory pattern we can extend the functionality to handle different types of query.The original code inside "SqlRepository.Get(...)" needs to be changed from:using (var command = connection.CreateCommand()) { command.CommandText = query.Text; connection.Open(); To:using (var command = connection.CreateCommand()) { var handler = QueryHandlerFactory.Create(query); handler.Assign(command, query); connection.Open(); The static factory class takes an instance of IQuery and determines which "query handler" to return depending upon the additional interface that the "passed in" query implements. This is implemented via the following code:public static classQueryHandlerFactory { publ…

Improving “Boiler Plate” Data-Reader Code – Part 3

In Part 1 of this series we started with a basic Data-Reader / SQL Connection/Command pattern and illustrated how it is possible to abstract the parsing of the Data Reader into a standalone object that can be fully unit tested in isolation of the calling code. In Part 2 of the series we made a very simple optimisation to the “DataReader” convertor and updated the tests to capture/verify the changes.In part 3 of the series we put this all together into a repository pattern to create a reusable and testable data access layer. The first step is to create an interface for the repository.namespace DataAccess.Example { using System.Collections.Generic; using System.Data.BoilerPlate; public interfaceIRespository { IEnumerable<TEntity> Get(IQuery query, IConvertDataReader<TEntity> dataReaderConvertor); } } The intent implied by the interface is that "Get" will be responsible for returning an enumerable list of a generic. To do this we pass in an implementation of IQuery and an …

Managing your dependencies in NuGet

When creating NuGet packages, how do you define your dependencies?If you're using the default setting of 'x' version or newer are you sure that all future versions of the dependency will work with the current version of your code? I'm not sure many people would be happy saying yes to that question but most NuGet packages are deployed with the default setting for their dependencies. Using a typical dependency, Log4Net, you might deploy a package today referencing the current build and everything's fine. But in a month or two's time there may be an update to Log4Net deployed that contains breaking changes. From that point on anyone that grabs your package from NuGet will find that it no longer works - instead of the version of Log4Net you developed against, they are now getting the latest version that breaks your code.Whilst it may be more work, the safer option may be to use the version "range" option for managing dependencies; only including versi…

What's New In Windows Workflow 4.5

Just as I start getting up to speed with WF4.0 MSDN magazine publishes an article detailing what's new in WF4.5. It looks like there's a lot of good stuff coming but the main thing that I noticed was that v4.0 requires full-trust to run. That shouldn't be a problem for the project we're intending to run workflow in, but if it will run in partial trust in the next release that will open up it's usage for many other applications.

Starting Windows Workflow v4.0

Today I've started learning about Windows Workflow v4.0, I'm hoping that it will help out with a current project. The original requirement was for mapping real world business processes to what would normally be complex long running computer tasks. Whilst investigating what it could do I'm beginning to think there could be real value using it for any task that requires process flow logic, even extremely short lived ones. This could be controlling page flow through a web application, or even defining the complex logic that can sometimes end up making MVC controller actions fatter than they really should be.For getting me started a really good starting point has been the MSDN WF4.0 videos under the beginners guide, if you have a PluralSite subscription, Matt Milner presents some really useful stuff too.As well as just learning the basics of Workflow; what really interests me is how it should be architected in a real world LOB application; taking into account the usual &quo…