About Me

Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

Interesting Collaboration Tool To Check Out
Purge Subversion Files
Did You Know?
How I’m Currently Writing My BDD Style Tests – Part 2
Code Formatting Issues Resolved (for now)
Fixing the Code Formatting Issue
Back on twitter
About the 2009 Course Schedule
How I’m Currently Writing My BDD Style Tests – Part 1
JP’s Daily Dose Of Inspiration - #6
So What Do Past Students Really Think About Nothin But .Net?
Nothin But .Net – Done For The 2008 Year!!
Excel Formatting with Visitors, Specifications, and Composites
JP’s Daily Dose Of Inspiration - #5
JP's Daily Dose Of Inspiration - #4
JP's Daily Dose Of Inspiration - #3
JP’s Daily Dose Of Inspiration - #2
JP's Daily Dose Of Inspiration - #1

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 519
This Year: 28
This Month: 0
This Week: 0
Comments: 1593

 Tuesday, December 23, 2008
Tuesday, December 23, 2008 3:42:00 PM (Mountain Standard Time, UTC-07:00) ( Tools )

My good friend Scott just pointed me in the direction of a really great (and very affordable) collaboration tool with excellent Skype support. Check it out at:

 

https://www.yugma.com/

 

Develop With Passion!!

Comments [3] | | # 
Tuesday, December 23, 2008 12:49:07 PM (Mountain Standard Time, UTC-07:00) ( )

Often times when I am copying files between different subversion folders, I want to make sure that I copy them and place them in the new location while not keeping any of the subversion folders/files kicking around. In the past I had a system for doing this (mostly with some well placed keyboard shortcuts). Now that I am moving most of my automation tasks into powershell, I thought I would share this script with you:

param([string] $folder)
  if (($folder -eq $null) -or ([System.IO.Directory]::Exists($folder) -eq $false))
  {
    "usage: kill_subversion_files.ps1 [path_to_folder_to_purge_subversion_files_from]"
  }
  else
  {
    "Deleting all subversion files from $folder"
    get-childitem $folder -recurse -force -include *svn | remove-item -recurse -force
  }

I place this scripts (named kill_subversion_files.ps1) in my powershell path, then I can just open up a powershell prompt and type in:

kill_subversion_files [path_to_folder_to_remove_subversion_files_from]

Develop With Passion!!

Comments [10] | | # 
Tuesday, December 23, 2008 12:35:00 PM (Mountain Standard Time, UTC-07:00) ( General )
Comments [2] | | # 
 Monday, December 22, 2008
Monday, December 22, 2008 2:29:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp | Programming )

We left off in part 1 with an example of a test written using my current style and I finished off outlining the skeleton for one of the base classes that shields the actual Concern classes from a lot of noisy test related nomenclature.

In this post I am going to break down the responsibilities of the “an_observations_basic_set_of_behaviours” class. For a quick reminder, here is the skeleton outline of the class:

        [Observations]

        public abstract class an_observations_set_of_basic_behaviours

        {

            static protected IDictionary<Type, object> dependencies;

            static Exception exception_thrown_while_the_sut_performed_its_work;

            static protected Action behaviour_of_the_sut;

 

            [SetUp]

            public void setup() {}

 

            void prepare_to_make_an_observation() {}

 

            [TearDown]

            public void tear_down() {}

 

            after_all_observations a = () => dependencies.Clear();

 

            ICommand build_command_chain<DelegateType>() {}

 

            void run_action<DelegateType>() {}

 

            protected virtual void initialize_the_sut() {}

 

            static public void doing(Action action) {}

 

            static protected Exception exception_thrown_by_the_sut

            {

                get { }

            }

 

            static Exception get_exception_throw_by(Action action) {}

 

            static protected object an(Type type) {}

 

            static protected InterfaceType an<InterfaceType>() where InterfaceType : class {}

        }

    }

Let’s start off by discussing the fields:

static protected IDictionary<Type, object> dependencies;

 

  • This field is hopefully pretty self explanatory. It is a dictionary that will contain any direct dependencies of the SUT. In most of my apps I tend to favour Constructor based DI so, this dictionary basically contains the set of objects (mocks and/or reals) that the sut will depend on. How this gets populated will be discussed later.

static Exception exception_thrown_while_the_sut_performed_its_work;

  • This field will be used to store a reference to the exception that the sut threw while it performed its work. Is used in conjunction with the doing() method (more on that later).

static protected Action behaviour_of_the_sut;

  • I am going to revisit this field when we discuss the doing() method

That takes care of the first set of fields, lets move on to a method that should look very familiar to MbUnit/NUnit people:

        [SetUp]

        public void setup()

        {

            exception_thrown_while_the_sut_performed_its_work = null;

            dependencies = new Dictionary<Type, object>();

            prepare_to_make_an_observation();

        }

This is a traditional MbUnit setup method. Because it is decorated with the SetUp attribute, all of the code in this method will get run once before each observation (test). Essentially this method is used to reset stateful fields, this is not that interesting. The guts of setup happen in the following method:

        void prepare_to_make_an_observationjjj()

        {

            run_action<context>();

            initialize_the_sut();

            run_action<after_the_sut_has_been_initialized>();

            run_action<because>();

        }

