Streamlining FubuMVC Bootstrapping & the Design Patterns Used

As I said in my last post, we’re rebooting FubuMVC as a new project called Jasper. As an intermediate step, I’m working up a FubuMVC 3.0 release that among other things, simplifies the application configuration and bootstrapping so that it’s quicker and easier to stand up a brand new FubuMVC web or service bus application.

At it’s very, very simplest for the classic Hello World exercise, the newly streamlined bootstrapping looks like this (when we rebrand as Jasper, just replace “Fubu” with “Jasper” in the class names below):

    // This little endpoint class handles
    // the root url of the application
    public class HomeEndpoint
    {
        public string Index()
        {
            return "Hello, World";
        }
    }

    [TestFixture]
    public class RunHelloWorld
    {
        [Test]
        public void start_and_run()
        {
            // Bootstrap a basic FubuMVC applications
            // with just the default policies and services
            using (var runtime = FubuRuntime.Basic())
            {
                // Execute the home route and verify
                // the response
                runtime.Scenario(_ =>
                {
                    _.Get.Url("/");

                    _.StatusCodeShouldBeOk();
                    _.ContentShouldBe("Hello, World");
                });
            }
        }
    }

Of course, as we all know, real world development gets a lot hairier than cute little hello world examples and you’re not going to get away with the framework defaults in most cases. In the case of FubuMVC, you might want to add services to the application IoC container, change or add conventions and policies, configure features, turn on “opt in” features, or run an application in either the special “development” or “testing” mode.

Real World Configuration in FubuMVC 3.0

After all the dust settled, a FubuMVC application is completely described, configured, bootstrapped, and cleanly deactivated by just two classes:

  1. FubuRegistry is used to express all of the configurable elements of a FubuMVC application
  2. FubuRuntime holds all the runtime elements of a running FubuMVC application like the application container, the activation logs, the routing table, the root file path, the application mode (development/testing/normal) and “knows” how to cleanly shut down the running application.

A custom FubuRegistry might look something like this one:

    public class ExampleRegistry : FubuRegistry
    {
        public ExampleRegistry()
        {
            // Turn on some opt in features
            Features.Localization.Enable(true);
            Features.Diagnostics.Enable(TraceLevel.Production);

            // Change the application mode if you want
            Mode = "development";

            // Have the application use an embedded 
            // Katana host at port 5501
            HostWith<Katana>(5501);

            // Register services with the IoC container
            // using a superset of StructureMap's
            // Registry DSL
            Services.AddService<IActivator, MyActivator>();
        
            // For testing purposes, you may want 
            // to bootstrap the application from an external
            // testing library, in which case, you'd want
            // to override where FubuMVC looks for static
            // asset files like JS or CSS files
            UseParallelDirectory("MyApp");
            // or
            RootPath = "some other path";
        }
    }

To bootstrap the application specified by ExampleRegistry, you can use this syntax below to create a new FubuRuntime object:

            using (var server = FubuRuntime.For<ExampleRegistry>())
            {
                // do stuff with the application
                // or wait for some kind of signal
                // that you should shut it off
            }

If you don’t want to bother with your own subclass of FubuRegistry, you can forgo it and bootstrap a FubuRuntime with syntax like this:

            var runtime = FubuRuntime.Basic(_ =>
            {
                _.Features.Diagnostics.Enable(TraceLevel.Verbose);

                // I'm opting for NOWIN hosting this time
                // and letting FubuMVC try to pick an open
                // port starting from 5500
                _.HostWith<NOWIN>();
            });


There is a FubuRegistry involved in the code above, but you’re configuring it inside the lambda expression argument. More on that below in the section on the design patterns.

Bootstrapping Use Cases and When You Want Your Own FubuRegistry

