Revisiting Edit and Continue

Leon,

if the language features you choose to include will widen the base of users, then it will ultimately be a good thing.

Good for who? Does a larger user base always equate to a good thing? Is there a tipping point at which a larger user base becomes a hindrance?

To me, unit tests and TDD in general are irrelevant to this argument. They are about FINDING the bugs, not about fixing them. No one fires up edit and continue, stepping through their code looking for bugs. They very likely know where the problem is, but don’t know why it is happening. The same scenario could occur with unit testing. “I don’t know why that test is failing…Silly me, my index is off by one!”, edit, continue, test passes, get on with life.

Phil: Leave it to me to be the degenerator. heh heh.

See, the TDD guys said that TDD eliminated the need for EC. But I haven’t seen any evidence to that effect anymore than TDD eliminates the need for comments or a story. Maybe it’s just the way I used EC in VB. I mainly used it to correct stupid off by one errors and associative array references. Oh, and adding in the stupid recordset.movenext calls. Those were my personal nemesis. See, TDD doesn’t really catch those any better than just running the app does. You still get stuck in a loop until the stack runs out. I never just fired up the app in debug mode and started writing app logic until I was done. I never made large, multi-module changes either.

I see TDD being a big advantage, if you are writing de novo code. Or if you are using a fragile API in your code.

Gee, Mr. Bellware, you have an amazing ability to generalize from your experience with one developer to a whole category of developers. That’s awfully open-minded. Maybe the reason that you haven’t met any Morts interested in TDD is that you invariably turn them off by your attitude towards them. Since you’re obviously one of the anointed few who are capable of practicing Agile methods, I sincerely doubt whether you can learn anything from me.

Mark,

“I don’t know why that test is failing…Silly me, my index is off by one!”, edit, continue, test passes, get on with life.

That’s not really an accurate depiction of typical TDD.

TDD practices often result in designs that are more reusable and thus classes that are reused more frequently. Making a change to code therefore could cause cascading defects.

The thinking is more often, “I KNOW why that test is failing…Silly me, my index is off by one. I’m going to fix that and run the unit test suite because I can’t completely guarantee that the change to a reusable class won’t cause failures elsewhere in the code.”

Even if a change is done in Edit Continue, the unit test suite will need to be executed after the change is done. It’s more likely that a test will fail, the problem localized, fixed, and then the suite executed. Most often this happens without necessitating time in the debugger. Since testability is a design concern, code is designed naturally by the shaping forces of test-first programming such that problems can be localized outside of the debugger.

Further, Edit Continue could leave the code in an invalid state along code paths that I have yet to traverse in the debugger after making a change with Edit Continue - especially for code paths that are re-entrant into the code changed in Edit Continue. This could lead to false positives or false negatives during the test execution, which is something that is pretty strictly eschewed in TDD. In fact calibrating out false positives and false negatives is what the Red and Green phases are all about in TDD’s Red-Green-Refactor process.

TDD in general is more often a design practice than a quality assurance practice aimed at finding bugs. But unit tests are certainly good at doing that to.

If I find myself in the debugger in the course of a test execution, I’m usually not deep in the call stack because TDD produces code with shallow stacks and low opacity. Upon localizing a problem in the debugger I would be more apt to stop the execution of the test, make the fix, and then verify that the fix didn’t cause un-localized failures.

If I had code that had to be tested into deep call stacks, with branching, and with opacity, I might consider the utility of Edit Continue, but that’s not the kind of code that TDD typically produces.

Oh, and adding in the stupid recordset.movenext calls

Oh, man. That brings back memories. If I had a nickel for every time I’ve written a loop and forgotten to put a .MoveNext in there. Seriously.

Does a larger user base always equate to a good thing? Is there a tipping point at which a larger user base becomes a hindrance?

Yes, a large user base is always good. More eyes reading and fingers typing means more code samples exist and more knowledge is shared.

I’ve often recommended products based solely on the community around them. Size matters.

I might consider the utility of Edit Continue, but that’s not the kind of code that TDD typically produces

I certainly don’t think that TDD and EC are mutually exclusive. I’m not sure they’re even related!

A good debugger is, however, CLEARLY a core feature of any competent IDE. So in that sense, I think EC got the right priority.

This is not to say that TDD isn’t important. But I have to go back to my “save anywhere” analogy-- removing features to force the “right” behavior is never the correct choice. You can do all the TDD you want with EC; you’re not inhibited in any way.

Yes, a large user base is always good. More eyes reading and fingers typing means more code samples exist and more knowledge is shared.

A large user base is good. But is there a point at which a user base is too large? Can and should a user base grow infinitely? If so, would we expect negative repercussions?

A good debugger is, however, CLEARLY a core feature of any competent IDE. So in that sense, I think EC got the right priority

When I look at a debugger, I see a non-repeatable, visual assert. I very rarely need an assert that is non-repeatable. I agree that an IDE needs a debugger, but it’s not as productive of an implementation verification tool, and too often it’s used for that purpose.