In this base class the initialize_the_sut method has an empty implementation. The prepare_to_make_an_observation method leverages a hook method (initialize_the_sut) that can be leveraged (it will be by an_observation_for_an_instance_sut). In the base class, it is a virtual method with no implementation. As you can see, this method is responsibility for performing the following actions before an observation can be made:

  • Establishing the context (run_action<context>())
  • Initializing the SUT
  • Invoking the behaviour under test (run_action<because>())

Again this is a small little method that basically serves as a driver for prepping the way to be able to make observations. By the time we actually enter an observation in our actual fixtures, the SUT has already performed its work!!

Now I am sure you are wondering what the deal is with the run_action method? Here is the signature for the run_action method:

void run_action<DelegateType>()

This method is a generic method that accepts a delegate type as its generic argument. Again this is a convention that is understood by the naming of the generic parameter. You can’t place constraints on a generic method that constrain the Generic argument to be assignable from a delegate (of course, you can do this with a guard clause). Here are the different delegate signatures that I defined for use in the test-harnesses:

public delegate void context();

public delegate void after_the_sut_has_been_initialized();

public delegate void because();

public delegate void after_each_observation();

You may be wondering why I did not just use the plain old action delegate as opposed to creating discrete delegate types. This is so the driver class (this one we are examining) has a clearer way of differentiation between the different delegates. Without the named delegate types, I would have to resort to following a convention for the name I assigned to a field for an Action delegate (messy, messy).

Here is the full implementation of the run_action method:

        void run_action<DelegateType>()

        {

            build_command_chain<DelegateType>().run();

        }

 

Once again, this method is pretty simple as it is really delegating its responsibility to whatever gets created by the build_command_chain method. So lets dive into the full body of this method, as this is really where the majority of the work is being done:

        ICommand build_command_chain<DelegateType>()

        {

            var actions = new Stack<ICommand>();

            var current_class = GetType();

 

            while (current_class.is_a_concern_type())

            {

                actions.Push(new DelegateFieldInvocation(typeof (DelegateType), this, current_class));

                current_class = current_class.BaseType;

            }

 

            return actions.as_command_chain();

        }

So what is going on here. Take a look at this test one more time as it will give you a good visual as to what is going on:

    [Concern(typeof (MappingStep<,,>))]

    public class when_an_expression_mapping_step_is_told_to_run :

        concern_for_mapping_step

 

    {

        static SomeSourceObject item;

        static SomeDestinationObject destination;

        static string name;

 

        context c = () =>

        {

            item = new SomeSourceObject();

            name = "JP";

            destination = new SomeDestinationObject();

 

            source_evaluator.Stub(x => x.evaluate_against(item)).Return(name);

        };

 

        because b = () => sut.map(item, destination);

 

        [Observation]

        public void should_run_the_target_evaluator_passing_it_the_information_retrieved_from_evaluating_the_source()

        {

            target_action.was_told_to(x => x.act_against(destination, name));

        }

    }

I chose not to also put in this Concerns base class, the only important thing to remember about the “concern_for_mapping_step” is that it also has its own context block :

         context c = () =>

        {

            target_action = the_dependency<ITargetAction<SomeDestinationObject, string>>();

            source_evaluator = the_dependency<ISourceEvaluator<SomeSourceObject, string>>();

        };

 

It is important to remember that the “an_observations_basic_set_of_behaviours” class is the test driver. Here is the inheritance hierarchy for this current test fixture:

  • an_observations_basic_set_of_behaviours
    • observations_for_an_instance_sut
      • obsevations_for_a_sut_with_a_contract
        • concern_for_mapping_step
          • when_an_expression_mapping_step_is_told_to_run

At any point in the chain (starting from the top, working down) each level could have its own context to run. The run_action method is responsible for walking the inheritance hierarchy of a particular concern and building a chain of “commands” for a particular delegate type. Once the command chain has been build, the chain can be executed in the right order (from top to bottom) to ensure that any prior context in a base class has been established before a subclass runs. If you are already thinking, could he not have done the same thing with abstract/virtual methods. Yes. When I initially started down that route, I kept getting stung by forgetting to call back into the base method. By now having to worry about calling the base method prior to doing your own work, you as a developer can just focus on the context that is applicable to a particular test. You can do this, as the driver class is responsible for ensuring blocks run in the order they are supposed to run. Without the driver class, all the fields that have lambdas assigned to them would be useless as they are just sitting there waiting to be invoked.

At the end of the while loop in the build_command_chain method there will be a stack (I chose stack as it is a LIFO structure, which is perfect for walking a class hierarchy, as when the last item is added – the base class, I can just start popping items off and they will be in the right order, ending with the ultimate test class itself). The stack itself is being used to store a set of ICommand implementations. Here is the ICommand interface:

    public interface ICommand

    {

        void run();

    }

This is a pretty stock interface that I have used for years. The uses are endless!! How does the loop know when to end? What is with the following method?:

current_class.is_a_concern_type()

The field current_class is of type Type. The is_a_concern_type method is a local extension method that has the following implementation:

    static public bool is_a_concern_type(this Type type)

    {

        return typeof (an_observations_set_of_basic_behaviours)

            .IsAssignableFrom(type);

    }

This method just adds a bit of readability (from the point of usage, which is a huge bonus of extension methods) and ensures that we wont worry about putting anything that is not either a derivative of an_observations_set_of_basic_behaviours or the an_observations_set_of_basic_behaviours type itself on the stack (it will always be the top item on the stack at the end of the traversal).

So lets explore the line that does the grunt work:

