Windsor 2.1 is out – now with Silverlight support
Krzysztof Koźmic has just announced it, so I will skip posting the details here and just let you read the entire announcement on his blog.
One thing that deserves special attention is that, as you can read from the post title, this Windsor release is for both .NET 3.5 and for Silverlight 3.0.
Have fun…
Optimizing Windsor
Recently we got a bug report about the performance of Windsor when registering large number of components (thousands). I decided to sit down and investigate this, and found out something that was troublesome.
Internally, registering a component would trigger a check for all registered components that are waiting for a dependency. If you had a lot of components that were waiting for dependency, registering a new component degenerated to an O(N^2) operation, where N was the number of components with waiting dependencies.
Luckily, there was no real requirement for an O(N^2) operation, and I was able to change that to an O(N) operation.
Huge optimization win, right?
In numbers, we are talking about 9.2 seconds to register 500 components with no matching dependencies. After the optimization, we dropped that to 500 milliseconds. And when we are talking about larger number of components, this is still a problem.
After optimization, registering 5,000 components with no matching dependencies took 44.5 seconds. That is better than before (where no one has the patience to try and figure out the number), but I think we can improve up it.
The problem is that we are still paying that O(N) cost for each registration. Now, to suppose systems that already uses Windsor, we can’t really change the way Windsor handle registrations by default, so I came up with the following syntax, that safely change the way Windsor handles registration:
var kernel = new DefaultKernel();
using (kernel.OptimizeDependencyResolution())
{
for (int i = 0; i < 500; i++)
{
kernel.AddComponent("key" + i, typeof(string), typeof(string));
}
}
Using this method, registering 5,000 components drops down to 2.5 seconds.
I then spent additional time finding all the other nooks and crannies where optimizations hid, dropping the performance down to 1.4 seconds.
Now, I have to say that this is not linear performance improvement. Registering 20,000 components will take about 25 seconds. This is not a scenario that we worry over much about.
The best thing about the non linear curve is that for a 1,000 components, which is what we do care about, registration takes 240 milliseconds. Most applications don’t get to have a thousand components, anyway.
There are also other improvements made in the overall runtime performance of Windsor, but those would be very hard to notice outside of a tight loop.
Why I released Windsor?
Because getting kicked that many times will hurt:

