Stuff they taught in Kindergarten… The “D” in TDD

“T” stands for Teddy! That’s good enough for me! Oh Teddy, Teddy, Teddy starts with “T”! Hi, I’m Cliff. You’re here because you wanna figure out what the heck that first sentence is talking about. I’m here because I got side tracked reading an Uncle Bob article which led to my singing a parody of the “C” is for cookie, Cookie Monster jingle. I’m STILL supposed to be working through negative password validation in an Android app but I don’t think I’ll finish in time for a planned demo in 2 days. You might ask “Why am I singing the letter ‘T’ when my title places emphasis on the letter ‘D'”? I’m glad you asked!

I’d like to tell you a story. Once upon a time there was a software engineer who ventured into the land of frogs where everything was green. It was like St. Patty’s day all time which was cool because this guy’s birthday happened to be in the month of March which is a green month. (I never understood why the month of March is always colored green. I suppose it has something to do with the Irish like they all came from Mars and make excellent landscapers or something but I digress.) So this developer *ahem* engineer was living in bliss because there were all of these segmented bars filling up in this magical land, each of which was green. He wanted to share the beauty of this whimsical place with his co-workers but they were all like, “Ain’t nobody got tahm of’ that!” So he goes on living in his shamrock colored habitat for the rest of his life. The end.

Now ask me why did I tell that story? (Again, I like how you ask questions!) Well partly because I sometimes feel compelled to inject random nonsense in the middle of my posts for no apparent reason. However the parody roughly represents my first encounter with TDD, a practice which I am extremely fond of. I want everyone to share in my euphoria but some folks are just wired different I suppose. It’s this wiring that causes some to focus on the wrong letter of the practice. Here we finally arrive at the point. By the way, welcome to the next entry in a series I’m titling “Stuff they taught in kindergarten”. In this series I will cover topics I just learn or re-learned. These are the very same topics my preschool teacher, Mrs. Marzie, covered during my early years. I missed out because I was busy fighting over who gets to play with the Green machine during recess.

“T” is for TESTING. As an avid practicer of TDD I will be the first to tell you that you should never write tests. If you are writing tests you are doing something wrong! When I practice TDD I never write tests or any test code. I hate tests. I despise the word “test”! Ask me how I could feel this way and still actually be a TDD supporter? I’m not a TDD supporter, I lied all this time. I’m a wolf in sheep’s wool. I support the practice but discourage the idea entirely. Let me elaborate.

The word “test” triggers the part of the brain that pulls you away from the most important part of TDD. Check the title to understand where I’m going here. I’ve seen so many well meaning engineers steer wrong because they start to get excited about tests and writing tests and testing their code. (Uncle Bob hits on this point somewhere in the middle of his article and I promised myself I would emphasize this point as the very first part of my blog but I’ve failed miserably!) If you are testing then you are looking for bugs. You are looking for holes in your code and weaknesses. All of this makes absolutely no sense because it implies you have working code. (I need to do an entire other post on the term “working code” because it’s another one of my pet peeves.) When you practice TDD the way it is intended then you don’t have working code. You don’t have broken code. You just don’t have code, instead you have a DESIGN. (Ah, there it is roughly 640 words in and I finally hit the point, design.) With TDD you have a design that you iterate into code that reflects a specific use case. It’s the emphasis on “testing” that turns people away from the discipline of designing. It is the discipline of design that gives TDD its power. When you practice TDD you never write tests, rather you etch a design using a testing framework.

Before I get too far I want to address some misconceptions. In particular I need to disagree with one point Uncle Bob makes:

It’s true that TDD is not going to help you defend against things you didn’t anticipate.

Bob is well meaning and he wants to play nice with others but this is not entirely true. One of the major benefits of TDD is that you have the ability to incorporate use cases you didn’t anticipate into your design through loose coupling and better cohesion. Th most difficult thing you will ever do as a programmer is change code. When you encounter some use that was unplanned you have to make a change to your code to get it to adapt. If you don’t do TDD then I can guarantee that the change is going to cost more in effort than it cost to write the code initially. In many of these cases you build a work around to adapt to the new feature without actually changing the original behavior. If you do practice TDD then you have already established a predictable pattern of creating, changing, and removing code and the cost remains flat. That means it cost just as much to change existing code as it does to add new work-around code.

Getting back to what I said earlier, you don’t write tests with TDD. A test implies there is code with a potential flaw or weakness. With TDD you use a testing framework to express a particular use of code that has not yet been written. (That’s why it’s called “Test First” because you first code with the testing framework but you really aren’t coding a test you are coding the actual use.)