actions.Push(new DelegateFieldInvocation(typeof (DelegateType), this, current_class));

Keep in mind that the actions field is a stack of ICommand. It stands to reason that the DelegateFieldInvocation class is an ICommand implementation. Which it is. The DelegateFieldInvocation class takes in its constuctor a delegate type to scour for, an instance to act against (always this), and finally the particular type to reflect against (this will change as we continue to walk up the inheritance hierarchy). Here is the implementation of the DelegateFieldInvocation:

    public class DelegateFieldInvocation : ICommand

    {

        const BindingFlags probing_flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly;

        Type delegate_type;

        readonly object instance;

        IEnumerable<FieldInfo> fields;

 

        public DelegateFieldInvocation(Type delegate_type, object instance, Type current_type)

        {

            fields = current_type.GetFields(probing_flags);

            this.delegate_type = delegate_type;

            this.instance = instance;

        }

 

        public void run()

        {

            all_fields_of_the_target_delegate_type().each(x => x.GetValue(instance).downcast_to<Delegate>().DynamicInvoke());

        }

 

        IEnumerable<FieldInfo> all_fields_of_the_target_delegate_type()

        {

            return fields.Where(x => x.FieldType.Equals(delegate_type));

        }

    }

All this command does in its run implementation is scour all of the fields in the “current_type” and filters them to look for only fields of the certain delegate type being searched for. Once the particular delegate type is found, we get the value of the field using the instance:

x.GetValue(instance).downcast_to<Delegate>()

downcast_to is just a utility extension method to do casting. At this point we have an actual reference to the delegate. With that, because we know (again by convention) that all of the delegate types we are working with are void with no arguments, they can just be invoked by using the DynamicInvoke method that lives on the delegate class. Again, the beauty of the command pattern allows this command to be queued up with all the information that it needs, and then it can simply perform it when it is told to run.

Of course, the build_command_chain ends with this line:

return actions.as_command_chain();

All that this method does is return a Composite of commands that when told to run, will run each of the commands that it is composed with (we’ll dive into that at a later date). So back up in the run_action method:

build_command_chain<DelegateType>().run();

It should now be clear to see that the run() method is invoked on the Composite, that will cause all of the commands to run in sequence. In the case of run_action<context> it will cause a Composite command to be built that is composed of commands to run “context” delegates from the Grandparent down to the actual Concern itself.

For clarification, look again at how the run_action method is used:

        void prepare_to_make_an_observation()

        {

            run_action<context>();

            initialize_the_sut();

            run_action<after_the_sut_has_been_initialized>();

            run_action<because>();

        }

The other calls to run action simply walk down the hierarchy invoking the appropriate delegate fields that may or may not be present in the actual test classes. The because block is the behaviour we are invoking of our system under test. In the case of the test we first examined:

because b = () => sut.map(item, destination);

For the design pattern aware, you will have already realized that the prepare_to_make_an_observation method (along with the use of delegate fields that can be defined at any level of the hierarchy) is just a specialization of the template method pattern, the main difference being that subclasses do not provide their behaviour by overriding abstract methods, rather they just simply have to define fields of a certain delegate type, that contain the code that will be invoked dynamically by the base class using reflection!!

That is enough for now, we’ll carry on the drilldown in the next part!!

Develop With Passion!!

Comments [4] | | # 
 Friday, December 19, 2008
Friday, December 19, 2008 3:02:00 PM (Mountain Standard Time, UTC-07:00) ( General )

A couple of people have gotten back to me about the formatting resolution, so unless I hear otherwise I will consider this issue closed (for the time being!!).

Comments [0] | | # 
Friday, December 19, 2008 1:46:00 PM (Mountain Standard Time, UTC-07:00) ( General )

After the many emails about the code formatting issues with feed readers. Here is my attempt to get it resolved.

Please get back to me with comments, if this fixes it (or if it doesn’t):

        static public void should_not_contain<T>(this IEnumerable<T> items, params T[] items_that_should_not_be_found)

        {

            var list = new List<T>(items);

            foreach (var item in items_that_should_not_be_found) Assert.IsFalse(list.Contains(item));

        }

Comments [10] | | # 
Friday, December 19, 2008 10:18:00 AM (Mountain Standard Time, UTC-07:00) ( General )

Most people who know me realize that I am almost obsessive about how I utilize my time during the day to maximize the 8-9 hours I spend developing. This is the main reason I did not stay on twitter long the last time I signed up. I use skype for most of my phone calls, I have probably been on MSN about 13 times in my career, and I never really jumped into twitter the last time I singed up.

My goals for rejoining are to simply provide small little updates as to what I and/or my family are doing. I realize that even just little jots of information are valuable to the people who care about what is going on with us (it is a season of change here in the Boodhoo house!!). I am not going to use it as a huge conversational mechanism, mostly for micro updates.

My username is jpboodhoo in case you are one of the people who has expressed interest in keeping up to speed.

God Bless You and Develop With Passion!!

Comments [0] | | # 
 Thursday, December 18, 2008
Thursday, December 18, 2008 3:18:00 PM (Mountain Standard Time, UTC-07:00) ( Training )

This is just a note to let people know that the schedule for 2009 has been penciled in and not yet posted. My hope was to get to provide my web site with some much needed TLC and that has not happened. Courses will start up again in May 2009 and run until December 2009. So far the countries that are on the list are:

  • Canada
  • USA
  • England
  • Australia
  • Germany
  • India/Cambodia (need to talk with more people before this is finalized)

