A Vision for FubuMVC’s Component Model (gems, Nu, engines, slices, oh my…)

I’m banging this out fast and trying to think out loud.  Blame the lack of polish on that previous statement.  The whole point of this blog post is to elicit feedback and get ready for Pablo’s Fiesta this weekend (no crazy tax evader can stop the ALT.NET community by merely crashing a plane into the building).

Pablo’s Fiesta starts tomorrow night with the typical Open Spaces agenda creation.  Coincidentally, we’ve got several FubuMVC contributors coming into town and we’re going to take advantage of that to carry out some FubuMVC project business.  My main concern for the conference is to nail down our component story for FubuMVC.  First off, I want FubuMVC to have a fullblown “engine” or “slice” strategy that allows you to build and reuse vertical slices of an application across projects.  Secondly, we need an easy way to apply those “engines” to other places.  For those of you familiar with Rails and Merb, I’m wanting nothing less than a “gems” like solution for FubuMVC that allows a project team to quickly assemble project infrastructure and share substantial parts of an application architecture with as little friction as possible.  Right now, my focus is on the resurrected Nu project as a way to distribute and apply engines to your code tree packaged up as “Nug’s” (the Nu analogue to a gem).

 

To really make the usage and distribution of FubuMVC “engines” go well, I think we need to do be able to package / discover / distribute the following:

  • Libraries.  One of the things I hear from people is that they just think it’s too hard to piece together OSS tools (it doesn’t matter if you disagree with that statement, because many people *do* feel that way).  The very first step is to finally get a decent .Net OSS story around distributing components.  I want something like “gems install fluent-nhibernate” that puts the latest released version of Fluent NHibernate into my “tools” directory, and oh yeah, also gets the correct NHibernate binaries with all the little Castle and LinFu pieces that live underneath NHibernate in one go.  This is obviously pretty complicated when you think about versioning and dependency trees, but it’s also been done in other development communities and we can take a lot of inspiration from things like gems, Maven, etc.
    • We’ll have to effectively agree upon a standard folder layout for external tools so that Nu can scan
    • I’m fully aware of HornGet, but I do not see it as the right approach to this problem. 
  • Extensible Command Line tools.  We have several command line utilities at Dovetail for our localization subsystem (exporting/importing data, filling in missing localization keys, etc.) that could easily be useful on other projects.  Other folks are keen on building “scaffolding” approaches into Fubu   Nu is built around extensible command line tools and I think it could be a powerful way to distribute little project utilities as part of an engine/Nug package.
  • Project Files.  I think it’d be nice if when I installed the (not yet existent) “NHibernate QuickKit” engine with Nu and Nu could reach into my *.csproj files and add the right references for me in order to use the NHibernate features.  That’s a big can of worms, but I think it could reduce friction in using a lot of tools – especially tools that come with lots of assemblies (I’m looking at you nServiceBus).
  • Configuration.  Your engine could easily require some external configuration.  I know one of the first engines I’d like to see is a NHibernate starter kit that would give you a basic NHibernate setup and a simplistic Repository implementation – and NHibernate just doesn’t go without a connection string somewhere.  My thought is to standardize FubuMVC on the AppSettingsProvider model that Josh blogged about here
    • When a Nug is installed, maybe it could scan the new imported assemblies and find any new “Settings” classes needed for the new engine.  We could have it add the new properties to the appSettings file automatically with any default values.  I think this could help to make things like NHibernate integration easier
    • The standardized configuration model for things like file paths, Url’s, and connection strings would make it easier to share deployment recipes and infrastructure for staging code through different environments (dev to test to UAT to production).
  • Services.  A slice/engine may easily need to expose other services to the underlying IoC engine.  Fubu can only function with an IoC container.   It’s been a very important goal to me to ensure that Fubu is IoC tool agnostic (it’s not there yet, too many assumptions about StructureMap runtime characteristics that aren’t necessarily true of the other tools.  We’ll get there) and that Fubu makes no restrictions on *how* you can use your IoC tool (many of the “abstract away the IoC tool” strategies do an awful job on this score).  You already have some limited ability to register services in FubuRegistry.  The FubuRegistry.Include( other registry ) doesn’t merge the service registry yet, but will at some point.
  • Conventions.  Html conventions, behavior policies, Url/Route conventions, View conventions, you name it, all of it is reusable in FubuMVC.  I think it’d be nice to say “I wanna use the ‘DataAnnotations’ pack” and just like that, you get Html conventions applied to your project that read metadata off of the DataAnnotation attributes and apply that towards client side jQuery validation.  Today this is done with code in a FubuRegistry class to explicitly add conventions.
  • JavaScript libraries.  Look, it’s a rich internet world now and you almost have to use Ajax to create a compelling user experience.  There’s the whole jQuery ecosystem with more useful plugins than you can shake a fist at.  However, a lot of these plugins (jqGrid comes to mind) require some server side integration to really shine.  What if your “Nug’s” could contain both server side functions and custom JavaScript libraries?  When you download a Nug, any Javascript libraries will be pushed to where the main Fubu app can find those libraries. 
    • We have to determine a standard location for the JavaScript files
    • We need some sort of script manager piece in FubuMVC.UI that can load them
    • Maybe we minify them on demand?
    • I think it would be nice if custom Html Helper from external engines could quietly declare behind the scenes that “I need this JS / CSS file” and a <script> tag is added to the page if it isn’t already there
  • Packaged Views.  It would be nice is some engines could include packaged views for things like admin screens.  You can do this out of the box by using some sort of embedded views, but it’d probably be nice if we had a good way for an engine installation to copy the view files to a known location where you could modify or skin those views at will (in this case, the reusable view from the engine is mostly just a template).
  • Warmup / Deployment tools.  I’ve always admired things like Capistrano in the Ruby world.  If we standardized the FubuMVC code structure, maybe we could reuse project setup, automated build tooling, and deployment recipes across projects the way that Rails developers do.  Wouldn’t that be awesome.

 

