Cleaning the Lines


Anyway, now that we have the OneDirtyLine test, our mission is to produce an ArrayList of lines with no vertical bars in them. (Here again, we re skipping something. We also need to be answering where the cursor-indicating vertical bar was. But we re not thinking about that, so stop thinking about that!) We played a bit with how to do CleanLines. One idea was to calculate the ArrayList right in the CleanLines method. I was going that route, but Chet suggested that we just create the clean lines right as we built the input. With our test not running, we changed the constructor to look like this:

 public InputCommand(StringReader reader) { 
lines = new ArrayList();
String line = reader.ReadLine();
while (line != null && line != "*end") {
lines.Add(line.TrimEnd());
line = reader.ReadLine();
}
CleanTheLines();
}

Note that we added the method CleanTheLines. We re expressing intention here. We also discussed that the constructor needs refactoring now. Because it has two things that it does ”setting up lines, which it does manually, and setting up the clean lines, which it does by sending a message ”we should make that first bit of code into a method also. But that s not for now: we have our adding functionality hat on, not our refactoring hat. So we wrote CleanTheLines, like this, adding a new member variable to hold the clean lines:

 private ArrayList cleanLines; 

private void CleanTheLines() {
cleanLines = new ArrayList();
foreach ( String line in lines) {
cleanLines.Add(CleanTheLine(line));
}
}

(By the way, the member variables aren t spread around in the code like I m showing them here: they re up at the top of the class. I just didn t want you to worry about that.)

Lesson  

I just mentioned sb two hats: the adding functionality hat and the refactoring hat. Kent Beck taught us to be aware when we re adding functionality, and he suggested that we should not try to clean up, or refactor, the code at that time. Likewise, when we re refactoring, we shouldn t try to add functionality. This is good advice, which we do well to follow. When we mix things together, we seem to get confused more easily. So we always try to do first one and then the other. Try it, you might like it.

Notice that we expressed intention again in the previous method. We went over each line and added a clean version of that line to the ArrayList. Let s underline that for a moment. By expressing intention here, we produce code that is more expressive, but we also limit what we have to think about all at the same time. When I m in C programmer mode, I d be more inclined to write the foreach loop there, and then, inside it, try to expand out what CleanTheLine would be. I m sure I m up to that challenge, most of the time, but sometimes I m not. And, again, when we work in these tiny steps, we find that we re more relaxed and we re more able to deal with the distractions that inevitably occur, especially when we re sitting in the Michigan Union. So now to write CleanTheLine(). We got smart and typed line . (line dot) in the editor. The dot brings up the list of methods on the object ”thanks, Visual Studio ”and we scrolled through the list until we found Replace, whose write-up says: Replaces all occurrences of a specified string in this instance, with another specified string. That sounds just right. We coded CleanTheLine this way:

 private String CleanTheLine(String dirty) { 
return dirty.Replace("", "");
}

That makes our test run! We ve now got CleanLines() working, and we decide to put the InputCommand into the CustomerTest class as well:

 private void SetInput(StringReader reader) { 
InputCommand input = new InputCommand(reader);
model.Lines = input.CleanLines();
}

Note also that we didn t put the SelectionStart stuff in, since it isn t built yet, but we wanted to check whether the string part of the customer tests still worked. Surprisingly, all our customer tests worked, including the following one, which we thought shouldn t have:

 *input 
<P>This is the first paragraph.</P>
<P>This is the second paragraph.</P>
*end
*enter
*output
<P>This is the first paragraph.</P>
<P></P>
<P>This is the second paragraph.</P>

We were surprised by this, because we expected that we needed the selection start logic to figure out where the cursor was. But the default cursor location is zero, so because we didn t set it explicitly, our TextModel assumed that the cursor was on the first line and worked correctly. Oops. We wrote another customer test to verify this theory, and sure enough this test does not run:

 *input 
<P>This is the first paragraph.</P>
<P>This is the second paragraph.</P>
*end
*enter
*output
<P>This is the first paragraph.</P>
<P>This is the second paragraph.</P>
<P></P>

Good. We thought we were wrong, and it turns out we were. Does that make us right?




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