MonoRail+++

September 13th, 2010

It’s been more than six years since the first prototype of MonoRail appeared on Castle’s SVN repository. By then our website was hosted in a linux machine, the web server was Webrick, running a beta version of Rails, and had to be restarted once per day (at least) due to memory leaks. WebForms was the winner in the .net space, Struts the winner in the java space (unbelievable!), cocoon committers were toying with the idea of implementing continuations, probably inspired by Seaside.

Back then I was fresh back from London (now you know where Windsor’s name came from), jobless, and entertaining with the idea of setting up a small software shop with Carlos and Rodrigo. One of the first challenges was to pick the technology to invest and potentially create a small product. Rodrigo was obviously biased towards .net with boo. I was playing with Ruby/Nitro. Carlos was inclined towards webforms with c#. We decided to pick one each, build somewhat similar and compare/contrast. AFAIK Rodrigo picked up some Java tech, Carlos chose boo, and I went with Rails.

I fell in love with Rails and became a strong advocate. However, as “our product” grew in complexity, Rails – by then – didn’t catch up. Big refactorings were hard due to the dynamic nature of Ruby, lack of unicode was a red flag for i18n, leaks and bad performance (couldn’t get fastcgi to work on apache!). Also, the ecosystem, the libraries for dynamic image generation were badly maintained, if ever…

That’s when I decided to combine the philosophy of Rails with the solid foundation of .net. By then it was called Castle on Rails.

Things have changed since then. MonoRail seems to have greatly inspired Microsoft’s take on Model-View-Controller for the web. Mongrel, Merb and REST ascendance, a ton of great ideas continue to appear in the Ruby community. Same in a slower pace for other communities.

 

Web apps then and now

While there was dynamicity in web apps six years ago, my perception is that today they have an aspect of multi-faceted apps. Html is just one of the multiple supported outputs of resource-based web sites. They expose services that can be used by your mother or another service. Twitter and Facebook are the greatest examples.

Bringing that to our work and especially the MS platform is somewhat puzzling. Who wants to maintain two entry points? Why a web app and a WCF Soap/Rest interface? Why it’s so unnatural to deal with syndication on web apps?

 

The reuse dilemma

Reuse has always been an OOP challenge. Many programming practices support designs that yield subsystems (size/complexity can vary) that can be reused. Not too many programmers embrace those programming practices, though.

As the complexity of web applications grow we see subteams owing subsystem with the same web application. Their technological choices are restricted by the common denominator. There ought to be a solution for this.

 

MonoRail 3.0

This and other interesting discussions are taking place with the Castle team. I try hard to influence them over the big picture – it’s easy to get distract by what seems to be cool and interesting but deliver no value. In the last two months I drafted and propose a new enhanced design that should deal with the common challenges of web apps of today – and hopefully of tomorrow! Today I completed a working prototype.

 

Minimal core

The core is based on MicroKernel pattern. It’s a truly example of Open-Closed principle. It works by orchestrating a minimal set of extension points. Those are called primitives as they represent core abstract concepts.

The core is split into three architecture layers:

Layer 1: ASP.NET core augmentation

The layer 1 replaces the HttpHandler and HttpModule in ASP.NET with composable equivalents. You can then implement a new “handler” that has “dependencies”, and be sure that those will be satisfied.

Layer 2: Orchestrator

Layer 2 defines a minimal set of primitives and pipeline execution process. It establishes the minimal policy (behavior) but does not make assumptions over the implementation – remember the Dependency Inversion Principle?

Layer 3: Model-View-Controller

Finally, the third layer is an implementation of layer 2 that exposes the common behavior of Model-View-Controller we all know and love. It also exposes extension points, such as an execution sink for controller execution.

 

Side-by-side extensions

Windsor turned out to be successful because it delivered a rich extensibility mechanism and a minimal but useful combination of default behaviors. MonoRail 3 is built with the same principles. In fact, its Model-View-Controller capabilities are just one implementation over a set of “primitive” contracts. Behavior can be modified, added or removed by using a small set of extension points.

