Revisiting Edit and Continue

Edit and Continue, which shipped in Visual Studio 2005, is generally regarded as A Good Thing. It's pretty difficult to argue against the benefits of immediacy when debugging, but that isn't about to stop some people:


This is a companion discussion topic for the original blog entry at: http://www.codinghorror.com/blog/2006/02/revisiting-edit-and-continue.html

The EC and Save Anywhere think sounds a bit like a strawman argument.

Sam hit the nail on the head - unit tests provide a better developer experience than edit and continue. It requires good unit tests written test-first that result in testable designs that defeat the design conditions that bring about the need for Edit and Continue. Without those qualities and without the developer knowledge, unit testing and Edit and Continue aren’t likely to express the differentiable qualities that folks like Sam and other testability and design folks take for granted.

Software developers who know how to achieve testability are often more accomplished software designers than folks who rely on EC. They achieve productivity that far outstrips the kind of penny-ante, short-term productivity achieved through RAD and tooling like EC.

And indeed, everyone should construct code the way we do. If we’re talking about building applications and systems, there’s a lot more at stake than a gamer twiddling away his study time in the glow of Halo. The domestic industry is being left with very little wiggle room to continue to play at coding rather than to take it head-on with a professional verve that spawns intellectual curiosity, inquiry, study, and practice.

In some respects, I think the analogy between coding and gaming is more telling about the attitude toward coding that folks who use EC as a low-grade buttress against their lack of understanding of testability. It highlights the lack of visibility into the meaning of testability by lethargic programmers who have yet to muster the person integrity and professional ethic needed to penetrate deeper into understanding testability and its inherent design considerations and benefits through practices like TDD.

Once you speak from real, prolonged experience with test-driven design, you realize that you’ve moved to another completely different game, rather than just a level in the same game with bigger monsters.

Sam, I understand and respect your position, as well as your experience. If I were to write the perfect unit test and perfect code to go with my perfect unit test every time, I would never need to go into the debugger. I would also have a candy keyboard with gumdrop keys. I mean, hey if we could all write perfect code the first time around, we wouldn’t need unit tests either. Most people I know, I may lead a sheltered life, don’t just slap any old syntax into their source file and say “well, I’ll just find all the bugs at runtime and set a breakpoint.”. They write well thought out code, even if their thinking is wrong or flawed. But sometimes, $#!t happens and who you gonna call?

The biggest irony in your position on EC is that you have spent a lot of time learning and loving dynamic languages like Python and Ruby. EC is a H U G E part of what makes Ruby, Python, and Ruby on Rails so great. Even if it isn’t called EC, it’s a big boon to productivity to be able to just fix the error and hit “refresh” rather than exiting the IDE, and doing the ctrl-shift-b shuffle.

I, however, have a BIG problem with this statement. I thinks it’s arrogant and counter-productive.
“I think EC comes out of the sloppy just hit F5 world of VB and people don’t think before they run”

yeah, if only those stupid VB programmers weren’t out there writing 90% of the business applications, there would be more room for perfect code right? Your bank probably runs on VB code. Your insurance company, your doctors office, everything. Every, and I mean EVERY, company large or small has a rinky-dink little Access database (with VBA) that they are completely dependent on for their day-to-day business. The time of the “hardcore” C/C++/COM programmer is over, finished, done, stick a fork in the old dinosaurs and put them out to pasture. VB, C#, Python, Ruby, and other languages and frameworks that don’t require you to wear sackcloth and ashes and self-flagellate to get real work done are here and they are the future.

– He said respectfully with a smile. :slight_smile:

Once you speak from real, prolonged experience with test-driven design, you realize that you’ve moved to another completely different game, rather than just a level in the same game with bigger monsters.

I agree that everyone should be trying to step up their “game”, no pun intended.

But you’ll get a lot more flies with honey than vinegar.

You could make the same point about refactoring being dangerous. If you design correctly the first time, you shouldn’t need to refactor, right? That kind of logic is flawed. Refactoring is a useful feature, Edit and Continue is also useful feature. If you don’t find it useful, don’t use it.

Ooh! Ooh! My turn to weigh in.

A couple things. I think the main argument around EC isn’t necessarily whether it’s “evil” or not, I think it has to do more with its priority. At least for me.