That is just the high level country list, not the city list. My wife and I are finalizing the schedule and even without posting it to the schedule page, there will be a post that outlines that actual destinations within the next 2 weeks. One of the plans for next year (late next year) is to also launch a new course targeting the development and delivery of smart client applications. Nothin But .Net has typically been delivered targeting web developers, this new course would be focused on strategies for building composable Smart Client applications. The majority of my development career has been in the smart client space, and since I have not shared a lot of information on the techniques I use, it would be the perfect venue to share a lot of techniques and strategies I use. My hope is to beta the course late next year, and have a Q4 2009 first offering, or at the latest a Q1 2010 offering.

At the end of the day this is just a heads up that courses will be continuing for next year and if you are planning on attending, stay tuned.

Develop With Passion!!

Comments [7] | | # 
Thursday, December 18, 2008 3:08:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp | Programming )

In the ongoing goal of “Competing against yourself daily” I have changed many things about my coding style over this past year. One of the areas that has been most affected by all of this is how I organize and write tests for the systems I am building.

Here is an example of a test that I wrote for something called a MappingStep:

public abstract class concern_for_mapping_step : observations_for_a_sut_with_a_contract<IMappingStep<SomeSourceObject, SomeDestinationObject>, MappingStep<SomeSourceObject, SomeDestinationObject, string>> { static protected ITargetAction<SomeDestinationObject, string> target_action; static protected ISourceEvaluator<SomeSourceObject, string> source_evaluator; context c = () => { target_action = the_dependency<ITargetAction<SomeDestinationObject, string>>(); source_evaluator = the_dependency<ISourceEvaluator<SomeSourceObject, string>>(); }; } [Concern(typeof (MappingStep<,,>))] public class when_an_expression_mapping_step_is_told_to_run : concern_for_mapping_step { static SomeSourceObject item; static SomeDestinationObject destination; static string name; context c = () => { item = new SomeSourceObject(); name = "JP"; destination = new SomeDestinationObject(); source_evaluator.Stub(x => x.evaluate_against(item)).Return(name); }; because b = () => sut.map(item, destination); [Observation] public void should_run_the_target_evaluator_passing_it_the_information_retrieved_from_evaluating_the_source() { target_action.was_told_to(x => x.act_against(destination, name)); } }

First thing to notice is a convention I have started using when it comes to writing tests. I create a base class named concern_for_[name_of_system_under_test]. You will also see that all of the fields in the test classes are static and not instance. The 2 fields in the base concern_for_mapping_step class are there to hold references to dependencies of the system under test. I don’t need to have them there as they are accessible using a helper method on the base test class (more about the base test class hierarchy in a minute), I just like to have them as I find it a bit more readable than calling methods to access the dependencies of the system under test ex:

  • I prefer referring to a field named: target_action as opposed to repeatedly having to call a method such as:
    • Mock<ITargetAction<SomeDestinationObject,string>> / the_dependency<ITargetAction<SomeDestinationObject,string>> (of course, in this example, the generic signatures emphasize the issue even more!!!)

Second thing to notice is the use of a field named c which is of a delegate type named context. Here is the definition for the context delegate type:

public delegate void context();

Nothing all that special about it. This field will get used back up in the base test class to “establish the context for the test to run” much like a traditional setup method would / constructor if you are using xUnit.

If we focus our attention now on the “when_an_expression_mapping_step_is_told_to_run’ class, you will see that it inherits from the base concern class. The base concern class will be used to hide fields/extra noise that would otherwise pollute the test. You will see that this test also has its own context block. Context blocks are applied recursively from the top of the hierarchy down, this ensures that any contexts in base classes will always run first. In the past I would use overriden methods to accomplish this, but then you had to deal with making sure to call the base “establish_context” method, and if you forgot you could have tests fail because of a silly omission. By adhering to a convention of placing scaffolding in a context block, the “framework” takes care of ensuring that contexts are run in the correct order.

The following block:

because b = () => sut.map(item, destination);

focuses our attention to what behaviour of the system under test we are testing (in the particular context). You will notice that I use the name of the class to embody both action and context. Of course, in this particular test I am focusing on a happy day scenario. An example of testing in another context could be a test fixture named:

  • when_a_mapping_step_is_told_to_map_from_an_invalid_source

This name implies context. In the first test I am just testing the behaviour of mapping. In the second test (which is a different context), I am testing how the sut behaves when it is provided invalid data. One of the things that is hard to see from this example is that one context (test fixture) could have several observations (assertions). In this current example there is only 1 observation being made.

Notice that the because block, like the context block is a field of a simple delegate type (another void delegate type). This means that the code does not execute as it is just an anonymous method of certain delegate type being assigned to a field of a matching delegate type.

Finally observations are made. Notice the use of the Observation attribute. Inside an observation (Test) I will make logical assertions against either the system under test, the dependencies, or the outputs of the method under test. It is best to try to stick to one logical assertion (keeping in mind that 2 actual assertions can be part of 1 logical assertion) per observation. This is why you will often see a single Context (TestFixture) with multiple Observations.

One of the things that you may have missed is the fact that the System Under Test is never instantiated. This is also taken care of in a base class. I have the ability to override the creation of the system under test, but for most tests, letting the SUT be created for me saves a couple of lines of code, and allows me to not have to change things as more dependencies get added.