removing features to force the “right” behavior is never the correct choice. You can do all the TDD you want with EC; you’re not inhibited in any way.

My contention is that EC is extremely rarely necessary in TDD. The point isn’t to introduce a motion that EC should be retired, but that the practices that precipitate EC are becoming rather dated in the face of emerging evolutionary software design disciplines.

“A large user base is good. But is there a point at which a user base is too large? Can and should a user base grow infinitely? If so, would we expect negative repercussions?”

Well, there’s always Microsoft as an example of a user base growing too large. Specifically, MS Excel. There are so many users of Excel in the world that the codebase is essentially frozen for eternity. It taks a special dispensation from the Pope to change code in Excel I believe. Some of the largest financial firms in the world are still dependent on really, really, old versions of Excel. So much that they have contracts with Microsoft to ensure that MS maintains those old versions. But market size and it’s impact on quality is a horse of a different color.

I came not to bury TDD, but to praise EC. Even the most ardent TDD adopter, Mr. Bellware, admits that EC is “extremely rarely necessary”. To which I say, “So is my medical insurance, but I’m not canceling that anytime soon.”. MS shouldn’t cut a feature in the debugger just because of a vocal minority, no matter how right that minority is. For more examples of this see the VB petition, and the many posts by Raymond Chen about backwards compaility and the Windows platform.

FWIW, I plan to use unit tests extensively when we re-write a major portion of our application this year. TDD, in some fashion, will be crucial to our development.

Yes, a large user base is always good. More eyes reading and fingers typing means more code samples exist and more knowledge is shared.

I’ve often recommended products based solely on the community around them. Size matters.

Of course, then there’s Lotus Notes. As you said:
“I won’t say that Lotus Notes was the reason I quit my last job, but it was definitely a factor in my decision.”

So despite the 120 million users and thriving community, you’re not about to reccommend it.

Bigger isn’t always better…

So despite the 120 million users and thriving community

Well, 119 million of those users don’t like using the app and had no choice in the matter.

Not exactly the same thing…

Well, 119 million of those users don’t like
using the app and had no choice in the matter.
Not exactly the same thing.

That’s not the point. You said:

“Yes, a large user base is always good. More eyes reading and fingers typing means more code samples exist and more knowledge is shared.”

Always good. Product improvement stems from having more people using the product is what I believe you are trying to say.

In the case of Lotus Notes, the large installed user base has not seen the benefits you describe. It continues to suck. In fact, the large installed base is probably a big problem rather than a benefit. They’re locked into it unless they want to undertake the expensive, risky and complicated process of migrating to a new platform. If people started leaving Notes in droves, IBM would either fix it, or kill it and put everyone out of their misery.

How many developers really have a choice of language or IDE in their daily lives? I’m thinking not many. You use what the project requires. All too often the choice of technology is not made by the front-line coders. Sometimes it’s not even chosen by a technical person.

The fact remains that there is a very big user community and it’s not a Good Thing ™.

Brilliant - you nailed it with the save point thing. Maybe in a video game there’s some honor in toughing it out, but if you’re too proud to fix a simple mistake on the fly then you’re wasting someone’s money.

Sure, this can be abused - anything can - but there’s no benefit to anyone in restarting, recompiling, and steping through a complex workflow just to fix a simple bug that could have been fixed in a few keystrokes.

Of course, the wisdom to know what should be fixed on the fly vs. thoughtfully reconsidered is important. Let’s assume some people have that wisdom.

If you thought then edit and continue debate was hotly debated, then you may want to jump into the XLINQ VB XML Literal debate going on now.

XLINQ XML Literals - Reemergence Of Classic ASP Spaghetti Hell? - http://donxml.com/allthingstechie/archive/2006/02/03/2517.aspx

The XML Literal topic is much more important then EC, since it really gives you the power to create some amazingly hard to maintain code (just like Classic ASP).

Don

James Shore ended with a great point, which underscores an underlying assumption we all bring to the table: what kind of code are you working on?

TDD is irrelevant when you’re doing production support on legacy code. Tests can be introduced over time, but when there’s an urgent issue in a production application, you need a debugger. E’n’C is especially useful when you’re trying to understand system response to varying inputs, since the time lag between input and response is eliminated. Then, armed with a clearer understanding of the system, you can go higher level and make the right fix. You might just want to write a test at that point, too…

The point is that you can’t even write a test when you don’t even know the intended purpose of the code you’re working on, or when you can’t trust it (a ProcessOrder() function that’s evolved over time to include new functionality, etc.). E’n’C can help the TDD process in this case; it’s not one or the other.

So, back to my original point: Are you architecting new systems? You’ll bring that bias to this discussion. Is the bulk of your experience in working on codebases you didn’t write? Biased towards production support oriented tools. Even generalists are biased towards their most recent pain point.