Should Microsoft have spent time on EC over other features? And that really depends on what features empirically help developers produce better code.

Like Sam, I believe that helping developers learn to write unit tests and approach pragmatic test driven development (which MS has unfortunately collosally failed at) gives more bang for their buck.

So while I agree that EC is useful (heck I’ve been in situations where I’m running a unit test in a debugger and would have loved to save time by fixing a typo rather than doing the whole recompile re-run bit) in the hands of a good developer.

The real question is whether other more useful, more helpful features were put aside in favor of EC.

Sam, I understand and respect your position, as well as your experience. If I were to write the perfect unit test and perfect code to go with my perfect unit test every time, I would never need to go into the debugger. I would also have a candy keyboard with gumdrop keys. I mean, hey if we could all write perfect code the first time around, we wouldn’t need unit tests either. Most people I know, I may lead a sheltered life, don’t just slap any old syntax into their source file and say “well, I’ll just find all the bugs at runtime and set a breakpoint.”.

I don’t understand the argument. Its fairly easy to write very useful unit tests with TDD. It takes me less time to write a 2-4 line unit test than a round of debugging and such. There is no such thing as a perfect test. There is a such thing as writing tiny small tests that each cover and assert a logic condtion.

on the ruby, etc.
Its not the same as rummaging around in the debugger. Dynamic languages use a ton of unit tests - check the ruby and rails sites. They come out of the agile movement

I would say that my imperfect unit tests which get refactored keeps me out of the debugger 99% of the time nowdays. We need to start teching people to do it right and spend time on tools that teach guide this, refactoring, etc rather than tools that encourage cowboy hackery

Sam,
“I don’t understand the argument.”

I think my main point is that the IDE shouldn’t punish people for having fumble fingers or for not having written perfect code before running the application. Removing EC, IMO, would punish people who don’t write perfect code. is it possible to write code that passes a unit test, but still contains an easy to fix flaw? Like an off-by-one error? Do you write unit tests for string localization and typos? Are there unit tests for control positioning? Wouldn’t it be useful, in both smart client and web development, to be able to change the positioning of a control when you notice that it’s two pixels too far to the left?

I guess a serious question I would have for you, or anyone else who is using TDD effectively is: Do you ever run the application inside the IDE in Debug mode before you deploy the application or do you go straight from development into production?

“Its not the same as rummaging around in the debugger. Dynamic languages use a ton of unit tests”

Agreed, but fundamentally both activities, editing a Rails controller/view/model/helper at runtime and changing code using EC are the same. You are changing code without having to completely stop the application and recompile. It often takes me as much as a minute or two to re-start my current application. More if I’m debugging client-side script in Visual Studio. (much, much more. Like go-downstairs-and-get-a-latte more). To me, that’s time wasted (unless I do go get a latte, at which point it’s a needed break).

Much as I admire Sam and the others, there’s far too much macho posturing on this subject. I wrote about good and bad EC scenarios here:
a href="http://sleeksoft.co.uk/public/techblog/articles/20051224_1.html"http://sleeksoft.co.uk/public/techblog/articles/20051224_1.html/a

Having a full-time job as an adult, games are now a regulated use of my time… Any game not featuring “save anywhere” is a waste of that time. I am playing the game for enjoyment and to get through it in a reasonable amount of time. If I have to play the same place OVER AND OVER (Prince of Persia is a shining example) I get fed up because I feel like I am wasting what little free time I have. Do I wish I had enough time to play games without save anywhere? Sure, but I also like not having to live with my parents.

Edit-and-continue is a tool like any other. Just because it can be abused is no reason for removal. I’ve used Delphi for some time now, but back in my VB 4/Access 2 days there were times that edit-and-continue was pretty nice for experimenting in real time, especially in loops.

We’re talking past each other. You keep saying “perfect code.” I don’t write perfect code and neither does anyone who uses TDD. With all due respect, I donb’t think you understand the purpose and method of TDD. TDD is not only about finding errors but a methodical way to develop software with a process of self-discovery along the way. It is not and ever been a way to write or gauyrentee “perfect code.” I don’t know what that is. You try to ensure some level of quality but I think you paint the agile people as going extreme on “perfect code” and writing tests forever to get there. Thats not what its about and I think you may benefit from Scott Bellware’s posts on TDD as well as Jim Shore, myself and otehrs.

