Archive for the ‘Reading Code’ tag
Reading Code: Unity
I spent a bit of time reading some of the Unity code base recently and I decided to try out a variation of Michael Feathers 'Effect Sketching' which my colleague Dave Cameron showed me.
'Effect Sketching' is a technique Feathers describes in 'Working Effectively With Legacy Code' and the idea is that we sketch a diagram showing the interactions between the fields and methods in a specific class while browsing through the code.
Dave suggested doing a similar thing but with methods and classes instead while stepping through the code with the debugger.
I set up this code to step my way through:
var container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterType(typeof (IIDProvider), typeof (HttpContextIDProvider)); container.Configure<Interception>().SetDefaultInterceptorFor(typeof (GetPaymentBreakdownsService), new VirtualMethodInterceptor()); object resolve = container.Resolve(typeof (GetPaymentBreakdownsService));
These are some of my observations from this exercise:
- I found it was much easier for me to remember where I was in the call stack then normal.
I often get quite engrossed in the individual method calls on objects that I forget where the code actually started before it ended up in the current location. Whenever this happened I was able to refer to my sketch to remind myself of where the code had started from.
- Despite having the drawing I still got a bit lost when the PolicyInjectionBehaviourDescriptor made a call back to the container's Resolve method which meant that the code went through the same path that I'd just followed:
32 33 34 35 36 37 38
public IInterceptionBehavior GetInterceptionBehavior( IInterceptor interceptor, Type interceptedType, Type implementationType, IUnityContainer container) { InjectionPolicy[] policies = container.Resolve<InjectionPolicy[]>();
I was getting really confused watching various different injection policies being resolved instead of the type I was trying to resolve!
- I've previously tried drawing diagrams which just contained the classes in a code base but I've found that including the methods that connect them makes it easier for me to understand what's going on.
I've been drawing these diagrams out by hand but I thought I'd translate some of it into dot notation so that I could create a version using graphviz to show on here.

The nodes in orange represent classes and the dotted line represents where an event was fired.
- I realised that I still need to spend more time reading code so that I know when to dive into an object and when the details are probably not important. At the moment I'm too prone to getting distracted by wanting to see how a specific method works instead of looking at those details later on when I actually need to know.
- I felt as I was reading the code that in a lot of places the option type from functional programming would have come in quite useful. There is often code similar to this bit from LifeTimeStrategy:
object existing = lifetimePolicy.GetValue()
if (existing != null) { context.Existing = existing context.BuildComplete = true } Instead of existing returning a null it could return 'None' to indicate it hasn't been resolved yet.
- I've read about the 'yield' construct before but I've never seen a need to use it yet in any code I've written so it was interesting to see it being used quite frequently inside PolicySet:
public IEnumerable<InjectionPolicy> GetPoliciesFor(MethodImplementationInfo member) { foreach (InjectionPolicy policy in this) { if (policy.Matches(member)) { yield return policy; } } }
From my understanding of this construct it seems like it acts in a similar way to a stream i.e. it's only evaluated when it's actually needed.
- In the 'Fundamentals of Object Oriented Design in Uml' Meilir Page Jones suggests that we might want to avoid replicated behaviour in our public APIs since it leads to greater complexity.
This would therefore seem to suggest that having overloads of methods on an object is something to be avoided. Interestingly in this code base the overloads for 'UnityContainer' are actually defined as extension methods which then delegate back to 'UnityContainer' and pass in default values for unspecified parameters.
This seems like quite a neat way of getting around the problem since we keep the API clean while also providing users of the code an easy way to do so.
On the subject of reading code I recently came across an interesting post by designbygravity which describes some approaches for reading code more effectively.
In particular I really liked the section about not hating the code :
You can get sucked into hating the code, merely because it is not yours. Software people tend to be equipped with ample egos, and other people’s code can offend. But realize, their working code is better than your imagined code, because their working code exists right now. So put your ego aside and learn the code in front of you.
It's so easy to drift into this mindset but it's rarely helpful so if we can stop ourselves it's almost certainly beneficial.
Reading Code: Rhino Mocks
I spent a bit of time recently reading through some of the Rhino Mocks to get a basic understanding of how some features work under the hood.
As well as just getting some practice at reading unfamiliar code I also wanted to know the following:
- How does the 'VerifyAllExpectations' extension method work?
- What's the difference between the 'GenerateMock' and 'GenerateStub' methods on MockRepository?
- How does the 'AssertWasNotCalled' extension method actually work?
These are some of the things I learnt from my exploration:
- I'm using a Mac so I originally started out trying to read the code in TextMate with the C# plugin before eventually realising that I couldn't really tell the difference between a delegate being passed around the code and a method call so I wanted an editor that would help me out with this.
I decided to try out MonoDevelop to see if I could keep on reading the code outside my VM. Unfortunately I kept making that crash every time I tried to move between classes so back to Visual Studio it was! MonoDevelop looks like quite a nice tool but it just isn't for me at the moment.
- I've been playing around with an idea adapted from Michael Feathers' Working Effectively With Legacy Code by drawing out the different classes and how they interact with each other. Where I could see a grouping between classes I've been drawing that into the diagram as well.
Some of the guys on Twitter showed me a cool web based tool at yuml.me that allows you to easily draw class diagrams and then grab the png/jpeg file and do whatever you want with it.

Although these diagrams are quite simple I find them more useful than I had expected and I've started drawing more diagrams at work to help understand bits of code that I'm not very familiar with.
I realised a couple of years ago when reading one of Scott Young's posts about drawing diagrams that I seem to understand ideas more quickly if I'm able to draw them out so I should probably look to do it more frequently!
- The way that stubs and mocks are generated is essentially the same which I'm told is also the case with Mockito although I haven't read Mockito's code yet.
'GenerateMock' eventually calls this bit of code:
public T DynamicMock<T>(params object[] argumentsForConstructor) where T : class { if (ShouldUseRemotingProxy(typeof(T), argumentsForConstructor)) return (T)RemotingMock(typeof(T), CreateDynamicRecordState); return (T)CreateMockObject(typeof(T), CreateDynamicRecordState, new Type[0], argumentsForConstructor); }
'GenerateStub' eventually calls this bit of code:
public object Stub(Type type, params object[] argumentsForConstructor) { CreateMockState createStub = mockedObject => new StubRecordMockState(mockedObject, this); if (ShouldUseRemotingProxy(type, argumentsForConstructor)) return RemotingMock(type, createStub); return CreateMockObject(type, createStub, new Type[0], argumentsForConstructor); }
The main difference is that when the 'Verify' method is called on stubs (which would call the 'StubReplayMockState' class) we don't do anything whereas with mocks a check is done to ensure that all the expectations setup in the test are met.
I found it quite interesting that the new 'Arrange-Act-Assert' style syntax has been written to make use of the older 'Record-Replay' syntax which I guess is quite a nice metaphor for the two states that you use the framework.
I haven't looked at the Moq code yet but it would be interesting to see how the code for that differs as it was built from the ground up with the 'Arrange-Act-Assert' syntax.
- The 'AssertWasNotCalled' method works fairly similarly to how I had imagined at a high level in that it goes and gets all the expectations for the mock for that method call and then checks that they aren't called although I found the implementation of that first bit quite interesting.
private static ExpectationVerificationInformation GetExpectationsToVerify<T>(T mock, Action<T> action, Action<IMethodOptions<object>> setupConstraints) { // ... var mockToRecordExpectation = (T)mocks.DynamicMock(FindAppropriteType(mockedObject), mockedObject.ConstructorArguments); action(mockToRecordExpectation); // .. }
The code actually creates a mock in order to record the expectation that we are checking does not happen before it goes on to check which methods were called against that method. We therefore need to ensure that any calls to 'AssertWasNotCalled' are made after the call to the system under test otherwise it will always return true which may not be accurate.
- I didn't realise quite how much code there is in Rhino Mocks and I've only read a very small part of it. A few of the interesting parts of the code seem to be making calls to Castle DynamicProxy which is being used to do the intercepting of method calls.
I'm never sure what the best way to approach a new code base is but this time I had a couple of starting points that I wanted to investigate and starting from those points seemed to work out quite well. I still find that I struggle to know when to stop digging down into how specific code works and when to just have a general understanding of that bit and move on to the next bit of code. I often find that I click all the way through to deeper methods and then I can't remember why I did it in the first place.