TextModel has nearly fifty variables, methods , and properties. It is the mainstay of our functionality, and our product is somewhat transaction-based, so we should not be surprised that it has a broad interface. Indeed, quite a few of the variables , methods, and properties are private, so the situation isnt as bad as it might be. Still, it feels too large to me. There might be things that could be broken out. Here are some thoughts:
Base functionality. We might break out just the amount of capability that is required to interface between the TextBox and the TextModel into a separate class. Perhaps this capability would move over into the TextBox subclass, providing a line-indexed interface to the TextBox. That would almost certainly make for simpler code on both sides of the line.
Saving and loading. We havent pushed this code very far but it might turn out to want to be off in a separate object that just deals with blobs of text. It would act a bit like a factory, perhaps, transforming files into arrays of lines and back, returning new instances of TextModel.
Menu and insert processing. We have those tag objects that we use to create the menus , and we have the corresponding methods to carry out those operations. Perhaps the generic InsertTags() method would remain on the base object and the others might be broken out into some kind of helper object.
Editing primitives. Quite a few methods exist for breaking lines apart, for figuring out where the caret is, and so on. These might want to be in some other object.
These thoughts aside, one might approach this question in at least two ways. One might design some kind of TextModel constellation of objects, do a little bit of CRC carding or UML design, and come up with a structure that breaks these things out in some way that might be reasonable. Or one could proceed bit by bit, finding bits of code that seem not to belong where they are, and findingor creatingbetter places for them to be.
Of course, this book is about focusing on the second approach, incrementally letting the code tell us what it wants to be. And your mission is to learn both ways and how to find your own balance. We could have done more up-front design on this project. Had we done so, we might have a better design right now, although I am not convinced of that. I am quite sure, however, that we would have fewer features and therefore a less happy customer, as well. I dont see that the time spent in coming up with a better design would have, as yet, begun to pay off in faster implementation. Frankly, I think it rarely does.
However, our large TextModel object might not be helping us as much as it might, so right now I am feeling the need to improve its design, to invest a bit more in it, because if it isnt slowing us down now, I feel that it will soon. If we were going to carry this project further forward, Id be looking for ways to do some of the changes listed in this section.
People often ask whether we should go back and refactor things like the TextModel. In my opinion, we should learn to do a better job of keeping TextModel clean as we go along, and I will be taking this experience into account as I write more code in C#. However, I would not make a special effort to go back, unless perhaps the project was truly complete and we had scheduled a few weeks for final preparation of documents for maintenance and for cleaning up the code for archiving. As a matter of course during the actual project, I would use the observations here to guide me in doing smaller refactorings as new features impacted on TextModel.
If this project were continuing, we would be touching TextModel for almost every feature. So as I plan and estimate each feature, Ill reflect on how to fit in a little refactoring to make TextModel a bit better. Perhaps I add an hour or a half- hour of cleanup to each day of programming. For the first couple of features, this might slow me down. But as the structure of TextModel gets better, I will actually speed up. Therefore, the practice I recommend in refactoring is not to make a separate task of it but just to focus a bit more during ordinary work delivering stories.
Think of the analogy of cleaning up the kitchen after each meal. Even if we have good discipline about keeping things clean, every now and again some things pile up. We could take Saturday morning and do a blitz on the kitchen, but that would get in the way of the football game. So instead, after each meal for the next few days, we just clean up a bit more vigorously than before, perhaps one dirty pot or a few of the dishes in that pile over there. Maybe we grab the rough sponge and give the counter an extra scrubbing. Without extending ourselves at all, in a few days the kitchen is back to spotless. The same is true for our code. Just a little extra effort can get us back up to speed.
All of this is about learning new skills and applying them with judgment. We always need to find a balance between design quality and prompt delivery. The good thing about the incremental approach is that the balance is easy to find, because we are looking at the real code and how well it is coming together, while with more up-front design we are always speculating to a large degree. I think Im very good at speculating accurately, but Im better at sensing what is really going on and responding to it as the real needs arise. And the real needs are always somewhat different from what I foresaw.