All the best

Jeff I think you’ve hit the nail on the head with this post. Most specifically:

not everyone writes code for the same reasons you do, either

Sam, Scott - I don’t think this is a strawman argument and I don’t think either of you actually addressed it in your replies.

Sam:
With all due respect, I think your analogy with hard core gamers doesn’t make much sense here. I am arguing aggainst being in the debugger at all.
(I think this is the same ‘EC is dangerous’ argument expanded to the Debugger as well. I’d respectfully say you missed the point of the analogy, rather than it not making sense.)

Scott:
And indeed, everyone should construct code the way we do. If we’re talking about building applications and systems, there’s a lot more at stake than a gamer twiddling away his study time in the glow of Halo.
(This seems to be an explicit denial that other people could have a software problem that looks different than yours, and would be better solved by different methods.)

The crux here is the desire to advocate TDD + Unit tests to the exclusion of tools and methods that support other modes of working. Basically it is dangerous to have support for anything that does not lead one to conclude a unit test is the right answer.

Projects with different goals will benefit from a different mix of tools and processes, whether that involves use of EC or Big Design up front.

To make some specific examples:
EC is perfect for prototyping game play mechanics. Would you really try to write a unit test to ensure you don’t regress the fun in your game?

EC is useful for letting a software aware Domain special-ist simply make a somewhat less supportable yet useful first pass of the required software. Sometimes that is the right business tradeoff. Does that kind of loose development practice create a headache for software professionals … you bet. But that is why those are paid positions, because the end goal is the benefit to the software user, not the developer.

