You are currently browsing the monthly archive for May, 2007.
Platform and language monoculture is a big issue in established software companies today. Perhaps a lack of it is one of the defining factors identifying the new ‘agile’ development outfits that have popped up so far this decade.
The Java and Microsoft ’shops’ are the best examples – companies that are willing, through principles of economy, to put all of their eggs in the one technological basket.
I recently overheard: “we can’t adopt application X because that would require training someone in Java.” Perhaps that is the reason that training is so often only given lip service and is considered to be of little real value? Training in a new facet of a platform you already know doesn’t really take you anywhere new. Significant insights most often come to me when I step back from my own work and see how other people are tackling the same problems.
Familiarity with multiple platforms and tools can give you a lead over the competition. NUnit, CruiseControl.NET and NHibernate have been being used effectively for quite a while now, by the .NET developers who looked over the fence and saw the advantages being enjoyed in Java-land. Microsoft have finally come to the party with Team Foundation Server and Linq to Entities – but now the competitive advantage is gone and a new set of not-so-secret weapons is needed to stay ahead.
The rationale for keeping the set of technologies in use in any one development team small is a sound one, but I think that taking this wisdom without a healthy grain of salt can lead to mediocre systems built using sub-optimal tools.
…what an ‘FBox’ is…
The FBox source code is the implementation behind this article. Why not elaborate a bit more…
The ‘Factory’ patterns (Factory Method, Abstract Factory…) can be really useful. For every class or hierarchy of classes that you’ll be creating from different pieces of code, you define another class (the factory) that is responsible for instantiating and initialising the products. Then, if the creation requirements of the product change, there is only one piece of code that needs to be updated. E.g.:
// The Person class is the product.
class Person
{
public Person(string name) { ... }
}
// PersonFactory has one responsibility - to create People
class PersonFactory
{
public Person Create(string name)
{
return new Person(name);
}
}
// Later...
PersonFactory factory = new PersonFactory();
Person john = factory.Create("John");
OK so despite the obvious need for a biology lesson, what’s going on here is really simple. If we ever need to add steps to the creation process, it is easy to change the Create() method without affecting the pieces of code that use it:
public Person Create(string name)
{
Person result = new Person(name);
Logger.Log("Created new person named: " + name);
return result;
}
Or even more interesting:
class FreakyPerson : Person { ... }
...
public Person Create(string name)
{
if (name == "John")
return new FreakyPerson(...);
else
return new Person(name);
}
In the second example, we introduced a whole new class – a subclass of person – that we’ll create under certain conditions but which the original users of the factory don’t need to know exists at all! With a lot of pieces of code potentially creating Person objects, this could be very inconvenient to do had we not used the factory.
Generally you’d only bother with a factory if you knew or suspected that you would need to vary the actual concrete implementation in this way. Unfortunately you can’t always foresee the kinds of changes that could be elegantly made with such facilities in place.
Anyway – the downside to using a factory, of course, is that it introduces quite a bit more code that in 99% of cases won’t do anything interesting. The example factory above is extremely oversimplified: most of the time, this kind of factory (a Factory Method) would be implemented using several classes and interfaces, with the associated plumbing to put it all together. With the appropriate using declarations, namespacing, etc, that could be 50 lines of code. You could just create one giant Factory class, with a method for every kind of product (CreatePerson(), CreateCat(), CreateMouse()) but that is going to create a large amount of coupling – everything dependent on the factory – and won’t be much fun in modular systems where Cat and Mouse aren’t even defined in the same assemblies…
…which is why you don’t see Factory being used extensively in real applications except those big fat overblown ‘enterprisey’ monstrosities that we all want to steer clear of.
I think that’s a shame, because the benefits in terms of flexibility and elimination of repetition can be great. Isn’t DRY (Don’t Repeat Yourself) something of a mantra within the agile movement?
FBox is pretty simple but might solve this dilemma. You need to create an FBox for every family of related products you’re going to create (I should mention at this point – the class that implements FBox is called ‘FunctionContainer’):
FunctionContainer animalFactory = new FunctionContainer();
You might create one FBox for domain objects like animals, one for GUI widgets, etc. – these could be static properties on a particular class – whatever.
The next step (we’re creating factories for Person, Cat and Mouse) is to declare a delegate that takes the place of the ‘Create’ method in a traditional factory:
delegate Person CreatePerson(string name);
delegate Cat CreateCat(string name, Color color);
delegate Mouse CreateMouse(int whiskers);
You then implement these ‘factories’ by registering a simple lambda expression implementing each delegate:
animalFactory.RegisterFunction<CreatePerson>(
name => new Person(name));
animalFactory.RegisterFunction<CreateCat>(
(name, color)=>new Cat(name, color));
...
So each factory has cost us two lines of code. To use the factory, we just get it out of the FBox and call it:
Cat tiger = animalFactory.Func<CreateCat>().Call("Tiger", Color.Gray);
(My Tiger is of a non-standard hue…)
The great thing about this implementation over other ‘generic’ factory approaches is that the Call(…) statement above is strongly typed. It requires a string and a Color parameter – if these are not provided, you’ll get an error at compile time rather than runtime.
To break it down:
1. animalFactory.Func<CreateCat>() looks up the expression that we registered: (name, color) => new Cat(name, color). It gets returned wrapped up in an object that exposes it through a property called ‘Call’.
2. Call(“Tiger”, Color.Gray) retrieves our expression from the Call property, and invokes it with the parameters we’ve given.
The actual code that creates the cat is the expression we registered using animalFactory.RegisterFunction().
Two lines of code probably isn’t too much to ask in return for a lot of flexibility. Let’s say we need to do more than just create an instance of the Cat class. The solution is simple – create a fully-blown function to do the work:
class CatFactory
{
public static Cat CreateCat(string name, Color color)
{
// Do whatever needs to be done to create a cat...
}
}
…and register it instead of the original expression:
animalFactory.RegisterFunction<CreateCat>(
new CreateCat(CatFactory.CreateCat));
The old code that we used to create our tiger will now use the new CatFactory.CreateCat function instead of the simple expression. Voila! You can even vary the actual function used at runtime…
I’ve never used this in an app, and never seen it done elsewhere (tell me if you do!) so I can’t say I’ve explored the possibilities or the drawbacks.
Just for the morbidly curious
the source code for the FBox function container can be downloaded here. It is built using the Orcas March CTP but the library itself could be compiled under VS2005.