Just for some background, here are the various use cases for bootstrapping a FubuMVC web or service bus application that I could think of:

  1. Bootstrapping for ASP.Net hosting in the good ol’ Global.asax like this.
  2. Spinning up an application adhoc inside of tests like this example from FubuMVC 2.2.
  3. We have a tool we call Serenity (yes, it’s named for what you think it is) that we use to setup integration tests for FubuMVC with Storyteller.
  4. Running an application with our fubu run development server
  5. Hosting a FubuMVC application within a background service using our JasperService tool (was BottleServiceRunner) that’s just a small shim to TopShelf

The easiest way to use Serenity is to say “here, use this FubuRegistry,” while options #4 and #5 use type scanning to find either the one single FubuRegistry in your code or to use one by name to activate the hosted application. In these cases, it’s highly useful to have a custom FubuRegistry. Even without that, it’s also valuable to have your application configuration done in a way that’s easily reusable within automated tests as in use case #2 up above so that you’re tests are more reflective of how the actual application runs.

 

An aside on the design patterns I’ve used

Other people certainly have much more negative opinions, but I feel like learning, studying, and applying design patterns in code has been very useful to my career. At Oredev 2010 I gave a talk about Internal DSL’s in C# whose content is still very much relevant to the work I did the past month with FubuMVC’s bootstrapping.

The FubuMVC bootstrapping uses at least three different design patterns you can find described in Martin Fowler’s DSL book.

  1. Fluent Interface — method chaining to create an internal DSL directly in C# “if you squint hard enough”
  2. Object Scoping. The FubuRegistry (or StructureMap’s Registry) are examples of using “object scoping” to shorten the signatures of fluent interfaces to a base class. Most of your declarations are going to be in a custom fluent interface called in the constructor function of a FubuRegistry base class.
  3. Nested Closure — The usage of FubuRuntime.Basic(x => {}) where you use an action that configures some option type as the single argument to a function. Nested closures are helpful where you need to allow a user to specify any number of optional parameters as the input to a discrete action. I discussed nested closures ages ago in an MSDN article.

I also remember going to a lot of talks at that Oredev on the new flashy HTML 5 technologies that have been long since passed by. The obvious takeaway is that conceptual knowledge tends to outlast the usefulness of knowledge about specific technologies.

 

Just for Comparison, FubuMVC before 3.0

When I was asked by some of our technical leadership to simplify the bootstrapping for FubuMVC 3.0, my first reaction was “it’s not that bad” — but this was what FubuMVC had previously:

  • FubuRegistry & FubuRuntime were just a little smaller than they are today
  • You used a static property called FubuMvcPackageFacility.PhysicalRootPath to change the root directory of the content files. And yes, the mutable static property was a problem.
  • FubuApplication was a static class that you used to trigger a fluent interface that would gather up your FubuRegistry and allow you to choose an IoC adapter or use a pre-built IoC container in order to create a new FubuRuntime
  • IApplicationSource was a reusable recipe for how to bootstrap a FubuRuntime that we previously used for fubu run or our older TopShelf service host.
  • EmbeddedFubuMvcServer was a class we used to stand up a FubuMVC application hosted with Katana for testing or just embedding a web server for diagnostics in service bus applications running as a background service. Of course, that all got duplicated when we added NOWIN support and it duplicated some functionality from FubuRuntime anyway.
  • FubuMode was a static class we used to detect and tell you whether the application should run normally or in “development” or “testing” mode. Statics are evil you say? Yeah well keep reading…
  • PackageRegistry was a static class from our now defunct Bottles library that exposed information about the loaded extension assemblies in the application and the diagnostic logging from application bootstrapping.

As of now, we’ve completely eliminated all of the static classes and properties. All of the configuration is done through FubuRegistry, and all of the runtime information about a FubuMVC application is exposed off of FubuRuntime. So yeah, it’s quite a bit better now. It’s good to pay attention to the feedback of others because they see things you don’t or problems you just get too comfortable working around.

 

 

Advertisements

3 thoughts on “Streamlining FubuMVC Bootstrapping & the Design Patterns Used

  1. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1928

  2. Pingback: Testing HTTP Handlers with No Web Server in Sight | The Shade Tree Developer

  3. Pingback: Automated Testing of Message Based Systems | The Shade Tree Developer

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s