(I have to use ‘special-ist’ above because there is a forbidden word embedded in it. :slight_smile:

(Also I should say though I am saying that TDD + unit testing isn’t the answer for every problem I fully acknowledge it is a HUGE leap forward in best practices.)

“With all due respect, I donb’t think you understand the purpose and method of TDD.”

I’ll admit to being mostly ignorant of hardcore TDD. Most of what I know is from reading blog posts about how great it is. The phrases I see most often associated with it is “increased productivity” and “increased code quality”. And the last time I read up on “Agile Programming” it was called “Extreme Programming” :wink:

Back to the point of EC, I still think it’s useful and shouldn’t be removed because there are some things that TDD can’t really test for. Or it seems to me that you’d go nuts writing unit tests to ensure that all of your spelling and grammer is correct. Most of my issues with TDD come about when I try to apply it to legacy code and web applications (worst of all legacy web applications).

TDD is good. Refactoring is good. Use them together and you get a look at a bigger slice of the agile picture – a picture which is astonishingly under-developed in the minds of folks who write software while tied to the traditional development practice anchor.

Agile approaches like TDD and refactoring aren’t about writing perfect code. Both of these approaches exists specifically to address often extremely less than perfect code. TDD and refactoring are about designs that allow for changeability. I’m personally not after perfect code; I’m after a methodology that allows me to make code better when a better solution is presented.

Through a conscientious practice of Agile approaches including TDD and refactoring, I rarely have to use the debugger – not because my code is perfect, because it certainly isn’t – but because there are alternatives to having to resort to the debugger which exist in a spectrum or color that the Mort species presently is either incapable of or unwilling to perceive.

The Agile movement didn’t just come up with a handful of useful tools like NUnit, NAnt, CruiseControl, etc, to revolutionize traditional software development. These tools were forged by the requirements and expectations of an emerging development methodology. Folks making use of refactoring tools in Visual Studio without knowing about the greater context within which they are used are simply engaging in an impoverished approach to development in comparison to the power that those tools bring to bear in the context of the development environments that shaped them.

There’s a lot more to refactoring than refactoring tools, there’s more to TDD than NUnit, but you can’t see any of it until you go looking. If you think the a-ha moment going from VB 6 to VB .NET was big, wait till you get feel the magnitude of the Agile a-ha moment. Moving into a deep understanding of TDD is an order of magnitude bigger zen smack than the switch from a procedural to an OO world. It’s much more on the order of moving from a flat earth to a round world.

There quite a number of deeply-ingrained superstitions that Mort has to let go of before something like TDD will begin to make sense, and until that time, Mort is confined to the limited capacity for software development thinking that hasn’t evolved significantly since VB 6. And frankly, I have yet to see anyone really get TDD who didn’t put in the effort to really try it first.

Indeed this is definitely more vinegar than honey, but recipes for change in paradigm shift aren’t always formulated with candy-coated gumdrops in mind.

I maintain that a prolonged exposure to TDD practice will totally change your perception of software development and will re-wire your mind toward a higher magnitude of expectation for productivity and quality that go far beyond the middling gains brought by a development style that requires Edit Continue. But first you have to be willing to open your mind to the possibilities that the world may indeed not be a flat disk held on the backs of giant elephants floating in a cosmic sea on the back of a giant tortoise.

Scott,

And the last time I read up on “Agile Programming” it was called “Extreme Programming” :wink:

Well no, Agile is an umbrella for all of the contemporary, test-centric methodologies like XP. XP is an Agile method, just like MSF is a waterfall method, but there’s no formal methodology called “Waterfall”.

Back to the point of EC, I still think it’s useful and shouldn’t be removed because there are some things that TDD can’t really test for.

Can you provide an example that can’t be resolved by refactoring the design to make it testable using Inversion of Control and Dependency Injection?

Or it seems to me that you’d go nuts writing unit tests to ensure that all of your spelling and grammar is correct.

Spelling and grammar for what?

Most of my issues with TDD come about when I try to apply it to legacy code and web applications (worst of all legacy web applications).

Indeed. TDD is a design methodology. If the code hasn’t been brought into existence by the design pressures inherent in TDD, it’s likely not going to have a whole heck of a lot of testability.

However, there are solid techniques for making legacy code testable. See: http://www.amazon.com/gp/product/0131177052/002-1083542-4004061?v=glancen=283155

How about an experiment? You can come work on my team for two weeks and if you still don’t see that TDD is much more than you thought it was, then we won’t charge you for the two weeks of training and coaching :wink: (-- yes, it’s a joke!)

“Because you get to focusing on that one bug and twiddle the code to fix that one bug and introduce six more.”

I’m sorry for anyone who has to work on code that is so entangled and badly designed that this could turn out to be true.

which exist in a spectrum or color that the Mort species presently is either incapable of or unwilling to perceive.

And if you treated Mort like an adult instead of a child, you’d have more success convincing him to adopt better development practices.

http://haacked.com/archive/2005/08/03/9210.aspx

We need to stop paternalizing. Java guys are the worst in this regard, though some of the more zealous C# purists are nearly as bad.

Instead of wasting time complaining about Mort and Edit and Continue corrupting the minds of innocent young developers, we should be pulling ourselves up by our bootstraps.

Similarly, time spent arguing about this stuff is better spent instilling a general culture of hard work and professional investment, so all developers CAN become talented.

"Can you provide an example that can’t be resolved by refactoring the design to make it testable using Inversion of Control and Dependency Injection?

Or it seems to me that you’d go nuts writing unit tests to ensure that all of your spelling and grammar is correct.

Spelling and grammar for what?"

Mostly for non-localized strings. Button text, label text. I do most of my developmet on web applications, so I spend a lot of time dealing with HttpCookie, HttpRequest, and HttpResponse. Which means a lot of hash accessing, which means lots of changing “Request.QueryString[“uesrID”]” to “Request.QueryString[“userID”]”. Web applications are harder to adapt to any kind of TDD methodology due to the code being spread out and not being covered effectively by all of the available tools. You can write unit tests for your client-side script, but NUnit can’t really test them. The VS IDE code coverage tools don’t seem to support client side script. Most of the UI unit tests seem to involve screen scraping and checking for the correct text in HTML elements, or checking for the HTML elements themselves.

See, I “get” where TDD is useful for biz objects, transactions, and other objects which encapsulate application logic. But I don’t get TDD for UI development. Which is where 90% of my pain during development is. 90% of my code is plumbing/data pump code. Put data in/get data out and display it. And that’s the easiest, and most tedious code, to have to write. But the remaining 10% is where most of my errors occur. How do I “test” that an event fired correctly?

I mean, if TDD only helps me out with the easiest part of the development…I’m just not seeing the benefit. Am I missing it? Does anyone DO GUI testing using TDD? Is it possible?

I’ve posted a challenge on my weblog. A nice shiny quarter to the first person who can write a unit test that would have prevented my bug. :wink: