SyntaxHighlighter

Wednesday, 27 March 2013

Moq As<> a code smell

The moq As method allows you to create a mock object that implements more than one interface:

(If IFirstInterface implements ISecondInterface then the As<> is not required.)

Its easy to see how this could help you write a test if the SUT cast the object of type IFirstInterface to ISecondInterface.

But what does this say about the code?

It's saying that you have a class that needs to implement more than one interface in order to performs it's job correctly. When you have a class that implements more than one interface, it suggests it has more than use, more than one reason to change. The need to use As<> is suggesting a Single Responsibility Principle violation.

While I wouldn't expect to see As<> used in tests for a Domain Model or Business Logic, it is possibly useful in "plumbing" layers, such as when adapting an external service. As always with code smells, use your own judgement.

To find a bug.

So I thought as I've suggested that debuggers are bad I should describe my "process" for tracking down bugs. I'm not going to claim this is as perfect approach, but it seems to work for me.

What is the bug?

The first thing I try and do when receiving a bug report is get information on what the bug actually is. What the expected behaviour was and what the actual the behaviour was. Any experienced developer will at some point have misunderstood an issue and fixed the wrong problem. This step is vital, but not really what I want to talk about in this post.

Where is the bug?

Time to start theorising. What components are likely to be involved with the operation? This may be an easy question to answer if you know the code well, but if you don't, try doing a search for keywords in your code this is where good naming (and also good spelling) can really make things easier. (I think there's another post in that statement).

Now the most important step of all - read the code!

When I read code, knowing there is an issue with it, I gain a new perspective on it. I notice things I didn't see before and question the assumptions that it makes. I start to theorize about how this could possibly be doing what it is actually doing. Tests are important here as well, is there a test for the behaviour seen? If there is, then maybe the behaviour is by design, or maybe there are situations that the tests don't account for. The amount that can be learnt from this type of inspection goes far beyond that of a normal code review, where you see what you expect to see rather than what is actually there.

You can also learn a lot about how to write code from this. If a particular pattern is hard to understand this will become very obvious at this stage, and you can consider other patterns in the future. You can also spot what is a good name and what isn't. At this stage if the code is quite complicated I will often refactor it. This is particularly useful if there are no unit tests as refactoring will require you to write some.

I'd say the majority of bugs I look at will be found and understood by this point, usually much more quickly than it would take to fire up a debugger. Plus my understanding of the code will be greatly improved.

If I still haven't figured it out, now is the time to fire up the debugger. But this is made much easier due to my increased understanding of the code. I know where to put break points and have an idea of what I should be seeing.

Where else could this bug exist?

It always surprises me how often the same bug occurs more than once within a codebase. Patterns of usage tend to be copied and reused. The most obvious benefit of looking for other occurrences of a bug is that you may uncover another bug in your software, but it also gives you the opportunity to increase your understanding of the code and possibly improve it. Looking for these bugs you may find alternative approaches to the problem. If the bug is in business logic you may find DRY principle violations, or you may find ways of simplifying the problem so all places can be cleaned up and improved.

How do we reproduce it?

Write a test. This could be a unit test, an integration test or an acceptance test, which one really depends on the bug. Unit tests are light, and easy to implement, but acceptance test have the advantage that they are easier to show to the user and get them confirm this is the behaviour they expected.

Fix, review, push the changes.

Go home.

OK, now I've finally got that post out of the way, I can get on to the interesting stuff - how to make this process easy.

Monday, 20 August 2012