The design supports side-by-side extensions, which means that extensions do not replace one-another, but instead are always additive. For example, I can have a WindsorIntegration and AutofacIntegration running at the same time. I can add to the mix Razor View Engine and IronRuby support. Not a single line of configuration code or xml.

 

Composition by default, even in your code

Yes, you can turn off or replace it, but by default your app will have an IoC Container (well, MEF) composing your controllers. The composition is not limited to your types, in fact, you can express dependencies over framework components and request level objects.

Maximized simplicity

The following is a valid controller:

public class ProductsController
{
    public ActionResult Index()
    {
        var products = // fetch list
        return new ViewResult() { Model = products };
    }

    [RespondTo(ContentType.Html|ContentType.Xml|ContentType.JSon)]
    public Product View(int id)
    {
        var product = // fetch by id
        
        if (product == null)
            throw new HttpException(404, "product not found");
            
        return product;
    }
    
    public Product New()
    {
        return new Product();
    }

    public ActionResult Create(Product product)
    {
        // pretend to save
        var product = new Product();
        
        return RespondTo( format => 
            format.Model(product).
              Html().
              Xml( new ViewResult("create.xml") ).
              Json()
        );
    }
    
}

If access to some response, request (or similar) objects are necessary, no worry, you have two options: use the Controller base class or specify the dependencies in your constructor.

Powered by MEF

One of my goals is to demonstrate how MEF can be used to enhance your frameworks, instead of just your applications. By using MEF I could easily skip any “registration” step usually required by typical IoC Containers. I can also discover extensions easily in runtime without extra code.


Where/When?

I’m planning to release a first drop later this week. Note I’m kinda extra busy as I’m getting married next weekend, but watch out for a preview drop.

The curse of knowledge

May 31st, 2010

While reading Made to Stick I had to stop to appreciate the epiphany of this realization: The curse of knowledge is so real and concrete. I find myself having real trouble explaining things that are obvious to me. Teaching the benefits of good design, IoC Containers, Composition vs Inheritance and what is common about enterprise kinda of development as opposed to other types are just extremely challenging.

People tend to think that having a great idea is enough, and they think the communication part will come naturally. We are in deep denial about the difficulty of getting a thought out of our own heads and into the heads of others. It’s just not true that, “If you think it, it will stick.”

And that brings us to the villain of our book: The Curse of Knowledge. Lots of research in economics and psychology shows that when we know something, it becomes hard for us to imagine not knowing it. As a result, we become lousy communicators. Think of a lawyer who can’t give you a straight, comprehensible answer to a legal question. His vast knowledge and experience renders him unable to fathom how little you know. So when he talks to you, he talks in abstractions that you can’t follow. And we’re all like the lawyer in our own domain of expertise.

Categories: General | Top Of Page | No Comments » |

Alive and well

May 6th, 2010

Wow, I thought I need to post something on this blog before the PHP code that runs it gets stale.

Still alive, still working for Microsoft, but a few months ago our MEF team was merged into the Common Language Runtime (CLR) team. The CLR teams owns all the low level stuff: execution engine, JIT, GC, and some not so low level things like the Base class library (BCL) and security model. So if you have any complains on any of these things let me know and I’ll ensure you I’ll forward to the appropriate person and make sure I get a reply :-)

While I’m still working on MEF I also managed to get involved in some new CLR stuff for the upcoming version. Early days, so nothing to talk about yet.

MEF updates

I’m working with ASP.NET MVC team to have MEF integrated with the next MVC version. There are a lot of constraints that won’t allow us to optimize a lot of the experience, but things should change soon.

I’ve managed to put together a sample depicting MEF integration with WebForms. I’ve used ControlBuilders to change the generated code to use MEF’s container to instantiate controls. Let me know how you like the approach. We’re considering productizing it, but we need to measure the interest level first. Would that be useful to you?

Finally, among other things we’ve been exploring, componentizing our container implementation is one of my goals. Simplifying some common tasks and APIs is another. For those who are not really fond of MEF’s attributes I’ve prototyped a convention-based registration API. Will blog about it soon.

Castle updates

So the Castle community really impressed me. They released a bunch of stuff and are managing to introduce loads of cool features.

Other stuff

