Calling the Shot
We *ARE* Gonna Need It
After a long delay caused by our failure to bring any Cat-5 to Borders, punctuated by a visit to Staples, Chet proposed a new test:
@Test public void summaryPageHasGunInformation() { report.process("orlich"); ReportPage summaryPage = report.pageNamed("SummaryPage"); ReportParagraph gunPara = summaryPage.paragraphNamed("GunInformation"); // ... }
We talked about this test and its implications for about 15 minutes, which was all the time we had before it was necessary to decide where to go for lunch. (Jimmy John’s). This entire article will discuss what we talked about in that 15 minutes, and close with a challenge that we plan to pick up.
Recall that the previous report-level test looks like this:
@Test public void coverSheetHasClientName() { report.process("orlich"); ReportPage coverSheet = report.pageNamed("CoverSheet"); ReportParagraph namePara = coverSheet.paragraphNamed("ClientName"); assertEquals("Dan Orlich", namePara.text()); }
The new test works to extend the model to have a new page, contining a new paragraph of “gun information”, which we imagine will be a summary for the client of the gun used in the analysis. We then riffed for about 15 minutes on what this would imply for the code. Let’s review the code here:
package com.hendricksonxp.patterning.model; import java.util.HashMap; public class PatternReport { HashMap<String, ReportPage> pageMap = new HashMap<String, ReportPage>(); public HashMap pages() { return pageMap; } public ReportPage pageNamed(String pageName) { return pageMap.get(pageName); } public void process(String folderName) { createCoverSheet(folderName); // other methods TBD } private void createCoverSheet(String folderName) { ReportPage coverSheet = ReportPage.makeCoverSheet(folderName); pageMap.put("CoverSheet", coverSheet); } }
package com.hendricksonxp.patterning.model; import java.util.HashMap; public class ReportPage { HashMap<String, ReportParagraph> paragraphMap = new HashMap<String, ReportParagraph>(); public ReportParagraph paragraphNamed(String paraName) { return paragraphMap.get(paraName); } public static ReportPage makeCoverSheet(String folderName) { ReportPage coverSheet = new ReportPage(); coverSheet.fillInCoverInfo(folderName); return coverSheet; } private void fillInCoverInfo(String folderName) { ReportParagraph namePara = new ReportParagraph(); namePara.setClientName(folderName); paragraphMap.put("ClientName", namePara); } }
package com.hendricksonxp.patterning.model; public class ReportParagraph { String text = "uninitialized"; public String text() { return text; } public void setClientName(String folderName) { text = folderName; } }
To implement this new feature, we’ll need to extend the PatternReport to add a new page, and add a new static method to ReportPage to fill it in, and create a new paragraph, and put a new method on it to contain the gun info. All this seems very wrong. Every time we add a page or paragraph, we’ll have to add some code. Every time our customer wants to change anything about the report, we’ll be changing the code. We’re not on hourly … it’ll get boring.
When you think about the report itself, it will be rather a simple sequential, though nested, object. There may be optional sections depending on conditions, we can imagine, and perhaps repeated sections for each pattern, but we can expect that each report will look much like all the others with the same basic pages and same basic paragraphs in the same basic order.
The customer will be changing the report all the time. He’ll be creating new pages, new paragraphs and so on. When he wants a new graphic, we’ll have to program that, but we can be sure there will be lots of little document tweaks that we don’t want to get involved in. Therefore …
We're Gonna Need a Framework
There is absolutely no doubt that we are going to need some kind of way for the customer to define and edit what’s in the report. He’ll need to define pages, paragraphs, to say what’s in each paragraph, and to control the order.
Therefore there is absolutely no doubt that we’re going to need some kind of internal data structure that defines what the report is, pages, paragraphs inside pages, and so on. This structure will need to be created and updated from some kind of external representation, a text file, an XML file, a hierarchical set theoretic database … something.
Therefore we know right now that we’d better get to work on setting up that framework, writing tests for it and so on. Right?
Well … lots of people would do that. On a given day Chet and I might do it. But today’s not that day. We’re going to go another way, and we’re going to call our shot.
The big fear is that if we don’t start now to build up that framework, our code will get all ugly and out of control and when we finally do get to needing the framework, it will be too hard to put in and the sky will fall. And, indeed, that might happen. But we don’t think it will happen if we do our jobs well, brightly brightly and with beauty: with Style and Grace.
So here’s what we’re going to do. We’re going to take stories in the customer’s preferred order. We’ll implement those stories, keeping the code as clean as we can. We’ll keep in mind that we want a framework – and our customer will keep in mind that he could type some of the things in that he has to explain to us. At some point, he may actually ask for a framework. At some point, we may suggest a little tool. We’ll keep the code good, and we’ll keep open to the possibilities.
And we think …
Everything Is Going To Be OK1
We’re pointing at the fence on this one. We’re going to proceed by following YAGNI – You’re Not Gonna Need It – even though we know we’re going to need it. The purpose will be to explore what happens when we defer implementation of something we know we’re going to need. Our belief is this:
- If we work on the framework, now, the customer won't feel the need for it and won't like the stories much;
- If we work on the framework, now, we won't really know what we need, and we're likely to do too much, and too little, both at the same time;
- Deferring the framework will get more useful work done;
- We'll learn more and make fewer mistakes;
- The cost of putting it in later won't be very large at all, because what will happen is that we'll be putting it in little by little.
We could be right, we could be wrong. Either way, someone is going to learn something. We hope it’s what we think it is.
“Watch this!”
- This is what Ann Anderson tells herself when the going gets tough. On a really bad day she'll ask someone else to tell her. It works really well. Try it.