I'm about to start building a new pluggable framework for my new project. I've built several over the years, but I've found that my approach is much different now than it was five years ago. Before I start, I thought that it might be worthwhile to jot down what I think about building a framework.
- If you're a real developer with blood pumping through your veins, building a pluggable, whitebox framework is about the most fun you can possibly have at work. I used to call designing a framework my mad scientist mode. I do think that feeling of creative joy probably explains much of the harmful overdesign being done out there.
- The mechanics of a pluggable framework are easier than ever because you can just grab an IoC/DI tool off the shelf (like StructureMap) to handle the plugin's and configuration. As a matter of fact, I would almost go farther and say that I would almost automatically use an IoC tool for any nontrivial enterprise system.
- Watch out for Architect Hubris. The idea that you can foresee all possible points of divergence ahead of time is flawed. You need to be tailoring your framework to providing value in exactly the way that the business functionality requires. The best way to ensure that your framework fits its actual usage is to grow the framework organically as you develop real functionality. In Ordering Software Construction Tasks, I tried to argue that the strategy of building the architectural framework first, then developing the actual business functionality second can easily be a delayed timebomb. Getting the perfect design upfront can be a boon, and sometimes you'll be right, but on the whole you're going to be better off measuring your design as you go with real world feedback.
- Where do you need to put the extensibility seams? I say let automated testing be your guide. It gets blurred by the word "Test," but Test Driven Development is a design technique. In my experience, the places where it's convenient to put a seam for the sake of writing small, concise, isolated tests are likely to be the exact same places where it's valuable to have an extension point later. I don't design my code upfront for extensibility anymore, but my code is much more extensible. If nothing else, a class structure that is hard to test is a pretty good indicator that extension will be difficult. Extensibility will most reliably follow by focusing hard on keeping class responsibilities cohesive and loosely coupled.
- One of the pieces of advice I try to give out about building frameworks is to put off the configuration mechanism at first. My theory is that it's better to concentrate at first on the classes that do the real work first. I say this for a couple reasons:
- It's easy to get bogged down in designing the configuration strategy first
- Sometimes building the "worker" classes in the middle will give you plenty of insight into how the configuration needs to work. Starting in the middle can help you prevent churn and often lead to a simpler configuration mechanism.
- You definitely want your framework to be decoupled from the configuration. My strong advice is to build an internal model representing the configuration of the framework. I think you have much more flexibility later, and easier testing upfront, if you completely decouple the end functionality of the framework from its configuration. Starting with the configuration first can easily leave you too tightly coupled to the configuration.
- Do hide the smelly, complicated details of your internal model from the consumers of your framework. That was a lesson I learned the hard way from early versions of StructureMap.
- The framework I'm starting on this week has some pretty stringent requirements for ease of configuration. I still think I want to start in the middle with the classes that do the work, but I think that I will tackle the configuration schema or DSL as early as possible. Bellware gave me an idea about more or less letting the tester define the syntax and format of the configuration as part of creating acceptance tests. I'm definitely going to give that some serious thought.
- How do you configure your framework? One easy path is to just use StructureMap or Castle Windsor and use their configuration mechanisms right out of the box. I know in my case that strategy would easily lead to some very verbose Xml descriptions with repetitive data, so another layer of abstraction might be valuable. One of my thoughts for the new Fluent Interface API in StructureMap is that you could use that as a base for creating your own application specific plugin configuration. For my new project I'm thinking about these alternatives (strangely enough, I think StructureMap 2.0 usage is a given):
- A new Fluent Interface API written in C# that sits on top of StructureMap. We're expecting the configuration to change frequently, and the personnel doing the configuration aren't necessarily hard core developers. I think we're already ruling this one out, but I might resuscitate the idea for StoryTeller later.
- Create a terse Xml format specific to the framework that would probably still feed StructureMap to minimize the amount of "builder" code later and provide easier paths to adding extensions. Xml is always a good fallback position, but a proliferation of angle brackets and readability don't always go hand in hand. All the same, you know that's where we'll end up.
- Create a new DSL with BOO scripts or Ruby/RubyCLR. I'll admit that's just the inner geek in me wanting to do that, but it might be a very viable option. I'm not confident about being able to sell that though.
- This is out of left field, but I think it's perfectly viable. Use the FitnesseDotNet engine to parse out HTML tables. Leaning on the DoFixture, you can cheaply build little languages quickly. That also comes with a cool advantage of being ready made for automated testing.
- Create an administrative tool. Blackhole here we come. In a way, I think it's nearly a mark of failure if your framework's configuration is only usable with a GUI designer.
Posted
04-04-2007 8:03 PM
by
Jeremy D. Miller