iPad: being an owner of an iPhone and MacBook Pro I see absolute no reason to have an iPad. My standard reply when the subject comes up is ‘I have an iPhone, which is the compact version of the iPad’. Sorry Steve Jobs, you won’t grab my $ for this one.

MS Courier: if you’ve been under a rock for the past year, go and check the Courier. It was canceled a few weeks back by MS. There was a short interview available to us on why this happened, but it wasn’t very convincing. I just truly hope they come up with something even better, and real soon.

Windows Phone 7: on the other hand, everybody here is excited about the new phone. Some (lucky!) few ones are already playing with prototypes. Did we get it right this time? Time will tell.

Categories: General | Top Of Page | 3 Comments » |

MEF and ASP.NET MVC sample

April 23rd, 2009

Just blogged it on the other blog.

Categories: MEF, MS | Top Of Page | No Comments » |

Progressive .NET Tutorials, May 11-13th, London, UK

February 24th, 2009

Progressive .NET Tutorials 2009

Skills Matter has agreed to co-organisie The Progressive .NET Tutorials with us. This will be a really exciting 3 day long event with 2 tracks featuring half day and full day Tutorials by me, Ayende, David Laribee, Gojko Adzic, Ian Cooper, Mike Hadlow, Scott Belware and Sebastien Lambla. I will be giving two half day tutorials on Tuesday May 12th and Wednesday May 13th. My first tutorial will be on the Castle and second will be on MEF.

For the full programme check http://skillsmatter.com/event/open-source-dot-net/progressive-dot-net-exchange

Special Community Discount

If you book on or before Feb 28th you will pay just £350

Skills Matter has given me a special promotion code that will entitle you to a nice discount off the Tutorial Fees. Simply book on or before Feb 28th, quote SM1368-622459-33L (in the Promo Code field) and pay just £350 (normal price £1000). Offer is only valid until February 28th only, and tickets are going fast, so if you would like to secure a place and claim your discount – get your skates on!

The code to use is: *SM1368-622459-33L* and must be entered in the box provided when booking online at https://skillsmatter.com/register-online/conf/280

Full details of the event can be found at http://skillsmatter.com/event/open-source-dot-net/progressive-dot-net-exchange

See you in May!

Categories: General | Top Of Page | No Comments » |

Farewell to dear friend

February 18th, 2009

I got a sad sad news this morning that a very dear friend had passed away due to a liver disease. He was only 34, recently married and had just moved to his dream house. An awesome C/C++ programmer that taught me many useful (and useless) things and all time funny person.

wenderson.png

Categories: General | Top Of Page | 1 Comment » |

Workshop on Inversion of Control Containers

February 18th, 2009

Next Friday (Feb-27) I’ll be in Seattle doing a workshop on one of my favorite topics: Inversion of Control Containers. Expect some digressions on the story of ioc containers, how they evolved, what problems they solve and what problems they introduce. Also why I think the DI term should be banished – call me a purist. Windsor, MEF and maybe others will be on my radar.

If you want to attend, keep an eye on this page. Currently registrations are closed, but should open in a few days.

I truly hope I dont have a cold next week :-)

MEF: Exporting and importing methods

February 17th, 2009

This is an interesting feature of MEF, usually overseen (maybe because it’s not documented anywhere). You can export methods with a specific shape and import them to delegates:

public class Validation
{
    [Export("validator")]
    public bool ValidateEmail(string value)
    {
        return true;
    }

    [Export("validator")]
    public bool ValidateNonEmpty(string value)
    {
        return true;
    }
}

[Export]
public class FormToValidate
{
    [Import("validator")]
    public IEnumerable<Func<string, bool>> Validators { get; set; }

    public void ValidateName(string username)
    {
        foreach(var validator in Validators)
        {
            if (!validator(username))
            {
                throw new Exception("validation error");
            }
        }
    }
}

Before you ask, yes this feature came from real world scenarios and we have plenty of customers using it. So far, we are constrained by the maximum number of arguments Func/Action supports, but Wes is in the process of fixing that.

Categories: MEF | Top Of Page | 4 Comments » |

Defaulting to Transient parts

February 8th, 2009