Another architectural issue is how the externalized engines are discovered by FubuMVC.  Right now, you have to explicitly add things to a FubuRegistry class.  I think we also need to consider some sort of dynamic discovery of the external addin’s.  It could just be a known folder that we scan at application startup, a partial class in your top level web project that could be auto-generated, an Xml/Json file listing the class names of FubuRegistry types to load as engines or something else I haven’t considered yet.  I’m leaning towards the scanning model, but I’m all ears.

 

The core architectural philosophy of FubuMVC is composition.  It’s completely wrapped around IoC service composition, the code basically follows the S.O.L.I.D. ideas for object responsibilities so there’s a lot of seams, and everything is swappable (think “sharp tools”).  Conventions can be packaged up and reused across projects.  Vertical slices of the application can be packaged and reused across applications by the FubuRegistry concept.  The thought right now is to keep a pretty spare core MVC infrastructure in the core assemblies and add additional UI magic in external assemblies that can be optionally added into your project.  The Html conventions feature was already developed in this way.  In the next 3-4 months I know where adding new facilities for localization, validation, and some more Html conventions on top of those things – but none of it will come out of the box.  The “tinker toy” approach gives us a huge advantage in being able to adapt FubuMVC for totally new scenarios and reuse code and avoid the original Rails problem of “use my opinions or go home,” but…

How the bleep is the average team going to be able to assemble all these little pieces and get them to work together without losing all their hair?

 

