I don't know why it took me so long to come up with this idea, but to save others potential headaches...have you ever thought "hmmmm, I registered this as an interface with an implementation, but I want Windsor to use a class proxy, not an interface proxy, how do I do that?"
For me, initially I almost went as far as implementing my own ProxyFactory to force it to use class proxy no matter what, and then the light bulb hit me and it turns out that there's a much easier way to accomplish this.
c.Register(Component.For<ConcreteImpl, IService>().Interceptors<AnInterceptor>());
Tada! The actual service is now a concrete type, so Windsor will go, OK, I need to create a class proxy. But since it's forwarded to the interface as well, all your dependencies can simply use the interface and everything magically works.
Yay!
Wednesday, April 21, 2010
Monday, April 5, 2010
How to Advocate Test Driven Development (TDD)
It seems that everywhere you read you will find blog posts asserting that it is difficult to convince others to use TDD, and that everyone talking about TDD is already a believer preaching to other believers. So what's the best way convince others?
I recently convinced a good buddy of me to starting doing TDD in his web development. It took a while, but finally he "saw the light." He tried to relay the information to his coworker, and his coworker didn't react as positively, citing the common "I don't want to waste time writing test code when I know my stuff works."
There are many many MANY hurdles of overcome to begin writing software using TDD. I won't go into great detail since you can easily find relevant posts on the web, but basically, if you have successfully transitioned to TDD that also implies that you have in one way or another adopted S.O.L.I.D. principles in software design.
The reason I say this is because it is literally impossible to do TDD otherwise. It is just plain painful. I've been there. It is so painful you shout in your head WTF are people thinking, how does this make my job easier?!
Usually when this happens, you'll probably notice that most (or all) of the SOLID principles have been violated one way or another.
<sarcasm>
Notice that even though this post was supposed to be about how to advocate TDD, I ended up talking about SOLID instead for a bit. What am I trying to get at?
TDD spans from the individual to the team to the organization. You need to be able to tackle it from all points of view. The obsession of the word 'test' has hurt TDD quite a bit. Anyone who's spent any reasonable amount of time will assert that tests are just a means to drive the design. Tests should read like a story (well to programmer eyes), and yes, I said read, as in readable!
At the individual level, you must convince them it forces you to design better code, because testing against badly designed code is not worth the pain/annoyance. You must assert that better designed code is good because it also means being more maintainable and less bugs.
At the team level, you must convince that collective code ownership is a good thing. There should never be a situation where "Bob's on vacation, we'll need to put a hold on Project A because only he knows it". Tests serve as a way on how to interact with a specific service, and are a jump-start to figuring out how to actually use a particular service. Moreover, collective code ownership is a means of sharing and distributing knowledge.
At the organizational level, you must convince managers that you are a professional software developer, and that it is your job to produce high quality work. And if what is required to produce high quality work involves writing proper unit tests, following SOLID principles, and even other agile practices like pair programming, then you should be allowed (and optimally encouraged) to do so. Now TDD might not work for everyone, or every organization, but I think everyone owes it to themselves to give it a fair chance.
I recently convinced a good buddy of me to starting doing TDD in his web development. It took a while, but finally he "saw the light." He tried to relay the information to his coworker, and his coworker didn't react as positively, citing the common "I don't want to waste time writing test code when I know my stuff works."
There are many many MANY hurdles of overcome to begin writing software using TDD. I won't go into great detail since you can easily find relevant posts on the web, but basically, if you have successfully transitioned to TDD that also implies that you have in one way or another adopted S.O.L.I.D. principles in software design.
The reason I say this is because it is literally impossible to do TDD otherwise. It is just plain painful. I've been there. It is so painful you shout in your head WTF are people thinking, how does this make my job easier?!
Usually when this happens, you'll probably notice that most (or all) of the SOLID principles have been violated one way or another.
<sarcasm>
- Single Responsibility Principle
- You mean 1 class to rule them all right?
- Open Closed Principle
- Does this have something to do with sockets?
- Liskov Substitution Principle
- I thought the point of Object Oriented Programming is that everything is an object!
- Interface Segregation Principle
- What's an interface?
- Dependency Inversion Principle
- I don't get it...I only have 1 super object anyway, I don't have dependencies.
Notice that even though this post was supposed to be about how to advocate TDD, I ended up talking about SOLID instead for a bit. What am I trying to get at?
TDD spans from the individual to the team to the organization. You need to be able to tackle it from all points of view. The obsession of the word 'test' has hurt TDD quite a bit. Anyone who's spent any reasonable amount of time will assert that tests are just a means to drive the design. Tests should read like a story (well to programmer eyes), and yes, I said read, as in readable!
At the individual level, you must convince them it forces you to design better code, because testing against badly designed code is not worth the pain/annoyance. You must assert that better designed code is good because it also means being more maintainable and less bugs.
At the team level, you must convince that collective code ownership is a good thing. There should never be a situation where "Bob's on vacation, we'll need to put a hold on Project A because only he knows it". Tests serve as a way on how to interact with a specific service, and are a jump-start to figuring out how to actually use a particular service. Moreover, collective code ownership is a means of sharing and distributing knowledge.
At the organizational level, you must convince managers that you are a professional software developer, and that it is your job to produce high quality work. And if what is required to produce high quality work involves writing proper unit tests, following SOLID principles, and even other agile practices like pair programming, then you should be allowed (and optimally encouraged) to do so. Now TDD might not work for everyone, or every organization, but I think everyone owes it to themselves to give it a fair chance.
Windsor/DynamicProxy/Mixin Powers!
Hmmm, I couldn’t really think of a good title except that this blog post has a little bit of everything of the title.
As with any multithreaded program, deadlocks are a huge pain in the butt, and when they happen it costs time, money, and stress.
In my code base I’ve introduced something called an ExtendedLock, which basically has something like this inside:
Pretty simple. IncrementLockTime, as the name implies keeps track of how long the current thread has been attempting to acquire the lock. It returns a Disposer which takes an Action, which releases the lock. This allows us to take advantage of the using syntax, and avoid boiler plate try/finally (oh, and it avoids typos in Monitor.Exit). After some configurable amount of time, if the lock cannot be acquired within, say, 2 minutes, it’s probably a good probability your application is blocked somewhere.
Now, using this class basically means replacing lock(_syncRoot) type code with _elock.Lock(). Also, I believe it’s a good candidate for “mixing” into any other component. Mixins are sort of like multiple-inheritance, but not. I like to think of mixins as a “can do” rather than “is a.”
Now, we know that C# doesn’t let you do multiple inheritance, but with libraries like Castle’s DynamicProxy2, it lets you do something very similar, and is extremely powerful. In a sense, it will automatically generate the following code for you:
_lock is a private instance variable, SomeService implements IExtendedLock, and simply redirects all the interface methods to _lock. This seems pretty simple and straightforward, but becomes tedious when the type you want to mix in has many methods (as my actual IExtendedLock is).
With Windsor/DynamicProxy, you can do this automatically with minimal amount of code. For example, first you define something like this:
Then, you register it in the container:
Now, whenever you need an instance of a lockable hashtable you can simply do something like this:
You might be wondering why it’s worth all this trouble, and what’s wrong with regular locks and Monitor. For our system it’s pretty critical that it stays running 24/7, and every minute it’s down is money lost, so it is in our best interest to detect any problematic condition.
Last but not least, here’s the important code that actually generates the proxy:
For those who are familiar with Windsor and wondering why I didn’t use the fluent Proxy.Mixins method, it’s because those mixins are created once per registration. In this case, it is very important that each mixin (which is an extended lock), is transient, otherwise every lockable hashtable ends up with the same extended lock, which is just asking for trouble.
As with any multithreaded program, deadlocks are a huge pain in the butt, and when they happen it costs time, money, and stress.
In my code base I’ve introduced something called an ExtendedLock, which basically has something like this inside:
1: public class ExtendedLock : IExtendedLock {
2: public IDisposable Lock() {
3: while (!Monitor.TryEnter(this, 5000)) {
4: IncrementLockTime();
5: }
6: return new Disposer(() => Release());
7: }
8: public event Deadlock;
9: }
Pretty simple. IncrementLockTime, as the name implies keeps track of how long the current thread has been attempting to acquire the lock. It returns a Disposer which takes an Action, which releases the lock. This allows us to take advantage of the using syntax, and avoid boiler plate try/finally (oh, and it avoids typos in Monitor.Exit). After some configurable amount of time, if the lock cannot be acquired within, say, 2 minutes, it’s probably a good probability your application is blocked somewhere.
Now, using this class basically means replacing lock(_syncRoot) type code with _elock.Lock(). Also, I believe it’s a good candidate for “mixing” into any other component. Mixins are sort of like multiple-inheritance, but not. I like to think of mixins as a “can do” rather than “is a.”
Now, we know that C# doesn’t let you do multiple inheritance, but with libraries like Castle’s DynamicProxy2, it lets you do something very similar, and is extremely powerful. In a sense, it will automatically generate the following code for you:
1: public class SomeService : ISomeService, IExtendedLock {
2: IExtendedLock _lock = new ExtendedLock();
3: public void DoSomething() { }
4: IDisposable IExtendedLock.Lock() { return _lock.Lock(); }
5: }
_lock is a private instance variable, SomeService implements IExtendedLock, and simply redirects all the interface methods to _lock. This seems pretty simple and straightforward, but becomes tedious when the type you want to mix in has many methods (as my actual IExtendedLock is).
With Windsor/DynamicProxy, you can do this automatically with minimal amount of code. For example, first you define something like this:
public interface ILockableDictionary : IDictionary, IExtendedLock { }
Then, you register it in the container:
1: var container = new WindsorContainer();
2: container.Register(Component.For(typeof(ILockableHashtable))
3: .LifeStyle.Transient
4: .Activator<LockableHashtableActivator>());
Now, whenever you need an instance of a lockable hashtable you can simply do something like this:
var hash = container.Resolve<ILockableHashtable>(); using (hash.Lock()) { hash["1"] = 1; }
You might be wondering why it’s worth all this trouble, and what’s wrong with regular locks and Monitor. For our system it’s pretty critical that it stays running 24/7, and every minute it’s down is money lost, so it is in our best interest to detect any problematic condition.
Last but not least, here’s the important code that actually generates the proxy:
1: internal class LockableHashtableActivator : DefaultComponentActivator
2: {
3: public LockableHashtableActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
4: : base(model, kernel, onCreation, onDestruction)
5: {
6: }
7:
8: public override object Create(CreationContext context)
9: {
10: IExtendedLock lockMixin = Kernel.Resolve<IExtendedLock>();
11:
12: // an additional object we want to "mix" with the implementation to provide combined functionality
13: ProxyGenerationOptions options = new ProxyGenerationOptions();
14: options.AddMixinInstance(lockMixin);
15:
16: return Kernel.Resolve<ProxyGenerator>().CreateInterfaceProxyWithTarget(
17: typeof(IDictionary), // the interface of the implementation
18: new[] { typeof(ILockableHashtable) }, // additional interfaces to use
19: Activator.CreateInstance<Hashtable>(), // concrete implementation to mix into
20: options);
21: }
22: }
For those who are familiar with Windsor and wondering why I didn’t use the fluent Proxy.Mixins method, it’s because those mixins are created once per registration. In this case, it is very important that each mixin (which is an extended lock), is transient, otherwise every lockable hashtable ends up with the same extended lock, which is just asking for trouble.
Subscribe to:
Posts (Atom)