Debugging (and why you shouldn't do it (yet))


I hate debugging!

I don't mean the removing of bugs from software, I mean firing up one of those nasty debugger applications like the one in Visual Studio, or WinDbg. The ones that run your software like it's on some kind of life support machine.

I know a lot of people enjoy it. They must do. They've spent years learning all the debugger tricks, all the keyboard shortcuts, how to set complicated watch and break points, they even know what "~*kp; ~*e !CLRStack -p; ~*e !dso; !SyncBlk" does in WinDbg. You wouldn't go through all that if you didn't enjoy it.

But to me it just means I'm too stupid to understand what's going on without having it spelled out to me step by step. There will be times when you need to resort to a debugger, but there are also some pretty good reasons to avoid it:

Reproducing the bug

If you want examine an issue with a debugger the first thing you need to do is reproduce it. This is not always easy, sometimes the steps to reproduce the bugs are not obvious, they may require being on a live system, may require some data that might be sensitive for other people or may even require some piece of hardware that you don't have. All these things can make using a debugger, time consuming and expensive.

Heisenbugs

Heisenbugs are where the act of trying to observe a bug makes it go away. The term is great if you want to annoy physicists, but it is in common enough use now that they know to just put up with it. There is a tendency to put these issues down to bad luck or "timing" issues, but there are also features of debuggers that can cause them, for example, in .Net attaching a debugger to a process changes when the garbage collector considers objects to be available collection. Most of the time you don't notice this, but have some badly behaved native code mixed in and you will come across it eventually.

"Insert fix here" coding

Debuggers give a very deep view of the software, and when your down in the noughts and ones it very easy to miss where you are in the architecture. This can lead to what I call "Insert fix here" coding. Your debugging a problem, stepping through a method and see that the issue is because numberOfDoohickies is 3 when it should be 4. Simple fix add numberOfDoohickies++ to the method, bug fixed, check in the code, off we go. Next person comes along they have only 2 doohickies, and the software breaks, developer looks at the issue and find that the method is called with numberOfDoohickies equal 3, closer examination shows that it is always set to 3 no matter how many doohickies the user actually has. The original developer saw that the state was wrong at a particular point and decided it needed to be fixed up at that point, rather than search for the root cause.

I wish I could say this doesn't happen, and it's easy to accuse the first developer of being "unprofessional", but when there's a critical issue you've been debugging for 4 days with a customer threatening to take his money elsewhere, or a deadline looming, it's easy to miss the wood for the trees.

(By far the most common of these must be checking for null to remove a null reference exception that is being thrown, when the variable really should never be null. I've got an entire post planned to talk about that)

Of course this kind of issue causes code to degrade, become overly complex and difficult to understand. These issues tend to become required behaviour of the code as other classes gain Insert Fix Here behaviour in order to work around earlier Insert Here Fixes.

Understanding the code

Bugs are undesired and unexpected behaviours in code, unless your very unlucky the bug is most likely in your code and not the frameworks/libraries you are using. This means there is some behaviour of your code that you don't understand, some nuance or interaction that isn't quite how you thought it was.

This is not good. It's important that you understand your code, adding new features to code you don't understand is difficult. You cannot be certain how your changes will affect other features, this leads to delays and missed deadlines. So how do you understand you code? By reading it! Run it through in your head. When you have a bug to find, identify a point in the code where you know that the state is bad and run the code backwards, very few debuggers can go backwards and fewer still do it well. Speculate over what could be the cause of the bug then look for code that verifies your theory.

Examining the code like this will give you an understanding that you won't get from stepping in a debugger. This will in turn lead to less bugs in your code, and less need for the debugger.

If you've read this far, (thankyou) there's a good chance you've thought "but you wouldn't have this issue if you ...". Well I probably agree with you and I've been collating some my favourite ways to avoid using the debugger. They were originally going to be a single post, but it was getting too difficult to make it small enough, so I now l hope to write them up into a series of blog posts, giving each subject the attention it deserves. Some of the tips are technology specific (most likely C# and .Net), others more general. I'd also love to hear your suggestions, feel free to leave them in the comments and I may write some of them up as later posts.


Monday, 15 March 2010

DevWeek Day One

I’m currently in London at DevWeek, and I thought it made sense to blog about it.  Unfortunately these won’t go up until the weekend as the Wifi at the Hotel is £12.95 for a day! And my supposedly 3G phone is took over a minute to bring up Google.

So, I spent the first day at Neal Ford’s The Productive Programmer workshop.  I’ve seen a few of Neal's talks before so a lot of it was repeated to me, but the content had been updated and Neal’s a good presented who manages to keep it interesting.

The first part of the talk was about maintaining focus while working, some simple things such as not having email open all the time, and turning off balloon tips.  Personally I quite like balloon tips, I find them a quick way of getting information across without distracting too much.  I think the real issue is Windows obsession with telling you about every little thing it wants to do. I don’t want Java updates, iPlayer Updates, Media Centre updates (I don’t even use Media Centre) etc, I just want to know when someone’s broken the build.  Luckily Windows 7 allows you to filter them based on application, so I can have just the ones I need.  That rant aside I find the constant interruptions of email, messenger, and meetings do cause a lack of focused which greatly slows down work.

The second part of the talk concentrated on avoiding unnecessary work, which included avoiding gold plating solutions and automating things whenever possible.  Neal described automation as a holistic application of the DRY Principle.  Which is an interesting idea.  He also suggested that you should automate even when it may not seem cost affective, due to the “intellectual” assets that are gained from it.

After lunch (which was surprisingly good by the way) the workshop went on to talk about Test Driven Design.  It started with a simple example of determining if a number is Perfect, which went on show the advantages of good design that come about from the use of TDD.  I must say I didn’t like the example.  It wasn’t really the way I normally go about TDD (not that I do that much of it) and I didn’t like some of the code produced.  Maybe it’s because I’m a functional software guy at heart and didn’t like the use of ‘state’ to just perform a simple mathematical function.  That not-withstanding the overall point of the section is still very valid, and something I’ve been wanting to implement for a while.

The final section of the workshop was a talk called “10 tips to improve your code”.  I have seen this before, but it was nice to see it aimed more towards .net developers a this helped me understand the points a little more easily.  The section “10 corporate bad smells” was a little depressing. I think we probably got 7/10, only really missing out on a perfect score because we don’t do web development.  Certainly “We don’t have time to unit test were too busy debugging” is one of my personal bug bares.

All in all, a very good workshop, with plenty for me to take back and try to implement at work, and also in my daily life.  Tomorrow is the key note, which I’m sure will be great, and the drinks tomorrow night are on Microsoft.  Can’t be bad. :-)

Saturday, 13 February 2010

Building a web application

There has been a lot of buzz about Personal Kanbans recently, many of my favourite bloggers and tweeters have been recommending them as a way of organising work and becoming more efficient.  So I’ve decided to give it a go.
But being a software geek, I don’t want some cumbersome board hiding in a dark cupboard.  (Our office is open plan, so there is no wall space)  I want it online so I can access it from anywhere.
I had a quick look on the internet to see if there was anything that looked interesting, and then realised using someone else’s is no fun, I should write my own.
So the decision was made.  I’m going to write my own Kanban website, using the following tools/techniques:
  • Ruby
  • Rails
  • TDD Development
  • Open source
  • Cloud hosting (if possible)
  • Blog about it.
The only problem is, I have no real experience in any of these. (As you may have already guessed)  Which is what this is really about.
OK, building my own online Kanban board is not the most useful of ideas, but learning the list of things above is.  The Kanban thing is an excuse.  Not that I’m giving in on Kanban at all, in fact I’ve started a board just for this project:
P1533_13-02-10
I plan to blog regularly on how the project is going and any interesting info/resources I find on the way.
Keep watching the blog for updates.