Tag Archives: Clean Code

Roulette Kata – exploring the affect of Time and Randomness in TDD

I did this Kata in response to a challenge set by @jjefries1 here
attempted by @RonJeffries here

For ease of reference the summary of the kata is repeated here;

A roulette wheel has numbers from 0 to 36. A spin of the wheel takes 20 seconds and leaves the ball on  a random number.

Design and implement a roulette wheel using TDD. Think about how using time and random numbers affects your design. Consider how much functionality each test covers and what responsibilities you are testing.

I wanted to drive this in a way where I did not need to mock out clocks or random number generators. To do this I thought that a pattern I have seen used extensively before would be suitable; where the generation of tick events was the responsibility of one class, whilst another had the job of responding to those events. Secondly I planned to  going with the model of “Object’s send messages to share data” so I knew straight away that I would be looking at a tell don’t ask approach.

The first notes I made on the kata were:

This is event based so avoid “World” stuff in test/codelets and to try for public methods are have void return types.

That about constituted the amount of “up front design I did before hitting the keyboard.

My very first failing, as opposed to not compiling,  test looked like this;

Note that at this point I am not taking any interest in time at all. Only that the observer is notified that the wheel has stopped after the spin.

I questioned where to go next and in writing my summary from the kata on cyber-dojo I think I went the harder route to start with. I took on verifying random number outputs, this took several goes round the red/green/refactor cycle and the final test I ended up with was a bit of a behemoth;

To push the design forward my next test looked like this;

This as you can see led to some changes in the interface. Which I didn’t jump straight to but my RouletteWheel class was starting to take shape;

There were quite a few more evolutions of this but the next interesting bit of work to talk about on a TickProvider class, something to generate those tick events

Again we are getting the basic communication right without worrying about timing.

to get to that we eventually ended up with;

Finally we got to the point where we needed to wire up an assembly of the RouletteWheel and the TickProvider. I did this by testing in TTDAIYMI (TDD as if you meant it) style writing the code directly in the test before extracting to a static method on RouletteWheel

The TDD approach has led my final code I think to show good separation of concerns between the generator of tick events (TickProvider), the consumer of those events (RouletteWheel) and the consumer of the stopped event that gives the final location of the ball (WheelObserver). This last one I particularly like as it totally separates presentation from the model, its also easy to envisage how the code could be adapted to publish intermediate events whilst the wheel was “spinning”.

No doubt someone will point out some horrendous threading (or other) bug, please note this is a Kata or practice and I didn’t pair on it. But if you do spot one can I suggest you respond by proposing a test that would expose it? Remember TDD is not about passing when software works, its about improving your design and as a bonus you get some tests that should fail when it doesn’t behave as you intended. I hope I showed that here.

For the full gist including test classes see below;

gist https://gist.github.com/daveneedstoknow/4cbb6a7d707d8efe4cb5fff1ee748923

You can also see my working on the excellent cyber-dojo here I hope no-one will make further changes at the time of writing my work goes up to revison 106. Note that revisions after that may not be mine.

You’ll see (as is my typical experience of TDD and coding in general) that progress is not quite as linear as some explanations will have led you to believe, including here 😉

The total time I spent on this was around the 3 hour mark so higher end of allotted time (I took a break in the middle to teach my nephew some TDD 🙂

I enjoyed the Kata, thanks to @jjefries1 for suggesting it. I tackles some of the more challenging things in TDD but I think it also shows that if TDD is followed it does give you that nudge to a better final design.

Advertisements
Tagged ,

Why I’m fed up with people claiming TDD is Snakeoil

Clark_Stanley's_Snake_Oil_Liniment

I just read Itamar Syn-Hershko’s  response to Uncle Bob’s Giving Up on TDD?  (itself  a response to Ian Sommerville’s blog). In his article Itamar proposes an approach to software development that he calls “Spaghetti Driven Development”. To be honest the opening remarks in his post were so maddening that I had to read the rest of the article just to be sure he wasn’t trolling (I’m fairly convinced he wasn’t but if he was, well done, you got me).

I’m not going to defend TDD itself here, as this has been done admirably by many before (eg. http://www.davefarley.net/?p=203) . No, my beef here is the seemingly never ending accusations of “Preaching” TDD from people who don’t know how to use the technique or even bother to try to learn it. I think quite the opposite is in fact the case and it is often they not the TDDist’s who are the preachers.

On to the post that made me write this rant in the first place…

In his article Itamar states upfront :- “I never really did TDD and probably never will.” – Well, at least we know his position on the topic is one held from a self-declared position of ignorance in it.

“I never really did TDD and probably never will.” – Itamar Syn-Hershko

He then goes on to explain an alternative approach to software development giving it the name “Spaghetti Driven Development”.  His approach as far as I can tell is in essence;

  • Write terrible spaghetti code
  • Refactor into something more understandable
  • Then and only then write tests

What the author is perhaps unaware of is that many of us, who are proponents for TDD, have been on a journey through software development and on that journey we have used approaches like this (among others) for many years. But, unlike the author, we found ourselves dissatisfied with the results. Ironically then, it is through our extensive experience of this type of approach, rather than ignorance of it, and through a continued desire for lifelong learning that we have chosen to look at alternatives such as TDD.

From a personal viewpoint I would summarise my ongoing journey in my understanding of software development as follows. Its worth saying that in all these approaches I have been privileged to have worked with many excellent developers and we delivered commercially successful products which I believe were to some of the highest standards achievable with the tools and techniques of the time.

Early 80’s

Write some spaghetti code and refactor it until it was tidy enough I could understand it. No automated tests but who did back then? This was when I was still at school and just beginning to learn how to code.

1980s-1990s

First professional job as an Analyst/Programmer. Small up front design, code and refactor manual testing – some of us were still arguing if “goto” was a good thing back then and COBOL wasn’t just legacy.

1990s-2000s

Big upfront design, starting to use some automated testing but only after development and often by a separate test team (as an aside; it seems this is about the time that somehow we moved away from the analyst/programmer who did everything from requirements capture, through deployment and support to user training and into more segregated roles of DBA/SysAdmin/BA – I’m glad to see the DevOps movement finally starting to bring this back again.  The use of patterns and OO started around here for me, along with a brief foray into Functional Programming in ML.

Early 2000s

Small upfront design, code and refactor, lots of automated testing after the code was written – this is the period where what I practised was closest to the approach Itamar seems to be championing.

Mid 2000s

Present day almost exclusively ATDD/BDD and TDD in line with what’s generally recommended for Continuous Delivery.
Even today I find that too often we have to refactor spaghetti code, almost invariably when encountering a code base which wasn’t test driven. Fortunately for those of us who have seriously undertaken to learn and apply TDD, our understanding of what good and testable looks like has been massively advanced by having done so, but it still hurts.

“Personally, right now, I would not consider hiring anyone into any senior development role unless they had considerable experience with TDD.” – @thinkfoo

The very nature of software development makes comparative studies difficult but we are increasingly seeing actual evidence that TDD and other Lean/Agile approaches to development such as continuous delivery are demonstrably better than the current known alternatives (see Puppet Labs 2015 State of Devops Report for example).

Personally, right now, I would not consider hiring anyone into any senior development role unless they had considerable experience with TDD. Whatever your position on it, TDD has been around long enough and is widely enough practised that, any senior developer, should, in my opinion, have taken the time to learn and properly understand the technique, even if they then choose not to apply it on a daily basis.
Now I don’t necessarily believe  TDD is the end of the journey and perhaps it will be superseded. Indeed if someone has extensively practised TDD and subsequently has ideas and arguments for a better alternative; Fantastic, lets hear about it!  If what you have is genuinely new and valuable, all us “TDD Preachers” would, I am certain, be very interested to listen and learn. But to convince us, you first will need to have used TDD full-time, for a prolonged period, with other skilled practitioners. But unless you have that authority and vision, please don’t risk peddling your own snake oil, I believe it is only serving to confuse the issue.

Tagged ,

One thing: Abstract till you drop!

A code smell is some characteristic of your code that indicates that something may not be quite right with its design. We can use them to gently guide us towards better, easier to understand, more maintainable code. One smell I have found particularly useful to pay attention to is “too many private methods” (aka Methods should be public). Having many private methods can often be an indication that you are missing one or more abstractions.

To illustrate this I will take an example reproduced here from Uncle Bob’s post One thing:Extract till you drop I think that Bob’s approach here is excellent, as far as it goes, but that to really get to “One Thing” we need to push on by seeing what our extracted private methods can tell us about possible abstractions, and to ensure that not only do methods do one thing but that Classes as well should do one thing our mantra should be;

Extract till we drop

then

Abstract till we drop

Continue reading

Tagged , ,

TDD teaches you how to code well

You may have seen the recent   Kent Beck, David Heinemeier Hansson, Martin Fowler discussion on Is TDD Dead? where David Heinemeier Hansson contests that TDD is “poisoning” good designs. My take on this can be summarised with the below diagram;

TDDvsGood-2

Not all Test Driven Code is good and not all Good Code is test driven. But a lot of code (probably most) is neither good or test driven. I contest that to be considered good, code must be both well designed and well tested. Now I could have labelled the above “tested” or even “testable” but I have seen very little code that is written without TDD which gets anywhere near approaching “well tested” or even “testable” no matter how well intentioned the developers. Moreover I believe that by practising TDD you have much better chance of getting to good than by not doing so.

I say this because I have found that people who consistently write good clean code have almost invariably been people who have mastered TDD. Why could this be?

I think the reasons for this is are that in applying TDD you learn that keeping your tests manageable is at least as hard as writing the underlying code. To avoid brittle difficult to understand tests you want tests that test only one thing and you have to balance this with code that is itself manageable and does one thing well. Consequently;

TDD leads you to code that has small interfaces and low cyclomatic complexity.

TDD tells you things about your code; Tests that require a lot of dependant objects to be constructed or mocked are telling you your code has high coupling. Tests that test more than one thing can hint at poor cohesion – classes under test are doing too many things.

Learning about techniques like mocking and stubbing teach you about coding to interfaces rather than concretions.

TDD teaches you about best ways to handle error conditions and exceptions

TDD teaches you about separation of concerns, why for example its beneficial to separate threading from business logic.

As you get practice writing tests you learn that testing multiple layers of abstraction at the same time is hard and intuitively start to understand what layers of abstraction really mean.

TDD also teaches you to understand what it is to be a user of your code and code for the users rather than the implementers benefit.

In becoming a master practitioner of TDD you provide yourself with all these learning opportunities. Some people having done this feel that TDD can occasionally be overkill (Dan North talks about Spike and Stabilise and opportunity cost of TDD here) but it is the very expertise they have gained from TDD that gives them the ability to make this judgement and to proceed in a way that is safe to retrofit tests to. It’s worth pointing out though that most people I know that have have become competent at TDD never really want to code without it (myself included).

So finally if you are wondering if your code is good or bad and haven’t yet mastered TDD I would suggest it probably has considerable room for improvement.  Check out Steve Freeman and Nat Pryce’s Growing Object-Oriented Software Guided by Tests and Kent Beck’s Test Driven Development.  But also check out what good code looks like, understand and apply SOLID read Uncle Bob Martins Clean Code

Tagged ,
%d bloggers like this: