Freigeben über


Unity + EntLib = ?

If you've been following Grigori Melnik's blog, you'll know a bit about Unity, the new Dependency Injection container that's coming in Enterprise Library 4.0. Unfortunately I won't be able to make it to the Unity Extensibility Workshop later this month (it's just a little bit out of my way), but I was lucky enough to have Grigori and Scott Densmore (yes, he's back!) give me a quick overview of Unity the other day, and I have to say it looks very nice so far.

However this initial presentation was really only about Unity as a stand-alone beast. That's fine - it's important to know that it can be used independently of the rest of Enterprise Library if you so wish - but the thing that I'm really interested in is how Enterprise Library application blocks will be "refactored to take advantage of Unity" (direct quote from Grigori's blog). There are a few clues in Scott's latest post, which focuses primarily on how this change will clean up some of the under-the-covers plumbing in Enterprise Library. This is a worthwhile goal (I've never been a big fan of the countless factories and assemblers), but I'm yet to fully understand what impact this will have on the average developer who, let's face it, doesn't normally need to look under the hood to see how it all works, provided it does all work.

In general, a key benefit of using dependency injection is that code can take a dependency on only the interface of a component, plus it needn't worry itself on how that object is created. This is particularly useful if you want to allow different implementations to be used at different times (such as mocks for unit testing), or if you need flexibility in how those instances are going to be created. It's a very useful pattern, but since the Enterprise Library application blocks already include several layers of abstraction internally it isn't obvious what advantages the Unity integration will provide.

To give an example, let's look at how a developer may call the Logging Application Block and Data Access Application Block today:

 Logger.Write("My message", new string[] {"Category1", "Category2"});

Database database = DatabaseFactory.CreateDatabase("Northwind");
int result = database.ExecuteNonQuery("spDoStuff", 5, "Foo");

Now in both of these cases, the developer doesn't know what concrete instances are created (TraceListeners, Filters and Formatters for the Logging Application Block, Databases for the Data Access Application Block). They also don't need to worry themselves about how those instances are constructed - granted the options are limited (configuration- or sometimes attribute-driven), but at least this is hidden behind the factory or facade.

So what might these blocks look like when accessed via Unity? I haven't seen any code that describes this yet, but I imagine it will need to look something like this:

 // First set up the unity container and tell it how to configure the blocks.
// I have no idea how this will work, so let's not speculate :-)

ILogger logger = unityContainer.Get<ILogger>();
logger.Write("My message", new string[] {"Category1", "Category2"});

IDatabase database = unityContainer.Get<IDatabase>("Northwind");
int result = database.ExecuteNonQuery("spDoStuff", 5, "Foo");

Now ignoring any potentially necessary bootstrapping code, this isn't drastically different from what we do today, although it would be a little more verbose for facade-based blocks such as Logging, Exception Handling and Validation. But what benefits does it provide? Well, for one thing, I could provide a completely different implementation of either block without changing my code. This sounds attractive, until you consider that your new implementation must have the exact same semantics of the original block - for example it would need to use the same LogEntry with the same properties, utilise categories and filters for the same purpose, and so on. So really I can't imagine why you would ever want to use a different implementation, since it would essentially need to behave identically to the current block. The pattern makes a bit more sense for the Data Access Application Block, but it's not really any different to what you can already do with the existing API using derived Database classes.

Scott made it very clear on his blog that they are not planning on doing away with the current block APIs anytime soon, so there isn't any need to panic. But still I think it makes sense to ask what benefits EntLib users will get out of this refactoring exercise, given that the team could be spending time on other priorities. I also know (as does Scott, more than anyone), that changing the core architecture of EntLib is very time-consuming, given that there are seven different blocks built on top of it.

Still I am willing to be sold on this effort. I would like to see the internal architecture cleaned up and I would be very happy if building and extending blocks were made a little easier. And if someone can explain to me how the Unity integration will make my life as an architect and developer easier, I'm more than willing to listen. But in my wishlist for EntLib 4.0, I have to say that other things are higher up on my list, so I'd like to hear the team explain exactly what we are getting out of this and why we would want to change the way we've been using the blocks for the past three years.

If you agree or disagree with me, or if you can inject any additional information into the conversation that will help me or the EntLib team think about this differently, please speak up - as you know, this is the kind of dialogue that patterns & practices team, and the developer community as a while, continues to thrive on.

Comments

  • Anonymous
    February 02, 2008
    Another thing I wonder is the performance impact of using Unity in the ent lib. I doubt doing an operation like "ILogger logger = unityContainer.Get<ILogger>();" every now and then would be a performance gain. Would love to hear about some performance numbers. So they dont integrate Unity just for the sake of it and it gets A) Lot slower B) Takes a lot of time that they could do better things with

  • Anonymous
    February 02, 2008
    The comment has been removed

  • Anonymous
    February 02, 2008
    Awww jyea! I'm officially slated a spot in the Unity Workshop announced earlier this week. This will

  • Anonymous
    February 02, 2008
    Casey - in what way are you unable to use one block without using others? All of the cross-block dependencies are factored into optional pluggable providers. Again, I believe a good IoC container would improve the internal architecture to support this, but I'm not sure what benefits this would provide to the average user.

  • Anonymous
    February 02, 2008
    I'll be at the workshop, flying all the way down from Montreal!!! I think Unity is a lot more than just a way to ease code behing the different blocks of EntLib as it is right now. It is essentially a new block based on some sample container from OB2.0. What will it give? Well probably the same benefits as any other IoC container...  + potential larger buy-in from the community. I really look forward to unity as I've been playing with OB2.0 for a while now. It is true that I don't really care whether the implementation behing Logger.Write is simplified or not per se. However, I always felt that Config Data + Designers + Assemblers + Factory were a bit overwhelming when came time to present to end-users. Also, I believe that simplifying the architecture might generate more contrib on EntLibContrib as it will become easier to extend/use.

  • Anonymous
    February 03, 2008
    >>>in what way are you unable to use one block without using others? All of the cross-block dependencies are factored into optional pluggable providers.<< Well the last time I looked, the dependencies were still there - though that was pre-3.0 ... however, even the Provider pattern that MS use/advocate isn't exactly a 'good' seperation ... it was/is overly complex and over specified... and there Unity could certainly help.