David has a nice blog post on having a custom container to default MEF parts to NonShared creation policy. Go MEF team! :-)

Categories: MEF | Top Of Page | 3 Comments » |

MEF and lifetime

January 30th, 2009

It has been interesting three months working on the lifetime story for MEF. Turned out to be bigger and more complex than any one could anticipate. As I walk you through what has been decided and implemented you may find things too trivial, but actually it was huge as key members in our team wanted something way different. Under this light I really considered the MEF/Lifetime a success as we – the feature crew (Wes and Daniel) – were able to demonstrate clearly the impacts of their proposed changes and how our proposal solved key scenarios.

Here is a summary of the top level decisions:

  • We will continue to support singletons and transients (we renamed them to Shared and NonShared)
  • We will continue to support disposable types (even when IDisposable is not part of the public contract of the service)
  • The container will have the ownership of parts it instantiates (we will not transfer ownership to parts)

You can get the bits from CodePlex, Preview 4 has all the lifetime features implemented and documented.

 

CreationPolicy

We now support three creation policies. They can be specified on the part level – using the CompositionOptionsAttribute – or on the import level, using the ImportAttribute. Both sides need to permissible in order to the dependency be satisfied.

  • Shared: former Singleton. A single instance per lifetime domain (ie, container)
  • NonShared: former Factory. Whenever an export is requested, a new instance is created.
  • Any: defines that the part can function as Shared or NonShared, it would be up to the import side to define. If “Any” is specified on both sides, it will default to Shared.

Container and parts references

The CompositionContainer will not hold references to parts it creates, unless for the following cases:

1. The ComposablePart.RequiresDisposal returns true – which for our default programming will be true only when it wraps an object instance that implements IDisposable

2. The part has one or more imports marked with AllowRecomposition=true. In this case, though, we hold conditional references, which means that while there’s an alive export instance the GC won’t collect the part instance.

3. Shared parts

For all other situations, parts are created, exports gathered and we drop the references leaving everything else to the GC.

One thing to note: if have NonShared disposable parts you might incur in memory bloat. There are two ways to avoid that, described below.

 

Disposing the container

Disposing the container will shutdown parts held (possibly disposing them, and disabling recomposition). Lazy exports wont work anymore. As any disposable type, we haven’t engineered the container to be reusable after being disposed.

 

Scoping containers

You can use container hierarchies in order to create scoped lifetime. For example, a web request is a great candidate to be mapped that way. However, as the container depends on Catalogs you will either have to filter the global catalog – the one that the parent container has access to – or handcraft a new catalog. Using the same catalog on the parent and on the child container won’t make much sense IMHO as then you start to have short lived Singletons.. and this doesn’t feel right to me.

Check the Filtering Catalogs for more information on this.

 

Early release of resources

If you don’t want to use container hierarchies, you can also release an object graph. This is a great solution for scoped operations that you control when it starts and ends.

Just use the method ReleaseExport exposed on the CompositionContainer class. It traverses the parts and its imports releases NonShared parts. It stops in Shared parts as we cannot touch them.

 

Lifetime of parts manually added to the container

When you add an object instance directly to the container you do not transfer its ownership to it – at least not now, we’re discussing and reviewing this behavior. However, adding a part manually will cause composition, so new parts may be created to satisfy your object dependencies. Who own them? The container. MEF is smart enough to shutdown them when you remove that object from the container.

 

Ordering

Due to the fact that we support – to some extend – cycled object graphs, we cannot create a 100% deterministic disposal algorithm. Hence, we do not guarantee disposal ordering and urge you to follow a simple guideline:

“Do not use imports on your dispose method.”

That means, do not use the things your part imported on your implementation of the Dispose method. Why? Because as we do not guarantee ordering, they might have been disposed when you try to use them.

 

Conclusion

It’s been a fun ride. Given the fact that we considered removing support for NonShared, transfer ownership of exports to imports and all sorts of options, I’m absolutely positive that we have made the right choices. I’ve learned that there’s no such thing as the perfect design for complex problems. In that case you have to strive for the right trade-offs and make sure you provide solutions for the key scenarios.

Categories: MEF, MS | Top Of Page | 1 Comment » |