So how does all of this work? Currently all of this is coded to run against MBUnit 2.5. I have a project called jpboodhoo.commons.bdd (part of jpboodhoo.commons) where I place all of the plumbing code to make all of this work. Here is a snapshot of the project:

image

This is one of those utility type projects that got harvested over time as I saw patterns start to emerge. Under the concern folder there are 4 main classes:

image

In my projects I derive from either one of the following 3:

  • observations_for_a_static_sut
  • observations_for_a_sut_with_a_contract
  • observations_for_a_sut_without_a_contract

Those 3 base classes cover the range of classes I may want to write tests against. I am hoping that the naming of the classes is pretty self explanatory. Here are the definitions for each of the above 3 classes:

public abstract class observations_for_a_static_sut : an_observations_set_of_basic_behaviours { }

This one is the most basic, it simply inherits from “an_observations_set_of_basic_behaviours”. I derive from this class when I am testing static classes. The other 2 are equally as simple with a little twist:

public abstract class observations_for_a_sut_with_a_contract<Contract, ClassUnderTest> : observations_for_an_instance_sut<Contract, ClassUnderTest> where ClassUnderTest : Contract { }

I derive from this class when I want to write tests against a class, but code the tests against an interface of the class, and not the class itself. Here the term interface/contract applies to either a C# interface, or a class that the ClassUnderTest inherits from (usually an abstract class). The final base class (that I can choose to derive from) is very similar:

public abstract class observations_for_a_sut_without_a_contract<SystemUnderTest> : observations_for_an_instance_sut<SystemUnderTest, SystemUnderTest> { }

Notice how this class derives from the same class as the previous class, except that it uses the same type for providing the generic arguments to the “observations_for_an_instance_sut”

Again, the 3 classes that I have just covered are there to introduce a convention for people (right now just me) to follow when they are writing their own tests classes. The naming of the 3 makes it pretty simple( I think) to figure out which one you would start with.

With those 3 covered it really leaves the 2 “big ones” that hide a lot of plumbing and MBUnit specific details. Let’s start by taking a look at the skeleton for the “an_observations_set_of_basic_behaviours”:

[Observations] public abstract class an_observations_set_of_basic_behaviours { static protected IDictionary<Type, object> dependencies; static Exception exception_thrown_while_sut_performed_its_work; static protected Action behaviour_of_the_sut; [SetUp] public void setup() { } [TearDown] public void tear_down() { } void do_setup() { } after_each_observation a = () => dependencies.Clear(); ICommand build_command_chain<DelegateType>() { } void run_action<DelegateType>() { } protected virtual void initialize_system_under_test() { } static public void doing(Action action) { } static protected Exception exception_thrown_by_the_sut { } static Exception get_exception_throw_by(Action action_that_should_be_taken_by_the_sut) { } static protected object an(Type type) { } static protected InterfaceType an<InterfaceType>() where InterfaceType : class { } }

This is just the interface (we’ll dive into implementation of each method in time!!). Let’s break it down step by step. First thing you should see is the use of the Observations attribute on the class itself. This is basically just an alternative to the TestFixtureAttribute (thanks go to Albert Weinert for suggesting this). Here is the code:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ObservationsAttribute : TestFixturePatternAttribute { public ObservationsAttribute(string description) : base(description) { } public ObservationsAttribute() { } public override IRun GetRun() { var run = new SequenceRun(); run.Runs.Add(new OptionalMethodRun(typeof (SetUpAttribute), false)); run.Runs.Add(new MethodRun(typeof (ObservationAttribute), true, true)); run.Runs.Add(new OptionalMethodRun(typeof (TearDownAttribute), false)); return run; } }

The main thing you should get out of this is that the GetRun method tells MbUnit to look for methods that are decorated with the ObservationAttribute, and to treat them as tests. The ObservationAttribute is really simple:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class ObservationAttribute : TestPatternAttribute { }

You have already seen this attribute used on the test earlier. The thing that should be immediately apparent about the “an_observations_basic_set_of_behaviours” class is that it is there to shield the rest of the test code from the details of whatever xUnit framework you are targeting (in this case, MBUnit).

Tomorrow I’ll continue by breaking down the responsibilities of this class in a piece meal fashion.

Develop With Passion!!

Comments [5] | | # 
Thursday, December 18, 2008 11:13:00 AM (Mountain Standard Time, UTC-07:00) ( )

The road lays out ahead of you. You can’t see your goal in sight, you just know it is waiting to be attained.

It is not important how long you will travel this road for, or how many obstacles you are going to have to overcome. You just know that without this pursuit, nothing in your life will be the same. How much do you want it? Are you willing to put in the enormous effort. Are you ready to start your marathon today?

If you start too fast and don’t set yourself a steady pace, you can risk burning out too early and not achieving your goal. On the other hand if you start off slow and don’t try to continually push yourself, you may find you reach your destination much later than your liking. Find your rhythm, a pace that works for you. Don’t get distracted by the sprinters speeding by you, and don’t get too confident if you start to leave people in your wake, as you might get complacent. Compete against yourself daily.

The road lays out ahead of you. You can’t see your goal in sight, you just know it is waiting to be attained. You take the first step, and then the other. You have started the marathon. After a long time running it is easy to get discouraged and sidetracked. Thoughts of giving up can sometimes consume you when you are running through the desert on your own. These times are there to test you, and to keep you humble.