My personal goal for FubuMVC is to get that question answered – and I’m hoping that Pablo’s Fiesta moves the conversation.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in FubuMVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/members/jmiller/default.aspx Jeremy D. Miller

    @Jon,

    At this point, we have full support for a couple different types of partial requests. We haven’t tackled the output caching yet, but the runtime/config model would allow you to add it in yourself w/o changing any Fubu code if you want to.

    We’ll get to the caching at some point — or we take pull requests.

  • http://www.joncurtis.co.uk Jon Curtis

    Hi Jeremy,

    Really interesting project.

    Does FubuMVC have a mechanism for partial requests?

    (http://blog.stevensanderson.com/2008/10/14/partial-requests-in-aspnet-mvc/)

    If so, does it have a mechanism for output caching that allows partial requests to be “donut” cached (ie the rest of the page cached, but not the partial)?

    What are your thoughts on this?

    Cheers,
    Jon

  • http://realfiction.net Frank Quednau

    Hi Jeremy, here’s my personal trackback.
    I am uncertain about Nu and the things you said about slices…a bit too far in the future for me :) I think the first bit would be to enable an open source project to specify what their library (or exe) is and for consumers to get to those libraries. I’d be willing to move that on and have jotted down a couple of ideas on my site: realfiction.net/go/157. I need feedback if it makes sense…

  • http://www.corebvba.be/blog Tom Janssens

    This sounds like a very good initiative.
    In order to resolve the different project structures you could implement an interface for it like this :

    enum ContentType {
    Projectinformation,
    Javascript,
    Views,
    Files,

    }

    interface IContentResolver {
    ContentType ContentType {get;}
    IDictionary Content {get;}
    }

    interface IServiceDiscovery {
    Assembly[] Dependencies {get;}
    IContentResolver[] ContentResolvers {get;}
    IRegistration[] Registrations {get;}

    }

    If a project uses default conventions, you could just use a default ServiceDiscovery.DLL .
    If a project does not use default conventions, one would need to write a custom ServiceDiscovery.DLL and put it in the root of the downloaded zip…
    This would also mean you could create for example a DoveTail specific implementation which follows you project conventions…

    I have not really thought this over, but IMO it looks acceptable.

    I would also be willing to invest some time in this project if it gets launched…

    Tom

  • http://tobinharris.com/blog Tobin Harris

    I agree with all of this. The Ruby community makes reuse a snap (which is why Ruby is my preferred platform these days).

    I’d love to see .NET benefit from the capabilities you’re suggesting. In fact, I was farting about with this, and managed to set up a local gem server that hosted a single NHibernate gem http://tobinharris.com/past/2010/2/1/net-gem-fun/.

    T

  • http://www.codinginstinct.com Torkel

    I have always thought that something like Gems would be increadibly good for .NET development. Let us know how you proceed with this, I would be interested in helping.

  • Mihai Lazăr

    It would be great to be able to package components in fubu and then just redistribute them.

    The way Grails does it ( or did it ) was something like this.
    – You have some conventions about how the project is structured ( in fubu thats defined by the conventsion )
    - When you finished an app you can very well call it a component and have it redistributed.

    It would be nice to be able to take something compiled just drop it in the right place and have it working in the way ASP.NET web sites let you drop a couple of dll’s in the bin folder and the .aspx page will automatically have access to that.

    What’s left is .. what do you do abut the views ( webforms, spark ) ? How can these be managed in a way that allows the user to set up his app.. build what needs to be built and insert it into Fubu withouth stepping into someone else’s code/convention/structure.

    This will be an interesting ride..

  • http://developernotes.com Nick Parker

    Jeremy,

    I’m glad there is a renewed interest in the nu project as well, when Laribee, Dru, Chris and myself initially worked on this project several years ago it silently fell to the way side due to everyone being busy with life. I like a lot of your ideas, for me, if initially I could replicate what bundler (http://github.com/carlhuda/bundler) does for .NET I would be happy. Maybe we can get you to contribute? :-)

  • http://jeffperrin.com Jeff Perrin

    I’d just like to say good luck (not sarcastically). There’s multiple *large* issues to tackle.

    - First, a gem-like system requires a whole bunch of stuff to get working, including agreeing on how to package an app/lib, where to host it, how to do dependencies, etc.

    - Second, a bunch of the stuff you’re talking about doing *really* requires a stable, opinionated platform to work well IMHO. It’s hard to do stuff like Packaged Views without a definitive place to put them (obviously).

    - Third, copy Rails3 wherever possible. They have the advantage of having gone through multiple iterations on all this stuff. Plugins/engines/gem dependencies are all different now than their original forms (in a good way). Look at Bundler.

    My advice would be to forget about all this stuff until you have a framework in FubuMVC that is actually somewhat polished through real-world use (other than your own) before worrying about how to fix the other problems. The main reason why this all works so well in Rails & Django is that the web frameworks are there to build upon.

  • http://thesoftwaresimpleton.blogspot.com/ Paul Cowan

    Hi,

    As the “hornget guy” or A.K.A. the guy who wrote “Go FUBUMVC yourself”, I honestly wish you luck in your quest for a gem like experience in .NET.

    If there is anything I can pass on or anyway I can help out after my experiences with hornget then please let me know.

    I honestly want somebody to crack this most difficult nut.

    To me, this is the most challenging thing left to make .NET a serious platform. Without this we cannot take ourselves seriously as a platform.

    The lack of a .NET gems is why I wrote my rant against people rehashing existing ideas.

    We need this more than anything and I really want to see this solved.

    Hornget was a valiant attempt but it does not cut it as a long term viable option.

    Too much maintenance involved.

    In all seriousnesss, I hope you make some headway on this.

    Paul