So, after going through the signup process, I finally gained access to this episode. Leading up to this review, I have watched the episode in total 3 times: the first time I watched straight through while taking quick short hand notes, the second time, I watched portions of it in succession, stopping to take more in-depth notes, the third time, I watched it to fine-tune my comments on specific sections.
Since I’ve been ragging on Tekpub, it is only fair to start off with a positive general note.
Tekpub’s Production Quality
Rob has been doing these webcasts, both at Tekpub and previously at Microsoft (and for all I know, before that as well) for years now, and one thing that is clear (pun intended) is that he has it down pat. The audio and video quality is top notch, produced in 720p High Definition. There’s no squinting or struggling to hear, it’s crystal clean in every respect.
This isn’t a trivial thing either. Although the cost of the episode was ‘only’ $12, the quality seems to me to be equal, if not better, than productions you can find elsewhere for more. When he mentions on his blog home page that “Tekpub provides superior-quality screencasts”, he isn’t joking. There’s no false bravado involved, he delivers on that claim.
But, of course, the true value comes down to the content provided. As they say on Iron Chef, “let’s get it on!”
But, of course, I must first preamble and digress.
Rob is in many ways, for better or worse, the epitome of a ‘polyglot programmer’ and is best expressed in his own words (from his web site):
“Developers tend to isolate themselves and cling to a given technology which they want to excel at in order to feel a sense of mastery. I'm just the opposite: this industry moves quickly! If you cling to a given technology, you will be left behind rather quickly.“
There’s been the occasional running joke that Rob sometimes appears to lack….”stick-to-itiveness”, as he tends to jump around a lot, but you can’t fault his enthusiasm for what he does, and Tekpub, by all accounts, seems to be a very successful endeavor.
Plus, he’s got that crazy smooth soothing voice. That’s just genetics, but no one can reasonably complain that he’s hard to listen to.
Brad has been at Microsoft for quite a while now, and is part of the group that produces ASP.NET (in its various flavors). He’s also well known for his co-creation of xUnit.Net, a leading unit testing framework in the .NET space (actually, I don’t know for sure if he is technically the co-creator or ‘just’ a lead contributor…whatever). For that reason alone, he’s an obvious candidate for TDD expertise. I’ve been a subscriber to his blog for a number of years now, and his writings have always been, in my mind, insightful and informative.
Given that the webcast involves a set of requirements that Rob actually used to develop the subscription system for Tekpub and has Brad as the TDD expert doing the coding, there’s no reason to think that any other webcast involving TDD could be better suited to showing its benefits (or lack thereof), especially since it is promoted as being a ‘real-world’ demonstration of it.
Which does raise one question….
Can you actually do a demo of TDD that accurately reflects how it gets done in the real world, in 65 minutes?
If you’ve ever spent time around various groups online involving DDD, you’ve no doubt encountered something like the following request (paraphrased): “Could someone create an example code base that exemplifies DDD and all its specifics? Thanks.” The daoists have always grossly exaggerated the point, but a legitimate point that they do make is that DDD involves an ongoing process, and a static codebase can never really encompass that process. The development, for instance, of the ubiquitous language (which is impossible to develop in actual fact, but I’ll not digress on that now) is something that involves an iterative and collaborative process that can’t possibly be captured in a static codebase.
In a vaguely similar fashion, TDD is a design process, and one that usually extends across a fairly significant period of time, certainly one longer than 65 minutes. Almost by default, it is generally impossible to accurately reflect that process in a 65 minute webcast. I don’t think it is fair to hold that against Rob and Brad, given the constraints of the media.
Having said that, I do think it is entirely fair to point out that, despite what Rob and Brad say or convey, this webcast does not accurately reflect a real world practice of TDD if only because the code that Brad writes, as far as I understand it, is not code that is or has been migrated to a production environment. It is code that is written and then, I assume, thrown away.
At best, this is a faux real-world practice of TDD, conveyed as if it were real-world. This might seem like a quibble, but I don’t think it is. This will become particularly important when it comes to the ‘curveball’ where the episode supposedly gives a real-world example of a change in requirements, in theory to test how TDD handles a requirement change. The extent to which this ‘curveball’ actually represents the real-world is important, especially given how much importance Rob gives to it.
Nevertheless, since Brad’s TDD expertise is (in my mind) unquestioned and unquestionable, it is probably the best that can be done, given the constraints of the media involved, so I think it is reasonable to accept how he codes in the webcast as (at the very least) indicative of how TDD would be practiced when designing a new billing subscription system similar to what Tekpub uses today.
Given my existing biases against TDD, what were my expectations for this webcast, and how could I possibly give an unbiased review of it anyway, since I’ve gone on record thinking that TDD sucks?
This is, admittedly, a tough one. Well, sort of a tough one.
A base line expectation was that the webcast would show a reasonable demonstration of how TDD works in ‘real world’ practice. As I’ve already mentioned, the fact that this webcast is not really real-world is an issue. However, I think that Brad’s pedigree really clears that as an issue. It was a fair test of how an expert in TDD practice approached a set of requirements as was given to him. Did Brad’s code make it into production? No, but, in order to judge the process Brad used, that’s worth setting aside.
Did I have the expectation that, having watched this webcast, I would reverse my negative judgment of TDD? No, of course not, and it would be unreasonable to think so.
What I could do, and do fairly, is to judge the webcast both in terms of what it stated it would do (describe how TDD would work in something like a real world session) as well as in terms of how I think that TDD matches up against other methodologies like BDD, given the parameters of the session.
The actual webcast, already
As Rob makes clear when describing his ‘full throttle’ webcasts, there is not a preamble where TDD is explained in any detail, they dive right into it. If you don’t have any background on what TDD is and how it works, you might be lost. You should keep this in mind.
The goal of the webcast is straightforward. Brad is going to do a TDD session where he attempts to implement a Subscription Billing System that (according to Rob) mirrors the system that Tekpub itself uses. As I mentioned above, the ‘squishy’ part about all of this is that Brad is not actually implementing a production system, but just a reasonable facsimile of what already exists. This is important to keep in mind, as we shall see. The ‘big ticket item’ is that Rob intends to throw Brad a ‘curveball’ mid-way through the session with a change in requirements, in order to see how the TDD process can handle it.
I’ll be commenting ‘in-time’ with the process as important points arise.
Right out of the box (1:00+): there was an out of band discussion about what the up-front requirements were. This is actually a sign of what can go wrong with TDD, but let’s let it go for now, since the list of requirements Brad lists out seems reasonable.
We’re going to let the name fall out of it (2:21+): this is also a sign of what can go wrong with TDD. Within DDD, there is the idea of the ubiquitous language, where the developers and the business should share a common language. Though the idea of the ubiquitous language is an idealistic construct that can never be attained perfectly, attempting to attain a ‘ubiquitous enough’ language is one of the most important things that you can do. A lot of what follows will involve Brad trying to find good names for things. In theory, Rob is the business and so he should be working with Brad on this. Given the lack of explicit communication between them, Brad’s ‘tryings’ are as good as one can expect.
Domain classes are defined inside of the test class (3:45+): given how Brad is proceeding, this makes a lot of sense. Even without any added ‘productivity enhancement tools’ (such as Resharper), it is trivial to move any classes that ‘meet muster’ at some point into their ‘proper’ place outside of the test class. This is an important point, as it is beside the point at this state of the process to worry about how the overall class structure of a solution will take shape, especially since that shape is often dependent on organizational/team standards that aren’t relevant at this point.
‘Well, I think the way that you intend this thing to be…’ (4:00+): again, we see a problem. It shouldn’t be part of the developers’ job to guess at this. Rob should be working with him collaboratively to determine how the thing is intended.
Brad is letting his stream of thought bleed right onto his code service (6:30+): this is, depending on how it is meant, potentially wrong. The design process should not be up to the developer to “throw things” around, at least to a certain extent. Technical implementations are not things that business users need to have any knowledge of, or input into, but the upfront requirements, which should be solidly designed based on business requirements, should limit the amount of ‘throwing around.’
However, this is probably one of the toughest things to tackle when it comes to software development, and it exists in any form of ‘advanced’ methodology, be it TDD, DDD, BDD, etc. How do you figure out how to get your technical implementation to implement your business requirements, with the least amount of ‘friction’ on both ends? On the one hand, as I’ve already mentioned, having a developer ‘throwing around’ things doesn’t seem to be a very efficient way of proceeding. On the other hand, stopping at each point of a particular technical implementation to ask, e.g., a business analyst his opinion isn’t any more efficient.
BDD claims to offer a way out here, and I think it happens to be the right way, and it involves finding a ‘common ground’ where the two sides of the development coin can meet, which is almost always through the UI process that involves (at the very least) how the overall business process will work.
Brad is talking to himself a lot (8:50+): which he shouldn’t be doing, he should be talking to the business.
“I’m not feeling all that great about the code that I am writing here” (9:45+): this is a red flag.
Rob: “You’re brainstorming in code” (10:55+): this is bad. As a developer, you should be developing clearly defined requirements. There is no sense that this brainstorming will survive as development proceeds.
“Look at that, we already have functionality” (12:00+): well, sort of. Brad has constructed method chains that meet the expectations he set up through mocks, that is true. But does it actually show tested functionality that meets the business requirement?
“As soon as I see something three times, I start thinking that I want to see it somewhere else”(18:55+): I’m not sure why he hits on the same thing that I do, but I think the exact same thing. If I need to copy code once (so that it is in two places), I’m okay with it, but once it gets to a third instance, I take that as a trigger to refactor it to somewhere common.
Creating a TestableBillingProcessor (20:50+): the second you start doing things like this, you can end up testing your test classes and not the actual classes. If you are good, this isn’t necessarily a problem, but is one of the inherent failures of unit testing when done wrong, as is usually practiced. The test classes start to make available what would usually be private classes in order to make the tests pass, which means that when you try to create BDD-style tests, you have an ‘impedance mismatch’.
Design Notes in Code (32:45+): although there is nothing inherently wrong with writing notes in code when you are not sure what to do (and in fact, it’s pretty obvious that this is something that you really should do), what it does in this case is point out how unclear the requirements are to the developer. If it is unclear at this point what the meaning of a domain entity like ‘Customer’ is, it is clear there is a breakdown. Whatever one thinks of the notion of the ‘ubiquitous language’, the concept of a customer should be clearly defined across both the business and developers.
Curveball (37:20+): subscription changes to allow for yearly. Okay, this is a curveball….only because the previously described requirements are invalid? Okay. Is this a test of TDD specifically? Yes, because the initial tests all worked under the assumption that subscriptions only had to consider months.
Backseat Coding (41:30+): Rob’s ‘helpful suggestion’ is what the development process should incorporate as interaction with the business. The developer should not be trying to figure out how to change the domain model to decide what an annual vs. a monthly subscription is, as it isn’t the developer who knows what this means. What does a ‘subscription’ mean to the business, in all of its forms, and how should it be tested against? This isn’t a thing to be decided by a developer.
“That is actually a bad test, false positive” (54:00): one of the hardest things to do when practicing any sort of testing methodology is to avoid these, and to find them when they occur. Because of how BDD works, you are much less likely to encounter these, as the interaction from the UI that typically defines them makes it harder to miss. However, there is nothing that prevents them here.
Emptying Customer Entity (56:40+): it’s a legitimate refactoring to get rid of information from an entity when it is no longer needed. It should not be done from the developer for something like ‘Customer’ which should be an entity that is understood across the business.
I inverted the logic (1:02:20+): this is something where pair programming helps. I’ve made the exact same sort of error countless times, in this case, I was yelling at the screen that he inverted the logic. Usually, it is someone else yelling at me. The fact that the tests failed is a clear sign that the tests were well written.
It might seem to be false praise, but the audio-visual quality of the webcast is unparalled. The small price ($12) that I paid for the webcast was, in those terms, well worth it. Tekpub delivered over and above what I expected here.
Of course, over and above audio-visual quality, you have to take into account the quality of the content provided. Here, things are mixed, but for obvious reasons.
Taken for what it purported to be, the webcast seemed to be as high in quality of a demonstration of what TDD is, given the constraints of the media. Watching Brad work through the vague requirements as given to him, you could see how well he worked through those requirements.
Having said that, I found that the webcast did nothing more than to highlight the deficiencies inherent in TDD. Brad spent an inordinate amount of time ‘throwing around’ ideas that should have been determined through interaction with a business partner.
Trying to find a common ground between the activities that developers do which should not involve business partners, and those that really should involve business partners, is not easy and there are no hard and fast rules, but I think a few things have proven to be true. Developers should not be guessing at what requirements are, and should not be trying to determine them on their own, instead they should be actively working with business partners to figure them out. A BDD style process allows every interested party to see how the code actually works in the real world and see if it works as expected. TDD doesn’t really allow this by itself.
I will include my usual caveat to my general negative take on TDD: if you are building a framework that can be used in many multiple and unknown ways, TDD seems to be the 2nd best way of designing a code base (the best way involves having a developer who is also a business expert, but this is very hard to achieve).
Is the webcast worth it?
The simple answer is, “yes.” I can’t say that I have seen every type of webcast created by every possible source, but Tekpub’s webcast quality is easily the best I’ve seen from a technical level.
If you don’t share my negative opinion of TDD, then it is also worth it, simply to see a top-quality developer practice his craft. By nature, developers are a disagreeable lot, so I’ve no doubt that someone more practiced with TDD than I that also has a high opinion of it might have some criticisms, but, I don’t really see them. In the short time span that he has to work on the design in question, Brad works quickly and competently.
If you do share my negative opinion of TDD, it could also be seen as worth it, if only to see the pitfalls that face a developer doing TDD as opposed to the superior BDD style.
Especially at the price point for the webcast, it’s a good value.