воскресенье, 4 августа 2013 г.

Following is a real-life demonstration of how effective one may be applying TDD to solve tasks under stress conditions. Imagine that you are limited on time, you are under stress and you have a task you've never solved before. Did I mentioned that you don't know the problem domain? How would you tackle this problem? What would you say If I'd tell you to write a test first? Sounds crazy, eh? You have so many things to do and you don't want to waste your time on testing. Afterwards, maybe... First you have to write... What are you going to write first? Remember, you aren't familiar with problem. Write a test.Alright, now the problem statement is as follows:

"Compare two CIDR ranges.

The significant part of IPv4 Address is prefix255.255.255.255/24 notation means that only the first 24 bits of the IPv4 address make up the network mask. The bits which are not included in the network mask are not important.There are several ways to write a CIDR rangeThese representations are equivalent:255.255.255.255/24255.255.255.0/24255.255.255.100/24Comparing CIDR RangesRanges can be in subset, superset, disjoint or equal to each other. Write a code comparing them."

- "Fuck, I never knew what this CIDR notation ment. I should have read about it before. Alright, let's google it. Whoooaaa! I'll read through this for half an hour. What do I do? I've already applied TDD in day to day job, I'll give it a try. First things first, I'll write down what I know about the problem. This is going to be my test list."

CIDR range has prefix and suffix parts;

Ranges with equal prefix and suffix are equal;

Only the Prefix of the IPv4 Address is Significant;

A CIDR Range Has Multiple Representations;

- "That will do for the moment. Which one of them do I pick first? I should pick the simplest one to implement it as fast as possible. The first one is an ideal candidate for Starter Test."

- "Now that the test is written I am going to write the CidrRange class itself. Forgive me Kent, but I am about to jump over one step - I won't Fake It, I consider this code to be an Obvious Implementation and 'll write it straight away. I had lot's of choclate and I can keep things in mind and I have very short time".

- "Green bar, hooray. Time spent? 10 minutes. OK, whats next? The next simplest test to implement - the shortest way to the green bar, is the second one: Ranges with equal prefix and suffix are equal".

- "Red bar. OK, obviously in order to implement desired behavior I can no longer compare bytes, I have to drill down to bits. What facilities does BCL provides for this? I remember BitConverter and also there is a BitArray class. A-ha! This is what I am going to use. The algorythm is simple: Given the CIDR range 255.255.255.255/24 we know that only the first 24 bits of the IPv4 address make up the network mask, - it means I have to take a prefix, turn it into a bit array, take a suffix, turn it into another bit array starting from the most significant bit and perform a bitwise AND operation in order to get a network mask. After I got both masks, I have to perform an operation, that will tell me if there any difference between them. Well, luckily I had lot's of choclate, and it's obvious that I need to perform a bitwise XOR".

- "Arghhh, red bar. I'm toast. Come on, keep it on, I've almost found the solution and I've got tests that will prove it. The broken test is simple - Starter test expects to see bytes in reversed order, I'll fix it in a twinkle".

- "red bar, eh? I was supposed to get a green bar!"After another five minutes in debugger it appeared that I've filled the suffix mask with wrong number of bits and took into account the least significant bits comparing network masks. Fix follows.

when CIDR ranges with exact suffixes differ in insignificant bits, they are considered equal;

when CIDR ranges with exact suffixes differ in significant bits, they aren't considered equal;

CIDR range is a subset of other range if prefixes are equal and the suffix is greater;

CIDR range is a superset of other range if prefixes are equal and the suffix is less;

CIDR range is a disjoint of other range if prefixes differ;

- "Time? Wow, I still got some time left."

This is a real life story disproving the myth of TDD nonproductiveness. Stay tuned as I'll continue my adventures in TDD.Next time I will refactor this code in a quiet and peacful manner.P.S. You can find code here.