Can't imagine how anyone doesn't do this - unless there's just a race of God-programmers I've never encountered that write everything perfect the first go. But I don't think so. :-)
Can't imagine how anyone doesn't do this - unless there's just a race of God-programmers I've never encountered that write everything perfect the first go. But I don't think so. :-)
Git stash can be helpful. Stash your "wrong direction" change, then apply just the good chunks from your stash.
Yes, git diffs help, but once I’ve passed a parameterized suite of unit tests, never needed to undo/redo. Maybe not perfect the first go, but only need one/two tries to working code. Then refactor for readability.
Consider, for example, a bug recently introduced during a refactor at my work:
The programmer optimized a conditional based on a regex by transforming it into a simple string compare. All the tests passed, code/branch coverage was good. Except that he missed that the regular expression tested case-insensitively, and our test suite didn't test upper and lower case scenarios.
This simple mistake outlines a few flaws:
- coverage was not robust, because it didn't take into consideration the branches inside the regex (which one could interpret as a form of macro expansion)
- the limited number of inputs used to test failed to capture the broader domain of possible input
- the test did not reflect a successful refactor
Obviously this is a fairly complicated example despite a pretty simple change, and several pieces had to fail in order for this change to fail. But it affirms that even basic changes to code aren't necessarily adequately covered by TDD.
Yes, the developer who forgot to test different letter cases made a mistake. Yes, regular expressions bring their own problems. But fundamentally, the result was that passing the tests did not affirm fitness of the change. Rather, it only proved a limited subset of conditions were error-free.
Effectively, tests are loaded with false negatives, so trusting them to identify problems should be done with a massive grain of salt.
If the developer had simply copy/pasted the code he changed and compared the two, then it's exceedingly more likely that he would have noticed that his code didn't capture the full breadth of conditions in the previous code.
A bug existed in the test suite, to start, and then a bug was introduced into the codebase. A human being looking at the two lines of code as it was rewritten probably would have noticed the regression. But even a code review missed it because it was a fundamentally small change among the other, more "make sure this looks good" code.
Personally, I very much value copy/paste/compare changes and never treat the test suite for anything other than "well we haven't broken anything in any exceedingly obvious ways." Maybe you're a superhuman programmer, but I'd lean more towards "you've probably added more bugs than you realize".
The caps vs. no caps issue would be easily caught using randomString() as the test case.
I do all of these. I’d use undo/redo when I want to look at something I /just/ did, meaning while in the process of writing something. The git gutter when I stumble upon some change I want to see what was there before. Or Sourcetree for a full diff.
But also, `git diff`.
On one hand it's nice that there are tools to support devs who get lost in their undo-redo history, on the other I feel like it's a matter of good habits to not even have this problem.
of course changing habits is hard, so maybe tooling is justified in this case. I'm just happy I don't have nother "history" type mental model to deal with.
All versions controls have a way to compare, merge and revert historical changes in and out of the current working copy.