Kicking off StructureMap 3
Actually, I started working hard on StructureMap 3.0 in the summer of 2010 but got badly derailed by other projects and a nasty bout of burnout. I’m writing this post because I would dearly love to get community input and contributions and I’ve got folks contacting me that are chomping at the bit to start working on this.
StructureMap was originally written in the summer of 2003 and revamped in the spring of 2004 for its very first release in June of that year. Over the years it has had some significant rework (the 2.5 and 2.6 releases were both large changes), but at this point I firmly believe that the current 2.6.* internal structure is not worth improving. Yes Virginia, I am opting to gut some of the internals of StructureMap in order to fix the most egregious problems and limitations of the current architecture and build a container that is good enough to last until we all give up on this silly .Net thing. I’d also like to tear out any feature that I think is obsolete or just plain ugly to use and make StructureMap much leaner.
Nothing here is set in stone and feedback is very welcome.
My thoughts for 3.0:
My personal drivers for doing StructureMap3 are mostly to kill the nested container problems and get StructureMap ready to better handle multi-tenancy scenarios in a high volume FubuMVC application. I think that better Profile’s and/or the child container feature below would make multi-tenancy easier to achieve without killing the server’s memory usage. Well, and I would like to make StructureMap easier to use for other people Making StructureMap the most used container in .Net or competing with the other hundred container tools to do every possible crazy scenario that folks can come up with is not on my agenda.
- Remove the [Obsolete] methods
- Better exception messages. The error messages and the stacktraces really took a step backwards when I replaced the old Reflection.Emit code with dynamically generated Expression’s in the 2.6 release. At a bare minimum, the stacktrace and exception messages need to be much cleaner and more accurately present what has gone wrong.
- Better configuration diagnostics. Completely taking a page out of FubuMVC and Bottles, I would like a StructureMap container to be able to tell you why and how it was configured the way it is. Why did it select this constructure, why is this the default, where did this type come from.
- Configuration model. Today there is the configuration model (PluginGraph) and a runtime model (PipelineGraph and InstanceManager). I would like to eliminate the separate models and make the configuration model much easier to consume by users. From the lessons we learned with FubuMVC, I think the key to making the convention model far better is a very good semantic model that can be easily altered and read by both conventions and explicit configuration. I think this is going to be the biggest change in the internals.
- Far better convention support. See the above feature. Think of policies like “set the value of each constructor argument named ‘connectionString’ to this” or “make any Instance the singleton lifecycle where the concrete class name ends with ‘Cache’.” We can do that kind of thing today with FubuMVC’s BehaviorGraph model. I’d like to do the same with StructureMap.
- Profiles. I think we just flat our redo Profile’s from scratch and completely redesign that functionality from all new requirements.
- Runtime flexibility. I would like to be able to allow users to register policies that could “teach” StructureMap how to resolve a requested type that it doesn’t know anything about. I think we’d convert some of the hard coded rules in current StructureMap to this new pluggable strategy. Think things like “this is a concrete type and I can resolve all of its dependencies, so I’ll just do it” or “this type closes an open generic type that I do know about” or “the name of this class ends in ‘Settings’ so I’ll use FubuCore’s ISettingsProvider to resolve it”
- Better Lifecycle support. A longtime limitation in StructureMap is that lifecycle can only be configured by the requested type, i.e., all instances of ISomething have to be the same lifecycle. I’d like to eliminate that limitation.
- Better support for modular configuration. We already have the Registry model and I think it has worked out very well. Most of the other IoC containers have implemented something similar by this point. I’d like to extend the model to allow you to specify ordering rules between Registry classes and dependencies (hence, FubuCore’s dependency analysis functionality). I would also like to add semantics to only add configuration if it is missing or conditional configuration.
- Pluggable strategies for selecting constructor functions. I don’t care for this one bit, but at least a couple prominent .Net OSS frameworks need this.
- Nested containers. I love this feature and its usability. FubuMVC depends very heavily on this feature in StructureMap. Its implementation, however, is horrific and there’s a nasty outstanding bug that I felt was too difficult to fix in 2.6.*. I think we rewrite the nested container feature so that we have proper separation in scoping between the parent and nested container and avoid the need to do any copying/shuffling of the underlying configuration structure.
- Child containers. Not quite the same thing as nested containers. This would be the ability to quickly clone an existing container and override the parent’s configuration.
- Eliminate the Xml configuration. I have already ripped the Xml configuration support out of the core assembly in StructureMap 3. I wouldn’t mind coming back and adding a subset of the existing Xml configuration back as an addon assembly and nuget.
- Eliminate the old attribute configuration. I had left this in there for years, but I’d never recommend to anyone that they use it. I would like to consider just using the convention support to work against a subset of the same CLR attributes that MEF uses.
- Full, living documentation. I rewrote the documentation for the 2.5 release, but it wasn’t usable enough and quickly got out of date when 2.6 was released. For 3.0 I’d like to use Sphinx for the documentation generation and host on http://readthedocs.org/ and make the documentation publish with pushes to Git. Another heavy lesson learned is that the we need to strive to make the documentation organized around the tasks that a user would do instead of organized around StructureMap jargon.
- Recipes. This is where I really need community help the most. I’d like to have some examples of integrating StructureMap into common .Net tools and frameworks. I’m at a disadvantage because I’ve become very disconnected from mainstream .Net. I have not used Entity Framework, WCF, Silverlight, Workflow Foundation, MEF, and barely used WPF, ASP.Net MVC, Prism, or WebForms. I just don’t have enough visibility into those tools to help much.
- Backwards Compatibility. With a few exceptions, I think the registry DSL in StructureMap has settled into something usable. I’d like to remove all the [Obsolete] methods and change a few things that seem to be confusing to use, but otherwise make it as easy as possible to upgrade from 2.6.* to 3.0.
- No Silverlight support. I have no intention of supporting Silverlight or any other mobile variant of .Net at this time. I’m open to this happening later and I’m contemplating at least a version of StructureMap that is usable in the client profile. This is an important decision to make soon-ish because I would like for StructureMap 3 to take a dependency on our FubuCore library and I don’t really want to care about the size of the assembly right now.
- Fubu project portfolio. I would like to fold StructureMap under the Fubu project family. Part of that is branding, but it’s also community, the convenience of the GitHub organization model, and the common infrastructure that’s starting to grow up around documentation, Ripple, and the build support.
- Use FubuCore. There is quite a bit of overlap between the FubuCore library and what’s in the current codebase that I’d like to eliminate. I’d also like to use FubuCore’s dependency graph support, the ObjectConverter, and integrate the SettingsProvider service out of the box for externalized configuration in StructureMap (here’s an explanation of an earlier version that’s still relevant).
Things I don’t plan on changing
- The interception model. By and large I think it’s been good enough for anything I’ve ever needed to do with it
- The basic Registry DSL
- Any of the methods on IContainer
- Still don’t plan on adding AOP, but I’d like to have addon Nuget libraries for integrating existing AOP solutions with StructureMap someday
So why do this at all?
A couple months back I expressed some admiration for where one of the other IoC containers was going and that I was perfectly willing to forgo trying to compete with that particular tool (don’t even ask which one because I took a harder look at it and changed my mind). He asked me why I didn’t just contribute the stuff I needed from StructureMap that was missing in that other container. Fair question, but no, I’m not going to do that. Why? Because one of the best learning experiences you can possibly have as a developer is to take a hard problem that you’ve already solved and reflect on how you could solve that same problem in a much better way with all the things you’ve learned. I’ve worked on and off on StructureMap for 8-9 years. I’ve rewritten some of the same subsystems in StructureMap a couple different times and even got a conference talk out of my experience called The Joys and Pains of a Long Lived Codebase at QCon – but I still think I will learn a great deal by going through with one last version of StructureMap.