Over time you will realize that the goal you thought was the goal may not be what you were expecting. Along the way I pray you will have the realization that the real goal of this “marathon” is the journey itself. Take time to breathe in your surroundings. Cherish the people you will meet on the way. Give encouragement to those who need encouragement. Share your “water” with those who are “thirsty”. The journey is beautiful and it is my hope and prayer that all of you cherish every single second of it!!

“.. I do not consider myself yet to have taken hold of it. But one thing I do: Forgetting what is behind and straining toward what is ahead, I press on toward the goal to win the prize for which God has called me heavenward in Christ Jesus.” – Philippians 3:13-14

Comments [1] | | # 
 Thursday, December 11, 2008
Thursday, December 11, 2008 7:58:00 AM (Mountain Standard Time, UTC-07:00) ( Training )

Now that the course has been running for over 2 years, there have been plenty of unsolicited comments about the course that have been posted to the blogosphere. This post attempts to aggregate a handful of them into one place so you can see for yourself what people really think about the course (good and bad!!).

If you are a past student and have a blog post that is not listed up above, please get in contact with me as I would love to be able to link to it!!

Looking forward to what next years students will say!!

Develop With Passion!!

Comments [4] | | # 
Thursday, December 11, 2008 12:10:00 AM (Mountain Standard Time, UTC-07:00) ( Training )

Phliiy course 012_small

The picture above is of the last class that occurred in Philadelphia. The last 2 courses introduced some new formats to the course. In particular, the length of group exercises has been increased significantly (a little too much for Philly, but a lesson learned for next time!!). This course has been a blessing that cannot be conveyed in words. The last 2 classes of the year were held in Vegas and Philadelphia and they were absolutely amazing. It was a great way to end the training year.

What is the secret to the course? Is it the:

  • Great meals (Philadelphia was treated to some of the best dining of the year. Thanks in large part to so many amazing establishments being so close to the venue).
  • Great technical content.
  • Screencasts of every minute of coding that takes place
  • Tips on how to maintain a great attitude about life and work
  • Laughs (lots of them!!!)

While the above are definitely reasons that people choose to attend the course, they are easily eclipsed by the PEOPLE that attend. The amazing energy, enthusiasm, and spirit that the group displays over the course of the week continually blows me away. How many classes do you know where a group of random strangers can come together and by the end of the week are actually planning on forming lasting friendships!!!

God has truly been in the details and I know that none of this would have been possible without Him. I am thankful for every opportunity to deliver this course and will continue to evolve the material and deliver it as long as I feel called to do so!!

One of the great things that was conveyed by a couple of repeat students is how much the course has changed over the period of a year. They came in thinking that it would be a refresher and they were greeted with completely new content!! My hope is that the course and its material will continue to evolve as I learn new things . I am excited to see what the 2009 year will bring (along with a much needed set of alumni meetings!!!).

To all of the people I have been blessed with the opportunity of sharing with over the past year, I want to send a big “God Bless You” out to all of you. It was an honor, a blessing, and a privilege to help you chart a new course for your development career.  And I am truly honored to be able to say I could help in some small way.

It is my prayer that all of you will continue to not worry about  “Keeping up with the Jones’s”, and will run your own marathon at your own steady, progressive pace!! Compete against yourself daily and you will develop habits that will keep you growing as a person (which in turn will influence your career).

Hopefully I will see some of you again next year (especially at the alumni get-togethers). And I really hope that people who have been thinking about taking the course who have been on the fence will jump on board next year!!

Develop With Passion!!!

Comments [2] | | # 
 Wednesday, December 10, 2008
Wednesday, December 10, 2008 4:44:00 PM (Mountain Standard Time, UTC-07:00) ( C Sharp | Programming )

The title is definitely a mouthful!!

A project a year ago (yep, I’m quite behind on the technical blogging front) required the need for Excel generation and formatting. Unlike other Excel generation tasks I had done in the past, this particular task called for generation of tabbed workbooks, with graphs, fancy formatting etc. Much more involved than the trivial stuff I had typically done with excel in the past.

Applying formatting to elements in a tree is a perfect job for the Visitor pattern!! Of course, different types of formatting need to be applied to different cells, some cells need multiple types of formatting applied to them. Composite pattern can come to the rescue here. How can we filter out different types of formatting to certain cells / range of cells? The Specification pattern can come in handy here.

The project resulted in the creation of a fairly flexible excel formatting engine (that has been run against 3rd party excel frameworks SpreadSheetGear, and OfficeWriter).

Here is the interface for a cell visitor:

public interface ICellVisitor { void visit(IRange cell); }

And here is the implementation for the composite visitor:

public class CompositeCellVisitor : ICellVisitor { private IList<ICellVisitor> all_visitors; public CompositeCellVisitor() { all_visitors = new List<ICellVisitor>(); } public void add(ICellVisitor visitor) { all_visitors.Add(visitor); } public void add_all(IEnumerable<ICellVisitor> visitors) { foreach (var visitor in visitors) add(visitor); } public void visit(IRange cell) { foreach (var visitor in all_visitors) visitor.visit(cell); } }

As you can see, a composite basically implements the same interface as the things it is being composed of and it simply (for the most part) does its job by delegating to each of its leaf items to do their jobs. In this case, each visitor is told to visit a cell. This means that when an iterator for a spreadsheet (which essentially makes sure to walk over each cell in the spreadsheet) walks to a certain cell, it can then tell the CompositeVisitor to visit the cell. Because the composite is composed of all the possible visitors that can visit a cell, you only need to pass through the spreadsheet once to apply all formatting.