Castle Windsor 2.0 RTM Released
Some would say that it is about time, I would agree. Windsor might not be the OSS project in pre release state for the longest time (I think that the honor belong to Hurd), but it spent enough time at that state to at least deserve a honorary mention.
That was mostly because, although Windsor was production ready for the last three or four years or so, most of the people making use of it were happy to make use of the trunk version.
If you will look, you won’t find Windsor 1.0, only release candidates for 1.0. As I believe I mentioned, Windsor has been production ready for a long time, and for the full release we decided to skip the 1.0 designator, which doesn’t really fit, and go directly to 2.0
The last Windsor release (RC3) was almost a year and a half ago, and in the meantime, much has improved in Windsor land. Adding upon the already superb engine and facilities, we have fitted Windsor to the 3.5 release of the .Net framework, created a full fledged fluent API to support easy configuration, allowed more granular control over the behavior of the container when selecting components and handlers and improved overall performance.
All in all, pretty good stuff, even if I say so myself. Just to give you an idea, the list of changes from the previous release goes for quite a while, so I am going to let the short listing above to stand in its place.
You can get the new release from the source forge site.
MEF & Open Generic Types
I read Glenn' s post about MEF's not supporting open generic types with somewhat resembling shock. The idea that it isn't supporting this never even crossed my mind, it was a given that this is a mandatory feature for any container in the .NET land.
Just to give you an idea, what this means is that you can't register Repository<T> and then resolve Repository<Order>. In 2006, I wrote an article for MSDN detailing what has since became a very common use of this pattern. Generic specialization is not something that I would consider optional, it is one of the most common usage patterns of containers in the .NET land. IRepository<T> is probably the most common example that people quote, but there are others as well.
This is not a simple feature, let me make it clear. Not simple at all. I should know, I implement that feature for both Object Builder and Windsor. But that is not what I would consider an optional one.
I am even more disturbed by the actual reasoning behind not supporting this. It is a technical limitation of MEF because internally all components are resolved by string matching, rather than CLR Types. This decision is severely limiting the things that MEF can do. Not supporting what is (in my opinion) is a pretty crucial feature is one example of that, but there are other implications. It means that you can't really do things like polymorphic resolutions, that your choices in extending the container are very limited, because the container isn't going to carry the information that is required to make those decision.
I would advice the MEF team to rethink the decision to base the component resolution on strings. At this point in time, it is still possible to change things ( and yes, I know it isn't as easy as I make it seems ), because not supporting open generic types is bad, but not having the ability to do so, and the reason for that (not keeping CLR Type information) are even worse. I get that MEF needs to work with DLR objects as well, but that means that MEF makes the decision to have lousier support for CLR idioms for the benefit of the DLR.
Considering the usage numbers for both of them, I can't see this being a good decision. It is certainly possible to support them both, but if there are any tradeoffs that have to be made, I would suggest that it should be the DLR, and not the CLR, which would be the second class role.
Didja know? Merging Windsor configuration with automatic registration
One of the most annoying things that we have to do during development is updating configuration files. That is why convention over configuration is such a successful concept. The problem is what to do when you can mostly use the convention, but need to supply configuration values as well.
Well, one of the nice things about Windsor is the ability to merge several sources of information transparently. Given this configuration:
<configuration> <configSections> <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" /> </configSections> <castle> <facilities> <facility id="rhino.esb" > <bus threadCount="1" numberOfRetries="5" endpoint="msmq://localhost/demo.backend" /> <messages> </messages> </facility> </facilities> <components> <component id="Demo.Backend.SendEmailConsumer"> <parameters> <host>smtp.gmail.com</host> <port>587</port> <password>*****</password> <username>*****@ayende.com</username> <enableSsl>true</enableSsl> <from>*****@ayende.com</from> <fromDisplayName>Something</fromDisplayName> </parameters> </component> </components> </castle> </configuration>
And this auto registration:
var container = new WindsorContainer(new XmlInterpreter()); container.Register( AllTypes.Of(typeof (ConsumerOf<>)) .FromAssembly(typeof(Program).Assembly) );
We now get the benefit of both convention and configuration. We can let the convention pick up anything that we need, and configure just the values that we really have to configure.
First Steps with Post Sharp
PostSharp is an AOP framework that works using byte code weaving. That is, it re-writes your IL to add behaviors to it. From my point of view, it is like having the cake (interception, byte code weaving) and eating it (I haven't even looked at the PostSharp source code, just used the binary release).
My initial spike with it went very well. Here it is:
[Serializable] public class Logger : OnFieldAccessAspect { public override void OnGetValue(FieldAccessEventArgs eventArgs) { Console.WriteLine(eventArgs.InstanceTag); Console.WriteLine("get value"); base.OnGetValue(eventArgs); } public override InstanceTagRequest GetInstanceTagRequest() { return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false); } public override void OnSetValue(FieldAccessEventArgs eventArgs) { int i = (int?)eventArgs.InstanceTag ?? 0; eventArgs.InstanceTag = i + 1; Console.WriteLine("set value"); base.OnSetValue(eventArgs); } }
This is an aspect that run on each field access. It is not really useful, but it helps to show how things works. A couple of things that are I think are insanely useful:
- Aspects are instantiated at compile time, allowed time to set themselves up, then serialized to an resource in the assembly. At runtime, they are de-serialized and ready to run. The possibilities this give you are amazing.
- InstanceTag is a way to keep additional data per aspect.
Now, let us assume that I want to add the aspect to this code:
[Logger] public class Customer { public string Name { get; set; } }
Note, there is no field. (Well, there is, it is generated by the compiler). Now we compile and run the PostSharp post compile step. With that, we can now investigate what is going on.
As you can see, we are deserializing the attribute and storing it in a field that we can now access. Let us check the Customer implementation now:
We have the logger field, which is used for something, but we also have the ~get~<Name>k__Backingfield and ~set~<Name>k__BackingField. <Name>k__BackingField (and I would love to hear the story behind that) is the compiler generated field that was created for us. The ~get~... and ~set~ are generated by PostSharp. Before we look at them, we will look at the implementation of Name.
Where it used to call the field directly, now it is doing this via a method call. And now we can look at those method calls.
There is a lot going on here. We create a new field access event arg, call the aspect method, and return the value. Note that the state (instance tag) is stored in the object as well, for each field access.
It looks very well done.
Windsor - IModelInterceptersSelector
In my previous post I introduced the basis of context as an architectural pattern. Now I want to talk about how we can implement that using Windsor and a new extensibility point: IModelInterceptersSelector.
The interface is defined as:
/// <summary> /// Select the appropriate interecptors based on the application specific /// business logic /// </summary> public interface IModelInterceptorsSelector { /// <summary> /// Select the appropriate intereceptor references. /// The intereceptor references aren't neccessarily registered in the model.Intereceptors /// </summary> /// <param name="model">The model to select the interceptors for</param> /// <returns>The intereceptors for this model (in the current context) or a null reference</returns> /// <remarks> /// If the selector is not interested in modifying the interceptors for this model, it /// should return a null reference and the next selector in line would be executed (or the default /// model.Interceptors). /// If the selector return a non null value, this is the value that is used, and the model.Interectors are ignored, if this /// is not the desirable behavior, you need to merge your interceptors with the ones in model.Interecptors yourself. /// </remarks> InterceptorReference[] SelectInterceptors(ComponentModel model); /// <summary> /// Determain whatever the specified has interecptors. /// The selector should only return true from this method if it has determained that is /// a model that it would likely add interceptors to. /// </summary> /// <param name="model">The model</param> /// <returns>Whatever this selector is likely to add intereceptors to the specified model</returns> bool HasInterceptors(ComponentModel model); }
And registering it in the container is simply:
container.Kernel.ProxyFactory.AddInterceptorSelector(selector);
Interceptors are the basis of AOP, but traditionally, you didn't get a lot of choices in how you compose your interceptors at runtime. Using IModelInterceptersSelector make it extremely easy to modify the selection of interceptors based on relevant business logic.
Let us take the following example. We have a warehouse service that we want to add caching to. However, we can't use the cache in the request comes from the fulfillment service. First, we define the caching interceptor, then, we define the logic that controls adding or removing it.
public class WarehouseCachingInterceptorSelector : IModelInterceptorsSelector { public InterceptorReference[] SelectInterceptors(ComponentModel model) { if(model.Service!=typeof(IWarehouse)) return null; if(Origin.IsFromFulfillment) return null; return new InterceptorReference[]{new InterceptorReference(typeof(WarehouseCachingInterceptor)), }; } public bool HasInterceptors(ComponentModel model) { return model.Service == typeof (IWarehouse); } }
And now we get caching for everything except for fulfillment. And we get this in a clean and very easy to understand way. :-D
Windsor - IHandlerSelector
In my previous post I introduced the basis of context as an architectural pattern. Now I want to talk about how we can implement that using Windsor and a new extensibility point: IHandlerSelector.
The interface is defined as:
/// <summary> /// Implementors of this interface allow to extend the way the container perform /// component resolution based on some application specific business logic. /// </summary> /// <remarks> /// This is the sibling interface to <seealso cref="ISubDependencyResolver"/>. /// This is dealing strictly with root components, while the <seealso cref="ISubDependencyResolver"/> is dealing with /// dependent components. /// </remarks> public interface IHandlerSelector { /// <summary> /// Whatever the selector has an opinion about resolving a component with the /// specified service and key. /// </summary> /// <param name="key">The service key - can be null</param> /// <param name="service">The service interface that we want to resolve</param> bool HasOpinionAbout(string key, Type service); /// <summary> /// Select the appropriate handler from the list of defined handlers. /// The returned handler should be a member from the <paramref name="handlers"/> array. /// </summary> /// <param name="key">The service key - can be null</param> /// <param name="service">The service interface that we want to resolve</param> /// <param name="handlers">The defined handlers</param> /// <returns>The selected handler, or null</returns> IHandler SelectHandler(string key, Type service, IHandler[] handlers); }
And registering it in the container is simply:
container.Kernel.AddHandlerSelector(selector);
A handler selector is asked if it wants to express an opinion on a particular component resolution, based on key (optional) and type. Assuming we say yes, we are called to select the appropriate handler from all the registered handlers that can satisfy that request.
Let us say that we want to recover from the database being down by serving an implementation that reads from only the cache, we can implement it thusly:
public class DataAccessHandlerSelector : IHandlerSelector { bool databaseIsDown = false; public DataAccessHandlerSelector() { DatabaseMonitor.OnChangedState += state => databaseIsDown = state == DatabaseState.Down; } public bool HasOpinionAbout(string key, Type service) { return databaseIsDown && service == typeof(IRepository); } public IHandler SelectHandler(string key, Type service, IHandler[] handlers) { return handlers.Where(x=>x.ComponentModel.Implementation == typeof(CacheOnlyRepository)).First(); } }
Now we automatically replace, based on our own logic and the current context what type of component the container should resolve.
I am giving the example of detecting infrastructure change, but as important, and as interesting, is the ability to easily use this in order to select services in a multi tenant environment. We can use this approach to perform service overrides all over the place in a way that is natural, easy and extremely powerful.
Have fun...
Components, Implementations and Contextual Decisions
I am a big believer in using context in order to drive a system. What do I mean by that?
Note, I am going to talk about the problem in general, and its solution implementation using Windsor. The example is fictitious and is here to represent the problem in a way that allow me to talk about it in isolation, it doesn't necessarily represent good design.
It seems like just about all the applications that I had to deal with recently had to have the notion of system variability. Now, let us make it clear. System variability is a fancy name for the if statement. The problem with the if statement is that when you have a lot of them, it gets pretty tricky to understand what is going on with the system. That is why a common refactoring is replace conditional with polymorphism.
What I am usually talking about is "when we are in this condition, we should do X, otherwise, we should do Y". Let us take the simple idea of a warehouse service. If we are making a call from the web site, it is okay to return data that may not be accurate to the second. If we are calling from the fulfillment service, we need accurate, up to date results. A simple way of handling this is:
public bool ItemIsPhysicallyOnTheShelve(Guid id) { if(Origin == Originators.Website)//can use caching { var result = Cache.Get<bool?>("item-on-shelve-" + id) if(result.HasValue) return result.Value; } // actual work and putting in cache }
A more interesting example might be different business rules for making order authorization, based on whatever we have a strategic customer or not. In both cases, we have some context for the operation that modify the way that we deal with this operation.
public bool IsValid(Order order, ValidationSummary summary) { IRule[] rules = CurrentCustomer.IsStrategic ? strategicCutomerRules : normalCustomerRules; foreach(IRule rule in rules) { rule.Validate(order, summary); } return summary.HasErrors; }
One way of dealing with that is as you see in the code samples, get the state from somewhere and make decisions based on that. Another, more advance option is to create:
- IWarehouseService
- DefaultWarehouseService
- CachingWarehouseServiceDecorator
And because decorators are really annoying, we will use AOP to deal with it by creating a caching interceptor.
Now the issue is mere configuration, I can deal with that by flipping bits in the container configuration. The second example can be solved by creating two components with different rule sets and using that. The problem is that this remove the coding issues, but it creates a more subtle and much harder to deal with problems.
If I rely on the container configuration alone, I suddenly have logic there. Important business logic. That is not a good idea, I think. Especially since this means that at some point my code has to make an explicit decision about what component to use, and that breaks the infrastructure independence rule.
What this boil down to is that now I have to manage a lot of the complexity in the application using the container configuration and tie the working of the system into it. That works if the number of variables that I have to juggle is small, but if I have a lot of axes (plural: axis) that are orthogonal to one another, it is getting complex very fast.
My solution for that problem is to define a service and its context as a cohesive unit. That is, the concept of a service contains its interface, all of its implementations and the business logic required to select which implementation (and configuration) to choose for a given context.
In the warehouse example above, what we will have is:
- IWarehouseService
- DefainltWarehouseService
- WarehouseCachingInterceptor
- WarehouseInterceptorsSelector
Now all of those are part of the same service. The last one is where we isolate the actual decision about what type of implementation we should get. In this case, we use Windsor's IModelInterecptorsSelector to add additional, context bound, interceptors to the service.
But that is just from the interceptors side, what about the selection of the appropriate rules? We can handle that using ISubDependencyResolver, where we can decide how we want to filter the rules that goes into IWarehouseService based on the context. For that matter, we might have a completely different warehouse implementations, VirtualWarehouseService and PhysicalWarehouseService. And we need to select between them based on some business criteria. We handle that using IHanlderSelector, that make the decision which component to create.
Again, IHandlerSelector, IModelInterceptorsSelector and ISubDependencyResolvers are all implementations of Windsor extensibility mechanisms (my next two posts will cover them in details) that allows us to make it aware of the context that we have in the application.
The purpose of the explicit notion of context is to allow us to deal with the variability in the application in an explicit manner. And that, in turn means that we get much better separation of concerns.
The Common Service Locator library
Glenn and Chris has already gotten the word out, but that is an important piece of news.
The idea is based off a post that Jeremy Miller had about a month ago, having a common, shared interface across several IoC implementation. That would allow library authors to make use of the benefits of a container without taking a dependency on a particular implementation.
The alternative for that is to each library to create its own abstraction layer. A good example of that is NServiceBus' IBuilder interface, or ASP.NET MVC's IControllerFactory. That is just annoying, especially if you are integrating more than a single such framework.
This project was created with the aid of most of the IoC containers authors on the .NET framework, and we have adapters for Windsor, Unity, Spring.NET already, with adapters for the rest of the containers coming soon.
What it is not?
It is not meant to be a complete container abstraction. The reason that the interface is so small (and you wouldn't believe the amount of time that it took to settle on exactly what is going to be there) is that this is not supposed to be the container that you are using. This is explicitly designed to be a read only interface that allows a library to use the container, not some uber container interface (which doesn't really make sense considering the differences between the containers).
Why Service Locator vs. Container? Again, the design is focused on enabling integration scenarios, more than anything else.
I still recommend to avoid explicit service locator usage whenever possible, and to rely on the container and dependency injection. This is not always possible, which is what this library is supposed to solve.
Who should use this?
If you are releasing a piece of code that is taking a dependency on a container, you should consider that as an option. It is generally considered to be a better idea than to force your choice of containers on the clients. The OAuth library for .NET is going to move to this, for exactly this reason.
I am from Microsoft, can I use this?
The code is released under the MS-PL, and all of the work on the project was done by Microsoft employees. That was quite intentional, since this is allow Microsoft projects to make use of that (this is Microsoft IP). If you are a Microsoft employee, you can make use of that. In fact, according to Chris, the next version of the Enterprise Library is going to use this as the container abstraction, so you'll be able to use the Enterprise Library with Windsor and StructureMap and Spring.NET and Ninject and AutoFac and all the rest of the things that I forgot.
I can use only Microsoft products, can I use this?
See previous question.
Where can I find the code
The codeplex site is here: http://www.codeplex.com/CommonServiceLocator
The Managed Extensibility Framework
The Managed Extensibility Framework is "new library in .NET that enables greater reuse of applications and components. Using MEF, .NET applications can make the shift from being statically compiled to dynamically composed. If you are building extensible applications, extensible frameworks and application extensions, then MEF is for you."
(I was too lazy to think about my own description for it, so I just copied the official one.)
Probably the first thing that you should know about MEF is what will undoubtedly be the most common cause for confusion.
The Managed Extensibility Framework is not an IoC container.
This is not a slug at MEF, it is an important distinction. If you try to judge MEF through IoC container glasses, you will come away confused. It may walk like a duck, but it meows.
MEF is, first and foremost, a composition framework. And its target audience are BIG applications. Those two, taken together, are important to understand what MEF is and how we should look at it.
What is the difference between a composition framework and an IoC container? On the surface, they are doing much of the same thing, managing dependencies for the application in an automated fashion. The difference (and the devil) are in the details.
IoC containers have long ago stopped just managing dependencies. They are taking care of a lot of additional responsibilities. Managing lifecycles, proxies, aspect orientation, event aggregation, transaction semantics and a lot of other features.
In addition to that, there is a lot of focus on problem solving by utilizing the container. Things like generic specialization or component selectors allows you to approach a lot of very complex problems in a completely different mindset.
A composition framework, on the other hand, is focused on a single goal: dependency management.
It sounds like MEF is a subset of what an IoC container is doing, I know. This is not the case. MEF, the bits we have right now, are doing a lot more in the area of dependency management than the containers are doing. Where a container is usually static and opaque, MEF primary focus is to make the dependency management itself a dynamic and transparent process.
This is where the second part of the MEF design goals come into place. MEF is targeting Big applications. The really big ones. One of the immediate customers of MEF is Visual Studio itself.
Things like ( take a deep breath ):
- being able to query meta data without loading assemblies
- statically verify the dependency graph for all the components and reject those that would put the system in in valid state
- being explicit by default
- contract adapters
- discovery
- metadata tagging
All of those are key concepts in the overall dependency management theme. And all of those are the product of having a Visual Studio being one of the first consumers of this project. Visual Studio needs this kind of things, across tens of thousands of components. And MEF is setup to handle those kind of scenarios.
So, MEF is very similar to IoC containers, but it has very different goals (or maybe it would be more accurate to say that it has very different priorities).
Another important aspect of MEF has nothing to do with it at all and everything to do with where it is going to be used. MEF is going to ship with .Net 4.0, which put it in a position to be very widely distributed, but more importantly, since it is on the framework, it can be used by other parts of the framework. Which is where it get interesting.
There are a lot of places in the framework that could make use of a container. IControllerFactory is a good example of something that should not exists, for example. I am ambivalent with regards to that, because I think that the correct abstraction for those kind of things is not necessarily MEF, but that is beside the point.
And that is enough for now, I am going to toss a coin and see if it is going to be Erlang code or meta documentation next.
Inversion of Control is NOT about testability
Jacob have an interesting perspective on testability:
The thing is that using Typemock means that you can unit test literally any public method of any public class, regardless of any and all internal dependencies that class might have. And you can do so without changing the design and/or architecture of your software at all.
In other words, using Typemock means that everything is testable. Unit testable. Seriously. Everything.
....
Which is why I had such a hard time reading Jeffrey Palermo's latest blog post entitled “Inversion of Control is NOT about testability”. Since I know Jeffrey Palermo is a .Net developer, my initial response is a big fat “Duh. He must be using Typemock.” Sadly, this is not the case.
...“Testable design” only has value in the things it allows us to do—namely, unit test our classes. If we can unit test our classes as easily no matter what design patterns we choose, then that frees us up to explore other aspects of design choices. It isn't that <le design du jour> ceases to have value, it's just that testability is no longer a factor in evaluating its utility.
...So, uh, forget all I just said. Spend lots of time making sure your .Net projects are testable. Also: Typemock sucks. Don't bother going there...
There are so many things that I disagree with in this post, I am not sure where to even begin. Before that, I need to point out, as usual, that TypeMock is an awesome tool, and that it can bring a lot of value to the table. It doesn't fit the way that I , personally, works, but that is a personal opinion, and I am just a little bit biased. I just want to make it clear that this post is not an attempt to dismiss TypeMock or its value.
With that out of the way, let us concentrate on the actual content of the post.
First, there is no silver bullet. TypeMock is wonderful, but it is not the answer to every testability prayer (is there such a thing?). If the code is bad, TypeMock can do a lot to help, but it will still be a PITA to test this code.
Second, it looks like Jacob missing the actual message in Palermo's post about "this is not about testability". Good design is one which preserves separation of concerns, maintain the single responsibility principal, amenable to change, etc. This also happen to be a design that is easily testable, but that is beside the point.
Good design is simple one where each piece of the code does one thing, and is not dependent on everything else in the application. To violate that means that you would run into issues the first time you need to make a modification. The reason that we want to avoid dependencies as much as possible is that we have to avoid the cascading change reaction.
I didn't have to look far for an example, two posts prior to this one, Jacob has given an excellent example why a design that is testable with TypeMock (and thus, holy*), run into problems with real world requirements. This is not my scenario, it is his. I can come up with quite a lot of war stories about the problems that code with too much dependencies caused.
Let us take Rhino Mocks as an example (I still think of it as my best work), the project is over 3 years old, started in .Net 1.1 and C# 1.0. It has got through numerous versions and grown through two (and a half :-)) major framework versions. The code is stable and as usable as the the day I started this project. If you dig into Rhino Mocks, you'll find that the code is heavily segregated. That allowed me to add functionality and modify the way things work without difficulty, even when dealing with major changes, like the move to Dynamic Proxy 2 or support the AAA syntax.
That is what you get out of having a good design, software that is maintainable.
* sorry, this is a snipe at Jacob, not TypeMock.
Putting the container to work: Refactoring NServiceBus configuration
One of the most common issues when people are building frameworks and applications that rely on a container is that they are not giving the container enough to do. Basically, they use the container to create some components, but they are doing a lot of things that the container could do for them outside of the container.
Note: Code for this post can be in the Scratch Pad.
NServiceBus and Mass Transit are good examples of that. I detailed some of the issues that I had with Mass Transit a while ago. Udi and I talked about this situation with NServiceBus a few days ago, and this is my attempt to figure out a better model for configuring NSB. Let us start from what we have right now.
We have XML configuration in app.config:
<MsmqTransportConfig InputQueue="messagebus" ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" /> <UnicastBusConfig DistributorControlAddress="" DistributorDataAddress=""> <MessageEndpointMappings> <add Messages="Messages" Endpoint="messagebus" /> </MessageEndpointMappings> </UnicastBusConfig> <MsmqSubscriptionStorageConfig Queue="subscriptions" />
And we have code to initialize the bus:
new ConfigMsmqSubscriptionStorage(builder); NServiceBus.Serializers.Configure.BinarySerializer.With(builder); new ConfigMsmqTransport(builder) .IsTransactional(true) .PurgeOnStartup(false); new ConfigUnicastBus(builder) .ImpersonateSender(false) .SetMessageHandlersFromAssembliesInOrder( typeof(RequestDataMessageHandler).Assembly ); IBus bus = builder.Build<IBus>(); bus.Start();
The ConfigXyz objects are there to configure the bus itself inside the builder (the container used in the sample.
My first step was to take this and move it to Windsor, and with no XML config. Which gave me this:
// configure bus container.Register( Component.For<IBuilder>() .ImplementedBy<WindsorBuilderAdapter>(), Component.For<IMessageSerializer>() .ImplementedBy<BinaryMessageSerializer>(), Component.For<ITransport>() .ImplementedBy<MsmqTransport>() .DependsOn(new { InputQueue = "messagebus", NumberOfWorkerThreads = 1, ErrorQueue = "error", MaxRetries = 5, PurgeOnStartup = true, IsTransactional = false }), Component.For<ISubscriptionStorage>() .ImplementedBy<MsmqSubscriptionStorage>() .DependsOn( new { Queue = "subscriptions" } ), Component.For<IBus>() .ImplementedBy<UnicastBus>() .DependsOn(new { ImpersonateSender = false, MessageOwners = new Hashtable { {"Messages", "messagebus"} }, MessageHandlerAssemblies = new[] { typeof (RequestDataMessageHandler).Assembly } }) ); // configure handlers container.Register( // yuck, we are registering concrete type! Component.For<RequestDataMessageHandler>() ); var bus = container.Resolve<IBus>(); bus.Start();
There are a few things that you would notice here. We have a lot more code, we hard code the configuration all over the place, you either need to understand Windsor or you have to copy/paste this, no XML (yeah!).
Some of this is good (no XML), the rest... need some work. If we will consider the fact that this is more or less standard bus configuration (configure bus on top of MSMQ), we will see that there is quite a lot we can do here to encapsulate the entire mess into a mechanism that would be much easier to work with.
In Windsor, packaging functionality is done using facilities. A facility is an extension to the container that contains certain behavior. It can be as simple as packaging up registration for several components into a single facility or it can be as complex as proxies and runtime component selections.
Let us start with what the least common denominator. A Windsor facility with XML configuration. The configuration I came up with is:
<configuration> <facilities> <facility id="NServiceBusFacility" type="Windsor.Infrastructure.NServiceBusFacility, Windsor.Infrastructure" useBinarySerialization="true" subsciptionQueue="subscriptions"> <transport inputQueue="messagebus" errorQueue ="error"/> <bus impersonateSender="false"> <message name="Messages" destination="messagebus"/> <handler name="Server"/> </bus> </facility> </facilities> <components> <component id="RequestDataMessageHandler" type="Server.RequestDataMessageHandler, Server"/> </components> </configuration>
And the code to make this happen is here (minus utility methods that I am not showing):
public class NServiceBusFacility : AbstractFacility { public bool UseXmlSerialization { get; set; } public bool UseBinarySerialization { get; set; } protected override void Init() { UseXmlSerialization = FacilityConfig.Value("UseXmlSerialization"); UseBinarySerialization = FacilityConfig.Value("UseBinarySerialization"); Kernel.Register( Component.For<IBuilder>() .ImplementedBy<WindsorBuilderAdapter>() ); RegisterTransport(); RegisterSerializer(); RegisterSubscription(); RegisterBus(); } private void RegisterBus() { var bus = FacilityConfig.Children["bus"]; if (bus == null) throw new InvalidOperationException("bus is a mandatory element"); var messageOwners = new Hashtable(); var assemblies = new List<Assembly>(); foreach (var element in bus.Children) { if (element.Name == "message") { AddMessageDestination(element, messageOwners); } else if (element.Name == "handler") { AddHandlerAssebmly(element, assemblies); } else { throw new InvalidOperationException("Unknown element in bus: " + element.Name); } } Kernel.Register( Component.For<IBus>() .ImplementedBy<UnicastBus>() .DependsOn(new { MessageOwners = messageOwners, MessageHandlerAssemblies = assemblies }) ); } private static void AddHandlerAssebmly(IConfiguration handler, ICollection<Assembly> assemblies) { string assemblyString = handler.Attributes["name"]; if (string.IsNullOrEmpty(assemblyString)) throw new InvalidOperationException("name attribute is mandatory in handler element"); assemblies.Add(Assembly.Load(assemblyString)); } private static void AddMessageDestination(IConfiguration message, IDictionary messageOwners) { string messsageName = message.Attributes["name"]; if (string.IsNullOrEmpty(messsageName)) throw new InvalidOperationException("message must have a name"); string destination = message.Attributes["destination"]; if (string.IsNullOrEmpty(destination)) throw new InvalidOperationException("message must have a destination"); messageOwners[messsageName] = destination; } private void RegisterSubscription() { string attribute = FacilityConfig.Attributes["subsciptionQueue"]; if (attribute == null) throw new InvalidOperationException("subsciptionQueue is a mandatory attribute"); Kernel.Register( Component.For<ISubscriptionStorage>() .ImplementedBy<MsmqSubscriptionStorage>() .Parameters( Parameter.ForKey("Queue").Eq(attribute) ) ); } private void RegisterTransport() { IConfiguration transport = FacilityConfig.Children["transport"]; if (transport == null) throw new InvalidOperationException("transport is mandatory element"); Kernel.Register( Component.For<ITransport>() .ImplementedBy<MsmqTransport>() .Parameters( // mandatory transport.Parameter("InputQueue"), transport.Parameter("ErrorQueue"), // optional transport.Parameter("numberOfWorkerThreads", "1"), transport.Parameter("MaxRetries", "5"), transport.Parameter("PurgeOnStartup", "false"), transport.Parameter("IsTransactional", "false") ) ); } private void RegisterSerializer() { AssertValidSerializationSettings(); if (UseBinarySerialization) { Kernel.Register( Component.For<IMessageSerializer>() .ImplementedBy<BinaryMessageSerializer>() ); } if (UseXmlSerialization) { Kernel.Register( Component.For<IMessageSerializer>() .ImplementedBy<XmlMessageSerializer>() ); } } private void AssertValidSerializationSettings() { if ((UseXmlSerialization && UseBinarySerialization) || (!UseXmlSerialization && !UseBinarySerialization)) { throw new InvalidOperationException("Must define either XML or Binary, not both."); } } }
I am not happy with this yet, the facility has a lot of code there, and we still have XML, but we have very little configuration and the code to use this is now:
IWindsorContainer container = new WindsorContainer("windsor.config"); var bus = container.Resolve<IBus>(); bus.Start();
Which is much better than both versions. It also doesn't require me to recompile to modify the configuration.
Hold the press, what about administrator configuration?!
One of the major emphasis that NServiceBus has in its configuration API it the explicit distinction it makes between developer level configuration (dependencies, which transport you are using, transactions, who handles what, etc) and administrator level configuration (queue names, mostly).
In the configuration above we have no such separation. Problem, isn't it?
Again, we can use the container itself as a way to deal with this. First, we will define a configuration file, which will contain the following text:
<configuration> <properties> <subscriptionsQueue>subscriptions</subscriptionsQueue> <inputQueue>messagebus</inputQueue> <errorQueue>error</errorQueue> </properties> </configuration>
And now in the configuration file itself we will include this configuration file, and refer to those values:
<configuration> <include uri="file://Configuration.config"/> <facilities> <facility id="NServiceBusFacility" type="Windsor.Infrastructure.NServiceBusFacility, Windsor.Infrastructure" useBinarySerialization="true" subsciptionQueue="#{subscriptionsQueue}"> <transport inputQueue="#{inputQueue}" errorQueue ="#{errorQueue}"/> <bus impersonateSender="false"> <message name="Messages" destination="messagebus"/> <handler name="Server"/> </bus> </facility> </facilities> <components> <component id="RequestDataMessageHandler" type="Server.RequestDataMessageHandler, Server"/> </components> </configuration>
And just like that, we got ourselves a nice dual configuration, one for the administrators and one for the developers.
I am still not happy with this, because I have XML and a lot of code to deal with this XML nonsense, but we did drop down to a very simple XML configuration with very little time.
Let us see what is going to happen if we will use Binsor...
Since we don't want to have replication of the XML syntax (we can do much better without the limitations of XML), we will start from scratch, and define a new facility.
Note: While writing this several improvements to Binsor itself occurred to me, so this is certainly something that can be improved.
The approach for building configuration language using Binsor is fairly simple. Create an object graph that represent your configuration, and just call it from the Binsor script.
We start by defining the configuration model:
public enum SerializationFormat { Xml, Binary } public class Transport { public Transport() { //default values for optional params NumberOfWorkerThreads = 1; MaxRetries = 5; PurgeOnStartup = false; IsTransactional = false; } public string InputQueue { get; set; } public string ErrorQueue { get; set; } public int NumberOfWorkerThreads { get; set; } public int MaxRetries { get; set; } public bool PurgeOnStartup { get; set; } public bool IsTransactional { get; set; } } public class Bus { public IDictionary MessageOwners { get; set; } public Assembly[] MessageHandlerAssemblies { get; set; } } public class UnicastBus : Bus { }
As you can see, this is about as simple as it can get.
Then we define the facility itself:
public class NServiceBusFacility_Binsor : AbstractFacility { public SerializationFormat SerializationFormat { get; set; } public string SubsciptionQueue { get; set; } public Transport Transport { get; set; } public Bus Bus { get; set; } public NServiceBusFacility_Binsor( SerializationFormat serializationFormat, string subsciptionQueue, Transport transport, Bus bus) { SerializationFormat = serializationFormat; SubsciptionQueue = subsciptionQueue; Transport = transport; Bus = bus; } protected override void Init() { Kernel.Register( Component.For<IBuilder>() .ImplementedBy<WindsorBuilderAdapter>() ); Kernel.Register( Component.For<ITransport>() .ImplementedBy<MsmqTransport>() .DependsOn(Transport) ); switch (SerializationFormat) { case SerializationFormat.Binary: Kernel.Register( Component.For<IMessageSerializer>() .ImplementedBy<BinaryMessageSerializer>() ); break; case SerializationFormat.Xml: Kernel.Register( Component.For<IMessageSerializer>() .ImplementedBy<XmlMessageSerializer>() ); break; default: throw new NotSupportedException("Serialization format " + SerializationFormat +
" is not supported"); } Kernel.Register( Component.For<ISubscriptionStorage>() .ImplementedBy<MsmqSubscriptionStorage>() .Parameters( Parameter.ForKey("Queue").Eq(SubsciptionQueue) ) ); Kernel.Register( Component.For<IBus>() .ImplementedBy<NServiceBus.Unicast.UnicastBus>() .DependsOn(Bus) ); } }
It is significantly simpler than the XML configuration based one. And now we can get to the configuration itself:
import System.Reflection import Windsor.Infrastructure import Server facility NServiceBusFacility_Binsor: serializationFormat = SerializationFormat.Binary transport = Transport ( InputQueue: "messagebus", ErrorQueue: "errors" ) subsciptionQueue = "subscriptions" bus = UnicastBus ( MessageOwners : { "Messages" : "messagebus" }, MessageHandlerAssemblies : ( Assembly.Load("Server"), ) ) component RequestDataMessageHandler
Wait! What about administrator configuration? Now that we are using a script to configure our application, it is even more important to separate the administrative configuration from the application configuration.
We will take the exact same approach as we did before. Creating a separate file for administration purposes. In order to do so in a way that gives the admin a nice syntax for configuration, we will define a configuration model:
public class MyConfiguration { public static string InputQueue { get; set; } public static string ErrorQueue { get; set; } public static string SubscriptionsQueue { get; set; } }
Now we can create the default AdminConfiguration.boo file:
import Windsor.Infrastructure # namespace of MyConfiguration MyConfiguration.SubscriptionsQueue = "subscriptions" MyConfiguration.InputQueue = "messagebus" MyConfiguration.ErrorQueue = "error"
And our Windsor.boo file is now:
import System.Reflection import Windsor.Infrastructure import Server import file from AdminConfiguration.boo AdminConfiguration().Run() # execute admin configuration facility NServiceBusFacility_Binsor: serializationFormat = SerializationFormat.Binary transport = Transport ( InputQueue: MyConfiguration.InputQueue, ErrorQueue: MyConfiguration.ErrorQueue ) subsciptionQueue = MyConfiguration.SubscriptionsQueue bus = UnicastBus ( MessageOwners : { "Messages" : "messagebus" }, MessageHandlerAssemblies : ( Assembly.Load("Server"), ) ) component RequestDataMessageHandler
Now we don't have any XML involved, but the format that we have is suspiciously similar to the way we worked when we had XML. So, except from a small reduction in the configuration complexity, what did we gain?
We have a full fledged programming language for our configuration purposes. We can now apply rules to our configuration, make logic based decisions, etc.
As a simple example, instead of having to hard code the message owners and handlers, we can scan the application directory for matching assemblies. Want to add a new handler, drop it into the directory, done. This is a really powerful concept, and I am using this extensively in my applications.
Note: Code for this post can be in the Scratch Pad.
Zero friction IoC: Auto registration is mandatory
This is the entire Binsor config file for a real application:
import Castle.MonoRail.Framework import Castle.MonoRail.WindsorExtension import Rhino.Commons.Facilities from Rhino.Commons.ActiveRecord facility MonoRailFacility facility RhinoTransactionFacility facility ActiveRecordUnitOfWorkFacility: assembly = "HibernatingRhinos" for type in AllTypesBased of IController("HibernatingRhinos"): component type.Name, type for type in AllTypes("HibernatingRhinos").WhereNamespaceEq("HibernatingRhinos.Services"): component type.GetServiceInterface(), type
And I am pretty confident that I am not going to have to do much in the future with those.
And yes, you can do it with the fluent registration API as well.
Binsor & Auto Registration - Making it even simpler
Here is the syntax that I am getting at...
for type in AllTypesBased of IView("Rhino.Commons.Test"): component type for type in AllTypesWithAttribute of ControllerAttribute("Rhino.Commons.Test"): component type for type in AllTypes("Rhino.Commons.Test") \ .WhereNamespaceEq("Rhino.Commons.Test.Binsor"): component type for type in AllTypes("Rhino.Commons.NHibernate") \ .Where({ t as System.Type | t.Name.Contains("NHRepository") }): component "nh.repos", type.GetSeriveInterface(), type
And this seems to cover just about any scenario that I can think of. Combine that with Binsor's extend facility, and we are more or less done.
Adaptive Domain Models with Rhino Commons
Udi Dahan has been talking about this for a while now. As usual, he makes sense, but I am working in different enough context that it takes time to assimilate it.
At any rate, we have been talking about this for a few days, and I finally sat down and decided that I really need to look at it with code. The result of that experiment is that I like this approach, but am still not 100% sold.
The first idea is that we need to decouple the service layer from our domain implementation. But why? The domain layer is under the service layer, after all. Surely the service layer should be able to reference the domain. The reasoning here is that the domain model play several different roles in most applications. It is the preferred way to access our persistent information (but they should not be aware of persistence), it is the central place for business logic, it is the representation of our notions about the domain, and much more that I am probably leaving aside.
The problem here is there is a dissonance between the requirements we have here. Let us take a simple example of an Order entity.
As you can see, Order has several things that I can do. It can accept an new line, and it can calculate the total cost of the order.
But those are two distinct responsibilities that are based on the same entity. What is more, they have completely different persistence related requirements.
I talked about this issue here, over a year ago.
So, we need to split the responsibilities, so we can take care of each of them independently. But it doesn't make sense to split the Order entity, so instead we will introduce purpose driven interfaces. Now, when we want to talk about the domain, we can view certain aspect of the Order entity in isolation.
This leads us to the following design:
And now we can refer to the separate responsibilities independently. Doing this based on the type open up to the non invasive API approaches that I talked about before. You can read Udi's posts about it to learn more about the concepts. Right now I am more interested in discussing the implementation.
First, the unit of abstraction that we work in is the IRepository<T>, as always.
The major change with introducing the idea of a ConcreteType to the repository. Now it will try to use the ConcreteType instead of the give typeof(T) that it was created with. This affects all queries done with the repository (of course, if you don't specify ConcreteType, nothing changes).
The repository got a single new method:
T Create();
This allows you to create new instances of the entity without knowing its concrete type. And that is basically it.
Well, not really :-)
I introduced two other concepts as well.
public interface IFetchingStrategy<T> { ICriteria Apply(ICriteria criteria); }
IFetchingStrategy can interfere in the way queries are constructed. As a simple example, you could build a strategy that force eager load of the OrderLines collection when the IOrderCostCalculator is being queried.
There is not complex configuration involved in setting up IFetchingStrategy. All you need to do is register your strategies in the container, and let the repository do the rest.
However, doesn't this mean that we now need to explicitly register repositories for all our entities (and for all their interfaces)?
Well, yes, but no. Technically we need to do that. But we have help, EntitiesToRepositories.Register, so we can just put the following line somewhere in the application startup and we are done.
EntitiesToRepositories.Register( IoC.Container, UnitOfWork.CurrentSession.SessionFactory, typeof (NHRepository<>), typeof (IOrderCostCalculator).Assembly);
And this is it, you can start working with this new paradigm with no extra steps.
As a side benefit, this really pave the way to complex multi tenant applications.
DI & IoC are not about testing!
Dependency Injection & Inversion of Control Containers are not about testing!
I hear this a lot recently. Dave Laribee mentioned that in the Hanselminutes podcast, The creators of Guise seems to think that this is the main concern (01:30 in the video).
Oh, those techniques help, obviously. But it is not about unit testing.
For me, it is like saying that the main purpose interfaces is to enable easier testing.
DI & IoC are about decoupling, better flexibility, having a central place to go to and increasing the maintainability of out applications. Testing is important, but that is not the first and foremost reason.
Non Invasive API, take 2
A few days ago I presented my typical way of handling container driven polymorphism.
// only use for selection public interface IRegion<T> : IRegion {} public void SetRegion(DependencyObject containerElement, string regionName) { IRegion region = (IRegion) IoC.TryResolve(typeof(IRegion<>).MakeGenericType(containerElement.GetType())); if (region != null) _regions.Add(regionName, region); }
I got an email with some good questions, and it is worth a second post to clarify. The questions:
The only thing I don’t like is that a lookup in the form of TryResolve(typeof(IRegion<>).MakeGenericType(containerElement.GetType())) would infer an explicit wrapper type for ever possible UI container type. On one hand it gives me the fine grain control I need to specify a different wrapper for an inherited UI container. But on the other hand, it means that ListBox, TreeView, ComboBox and TabControl would all need their own custom wrappers even though they all derive from ItemsControl and all handle adding and removing child entities in the same way.
But if containerElement == typeof(ListBox), won’t TryResolve(typeof(IRegion<>).MakeGenericType(containerElement.GetType())) fail to resolve? TryResolve expects an explicit match. It would need to find a registration for IRegion<ListBox>, not IRegion<ItemContainer> right? (Assuming Unity here.)
Even if that worked, what if I want all elements that inherit from ItemContainer to be handled by IRegion<ItemContainer> except TreeView? Say I need to handle TreeView differently for some reason. What’s a nice way to handle the 80% rule generically but still allow an override for special cases?
My response to that is very simple. Take the same approach, but bigger. Here is all we need to make this happen.
public void SetRegion(DependencyObject containerElement, string regionName) { Type current = containerElement.GetType() while(current != typeof(DependencyObject)) { IRegion region = (IRegion) IoC.TryResolve(typeof(IRegion<>).MakeGenericType(current)); if (region != null) { _regions.Add(regionName, region); return; } current = current.BaseType; } }
Now, we can register the following:
- IRegion<TreeView>
- IRegion<MyCustomRegion>
- IRegion<ItemsControl>
And no matter what we will send to SetRegion, we can modify the behavior merely by changing the registration of IRegion<T> implementations. Note that this doesn't assumes any capacity on the container (except the basic resolve-generic-service one).
This is also a very natural model to follow, in nearly all cases (there is an issue here regarding whatever we should consider interfaces as well, but that is beside the point for this demo, and I would generally not do that anyway).
Non invasive API - Now with an IoC container
I talked about ways to avoid invasive API design, and a lot of people asked about how to handle this with a container. First, I want to make it clear that the previous example assumed that you can't rely on a container, so it used Poor Man IoC to do that. Now that we can assume that there is a container, this is another matter entirely.
The API design now shifts to allow me to select the proper implementation from the container automatically. This generally ends up being either as a naming convention on top of a fixed interface, or as a generic interface with a given type as a parameter. The decision depends on what you are doing, basically, and the capabilities of your tools.
For myself, I strongly favor the generic interface approach, which would give us the following syntax:
public interface IMessageHandler<TMsg> where TMsg : IMessage { void Handle(TMsg msg); } public class EndPoint { public void HandleMsg(IMessage msg) { // this should be cached and turned into a delegate // not reflection call GetGenericHandleMsgMethod().MakeGenericMethod(msg.GetType()) .Invoke(this, new object[]{msg}); } public void HandleMsg<TMsg>(TMsg msg) where TMsg : IMessage { IoC.Resolve<IMessageHandler<TMsg>().Handle(msg); } }
There is some ugliness in invoking the method with the generic parameter, but this allows you to handle a wide variety of cases very easily.
Let us take another example, this time it is from the Prism.Services.RegionManagerService:
public void SetRegion(DependencyObject containerElement, string regionName) { IRegion region = null; if (containerElement is Panel) { region = new PanelRegion((Panel)containerElement); } else if (containerElement is ItemsControl) { region = new ItemsControlRegion((ItemsControl)containerElement); } if (region != null) _regions.Add(regionName, region); }
I don't really like this code, let us see what happens when we introduce the idea of the container as a deeply rooted concept:
// only use for selection public interface IRegion<T> : IRegion {} public void SetRegion(DependencyObject containerElement, string regionName) { IRegion region = (IRegion) IoC.TryResolve(typeof(IRegion<>).MakeGenericType(containerElement.GetType())); if (region != null) _regions.Add(regionName, region); }
Now the code is much clearer, we can extend it from the outside, without modifying anything when we add a new region type.
Evaluating IoC containers
Scott Hanselman is learning IoC, and he listed a lot of the IoC frameworks on the CLR. I was also pointed to this comparison IoC containers.
I don't like that comparison, and I am not sure that I can quite explain it. Most of the time, comparison of IoC container focus on simple dependency resolving scenarios and the related configuration.
From my point of view, it is like deciding to use C# or Java after reading a comparison of the syntax of an if statement.
Dependency resolution is the most basic feature that an IoC container can have.
Of the top of my head (and probably biased toward Windsor, since that is what I tend to use), I would say that you need to think about the following points, instead of focusing on the baseline scenario:
- Error handling
- Generic components
- Decorators
- Interception
- Configuration vs. Convention (in other words, how much smarts does the container have?)
- Extensibility scenarios
Interception as an extensibility mechanism
I got a request to allow system-mode for Rhino Security, something like this:
using(Security.ActAsSystem()) { // in here the security behaves as if you have permission // to do everything // queries are not enhanced, etc. }
It is not something that I really want to allow, so I started to think how we can implement this, I came up with the following solution:
public class AuthorizationServiceWithActAsSystemSupport : IAuhorizationService { IAuhorizationService inner; public AuthorizationServiceWithActAsSystemSupport(IAuhorizationService inner) { this.inner = innner; } private bool IsActAsSystem { get { return true.Equals(Local.Data["act.as.system"]); } } public bool IsAllowed(IUser user, string operationName) { if(IsActAsSystem) return true; return inner.IsAllowed(user, operationName); } public void AddPermissionsToQuery(IUser user, string operationName, ICriteria query) { if(IsActAsSystem) return; inner.AddPermissionsToQuery(user, operationName, query); } // .. the rest }
Now, all we need to do is register it first:
component IAuthorizationService, AuthorizationServiceWithActAsSystemSupport faciliy RhinoSecurityFacility
And that is it. This both answer the requirement and doesn't add the functionality that I don't like to the system.
Again, neat.
AOP: Be aware where your point cuts are
So, this issue cause some head scratching today. We are using WIndsor's Automatic Transaction Management with NHibernate's flush-on-commit option, so if a transaction doesn't commit, nothing is written to the database.
Anyway, this is a story about refactoring, and what it showed us. We performed the following refactoring:
Some things that is important to understand, the LoginController is decorated with [Transactional], and there is a [Transaction] attribute on CreateUserLoggedInAuditRecord.
When it was on the controller, it just worked. When we moved it to its own class, it didn't work. To be rather more exact, it worked, it just never committed the transaction. That was weird. After some head scratching I found out that I forgot to put [Transactional] on the UsageRegistrationImpl. With a small smile of geeky triumph, I run the code again. It didn't save.
That was really worrying, and I had no idea what was going on. Since this is rarely popular, I repeatedly run the code, hoping that something would turn up and that no one would pull the old quote about insanity.
After a few repetitions, I suddenly saw the light.
It had to do where I placed the pointcut. A pointcut, in AOP terms, is where the AOP can interfere with the running code. Let us take a look at how it worked when we used the LoginController directly. Because we (well, the transaction facility) asked the container to create an interceptor for it, we got the following classes at runtime:
The login controller is the original class, the login controller proxy was generated at runtime, and any invocation of any of its methods would fire the transaction interceptor, so it would get a chance to create/rollback/commit a transaction if needed. Since those methods are virtual, this means that even if I am calling methods on the same class, they will be intercepted correctly.
Now, when I moved to the interface + implementing class, we have a different behavior. Now, we use the interface pointcuts in order to inject behavior, it looks like this:
Windsor will create a proxy interface implementation that would call the AOP interceptors and will forward to the UsageRegistrationImpl.
The problem was with the RegisterUserLoggedIn method. It was similar to this:
public virtual void RegisterUserLoggedIn(string username) { // do other things CreateUserLoggedInAuditRecord(username); } [Transaction] public virtual void CreateUserLoggedInAuditRecord(string username) { //do database stuff }
Given the story so far, you can obviously see the problem. When we call the CreateUserLoggedInAuditRecord() method, we call it from the UsageRegistrationImpl class, so we never pass through any of the pointcuts.
When we used the method from the controller directly, we made a virtual method call, which was intercepted, but since in this case, we were using the interface as our pointcut, this simply by passed the whole thing.
That was an interesting lesson, and one that I'll need to remember for the future.
DSL & IoC - Combining powerful concepts
I was just writing this line of code:
DslExecuter<SchedulingDslEngine>.Create(“validateWebSiteIsUp”)
When it occurred to me that this looks a look like an IoC resolve call. Which got me thinking about combining both concepts together, which gave me the shakes.
The idea is that we can expose those dependencies like this:
customers as ICustomerRepository fraudService as IFraudService alerts as IAlertService for customer in customers.FindAll(With.Orders): for order in customer.Orders: if fraudService.IsFraud(order): alerts.ForFaurdOn(order) if customer.Important: alerts.NotifyCustomerAboutFraud(customer)
Leaving aside the mountain slope code*, consider what is going on here. We are exposing dependencies by specifying the types that we need. We can then get them through the IoC and execute the code in hand.
This means that the DSL has full access to everything in the application, and is subject to the same rules and behavior as all the other components. From my point of view... sweeeeeet.
* First example that popped to mind, yes, I know it is a bad one.
Dogmatic? Who, me?
Jacob Proffitt calls me up to task for being inconsistent:
In this, Ole Friis is echoing the response I got from the intimidating Oren Eini when I suggested that TypeMock makes arguments that couple DI with unit testing go away.
The main weakness of Type Mock is its power, it allow me to take shortcuts that I don’t want to take, I want to get a system with low coupling and high cohesion.
The implication is that he wouldn’t be developer enough to create a system with low coupling and high cohesion if he used powerful tools like TypeMock. Oren is inconsistent here because he’s otherwise all for developer empowerment as illustrated by his support for Jeffrey Palermo’s excellent post regarding treating developers as professionals.
How can I support the idea of alt.net as "running with scissors", responsible adults that are trusted to know what we are doing, with my comments on Type Mock having "too much power"?
It is a good thing that I never felt the need to be self consistent. It makes things much more... invigorating.
I'll start by saying that I often write bad code. What is bad code? In DevTeach, I showed James Kovacks a 150 lines methods that involved threading, anonymous delegates and exception handling in a ingeniously unmaintainable form. Bad as in you will get the axe and come after me with froth coming out of your mouth if you ever see it.
I have a certain style that works for me. It comes with a set of tools and practices that are built to encourage that style and mindset. Being a lazy bastard, I am careful to make sure that I cannot be too lazy, because otherwise it is usually me who needs to clean up my mess.
I believe that the choice of tool has a profound affect on my ability to work. That comes both at the tooling level (IDE, extensions, R#, etc) and the frameworks sides (IoC, OR/M, DSL, etc). Tools & frameworks should guide me where I want to go, and make it harder to do the wrong thing. This is a decision that I made based on my experience and observations.
After dealing with tools that do not encourage best practices, or tools that forces you to work harder to get there, it is a very important consideration to me. I don't see an inherent disconnect between the two. I believe that the term is that "with great power comes great responsibility". Recognizing that, I intentionally limit my own choices, in order to get things done using the approach that I believe is the best for what I am doing.
Does this mean that this approach is a one size fit all? Absolutely not.
In fact, I can tell you that from each and every project I come out with a profound understanding of how stupid I was when I got into the project, and how many mistakes I made in that project.
But, I do believe that this approach is applicable for a broad set of scenarios. Not all, but a broad set of scenarios.
The implication is that he wouldn’t be developer enough to create a system with low coupling and high cohesion if he used powerful tools like TypeMock. Oren is inconsistent here because he’s otherwise all for developer empowerment