Javaв„ў EE 5 Tutorial, The (3rd Edition)

We got only one test out of the deal, but it s at least good enough to check that the PutText method never loses its ScrollToCaret. And breaking out the PutText gives us a better chance of not making the same mistake again by accidentally duplicating the code. What we learned is more important.

Feature Envy

Take a look at the code for PutText again:

public void PutText (ITestTextBox textbox, string[] lines, int selectionStart) { textbox.Lines = lines; textbox.SelectionStart = selectionStart; textbox.ScrollToCaret(); }

This is a method in XMLNotepad class, and it s sending messages only to textbox! This is a major case of Feature Envy, a greater interest in some other class than in one s own. When we look at this code, we see that what we really want is that the text box have the ability to take the data and selection all at once and that it keep its cursor set properly.

We could do something about that if we wished. Because the TextBox class was subclassed to create our TestableTextBox, we could move this function over there. Maybe in a separate chapter we ll do that, although I have something else in mind for the next step.

Object Being Born

Look also at the header for that method. It has the lines and the selection start together. In our usage, we are always dealing with both at once. The code may be telling us that we need a different kind of object here, one that binds the text and the selection together. We have other signs that things are odd in this area, including some bouncing back and forth between string[] and ArrayList. When a program is switching back and forth between data representations, we need to consider whether the objects are quite right.

Building and Using an Interface

We learned how to build an interface. To you Java folks, or people more experienced with C# than I am, that s no big deal, but to a dynamic typing person like me, that s a bit of learning. It s good to have it under my belt, and now I ll know how to do it for next time.

And I implemented an object matching the interface, which netted me a few compiler errors that I spared you. So now I ve done both sides of the interface/implementation equation, in a pretty simple form and driven at least partly by tests.

Building a Mock Object

This is the first time I ve ever consciously used a Mock Object. It certainly did the job perfectly : it told me whether the text box was getting sent the message ScrollToCaret(), though of course reading the code made it clear that it was. But now we have a test, which feels more secure to me.

I broke the Mock Object out into a separate class for simplicity of learning. But it puts a new class in the system, and I m inclined to combine the TestScroll class and the MockTextBox class into one class, using a technique called Self Shunt. (At http://www.objectmentor.com/resources/articles/SelfShunPtrn.pdf , you can find an article by Michael Feathers about Self Shunt. The tag line is Let s say that you are a test case. One of the things that you can do is pass yourself to the objects you are testing so that you can get more information. Read Michael s article for more detail.)

Tests, Tests, We Need More Tests

You probably can t feel this as clearly as I do, but I am actually relieved to have this new test. Not that it tests anything that didn t work, nor did it find a bug. What it does, though, is extend my ability to test things a bit further, allowing me to work more quickly by avoiding manual tests, and more reliably by extending my testing in new directions.

At the same time, I don t find this particular test to be very satisfying . We have learned a technique that we can use to be sure that our code calls a particular method at the right time. But the test doesn t really show us that the text is displayed on the screen as we might wish, and, besides, we already knew that our change worked from the manual testing. The value of the specific test itself is pretty low. Still, I m glad we had this time together to look into how we might test this kind of thing, and I think the learning was worth it.

Miles to Go...

Looking at where we are, we can see that things are left to do. In a book with a different perspective, an author might take you from zero to the perfect design in one amazing magical act. But our purpose here is to show you that it s OK to experiment and OK to start from something rough, so long as you keep testing and keep making it better.

Notice that most of our time, even when we re reworking the code, has been spent learning new things and putting in new capability. From time to time we do pause and regroup, but the bulk of the work is productive and provides us with more concrete understanding of what to do and how to do it. That s what program design, and programming, are about: learning how best to do the job at hand, given all the things we already know and using well the things that we learn along the way.

Категории