Here are the names of some of the formatting that can be done:

  • ApplyAllCellBorders
  • AutoFitCellWidth
  • BoldFont
  • ChangeFontSize
  • CustomFormat
  • FormatBackColor

Here is the implementation of one of the visitors:

public class FormatBackColor : ICellVisitor { private Color color; public FormatBackColor(Color color) { this.color = color; } public void visit(IRange cell) { cell.Interior.Color = color; } }

As you see, the visitor is only responsible for a single discrete action. It has no knowledge as to whether or not it should actually apply itself against a cell, it just goes ahead and applies itself. This would obviously cause problems as there needs to be a way to allow a Visitor to visit/not visit a cell, without necessarily giving the visit the extra responsibility of making that determination. To accomodate this I separated responsibilities (matching/visiting) by “favouring composition” here is a class that was created to solve this problem in an SRP fashion:

public class ConstrainedCellVisitor : ICellVisitor { private ICellVisitor cell_visitor; private ISpecification<IRange> constraint; public ConstrainedCellVisitor(ICellVisitor cell_visitor, ISpecification<IRange> constraint) { this.cell_visitor = cell_visitor; this.constraint = constraint; } public void visit(IRange cell) { if (constraint.is_satisfied_by(cell)) cell_visitor.visit(cell); } }

The ConstrainedCellVisitor is composed of a raw visitor (that will perform an action against the cell) as well as the specification that will determine whether the cell in questions meets the criteria to be visited with the actual concrete formatting visitor.

The specification interface is something I am sure you have seen me use before (lots of usages, different contexts):

public interface ISpecification<T> { bool is_satisfied_by(T item); }
 
 

All that is needed to finish it off is a very simple configuration api to configure visitors with specifications. Here is one example of a line that builds a visitor and a specification:

yield return new ConstrainedCellVisitor( new ChangeFontSize(8), Cell.occurs_between_columns(3, 8) .and(Cell.occurs_after_row(5)) .or(Cell.is_named("P3")));
 
 

With this model, the ability to add new formatting needs was as simple as adding a new visitor that was only concerned with a specific formatting. This allowed for the incremental growth of formatting visitors as the report demanded it.

This is just one example of where using the power of composition and a couple of “seemingly” simple patterns, can yield results that are extremely extensible results. IMHO the Command and Visitor patterns are 2 of the most powerful and highly underused design patterns a developer has in their toolkit (of course, like with any design pattern, you need to use them wisely).

Comments [2] | | # 
Wednesday, December 10, 2008 3:53:00 PM (Mountain Standard Time, UTC-07:00) ( Inspiration )

 

One of my friends JR made a comment one time that is the message of today’s video: Fail Your Way To Success!!

Comments [2] | | # 
 Tuesday, December 09, 2008
Tuesday, December 09, 2008 11:26:40 PM (Mountain Standard Time, UTC-07:00) ( Inspiration )

A post student emailed me and was sharing with me that he felt that I had inspired him during a bootcamp and he has taken that inspiration and is now using it to inspire others!!! Here is a speech that he gave at DSU that I think is incredible and inspirational!! Dare to do.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

What do Doritos and DSU have in common? Actually, what does Doritos, Nike, and Microsoft have in common with DSU?

Think about it and in a moment I’ll answer it.

In 1999, ~9 years ago, was the first time I sat in the place where you students are sitting now and even in the same building. I remember thinking at the time, that this was going to be an exciting and thrilling journey through life and at the same time thinking…

“What did I just get myself into?”…… “Should I even be here?”

Let me explain a little bit. At that time the dot com boom was just beginning and me being a creative person I wanted to jump right in and skip the “edu-tainment”. I embarrassingly even remember saying to Lynette Molstad in our required freshman orientation/success meetings something along the lines of “Michael Dell and Bill Gates didn’t finish college look at how they turned out.” After that meeting I don’t think I showed up for another freshman success meeting. In the end I did graduate with two BS’s, and three minors in four years.

Yes… I did find time to sleep and I was also quite active in on-campus activities and organizations… primarily with Student Senate, serving both positions of President and Vice President.

I’m not telling this just to gloat. Nor am I telling you that you need to do 2 majors and 3 minors. I’m telling you that if I could find time to be involved and apart of the community that DSU has to offer then you too can find time to do anything. Time should not be an excuse to get not involved as there are many opportunities that a student can have at DSU that might not be found on any other campus. Dr. Kevin Streff once told me, you make time to do the things you need/want to do. And that is true whether you are a student, faculty or donor. Whether it is making time to study, exercise, be apart of an organization, start a business, or making time to spend with your spouse, son, daughter, mom, or dad.

Time gives you the ability to take advantage of opportunities. One type of opportunity is the obvious “Be Involved” which include:

* Being apart of and take lead of an on campus organization, like Student Senate, SIFE by the way congrats to SIFE’s 2nd regional win, PBL, SDEA, and many others that President Knowlton could rattle off.

However there are little known opportunities. And they may need a little more light shed on them.

* Create a project/open source project that could be used by others and depending on the project could even be used by DSU? My self and 2 others created such a project called Online Academic Course Information System, aka OACIS. Which Basically a WebCT / BlackBoard web application and was used by DSU until the Board of Regents mandated WebCT.