Another misconception:

the way to address that is to work hard at anticipating as much as possible.

I don’t know why people think working harder is the answer to tough problems. It is actually the cause of the tougher problems. If you are working hard at something then there is a flaw in the design. Also anticipating as much as possible is the opposite of what I like to do. I anticipate only what I feel comfortable anticipating and let the detail emerge as my project matures. As an example, I’ll use this Android app I’m currently building. I stopped working on it about 4-5 months ago and intentionally left holes in my design. I was only concerned about the app paths and getting a prototype working. I recently resumed the project and was able to easily cover some of these holes as I explored new unplanned uses of the code. When I originally wrote the code I just didn’t feel like anticipating these uses because they weren’t important. Now that many have become important I am able to address them with a fresh perspective and solve them in ways I wouldn’t have thought of earlier. Had I anticipated these uses I would have written code that would not be as flexible. It’s hard to describe actually. It’s one of those “you had to be there and live it” kind of moments.

I’m not picking on Uncle Bob… I love his writing/articles, and I’ve unfairly taken a couple of his points slightly out of context to drive a broader point. The point is that writing tests and testing code is not TDD. Designing the proper use of code before you implement it is the core of the practice. This is, by far, my biggest pet peeve with TDD and people who try to explain or defend it. I honestly think we should abandon the word test in favor of something more definitive like “specify”. I like the practice of Specification Driven Design where you specify how you will use/invoke an object with a test specification framework. Still its acronym, SDD, sounds too much like STD and could give the wrong idea. I wouldn’t want to announce I am giving a class on SDD or tell folks I got this SDD thing at work. They’d be all like, “fo’ realz??? Yo, keep ya’ distance!”

That’s all for this installment of stuff they probably taught in kindergarten. I’ll see you next time I get inspired to blab about something.

TDD- Is it worth it?

It’s been a long time, I shouldn’t have left you… without some strong code to step to. Step to, step too… step to… (Cliff re-quoting Timbaland re-quoting

I’ve been attending a Srcum certification course led by none other than James Coplien. This guy is fantastic and I’ve already learned a great deal about the practice in the one day I’ve spent with him. Now here’s the controversial topic. Jim, is totally against TDD. If you know me, I am from the polar opposite camp. I had a breif dsicussion with Jim yesterday which I plan to continue today if he allows the time. In the interim I took the liberty of reviewing some of a standard email he sends to people like me who are unaware/unsure of his strong opposing position. The 1st link features Jim in a debate with a person I admire, Uncle Bob Martin from Object Mentor. This debate felt almost identical to my discussion with Jim yesterday and while both leave me unconvinced that TDD is harmful I remain open-minded. I am so open-minded to Jim’s position that I wanted to rush a quick post this morning to explain where I could potentially agree that TDD does more harm than good.

Testing at the wrong level

One of Jim’s primary arguments is that developers practice TDD at the wrong level, the class level that is not responsible for external features and contracts. This leads to code bloat from the test and gives you the wrong architecture from the onset. I whole heartedly agree with Jim on this point and it is something I still find myself doing from time to time. The practice requires a certain discipline and experience that you get only from making this and other similar missteps. In all, your design should come from your specifications or contracts and these should precede your implementation. I believe (without asking him) that Jim would agree with me here.

Poorly factored unit tests

One of the primary reasons TDD fails is because many miss the last R in the RGR cycle. RGR stands for Red Green Refactor. That means you write a failing test (reports red), make it pass (reports green), then you refactor both you system under test and your test code. I’ve made the mistake of not properly refactoring my test code in a hurry to move onto the next thing. Your test code should read like a contract or a usage guide for how to interact with your code. In practice the test code tends to grow rather quickly, which exceeds a developer’s ability to properly maintain it, which leads to the code bloat mentioned above. This step takes discipline and can be easy to neglect even for experienced developers.

Writing too much test or too much code

Following Uncle Bob, the TDD cycle is a tight and minimalistic cycle where you write only enough test to state or explore the current part of the specification you’re working on and only enough code to satisfy that test. Problems arise from writing too much test code without iterating over implementation code which is the inverse of YAGNI, YAGII! (You Ain’t Gonna Implement It.) Also you get into trouble from writing too much implementation code without a requirement or specification to justify it. ┬áThe power comes from the iterative approach to explorative development. As you iterate you uncover pieces of the spec that are not complete which might require discussion with your QA or business analyst and trigger discussions and that leads to an important distinction I’d like to mention. Many people make a distinction between bugs and features. I see them as one in the same. A bug is simply a non-feature or a hole in your spec. It represents some edge case or usage scenario that has not been explored which leads to errant unexpected or undefined behavior. You iterate on these the same as you do your features by amending your spec and filling in the holes in both the spec and your test cases which should mirror your spec.

I have to cut this short now since class is starting. It’s an interesting topic and I’d love to hear more about what Jim and others have to say on the topic.

Classic vs Mockist, TDD vs BDD

I’ve been having constant issues with Behavior Driven Design using xUnit tools. For those that don’t know what behavior driven design means check out Dan North’s introduction. When writing tests you can choose from a number of approaches. I feel I’ve followed an evolutionary chain through the most popular. Most people start with CWT, or Coding While Testing. This is an approach where the tests are written with the code, not necessarily before but along side. People take this “feel good” approach in order to cover their code with tests and to gain confidence that their code won’t break without them knowing why/where. Eventually tests become brittle and break all around and the tests become a burden to maintain. Some people evolve into TDD or Test Driven Design. This is where the test is written first in an attempt to achieve better design. When I evolved this far I was still struggling in the “implementation zone”. That’s where most developers get their mail delivered. The implementation zone is where the major concern is how things work. You can’t rest well unless you know exactly how things work beneath a method call. There are no surprises because everything is understood. Doing TDD while living here leads to “White Box” tests. These are tests that mirror the implementation of the system. These test scream immediately when the system change in the slightest. It’s no fun.

Later I learned about the Behavior Driven approach which lead to my understanding DSLs, or Domain Specific Languages. Actually I picked up my understanding of DSLs when I started using JMock, which is still one of my favorite tools. I started to remember why programming languages were invented. “Code is for Humans” became my mantra. I stopped caring about how code worked and started concerning myself with why code was written. With today’s systems rivaling NASA in their complexity it becomes impossible to obsess over every implementation detail. It’s more natural to trust that something works through an automatable specification that says it works. Its hard to put in English, but there’s a subtle difference in how I look at code compared to how I see most of my co-workers look at code. I rely on a system of trust which helps both in design and in debugging. I digress.

This morning I began reading Martin Fowler’s revised write up on Mocks vs. Stubs. If you do any automated testing of your system at all I demand you read this article. If you’ve read it in the past (as I had) I demand you read it again because it’s updated. If you read it last week then I demand you read it to your 5 year old tonight at bed time. The point is that Martin makes very good distinctions on what he calls classic TDD and Mockist TDD. He explains the difference between state verification and behavior verification. He explains it in a way that shocked me, because I’d classify myself as a mockist. The entire time I obsessed over implementation being secondary to design I see how and why the mockist frame of thought can easily shackle your design to your implementation details. I almost wanted to change ships, jump on the classical bandwagon. However the article very fairly points out several flaws in both approaches while not condemning either. In the end the choice is left to you. Well done Martin. Well done.

I titled this post, “Classic vs Mockist, TDD vs BDD” not to align BDD with the mockist approach though it fits better. The truth is that you can use Martin’s classic TDD style when doing BDD and vice versa. There really isn’t much of a difference between classic or mockist, TDD or BDD. It’s all really a matter of style as all these approaches aim in the same direction. Its similar to comparing Baptist to Methodist religions. There are differences but one is not more true than the other and its the faith or general direction that both point to that makes them equally as important. Here’s what’s really important.

Back to my problem. I posted on Stack overflow yesterday asking the question of how to avoid so many mocks. I have yet to receive a solution to the core problem I’m seeing. If you or someone you know has a mastery of TDD please chime in. I’d love to finally have a good discussion on how to solve a complex problem using the practice. I feel like I’m 80% there but I’m missing one piece of the pie.

TDD and the warm-fuzzy Un-learning curve…

I’ve been interacting with many more developers in my current company than I ever had in other companies over my career. One pattern I’m noticing is the warm/fuzzy philosophy. That is when somebody gets really comfortable with a certain way of doing things then you show them a new thing. Eventually they will find a way to use or associate the new thing with the way they always do things in order to get that warm/fuzzy feeling of, “it’s just like the other thing.” Hi, I’m Cliff. You’re here because you were probably looking for a product like Sham-Wow, Googled “warm fuzzy“, and clicked on a link to my crazy site. While you won’t find anything that sops up 32oz of Kool-Aid from your hard-woods after a three-year-old decided to play monster trucks on the kitchen table, you will get a lesson on how to forget what you thought you knew. Wait a minute, I forgot where I was going with this. You’ll get a lesson on why you should forget what you thought you knew. How to displace that knowledge is an exercise best left to the reader… (You, being that reader… you don’t get much exercise do you? Not with all the online reading and stuff.)

So when I talk to people and explain TDD (hereafter referred to as “the solution”) I usually get the response “it’s kinda like that system I used back at my other job only then we didn’t automate. We were just…”? Better? Honest? More careful? Clever? “Yeah back then we used to catch all of our bugs and…”? Re-fix them? Explain them as features? Double them? I occasionally get responses like, “you really don’t need to test first to get good code.” Let me ask a question. Have you ever seen good code? Chrysler 300 What does it look like? Does it where a tight-knit skirt and flirt from the corner? Does it come with a “HEMI” label, high RPMs, dual exhaust and chrome wheels? Is it tucked between two all beef patties, special sauce, lettuce, cheese, pickels, onions and a sesame seed… What does it look like, really?

What should it look like?
Call me crazy but I believe code (good, bad, ugly, and indifferent) should look like your spec. Do you know what your spec looks like? No you don’t! Because it just changed! Look again. There, it changed again! A decent spec is like a chameleon. It constantly changes colors, shapes, sizes. (For the record, chameleons don’t change shapes/sizes unless you put them in a blender. It has been proven that such a device, when activated, can render a chameleon very small and suddenly change both the size and appearance of the creature.) A poor spec is like a TV guide from 1976. It’s nostalgic to think about what was showing back then but of no use to anybody that wishes to figure out which station to tune to catch Judge Judy at 7:30EST. That is, a poor spec doesn’t tell you what you code should look like right now or what it should look like tomorrow. Did you catch that? I just explained that you need a TV guide to figure out what your code should look like tomorrow… not just any TV guide either. You need tomorrow’s TV guide, well, because it has tomorrow’s TV listings. Let that sink in a moment while I grab some coffee.

“Writing tests is like the ECMO system we had back at Rutherford And Son’s company. ECMO was the Enhancement/Change Management Officer in charge of each project. That person was a developer in charge of reviewing your code prior to commits and…” What was ECMO looking for? “We shouldn’t waste time futzing with tests… We just need to designate a [insert warm-fuzzy here]” What does any warm/fuzzy recreation of last year’s change management solution attempt to find? Defects, violation of practices, and unapproved system calls/libraries come to mind as common things to look for. What does any of this have to do with the spec? What does that spec look like again? “Who cares! We’re about to land some code, man! Plus we have approval for the EZ-Test framework which comes with new improved static analysis support.” (Ever wonder how new-improved some products really are?)

What Bad Code looks like
The unfortunate side effect of warm-fuzzy is that it fools you into believing that you’re creating good code. We all have seen Jeff Atwood’s Horror code examplesBad Code so there’s no question of what bad code looks like, right? Bad code has a smell. We don’t write no stinky code here because we have ECMO! (Trumpets blare to the sound of the Nightly News theme song introducing Brian Williams.) Warm-fuzzy overlooks an important but subtle point of the agile philosophy. Agile is not practiced to get good code, it’s a means of getting correct code. We’ll come back to that point in a moment. Let’s forget warm fuzzy for now. Let’s forget all we remember about ECMO. Let’s forget everything we were ever taught about good code, bad code, Dallas Cowboys and the Indiana Pacers.

The UnLearning Curve
Because technology constantly evolves our understanding of it must evolve. People learn things by association which makes picking up new technology and concepts a challenge. With technology you can flip a bit in a micro-processor and dramatically alter the flow of an application. Subtle changes can reveal brand new concepts that are completely disassociated with our understanding. (Try explaining the subtle change of a pointer variable vs. a regular variable which holds an address rather than a value to a Comp. Sci-101 student who only knows Java or VB.) In short, we have to unlearn to evolve. Remember the goto statement? An entire evolution of sub-routine evangelists had to scrub the planet and assassinate all other developers on the planet before “goto” finally got removed from modern languages. Believe it or not, there’s another similar revolution happening between those who do/don’t program with assignment statements. (Maybe one day they’ll remove the equals symbol from your favorite language… sounds far-fetched but so did dropping goto.) Those who lived by the word “goto” were hung up on it’s warm/fuzzy benefits so much that when you explained a subroutine to them they understood only to the point where it would return back to the caller. You truly had to changed your views/ideas/opinions on program flow and structured thinking in order to “get” subroutines. Simply stated, to learn new technology you often have to dis-remember old technology… the benefits in particular.

The Solution doesn’t care about good code
That’s a strong statement to make, but if you ask anyone who understands the true benefit of any philosophy from “the solution” they’ll tell you that it’s perfectly acceptable to use it with bad code. In fact, some may encourage you to write bad code in order to get a green bar. Better stated, instead of getting the code right you want to get the right code. If I pay you $50K for transportation what will you build me? A car right? Not just any car but a nice sports car with variable five speed transmission, anti-lock brakes, dual suspension and an auto-defog mirror. Nice! Good for you! I’ll go drive you’re treasured car into the ocean because I needed transportation to return to Jamaica and visit my long lost relatives. (What did your transportation spec look like again?) I would have been soo much better off with a shoddy rowboat than I’d ever be with my soggy car. Sure you got the transportation tool right. You even went as far as to pre-load my favorite MP3s. That’s how lots of people work because they’re stuck in “go” mode. Management says go! Get it done!

With software it’s soo much more dangerous because we can be creative and sorta dig ourselves out of the ocean. Many developers, after loading Method Man’s “Tical” to the in-dash mp3 storage, would eventually realize that the delivery date is approaching and maybe they should ask for a destination. I love it when we get to this point because that’s where the creativity truly begins. You might see fins under the tire, or a possible grappling hook that fires to attach to the complimentary aircraft – yet in design. Rarely and only in the most extreme cases does the car get dismantled.

To the left
The solution puts the focus on the left [consumer-facing] side of the code (which is why we lefty’s have so much fun with it!) The shape of the calling code becomes more important than the shape of what others refer to as “the real code”. It feels awkward because we think of ECMO. It feels redundant and slow because we already visited the left side of the equation. We know what we’re doing and we don’t want to waste time obsessing on the left side of the product. How many times should we keep asking “you want me to build you some transportation, right?” So to appease other people who obviously think it’s important, we ask a few more questions, like “where are you headed?” When we get a typical answer like, “far away to see my family” it further underscores the time wasted on the left. We then assume total control of the decision making process because our customer is clueless. “You’re obviously going to need dual overhead cam for speed since it’s so far away”, we think to ourselves. Many of us have gotten so good at it that we could literally assemble half the car before asking a third question.

I would continue my babbling but I have to cut it short because I’m off topic. The general idea is lost up there somewhere I’m sure. For all my people that understand where I’m going here speak out and nobody will care. Nobody will care because you’re expressing your opinion here rather than on Slashdot or Stack Overflow, or some other popular network. Here it’s just you, me, and the chickens… and the chickens have automated regression suites so we should listen to them instead. I now step down from my soap box and yield to the poultry.

iPhony Development – Unit Testing?

I’ve been at it all weekend. Off and on, spawning threads, updating a dumb UI, now exploring Test Driven Design with Cocoa. Here’s an interesting tidbit that I turned up somewhere in the Apple docs last night. (It was past 12am when I read it, I was tired and now I can no longer find it so I might as well be lying to you but…) “Creating unit test targets is not supported for iPhone development…” or so the text read. Why is it that the mobile community thinks they’re so special? Why do they not need unit tests for their software? Am I missing something? I found an article demonstrating how to Test Drive a TicTacToe game in Cocoa and so far it’s been working pretty well. I’m still hitting my random stumbling blocks here and there. My latest blocker comes from the following test auxillary method:

- (void) assertWinnerIs: (int) expectedWinner withMoveInRow: (int) row andInColumn: (int) col {
	int actualWinner = [game makeAMoveInRow: row andInColumn: col];
	NSString *winner = ( (actualWinner == _X_) ? @"_X_" : (actualWinner == _O_ ? @"_O_" : "NONE") );
	STAssertEquals(expectedWinner, actualWinner,
				   @"Move made in row %d and column %d by player %@ should win but returned winner was %@", row, col, 
				   [game valueInRow:row andInColumn:col] == _X_ ? @"_X_" : @"_O_"winner);
	[winner release];

It’s complaining about a pointer type mismatch in my conditional expression. I think I’m being too clever here using ternary operators instead of breaking out the classic if/esle or switch statements. I’m just trying to print out exactly which player is reported as the winner in my test because I like fully descriptive assertion failure messages but at the same time I like more terse code. I hate breaking out verbose if/else blocks if I can avoid it.

On a side note, none of this will do me any good if I can’t run test suites in an iPhone project. Still I’m thinking that I could probably hack around the limitation somehow by creating a Cocoa library project just to get the core logic unit tested then somehow figuring out how to include that unit tested code in my iPhone project. I’m certain there’s a loophole somewhere and I’ll stumble across it shortly. I still wonder why it has to be such a challenge? C’mon, we’re in like, the 27th century or something like that! There’s no excuse for any moder frameworks to be created sans unit test support. I view this as completely unacceptable!