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.