* Did you know you could get a paper/project published in an academic publication? The previously mentioned project OACIS was also submitted as a professional paper and was approved by ISECON, an education conference. We even were able to go with Tom Farrell and Dr. Wayne Pauli to San Antonio, TX to present it. Which was quite a memorable experience on the river walk!

* Write a children’s book for disaster preparedness like 18 year old Hannah Watkins in AK.

* Start a fund to give girls in Tanzanian a chance that many of us take for granted like 22 year old Ashley Shulyer.

These are just some of the opportunities available and what I want all students, faculty, and donors to take out of tonight is that you could just sit, like a bump on a log, and have your years pass you by. OR you could take action and do something. And by doing something I’m not just saying do something with only DSU in mind. Even though Knowlton would like that.

Companies, organizations, and I are daring everyone, students, faculty, and donors, to do something. Unfortunately I believe these sayings, tag lines, or mottos are falling on deaf ears.

Doritos is telling you to “do something”. Nike says “just do it”. Microsoft says “change the world or go home”. And DSU is telling you to __________ “dare to do”.

Now, think for a moment about these tag lines and what they mean and are telling you.

“do something”, “just do it”, “change the world, or go home”, “dare to do”

These lines are blunt and profound yet the majority of people do not act on what they are saying. Dale Carnegie once said “Take a chance! All life is a chance. The man who goes farthest is generally the one who is willing to do and dare.”

Many people do not dare to do and become creatures of the common place, the play-it-safers. This is due to several things. Two of which are, not knowing what to do and fear.

Not knowing what to do is usually attributed to not having a path or direction. What I call passion. People falling into this category are usually associated with the feeling of being lost or constantly bored… do you feel that way… the usual answer for this is to find a hobby.

While finding a hobby does work, it doesn’t always or may only work temporarily. I know I’ve fallen into this trap. The reason why is at the time it might sound good but what they have found isn’t congruent with who they are. The less congruence, the less passion and drive you have for what you are trying to do. That is why it is usually best to go back to the basics. The basics of who you are and what is important to you. These are your core values and are usually long lasting and rarely change. Some may know their values, others may not. I didn’t start finding my core values until attending DSU, although I wish I would have started finding mine sooner.

If you don’t know what your core values are, ask yourself the following three questions to help you get started.

* What do you hold most dear? Friends, Family, Technology, Teaching

* What are you willing to fight for? Money, Politics, a new idea, your Community

* What 5 values are most important to you? Values, such as but definitely not limited too, Achievement, Adventure, Affluence, Challenge, Community, Enjoyment, Family, Friendship, Humor, Knowledge, Love, Spirituality, Trustworthiness.

Think about it when you return home and write it down.

If you still don’t know how to answer or your answers feel vague, then you need to step out and leave your comfort zone. Take a risk. Dare to do. Soren Kierkegaard said “To dare is to lose one's footing momentarily. Not to dare is to lose oneself.” Let me repeat that last part. “Not to dare is to lose oneself”. In other words, by daring you find yourself and your core values; your passion; your meaning to life.

Tony Dean, a well regarded conservationist, sportsman, brother, father and friend of the family passed away recently. It was definitely not his time and was completely unexpected. He had a complication with his appendix surgery and was flown to Sioux Falls. Almost at two weeks the doctors told him and his family there was nothing else they could do for him and it would probably be best if he was in a comfortable place. Tony said “good then I can shoot geese off my deck.” Which is completely Tony. His wife Dar and family then took him back home so he could see the water and the ducks. One of Tony’s last words were “You know, I’m not afraid.”

[PAUSE]

Mary Kay Ash once said “Most people live and die with their music still unplayed. They never dare to try.”

Knowing Tony for the last 14 years, I know why he wasn’t afraid. He was true to his core values even up to the end. He stood up and took risks even at considerable risk financially and politically. He played his music. He dared to do.

Will you dare to do… or will your music go unplayed?

Comments [3] | | # 
 Monday, December 08, 2008
Monday, December 08, 2008 12:27:31 PM (Mountain Standard Time, UTC-07:00) ( Inspiration )

This is one that you will have to set some good quiet time aside to watch!! The amazing "Really Achieving Your Childhood Dreams" by the late Randy Pausch.

Are you a Tigger or an Eeyore?

http://www.youtube.com/watch?v=ji5_MqicxSo

Comments [0] | | # 
 Friday, December 05, 2008
Friday, December 05, 2008 6:05:00 PM (Mountain Standard Time, UTC-07:00) ( Inspiration )

If you’ve never failed you’ve never lived!!

Thanks to Zak for sending me the link to this one!!

I have also setup a tumblr weblog (thanks Craig for suggesting this) that will contain the video posts only.

Comments [0] | | # 
 Thursday, December 04, 2008
Thursday, December 04, 2008 11:35:00 PM (Mountain Standard Time, UTC-07:00) ( Inspiration )

I am sure that sooner or later I am going to get back to posting about technical stuff!! In the meantime I am going to start posting a link a day to either a video/article that will hopefully challenge your attitude toward life (and in turn work).

If you have any articles/videos you think I may be interested in sharing, please feel free to contact me at jp@jpboodhoo.com .

Today I will share with you a video that has a great message (that I took from it):

"Imagine what would happen if each one of us displayed this kind of passion......everyday"

http://www.youtube.com/watch?v=MDLK6Ds88Ok&feature=related

Comments [1] | | #