The Third Attempt


This time we started with some rather neat tests that expressed little editing scenarios and that checked an OptimizedTextModel object to see if it was going to do the right thing. Here s an example of one of those tests:

 [Test] public void LinesToRemove() { 
model.SetLines(new String[] { "abc", "def", "ghi" });
model.SelectionStart = 8; // after e
model.Snapshot();
model.SetLines(new String[] { "abc", "deXf", "ghi" });
model.SelectionStart = 9; // after x, user inserted X
model.OptimizeSavedModel();
TextModel oldModel = model.TopSavedModel();
AssertEquals(1, oldModel.FirstLineToRemove());
}

That might seem a bit cryptic still, but it expresses a pretty easy edit, from abc/def/ghi to abc/deXf/ghi , where slash represents a newline and the vertical bar represents the position of the caret. The notation above would have been even better, but we didn t think of it at the time.

We wrote four increasingly difficult tests and made them work, and we were feeling pretty good. However, we were working on low-level functions, not Undo itself, and the result was that we didn t see that our idea was fundamentally flawed. A more top-down approach, or fake it till you make it, would have been better. We were working on infrastructure that we assumed we would need.

Ironically, I am the inventor of the XP motto YAGNI meaning You Aren t Gonna Need It which we use to remind ourselves to build infrastructure as we need it, not in advance. Why didn t I listen to myself ?

Chet and I went on, refactoring and refining our infrastructure for quite some time, about ten book pages, and a few hours work. We even wrote some new Customer Acceptance Tests, and at the end of the session I concluded:

The answer appears to be that we have successfully built code that knows which lines of the saved TextModel need to be saved and which lines need to be removed and replaced when doing an Undo. We still need to delete the unneeded lines and to wire up the Undo correctly. This has been a good session: the problem seems to be completely caged now.

I m noticing the weasel words now ” appears to be and seems to be ” but at the time I was pretty confident that we were on the right track. At this point, I needed to continue without Chet s help for a while, and my plan was to plug this infrastructure into the product. Good idea, even if a bit late: Infrastructure doesn t please the customer, features do.

I wrote some tests, turned up some problems, put in lots more tracing statements (a telltale sign of corruption), and wrote more detailed tests. I ran into a long series of off-by-one errors and indexes out of range but I didn t recognize these for what they represented: faulty reasoning. In editing the original chapter, I wrote this lesson, which is worth preserving :

Lesson  

First-take excerpt: Another telltale sign of corruption is that I m instrumenting the code to print things out. When do we do this? When we don t know what the code is doing. This is a bad sign. I m resolving to raise my sensitivity to this practice.

Later, I added this signpost and ignored it:

Lesson  

First-take excerpt: Whenever we have the urge to test the program manually, we need to recognize that this might reflect a lack of confidence in our tests. Since I ve been having these little problems with off by one and array out of bounds, I think it s more that I m not entirely confident in the code ”but the fact is that my tests are supposed to give me that confidence. More evidence that the tests need some beefing up.

I fiddled around with improving the tests ”for about four pages! ”and then discovered that the tests were making assumptions that weren t consistent with the program. Even if they ran, my tests were no assurance that the program would really work.

Lesson  

This is an inherent issue with working with infrastructure first: when our assumptions are wrong about what s going to be needed, the result won t work even if it passes all its tests. Outer design should drive inner design, always.

I messed around to try just fixing the exceptions that were arising. Special case code indicates bad design. But still I didn t listen.

Finally, Chet came and joined me again and managed to increase my recognition that there was trouble, but we pressed on for a while anyway. We even put in a special object called a Hint and didn t recognize it for what it was. We should have named it Hack! Here s a quote from the chapter, showing that a sufficiently stuck programmer can t even be pulled out by his pair. Chet should have formatted my hard drive, I guess:

It has been a long time since all the tests worked. We like to make them work every ten minutes or so, and we have been working much longer than that. In a phone call setting up another pairing section with Chet, we talked about this. I heard myself saying: If someone told me this story, I would be advising them to tear out the code and start over. It sounds like they are going down a rat hole. But I m sure that we re just one problem away from having this work.

There was a long silence, as Chet let me listen to my own words. I would advise anyone else to start over, yet I want to go ahead. We all know that feeling of just one bug away, and we have all spent a lot of time discovering one more. In the end, we agreed to meet and work on it just a bit more.

We continued on with some very nice double-dispatching code between the TextModel and the new OptimizedTextModel. I was looking forward to showing you how nice it was, until I realized that it was a good implementation of a bad idea.

This part of the original chapter is full of huge blocks of code with very little text. In my work, that s a sign of working but not thinking. If I had been thinking then, I would have told you about it now. Programming without thinking ”what good is that?

Over 30 pages later, we hit the fatal flaw. We couldn t handle the InsertTags operations. We put in another hack and bashed on the code a bit longer. I put more and more tracing code into the system to try to find out what was going on. Finally, after 32 pages of chapter (although only about six hours of programming), everything worked. Jubilation!

One paragraph and one thoughtful manual test later, I discovered that the whole idea just wouldn t hold water. Cuts, pastes, cursor movements all fatally confused my carefully designed OptimizedTextModel. Despair, weeping, gnashing of teeth!

Enough! Convinced at last, I stopped and started over with more focus on the specifics, and I moved quickly to the version in the preceding chapter, which reduces storage requirements to less than one percent of what they were. As you have seen, that simple approach worked well. It s what I should have done the first time.

Here is the conclusion I wrote for that long, dark chapter. It concludes this chapter as well.




Extreme Programming Adventures in C#
Javaв„ў EE 5 Tutorial, The (3rd Edition)
ISBN: 735619492
EAN: 2147483647
Year: 2006
Pages: 291

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net