A worked example of TDD in D, with some personal ruminations on my own style, and notes on the D language..

John Carter <[email protected]> Mon, 30 Dec 2013 09:40:56 +1300
Newsgroups gmane.comp.programming.test-driven-development
Message-ID <CAFD1m3GGk_sH-FRfMGr-a=RCommW6ebzcHB7+h1B4Y+UJGRYNg@mail.gmail.com>
So I have being doing TDD for years now.

But I started noting I tend not to do it exactly "By The Book".

So as an exercise I tried going back to doing it...

* Very fine grained steps.
* Small change so Test fails - commit.
* Small change so Test passes - commit.
* Refactor so test passes - Commit.

As small as I could.

Oh, and just for the fun of it, I'm learning the D language, so I did it in
D.

So here is the result, complete with a blow-by-blow Mercurial Repository of
every step.

https://bitbucket.org/JohnCarter/roman/src/47ab019ccdf7a4d5d64c1f10ffc7418e67d6f916/roman.d?at=default

* Conclusions from the exercise.*

   1. Very fine grained steps resulted in fewer bugs and fewer backtracks.
   2. Very fine grained steps resulted in better factored code.
   3. Watching others do the same exercise led me to the attitude "adding
   more test cases is Bad". (Slower, hard to maintain tests, more lines of
   code)
   4. Very fine grained steps slowed me down compared to my more usual
   somewhat loose style.
   5. *Thoughtfully adding Provocative test cases in the order of "What I
   need to Handle Next" is Very Very Good.*
   6. *Replacing "Fine Grained Steps" with, whenever stuck, pull out a
   smaller  chunk and TDD that first (with Provocative test cases) works Very
   Very  Well.*


Bottom Line?
In future I will be doing...

   1. Thoughtfully choosing a minimal number of provocative test cases in
   the order that challenges a single new behaviour, ie. A test case that
   requires a single additional behaviour in the code.
   2. I will take the largest steps I can where I can go from test fail to
   test pass in a single change.
   3. Whenever I misjudged and take too large a step, I will factor out a
   smaller function and test and develop that first via the same process.
   4. Factoring out works best like this...
      1. Revert to last passing state, leaving failing test commented out.
      2. Copy pasta the code you wish to factor / enhance into a small
      function leaving original function untouched.
      3. Get tests for new function to pass.
      4. Wire new function into parent cleaning out original copy.
      5. Get tests to pass.
      6. Reenable commented out test... hopefully it passes now.


*What do I mean by provocative test cases?*

For example, when converting Roman numerals.


"I" is provocative.

"II" is provocative.

"III" is NOT provocative, it merely is extra Lines of Code (and hence a
liability).

"IV" is provocative, but a bad choice for next test case as it adds two new
behaviours at once.

"V" is provocative and adds a single new behaviour.

"IV" is now provocative and adds only a single new behaviour.


Conclusions about D.

 I love it.

 It is C / C++ with the worst stuff removed, and the best stuff stolen from
it's competitors.

 If you are serious about industrial grade, high quality, defect free,
efficient programming, you urgently need to be looking at D as your next
language.

 Sigh! Unicode.

 That's not D's fault.

 D handles Unicode remarkably smoothly, but ye ancient 7bit ASCII is always
going to be faster and conceptually easier than variable length code point
UTF8.

 It took a bit of time and effort to get my head around D's template system
(richer, safer, better than C++)

 It took even more time to get my head around Ranges, (again, richer, more
flexible, safer than C++ iterators, more efficient than generators,
coroutines or enumerators.)

 The choices D has made are rich in very powerful, very efficient
implications.

Possibly the most striking is Compile Time Function Evaluation.

If it can be evaluated at compile time.... in D it will be.

And that is startling powerful.


-- 
John Carter
Phone : (64)(3) 358 6639
Tait Electronics
PO Box 1645 Christchurch
New Zealand

-- 

------------------------------
This email, including any attachments, is only for the intended recipient. 
It is subject to copyright, is confidential and may be the subject of legal 
or other privilege, none of which is waived or lost by reason of this 
transmission.
If you are not an intended recipient, you may not use, disseminate, 
distribute or reproduce such email, any attachments, or any part thereof. 
If you have received a message in error, please notify the sender 
immediately and erase all copies of the message and any attachments.
Unfortunately, we cannot warrant that the email has not been altered or 
corrupted during transmission nor can we guarantee that any email or any 
attachments are free from computer viruses or other conditions which may 
damage or interfere with recipient data, hardware or software. The 
recipient relies upon its own procedures and assumes all risk of use and of 
opening any attachments.
------------------------------