reAre you smart enough to do without TDD
Daniel has posted a reply to my post, titling it: Are you smart enough to do without TDD. I more or less expected to get responses like that, which was why I was hesitant to post it. Contrary to popular opinion, I don’t really enjoy being controversial.
There are two main points that I object to in his post:
You see, Ayende appears to say that if you're smart enough, you'll just know what code to write, just like that. Ergo, if you don't know, maybe you're not that smart and hence you would need this technique for losers called Test Driven Design/Development.
That is not what I said, please don’t put words in my mouth. What I said was: “The idea behind TDD is to use the tests to drive the design. Well, in this case, I don’t have any design to drive.” Combine this with my concepts & features architecture, where the main tenets is: “A feature creation may not involve any design activity.” and it should be clear why TDD simply doesn’t work for my scenario.
And his attack on Rhino Mocks:
Moq vs Rhino Mocks: he [Ayende, it seems] read the (useless IMO) literature on mocks vs stubs vs fakes, had apparently a clear idea of what to do, and came up with Rhino's awkward, user unfriendly and hard to learn API with a myriad of concepts and options, and a record-replay-driven API (ok, I'm sure it was not his original idea, but certainly it's his impl.) which two years ago seemed to him to stand at the core of mocking. Nowadays not only he learned what I've been saying all along, that "dynamic, strict, partial and stub... No one cares", but also is planning to remove the record / playback API too.
This is just full of misinformation. Let me see how:
- Rhino Mocks is 5 years old.
- Rhino Mocks came out for .NET 1.0.
- Rhino Mocks actually predate most of the mocks vs. stubs debate.
I keep Rhino Mocks updated as new concepts and syntax options comes. Yes, AAA is easier, but AAA relies on having the syntax options that we have in C# 3.0. Rhino Mocks didn’t start from there, it started a lot earlier, and it is a testament to its flexibility that I was able to adapt it to any change along the way.
Oh, and Rhino Mocks was developed with TDD, fully. Still is, for that matter. So I find it annoying that someone attacks it on this grounds without really understanding how it worked.
More posts in "re" series:
- (19 Jun 2024) Building a Database Engine in C# & .NET
- (05 Mar 2024) Technology & Friends - Oren Eini on the Corax Search Engine
- (15 Jan 2024) S06E09 - From Code Generation to Revolutionary RavenDB
- (02 Jan 2024) .NET Rocks Data Sharding with Oren Eini
- (01 Jan 2024) .NET Core podcast on RavenDB, performance and .NET
- (28 Aug 2023) RavenDB and High Performance with Oren Eini
- (17 Feb 2023) RavenDB Usage Patterns
- (12 Dec 2022) Software architecture with Oren Eini
- (17 Nov 2022) RavenDB in a Distributed Cloud Environment
- (25 Jul 2022) Build your own database at Cloud Lunch & Learn
- (15 Jul 2022) Non relational data modeling & Database engine internals
- (11 Apr 2022) Clean Architecture with RavenDB
- (14 Mar 2022) Database Security in a Hostile World
- (02 Mar 2022) RavenDB–a really boring database
Comments
As I said "...if he had sat down with a blank project, two years ago...", so I fail to see how being 5 years old or coming out for .NET 1.0 has anything to do with what I said.
And if Rhino has 5 years, it does NOT predate the debate. Even Fowler's often cited article on the matter ( martinfowler.com/articles/mocksArentStubs.html) is first dated as 08 Jul 04: First published.
"The main tenet is: “A feature creation may not involve any design activity.”
I stand by my idea that all you've done is invent a fancy name for an interation test and trying to use that as an excuse not to write actual unit tests. I say you still need both. Either one is a risk without the other.
Note that I'm defending unit tests, NOT TDD in this particular case where "feature creation" is not a design activity (i.e. you have a whole infrastructure that allows a business app developer to just implement IRule and that's it). You still need unit tests.
Daniel,
Starting from blank slate would mean having to re-do a LOT of stuff. Things like partial mocks, multi mocks, delegate mocks, etc.
That would be truly stupid thing to do. Adding the AAA merely added, not substracted, and we kept all the power in Rhino Mocks.
Interaction tests? That is most certainly not what I am doing there.
And when using my approach, writing a unit test is stupid, it is actually harder to do than a scenario test, and doesn't tell you much about what is going on
Just keep Mocks&Stubs separated. That's the thing i dislike about Moq - there's a bunch of mocks in my tests despite that test is supposed to contain 1 mock only.
P.s. Ignore Daniel.
"Either one is a risk without the other."
Sometimes risks are worth taking. When TDD gets in the way of design flexibility, you have to weigh your development time vs. time spent fixing bugs in the future. Integration tests are the sweet spot in the middle. You test your entire system as a whole, writing fewer, less-brittle tests, but still catching the biggest bugs. When smaller bugs appear, you write regression tests for them. When you are forced to write code that may be especially bug-prone (complex logic, regular expressions, etc), then you write some lower-level (maybe even unit-level) tests for it.
There's always risk. There's a risk a meteor could come through my ceiling and strike me dead, right this instant. But you don't see me adding armor plating to my roof, because in all practicality I don't need it.
We wouldn't read you if you weren't so good at being controversial and relevant at the same time...
Well, that's what you get if you go against religion. TDD is a lot about "it _will_speed you up" and "it will life merry and happy", lot of guys have sold this idea for long, most of them have little to no actual measurements to back up their bidding. Note that I don't contradict those claims, just that like always with any other shining sd-methology, evangelists attack and zombies follow. Remember RUP and UML? Like usual, software engineers are passionate about development strategy and pretty crappy when it comes to tactics and actual, verified measurement of their work. U know, this "i'm an artist" "i'm an engineer" thing depending on the suitable context.
I find the scenario model of doing testing on a higher level that you have talked about very interesting. Not as a complete substitute for TDD (which is not what I understand you propose) but just as another way of doing BDD like integration testing (or what ever you call it, doesn't matter).
But it would be very nice with complete examples that show the scenario runtime, the application, etc, and how this can be applied to an MVC or WPF application.
Ayende,
I think Daniel meant to say Integration tests (not interaction). I think your scenarios are of an integrative nature.
It is interesting though that people witness your posts as controversial while you are not even really criticizing any of the current practices, merely adding something new to the plate worth thinking about.
People should consider that a design and process evolution cannot be complete after, what, not even a decade of putting those things (testing, mocking, etc.) into practice. Those things are still evolving and the full story is not known yet. It seems we are just now reaching the stage of craftmansship. If history is anything to go by, we haven't reached the age of Engineering yet in software development (oh dear, what have I said?!).
Hence the correct reaction for now in many areas of software development seems to me: Find your masters, see how they do it, compare and use their methods and draw your conclusions. Thank God many of them are willing to put their experiences onto the web.
@Nick - Integration tests are the sweet spot in the middle. You test your entire system as a whole, writing fewer, less-brittle tests, but still catching the biggest bugs.
Yeah buddy!
www.idesign.net - C# Coding Standard v2.32 - page (8) - item (14)
Assert every assumption. On average, every fifth line is an assertion.
I load my programs with Assert's. Assert arguments, Assert return values. Gives me warm fuzzies everytime I press F5.
I also log everything with SmartInspect. Client has a problem, send me the log. It makes debugging a complete no-brainer. A complete no-brainer. Almost boring.
Between these and unit test as needed, sleep comes easy, software is stable and runs as expected, and client's are happy.
Rocket science isn't always needed to achieve rocket science results.
I don't see what his issue is with Rhino Mocks. It supports R&P and AAA.
This is why I advocate the Do Exactly What You Have To Do Exactly When You Have To Do It methodology (DEWYHTDEWYHTDI), of which I am a licensed Invincible Grand Master. I will teach it to you for one million dollars.
Ayende: "I don’t really enjoy being controversial"
That's too bad, because I think if you did enjoy it the world would be in for a lot of hurt. Shake up the status quo, and all that.
I think most of the readers here are just happy to hear your thoughts.
I'm clever enough, but I still do TDD for people who aren't...
The fact that we're having arguments...err, discussions about TDD and/or mocking/isolation frameworks makes me smile. I don't care who "wins".
As long as people have their preferred framework and are even using one is good enough for me. We'll figure out all the details later, but the positive note is that there even is a discussion about this.
It amazes me how so many programmers have a tendency to learn about some methodology or set of rules and stick to it as if they are the ten commandments. They also feel the need to crusade against those who dare to 'disobey' these rules. I battle this everyday at my company and it is exhausting. Ayende you have fearlessly battled the entire internet and that makes you a freakin hero!
As Frank corrected, I meant to say Integration test, of course, which is what your scenario tests are in reality.
Ayende:
Precisely the myriad of concepts people have to learn to use the tool and increasing the learning curve. I'm not saying you should not have reused what you had. I'm saying that the public API could use a severe revamp, what you seem to be doing for 4.0, which is a GREAT thing to do. Backs compat for an OSS project that wants to stay at the edge of programming paradigms and styles, should be low pri. (maintained if possible, provide legacy wrappers if possible, etc.)
Just to reiterate: I'm not opposing to have integration tests. I do believe people may use those as an excuse not to do TDD. And you should not encourage that. It's irresponsible.
If it wasn't clear from Daniel's post, it certainly is after his comments here—this is just a spring-board for Rhino Mocks bashing. If you don't like it, fine, don't use it. Don't be crappin' on Ayende for not completely refactoring it to suit you though.
Daniel,
Those aren't concepts, those are features. Features that make using Rhino Mocks possible in complex scenarios.
Backward compact is essential for long term projects. When you have 1000s of tests using Rhino Mocks, you really care about this.
Sean: it's unfortunate that you end up picking on the one thing that is not the key of my post, but whatever.
Ayende: yeah, it's so important that you're explicitly letting everyone know that Rhino 4.0 will break compat in a big way.
Don't be hypocrite. You know there's a limit to back compat. You know how that ends up by just looking at .NET BCL.
Daniel,
Rhino Mocks has 5 years of backward comparability.
One of the most frequent requests that we got for Rhino Mocks 4.0 is backward compact, and we intend to deliver on that.
Feel free to ignore this for Moq 2.0, see what would be the result.
You mean your entire first "proof" and the main content of each of your comments here? As others noted on your blog that "one thing" ended up detracting greatly from the "key" of your post. The comments here only add to that, making it look like the entire point was to bash Rhino Mocks, I assume in favour of Moq. That is indeed unfortunate.
Daniel:
We often disapprove when people blindly follow the patterns and practices that Microsoft lays out for us, but it also applies to everyone else who is passionate to share their opinion. Somebody who follows what Ayende says without first thinking and drawing their own conclusions, deserves everything they get. We are not sheep, and individual developers should not feel they're unable to voice their opinions for fear of misleading people.
Feel free to disagree and debate all you like, that's one of the great things about our industry, but it's not your place to embue responsibility where none is appropriate.
Comment preview