Monday, July 03, 2006

The Simpler Life 1.0

I have no self-control.  What started as a simple redesign of my old website turned into an endless year of tweaking and distraction. It ended in liberation.

For the better part of a year, I obsessed over the little design details of my blog.  I read all about making access to information easy.  I experimented with branding and identity and style.  I lurked about in CSS and design forums.  Tinkered. Cobbled. Forged.

Never happy with the results.  Many designs in the dustbin.  Why was I doing this?

Good question.

And like that, I realised I couldn't remember what I was doing. I wanted to write, not tweak. I woke up.

First thing to go - the original blog.  I was spending so much time fiddling with the styles, admin settings, and all the other goodies that I was left with little time to actually add content.  So goodbye old blog, hello Blogger.  Free, configurable enough, but not enough to be distracting.

Next, I started using Backpack to store ideas to write about.  When I get an idea, but can't write about it immediately, I send my Backpack a note. All my great ideas are carved into a safe place.

Momentum gathering, feeling free-er.  Anthing else? What else can get scrubbed?  What about all those lists I read everyday?  My Gmail box has 15 filters for all the lists I don't read but wish I did.  Easily fixed - Login to Yahoo! Groups and set all but the mighty few groups to 'no more email please'. Oh ya, delete a few thousand unread emails.

Speaking of blogs, I subscribe to a whole pile of them too.  Not anymore.  I had about 50 that I read (or tried to read). Whittled them down to 10. 

Finally, I'm going document-free.  I repaved my laptop recently, and as part of that, I didn't put any of my old files back on my machine.  It turns out I'm not going back to the archives as much as I thought I would.  And I'm using text files more.  I've even been experimenting with one big text file.

I'm free.  Free of the fiddling, tweaking, searching. Free of the guilt of not keeping up with all the info.  And free to fill this new blog full of content.

Simpler life?  Time will tell. For now, I'm back in control.




technorati tags:, ,

WriteRoom

Would someone please create this for Windows? Now!

technorati tags:,

Friday, September 23, 2005

TDD and the Single Printer

Disclaimer: This article does not show all code and possible refactorings. It gives just enough to show how a design for testable printing evolved.
Credit for the ideas here go to all members of my team who paired and collaborated on the reporting story.
Let's get started. Of course, that's the problem, isn't it? Where do you start when you don't know where to start? Well, me, I cheat. The XP community over at Yahoo! helped kick the brain into gear with some helpful starters.

So here's what I decided: For now, I'm going to focus on what I know how to test, and maybe that will help me figure out how to test the stuff I don't know how to test. Initial thinking is that I can probably figure out how to test-drive content and presentation, and maybe that will lead me to a testable design for the printing part.

Ok, enough talking, lets see some tests. I'm lazy, I want to test the easiest thing - for me, that's probably the content.


[TestFixture]
public class ContentTest
{
[Test]
public void SeldomReferredToStats(){
Assert.IsTrue(false);
}
}


Red! At least the NUnit framework works. Ok, so I'm going to try to get the content for the very first section of the report.

[TestFixture]
public class ContentTest
{
[Test]
public void SeldomReferredToStats()
{
Content content = new Content();
Assert.AreEqual(670, content.YawnFactor);
}
}

And now the Content class:

public class Content
{
public int YawnFactor { get {return 670;} }
}

Green!

That wasn't too interesting. But to tell you the truth, the Content class was not that exciting. In the real application, it served as a place to gather a whole bunch of different objects that were alive in the system and turn them into content. For now, let's pretend that we wrote a bunch of tests that let us develop a Content class that provides us with all the text for the Seldom Referred-to Stats section. We'll revisit this class in a bit, when it gets more interesting.

Now that I've got this content, I have to do something with it. Looking at the report, it makes sense to divide the content from the way it is presented.


[TestFixture]
public class PresentationTest
{
[Test]
public void Title()
{
Presentation presentation = new Presentation();
Assert.AreEqual("TPS Report", presentation.Title);
}
}

public class Presentation
{
public string Title { get {return "TPS Report";} }
}

Great. I've got a title. Now I need that title underlined and centered. Time to stop coding for a second and think about this. Looking at the report, I can see a title, a bunch of sections, and a footer. And to me, the title and footer are just sections, so maybe the report presentation is just a bunch of sections. Enough talking, let's do some walking.

[TestFixture]
public class SectionTest
{
[Test]
public void TitleSection()
{
Assert.AreEqual("TPS Report", section.Title);
}
}

public class Section
{
public string Title { get {return "TPS Report";} }
}

That passes. And there is duplication, which reminds me that I have to actually use the new class.

[TestFixture]
public class PresentationTest
{
[Test]
public void Title()
{
Presentation presentation = new Presentation();
Assert.AreEqual("TPS Report", presentation.TitleSection.Title);
}
}

public class Presentation
{
private Section titleSection = new Section();
public Section Title { get {return titleSection;} }
}

Looking good. I guess I could do one of two things. I could try to get the underline in there, or I could try to do the next section, because right now the Section class is pretty useless for anything but a title. Underlining interests me more, so I'm going to try that. I don't know how.

[TestFixture]
public class SectionTest
{
[Test]
public void TitleSection()
{
Section section = new Section();
Assert.AreEqual("TPS Report", section.Title);
Assert.AreEqual("-----", section.Line);
}
}

public class Section
{
public string Title { get {return "TPS Report";} }
public string Line { get {return "-----";} }
}

Another pass, update the Presentation test:

[TestFixture]
public class PresentationTest
{
[Test]
public void Title()
{
Presentation presentation = new Presentation();
Assert.AreEqual("TPS Report", presentation.TitleSection.Title);
Assert.AreEqual("-----", presentation.TitleSection.Line);
}
}

And green. If you are looking at this about now, and saying that the presentation test doesn't add much value, think again. It adds a very important piece of value. It says to me that the design is kind of wierd. I'm exposing data that maybe shouldn't be exposed. I'm not happy about that. Also, it tells me that if I keep going down this path without being careful, I may not get what I want. If that sounds kind of non-committal, it is. I don't know what is wrong, but I get the sense, even this early, that something doesn't jive. Let's keep going to see if we can find out what doesnt' work here.

So, maybe now would be a good time to figure out how to print. Not quite yet. One thing that is wrong is that I have some dead code. The Section class isn't employed at the moment, and in my books, that means it either gets used, or it gets tossed. Maybe I should have waited till I needed that class. In this case it did some good to start with it because it got the juices flowing and the confidence up.

Back to the code.

[TestFixture]
public class SectionTest
{
[Test]
public void TitleSection()
{
Section section = new Section();
Assert.AreEqual("TPS Report", section.Title);
Assert.AreEqual("-----", section.Line);
}

[Test]
public void ContentSection()
{
Section section = new Section();
Assert.AreEqual("Section Title", section.Title);
Assert.AreEqual("A bit of content" section.Line);
}
}

Red, of course. We need a way to set the title and content.

[Test]
public void ContentSection()
{
Section section = new Section();
section.Title = "Section Title";
section.Line = "A bit of content";

Assert.AreEqual("Section Title", section.Title);
Assert.AreEqual("A bit of content" section.Line);
}

public class Section
{
private string title;
private string line;

public string Title {
get {return title;}
set {title = value;}
}

public string Line {
get {return line;}
set {line = value;}
}
}

That test passes now, but the TitleSection and Presentation tests fail. One at a time:

public class Presentation
{
private Section titleSection = new Section();
public Presentation()
{
titleSection.Title = "TPS Report";
titleSection.Line = "-----";
}
public Section Title { get {return titleSection;}}
}

Presentation tests are now passing. What about that section test?

[Test]
public void TitleSection()
{
Section section = new Section();
section.Title = "TPS Report";
section.Line = "-----";
Assert.AreEqual("TPS Report", section.Title);
Assert.AreEqual("-----", section.Line);
}

Hmmmm....

[Test]
public void TitleSection()
{
Section section = new Section();
section.Title = "TPS Report";
section.Line = HorizontalLine;
Assert.AreEqual("TPS Report", section.Title);
Assert.AreEqual(HorizontalLine, section.Line);
}

private string HorizontalLine { get {return "-----";} }

Green now, and I have a new idea. There is a difference between the types of lines that are in a section. It seems as though a section can have a horizontal line or a text line. I'm going to put that on the back burner for a second or two. I think that what I really need to do is let a section have more lines.

public class SectionTest
{
...

[Test]
public void ContentSection()
{
Section section = new Section();
section.Title = "Section Title";
section.AddLine("A bit of content");
section.AddLine("A bit more content");

Assert.AreEqual("Section Title", section.Title);
Assert.AreEqual("A bit of content" section.Lines[0]);
Assert.AreEqual("A bit more content" section.Lines[1]);
}
}

public class Section
{
private string title;
private ArrayList lines;

public string Title {
get {return title;}
set {title = value;}
}

public string[] Lines { get {return (string[])lines.ToArray(typeof(string));}
public void AddLine(string line) { lines.Add(line); }
}

Of course, this passes, the other tests fail, we refactor those, and they all pass. Now I feel a little better. But I don't like this code, in the Section test:

section.AddLine(HorizontalLine);

Lets make it this:

section.AddHorizontalLine();

And implement it this way

public class Section
{
...
public void AddHorizontalLine() { AddLine("-----"); }
}

Time for a recap of all the classes:

public class Section
{
private string title;
private ArrayList lines;

public string Title {
get {return title;}
set {title = value;}
}

public string[] Lines { get {return (string[])lines.ToArray(typeof(string));}
public void AddLine(string line) { lines.Add(line); }
public void AddHorizontalLine() {lines.Add("-----") }
}

public class Presentation
{
private Section titleSection = new Section();
public Presentation()
{
titleSection.Title = "TPS Report";
titleSection.AddHorizontalLine();
}
public Section Title { get {return titleSection;} }
}

public class Content
{
public int YawnFactor { get {return 670;} }
...
}

Time to make that Content class a full contributor. Some of my team mates would have axed it already, since it's not being used anywhere but inside of a test.

[TestFixture]
public class PresentationTest
{
[Test]
public void TPSReport()
{
Presentation presentation = new Presentation(new Content());
Assert.AreEqual("TPS Report", presentation.TitleSection.Title);
Assert.AreEqual("-----", presentation.TitleSection.Lines[0]);
Assert.AreEqual("Seldom Referred-to Stats", presentation.SeldomReferredToStatsSection.Title);
Assert.AreEqual("Yawn Factor:\t\t\t\t\t670", presentation.SeldomReferredToStatsSection.Lines[0]);
Assert.AreEqual("Average of a Bunch of Averages:\t\t\t\t\t1", presentation.SeldomReferredToStatsSection.Lines[1]);
Assert.AreEqual("Sleep Quotient\t\t\t\t\tPurple", presentation.SeldomReferredToStatsSection.Lines[2]);
}
}

public class Presentation
{
private Section titleSection = new Section();
private Content content;
public Presentation(Content content)
{
titleSection.Title = "TPS Report";
titleSection.AddHorizontalLine();
this.content = content;
}
public Section Title { get {return titleSection;} }

public Section SeldomReferredToStatsSection
{
get
{
Section section = new Section();
section.Title = "Seldom Referred-to Stats";
section.AddLine("Yawn Factor:\t\t\t\t\t" + content.YawnFactor);
section.AddLine("Average of a Bunch of Averages:\t\t" + content.AverageOfAverages);
section.AddLine("Sleep Quotient\t\t\t\t\t" + content.SleepQuotient);
return section;
}
}
}

That passes. Notice I took out the title test in the Presentation test. It wasn't needed anymore. While doing that last test, I noticed some more refactoring that could be done. That silly titleSection needs to go:

public class Presentation
{
private Content content;
public Presentation(Content content)
{
this.content = content;
}

public Section Title {
{
get
{
Section section = new Section();
section.Title = "TPS Report";
section.AddHorizontalLine();
return section;
}
}

public Section SeldomReferredToStatsSection
{
get
{
Section section = new Section();
section.Title = "Seldom Referred-to Stats";
section.AddLine(content.YawnFactor);
section.AddLine(content.AverageOfAverages);
section.AddLine(content.SleepQuotient);
return section;
}
}
}

That's a little better. But why am I distiguishing between the Title section and the SeldomReferredToStatsSection? It's an iffy call. I could leave it because it is readable. But I have an idea about how to refactor my tests that I can't give up:

public class Presentation
{
private Content content;
public Presentation(Content content)
{
this.content = content;
}

public Section[] Sections {
get{return new Section[] {Title, SeldomReferredToStatsSection};}
}

private Section Title {
get
{
Section section = new Section();
section.Title = "TPS Report";
section.AddHorizontalLine();
return section;
}
}

private Section SeldomReferredToStatsSection{
get
{
Section section = new Section();
section.Title = "Seldom Referred-to Stats";
section.AddLine("Yawn Factor:\t\t\t\t\t" + content.YawnFactor);
section.AddLine("Average of a Bunch of Averages:\t\t" + content.AverageOfAverages);
section.AddLine("Sleep Quotient\t\t\t\t\t" + content.SleepQuotient);
return section;
}
}
}

Now I can do this:

[TestFixture]
public class PresentationTest
{
Section sectionUnderTest;

[Test]
public void TPSReport()
{
Presentation presentation = new Presentation(new Content());

sectionUnderTest = presentation.Sections[0];
CheckTitle("TPS Report");
CheckLine(0, "-----");

sectionUnderTest = presentation.Sections[1];
CheckTitle("Seldom Referred-to Stats");
CheckLine(0, "Yawn Factor:ttttt670");
CheckLine(1, "Average of a Bunch of Averages:tt1");
CheckLine(2, "Sleep QuotienttttttPurple");
}

private void CheckTitle(string expected)
{
Assert.AreEqual(expected, sectionUnderTest.Title);
}

private void CheckLine(int line, string expected)
{
Assert.AreEqual(expected, sectionUnderTest.Lines[line]);
}
}

I like that! Now that I have a bit of a report, it's time, I think, to start printing. This is where I step back and say, what do we have and where can we go?

Well, printers print reports, don't they? I guess we could start there. First, I need a printer. I still don't know how to test printing, so I'm going to start by creating my own printer that's not really a printer.


[TestFixture]
public class MyOwnPrinterTest
{
private string expectedReport = "TPS Report\r\n" +
"-----\r\n" +
"Yawn Factor\t\t\t\t\t670\r\n" +
"Average of a Bunch of Averages:\t\t1\r\n" +
"Sleep Quotient\t\t\t\t\tPurple";

[Test]
public void PrintReport()
{
Presentation presentation = new Presentation(new Content());
MyOwnPrinter printer = new MyOwnPrinter();
printer.Print(presentation);
Assert.AreEqual(expectedReport, printer.PrintedPage);
}
}

public class MyOwnPrinter
{
public StringWriter Page;

public void Print(Presentation presentation)
{
foreach (Section section in presentation.Sections)
{
Page.WriteLine(section.Title);
foreach (string line in section.Lines)
Page.WriteLine(line);
}
}
}

I knew that putting all the sections into an array would make sense. So there we have it. We have our report printing to a fake printer. But we aren't done yet. We need this to go to a real printer. The reason I made the fake printer first was simple - make sure the report can be printed. If a fake printer can define an interface to print the report to a stream, then the real printer can implement the same interface and change the underlying mechanics.

But, once again, I'm not happy. We are so close, but the interface doesn't seem right. For instance, how can I draw '-----' as a nice horizontal line on a real printer? I probably have the interface wrong. Let's think about this for a minute.

What does a printer do? It prints reports, right? Well, that was my first thought. But really, a printer is just like a monitor or even a web browser. And all those things provide services for rendering images. If that's the case, then maybe I have the relationship between Presentation and MyOwnPrinter backwards. Maybe Presentation draws itself using the services that MyOwnPrinter offers.

Lets try that. I feel a big refactoring coming on.

[TestFixture]
public class MyOwnPrinterTest
{
private string expectedReport = "TPS Report\r\n" +
"-----\r\n" +
"Yawn Factor\t\t\t\t\t670\r\n" +
"Average of a Bunch of Averages:\t\t1\r\n" +
"Sleep Quotient\t\t\t\t\tPurple";

[Test]
public void PrintReport()
{
Presentation presentation = new Presentation(new Content());
MyOwnPrinter printer = new MyOwnPrinter();
presentation.To(printer);
Assert.AreEqual(expectedReport, printer.PrintedPage);
}
}

public class Presentation
{
private Content content;
public Presentation(Content content) {
this.content = content;
}

public Section[] Sections {
get{return new Section[] {Title, SeldomReferredToStatsSection};}}

public void To(MyOwnPrinter printer)
{
foreach (Section section in Sections){
printer.Render(section.Title);
foreach (string line in section.Lines)
printer.Render(line);
}
}

private Section Title {
get{
Section section = new Section();
section.Title = "TPS Report";
section.AddHorizontalLine();
return section;
}
}

private Section SeldomReferredToStatsSection {
get{
Section section = new Section();
section.Title = "Seldom Referred-to Stats";
section.AddLine("Yawn Factor:ttttt" + content.YawnFactor);
section.AddLine("Average of a Bunch of Averages:tt" + content.AverageOfAverages);
section.AddLine("Sleep Quotientttttt" + content.SleepQuotient);
return section;
}
}
}

public class MyOwnPrinter
{
public StringWriter Page;

public void Render(string line)
{
Page.WriteLine(line);
}
}

I like that better. MyOwnPrinter now doesn't know about Presenation or it's structure. It just knows how to print stuff. Cool. But that still doesn't fix the problem of printing horizontal lines on a real printer. So maybe a service that the printer offers is to print horizontal lines. Before I even write a test for that, I don't want to have a bunch of 'if string == '-----' ' code everywhere. Maybe it's time to go back to that idea of lines.


[TestFixture]
public class HorizontalLineTest
{
[Test]
public void HorizontalLine()
{
MyOwnPrinter printer = new MyOwnPrinter();
printer.Render(new HorizontalLine());
Assert.AreEqual("-----", printer.Page);
}
}

This will seem a little tricky, but here is what is in my head - the printer knows how to draw a horizontal line, and the HorizontalLine class uses the printer. Watch:

public class HorizontalLine
{
public void Draw(MyOwnPrinter printer)
{
printer.RenderHorizontalLine();
}
}

and then add the service to the printer:

public class MyOwnPrinter
{
public StringWriter Page;

public void Render(string line)
{
Page.WriteLine(line);
}

public void RenderHorizontalLine()
{
Render("-----");
}
}

And we have a green bar. And I love that design, because now I can see how to extend it a little and make any line draw itself by extracting the Draw method into an abstract class.

Let's refactor a bit to use that concept:

public class Section
{
private string title;
private ArrayList lines;

public string Title {
get {return title;}
set {title = value;}
}

public Line[] Lines { get {return (Line[])lines.ToArray(typeof(Line));}
public void AddLine(string line) { lines.Add(new TextLine(line)); }
public void AddHorizontalLine() {lines.Add(new HorizontalLine()) }
}

The test can no longer access the data directly because it is nice and encapsulated. Remember that test refactoring earlier? Maybe that can help:

public void TestHelper
{
Section sectionUnderTest;
MyOwnPrinter printer;

[SetUp]
public void SetUp()
{
printer = new MyOwnPrinter();
}

protected void CheckTitle(string expected)
{
sectionUnderTest.Title.Draw(printer)
Assert.AreEqual(expected, printer.Page );
}

protected void CheckLine(int line, string expected)
{
sectionUnderTest.Lines[line].Draw(printer)
Assert.AreEqual(expected, printer.Page);
}
}

Use it in the Section Test:

public class SectionTest : TestHelper
{

[Test]
public void TitleSection()
{
Section section = new Section();
section.AddTitle("TPS Report");
section.AddHorizontalLine();
sectionUnderTest = section;
CheckTitle("TPS Report");
CheckLine(0, HorizontalLine);
}

[Test]
public void ContentSection()
{
Section section = new Section();
section.AddTitle("Section Title");
section.AddLine("A bit of content");
section.AddLine("A bit more content");
sectionUnderTest = section;
CheckTitle("Section Title");
CheckLine(0, "A bit of content");
CheckLine(1, "A bit more content");
}

private string HorizontalLine { get {return "-----";} }
}

And the Presentation test:

[TestFixture]
public class PresentationTest:TestHelper
{
[Test]
public void TPSReport()
{
Presentation presentation = new Presentation(new Content());
sectionUnderTest = presentation.Sections[0];
CheckTitle("TPS Report");
CheckLine(0, "-----");

sectionUnderTest = presentation.Sections[1];
CheckTitle("Seldom Referred-to Stats");
CheckLine(0, "Yawn Factor:ttttt670");
CheckLine(1, "Average of a Bunch of Averages:tt1");
CheckLine(2, "Sleep QuotienttttttPurple");
}
}

and refactor the classes:

public class Presentation
{
private Content content;
public Presentation(Content content)
{
this.content = content;
}

public Section[] Sections {
get{return new Section[] {Title, SeldomReferredToStatsSection};}}

public void To(MyOwnPrinter printer)
{
foreach (Section section in Sections) {
printer.Render(section.Title);
foreach (Line line in section.Lines)
printer.Render(line);
}
}

private Section Title {
get {
Section section = new Section();
section.AddTitle("TPS Report");
section.AddHorizontalLine();
return section;
}
}

private Section SeldomReferredToStatsSection{
get {
Section section = new Section();
section.AddTitle("Seldom Referred-to Stats");
section.AddLine("Yawn Factor:ttttt" + content.YawnFactor);
section.AddLine("Average of a Bunch of Averages:tt" + content.AverageOfAverages);
section.AddLine("Sleep Quotientttttt" + content.SleepQuotient);
return section;
}
}
}

public class Section
{
private ArrayList lines;
public Line[] Lines { get {return (Line[])lines.ToArray(typeof(Line));}
public void AddTitle(string title){ AddLine(title)};
public void AddLine(string line) { lines.Add(new TextLine(line)); }
public void AddHorizontalLine() {lines.Add(new HorizontalLine()) }
}

And done. Well almost, I need to add a real printer. I think it's safe to extract an interface from my own printer:


public abstract class Printer
{
public virtual void Render(string text){}
public virtual void RenderHorizontalLine(){}
}

Any printer that implements that interface can now be used to print presentations. You will see the final refactoring in the class recap at the end. We've finally come down to the very bottom - using a real printer to print. And really, it shouldn't be too hard to create a class that represents the real printer. In this case, I'm going to show you the class first, pseudo-coded:

public class RealPrinter : Printer
{
Graphics printerSurface;
public override Render(string text)
{
printerSurface.DrawString(text);
}

public override RenderHorizontalLine()
{
printerSurface.DrawLine(...)
}
}

Pass that to the Presentation class, and everything should draw. But where is the test? Ok, this may seem a little anti-climactic, but to test this, we write a very simple test:

[TestFixture]
public class RealPrinterTest
{
[Test]
public void LookAtTPSReport()
{
Presentation presentation = new Presentation(new Content());
LookAt(presentation);
}

private void LookAt(Presentation presentation)
{
presentation.To(printer);
System.PrintPreview();
}
}

(GRIN) I hope you haven't gotten this far, expecting an out of this world way of testing the actual printed page, only to feel like strangling me because I am using the print preview capabilities of the .Net framework (which I have pseudo-coded here because it is really not important to understanding the design).

However, the reason we feel confident doing this is because we have used TDD to drive every single part of the design right down to the interface to the printer. So we know that the lines, sections, and layout work properly before putting ink on the paper. By the time we get to the printer, we are dealing with a thin wrapper around graphics calls. And we don't test low level graphics calls to the OS because we won't be changing that stuff. What we have done is isolated the printer as much as possible so that we could have confidence in every other piece of the design.

So that's it for now. I'm not going to publish how we put the graphics or tabular elements on the page, or how we did the footers, or pagination, or any other detail. I have to maintain some element of mystery. And I need to keep my job, so I can't give away all our secrets to the public :) Look me up on the XP mailing list if you have questions about those things (hint - it's the same as all the other lines).

Here is a recap of all classes, sans tests:

public abstract class Printer
{
public virtual void Render(string text){}
public virtual void RenderHorizontalLine(){}
}

public class RealPrinter : Printer
{
Graphics printerSurface;
public override Render(string text)
{
printerSurface.DrawString(text);
}

public override RenderHorizontalLine()
{
printerSurface.DrawLine(...)
}
}

public class MyOwnPrinter : Printer
{
public StringWriter Page;

public override void Render(string line)
{
Page.WriteLine(line);
}

public override void RenderHorizontalLine()
{
Render("-----");
}
}

public class Presentation
{
private Content content;
public Presentation(Content content)
{
this.content = content;
}

public Section[] Sections {
get{return new Section[] {Title, SeldomReferredToStatsSection};}}

public void To(Printer printer)
{
foreach (Section section in Sections) {
printer.Render(section.Title);
foreach (Line line in section.Lines){
printer.Render(line);
}
}

private Section Title {
get {
Section section = new Section();
section.AddTitle("TPS Report");
section.AddHorizontalLine();
return section;
}
}

private Section SeldomReferredToStatsSection {
get {
Section section = new Section();
section.AddTitle("Seldom Referred-to Stats");
section.AddLine("Yawn Factor:ttttt" + content.YawnFactor);
section.AddLine("Average of a Bunch of Averages:tt" + content.AverageOfAverages);
section.AddLine("Sleep Quotientttttt" + content.SleepQuotient);
return section;
}
}
}

public class Section
{
private ArrayList lines;
public Line[] Lines { get {return (Line[])lines.ToArray(typeof(Line));}
public void AddTitle(string title){ AddLine(title)};
public void AddLine(string line) { lines.Add(new TextLine(line)); }
public void AddHorizontalLine() {lines.Add(new HorizontalLine()) }
}

public class HorizontalLine
{
public void Draw(Printer printer)
{
printer.RenderHorizontalLine();
}
}

public class Content
{
...
public int YawnFactor { get {return 670;} }
}

Wednesday, September 21, 2005

TDD and the Single Printer: Introduction

Test-driving some development is impossible. Ok, really hard. Alright, not hard, but really tedious. Ok, not tedious, but...

I find myself going through that loop of thought when I don't know how to start using TDD on a programming problem. The catch is, TDD is perfect for exactly this type of development!

And so, I present my latest problem to which I thought I could not possibly use TDD, but ended up using it to create a very nice design, the likes of which will not be rivalled in all of programming lore! Ok, that's stretching it a bit, but the design made me happy, and in my books that counts for something.

Here's the story: Print an unmodifiable report to the printer when the user hits the 'Print' button. Use the following mockup as a guide:

The mockup above contains all the elements of the real report that we were asked to add to the real product. And so the story begins...

Next time: Where do we start?!?!

Friday, August 12, 2005

Incentive To Change

Summer's a good time to catch up on some reading. A book, a blog, and a radio program have reshaped some of my thinking about agility.

Freakonomics is one of those books that makes you want to ask questions. Deep questions. Economist Steven Levitt, one of books authors, makes the claim that he wants to shed light on the ideal world and expose the actual world. And he does this brilliantly by asking the right types of questions and not shying away from the results. From why drug dealers live with their mothers, to real estate agents and their ability to move homes, right down to the way people name their children, there is usually and answer different from the one that you expected to get. The thing that was striking, and that started me down a path of thought, was that all of those unexpected answers had a common flavour - they all focused on incentive structures that cause people to do the things that they do.

More on that in a minute.

Ron Jeffries wrote a great piece about what he would do if he were an executive and wanted to make 'software cheaper, sooner, and with fewer defects.' How does he do it? Well, read the article for all of the details. My learning from Ron's article, and viewed in the glow of a dimn enlightenment, was that if an executive is able to change the incentive structures in an organisation, then the people in that organisation will change their behaviour in response to those changes. It seems like common sense. In Ron's case, as the executive of a company, he made it clear that he wanted a simple measurement of project success: Running tested software delivered this month that customers are either saying they want, or are using now. Ron goes on to say that he doesn't expect to have to change incentive programs. However, he is changing incentive structures - his people now have to report something very specific to make Ron happy. Happy Ron - happy subordinate-to-Ron.

Moving along, the final twist came when I was listening to the CBC, which plays a top-notch show called Ideas. This episode happened to be about the cost of adopting environmentally-sound products and practices. One of the guests, Joseph Heath, a professor of philosophy at the University of Toronto, spoke about, you guessed it, incentives. Dr. Heath spoke about crisis and values.

Crisis leads to action because there is an incentive to do so. One example is a natural disaster. Disaster alters social structures, and brings about communal cooperation. People behave differently because the incentive is there to rebuild as quick as possible and return to a state of normal. Once normal is achieved, these same people tend to go back to a more individual style of living. Crisis is not always about disaster, sometimes it is about radical change. For example, revolutionary change in a country's government via coup or mass revolt. People band together and get swept up in the crisis-atmosphere, the incentive being that change will bring about a better life. However, as has been in seen in many examples world-wide, once the revolution is over, the atmosphere of revolution rarely continues, because people go back to what they know - the daily grind.

Changing values, beliefs, and world-views is not an effective means of change without revisions to supporting incentive structures, says Dr. Heath. An example of this is seen in towns with watering bans. Much effort is placed on educating citizens about the need to conserve water, the positive effects of conservation on the environment, and individual contribution to a greater good. One would expect a substantial decrease in water usage, given a majority of residents had changed their way of thinking. Water usage did not decline substantially. Did a change in thinking not occur? Well, it was shown that campaigns were effective in changing views on conservation, however, people also believed that the greater good was accomplished by the community as a whole, and that sneaking out to water a lawn at midnight wasn't going to be the tipping point towards an outright drought. Even though the values, beliefs, and world-views of the citizenry had changed,there was no supporting incentive to prevent them from actually watering their lawns. Yet, when municipalities started installing water meters in new homes and existing residences, water usage dropped 40 percent because residential water usage was now monitored and billed according to usage (and I believe, availability). Once a new incentive structure was introduced to 'support' the new values and beliefs of the citizenry, all was well.

Enough rambling about the obtuse. Many companies turn to agile and XP when software crisis hits (software is more expensive, delivering later, with more defects). Lots of practices aren't adopted by management or by programmers or by customers. Companies have problems trying to bring agile and XP online. And the adoption of XP and agile isn't moving forward as expected.

Agile and XP are about values and principals and practices. People can buy into them, but still have no incentive to put them into practice. So maybe the future of agility is about exploring the incentives that are in non-agile organisations, and replacing them with incentive structures that allow agility to work, or making agility work in existing incentive structures.

What do I mean by this? Perhaps it's best illustrated with a few examples:

We all love pair programming. Once programmers get used to it, the incentive to pair is stronger than the incentive to not pair because the benefits are obvious - two brains, two sets of eyes, lots of collaboration, etc. But in some companies, the incentive to continue pair programming as a regular practice isn't all that obvious - two programmers == twice the cost for the same number of features. Without properly demonstrated benefits - economically feasible level of defects, same number of features as two programmers - there is no incentive to adopt pairing.

Evolutionary design is another. How do we convince companies that heavy requirements gathering and upfront design complete with docs is not the way to go? Well, the convincing is easy. Changing the need is the hard part. The incentive to produce these artifacts is great - show us the design, get it approved, and we'll give you money to proceed. Documents and approved design == confidence. Changing this incentive to a structure where funding is based on confidence in agile techniques is the real challenge.

So that's my thinking, as of now. To really make a company agile, the incentives to become agile and remain agile need to be created throughout the entire organisation. From an incentive-based stance, that means looking at the ideal world that you work in, ask some pointed questions, and expose the actual world that you work in. There's great incentive to do just that.

I'm going to explore some practices and look at them from an incentive point-of-view over the next few postings. I hope you will find them useful.

Tuesday, June 14, 2005

Text and Code Don't Mix

I just got over a nasty case of string duplication. My current code was littered with strings that represented tags, attributes, and XPath queries, and over a very short time, the buildup resulted in some big time duplication of text.

No problem, right? Wrong! What I thought would take me an hour or so to remove ended up taking my pair and me around 6 hours! Like code duplication, I've learned that string duplication can be everywhere - embedding common string patterns in other strings, and then extracting them later, is a huge pain in the neck. Using the same string in 15 different places is a big headache. And don't get me started on using hardcoded strings in tests. Before you know it, they are everywhere.

Here is what we learned as we refactored to remove hardcoded string duplication:
1) It's boring and mind-numbing.
2) Microsoft doesn't have any nice tools to help us .NET programmers yet. Search and Replace is primitive, and unless you are a regular expression guru, forget about using this tool effectively.
3) Make expression builders as early as you can to help build compound expressions where only part of the text in the string varies.

I'd give some code examples, but I've had a long day of removing hardcoded strings, and I'm going to bed.

Wednesday, May 25, 2005

My Favourite Smells

Hi, I'm Chris, and I've written smelly code. In fact, I still do it. I mean, you can't remove code smells if you don't put them there in the first place.

A recent conversation around continuous design and refactoring towards a good design got me thinking along a tangent- are there smells that I have a hard time escaping? What are the ones that I can't seem to shake, no matter how hard I try?

So I came up with one that I am especially fond of, and that special place in my heart goes to primitive obsession. This is the smell that I use all the time. What is it? Well, it's when you use primitive types, like doubles, strings, ints, to represent ideas that really deserve their own type.

My brain doesn't always detect the need for a new type. Sometimes I am perfectly content to represent something, say, like the concept of Mass, as a double. All over the system, I merrily use my 'Mass is a double' notion, until....

I need a tolerance!?! You never told me I needed a tolerance! Now I need to go around the system and change all my Masses to use a tolerance... ok, done, not so bad... What!? I need to convert my Mass to Energy?!?! Why didn't you tell me?! Ok, why is this not working? Those darn tolerances are messing everything up!

This is a semi-regular occurence, and I personally find two things interesting about primitive obsession.

  • It is easy to live with for a while, sometimes a long while. But it tangles itself into a system nice and tight, and is one of the hardest smells to remove.
  • If avoided, your code is so easy to change and you get some nice side benefits.

Let me give an example of the latter point. I work on a system that has a mixture of one-based indices and zero-based indices (legacy, gotta live with it). As we built the new stuff, we decided everything would be one-based. However, there were all kinds of errors popping up. Anyone who has programmed for more than a week will concur (hopefully, or I'm the only fool who can't add and subtract) that i + 1 and i - 1 all over the place get's really hard to figure out after a while, and your head spins while trying to convert zero-based and one-based indices back and forth. Never mind all the guess work when trying to figure out if a parameter to a method was zero or one based.

Well, I tried something. I made a OneBasedInt and a ZeroBasedInt value type and began using them everywhere. Soon, there were all kind of cool things happening:

  • People suddenly knew the type of index they should pass into a method
  • Things started to fail fast - I could no longer assign zero to a one-based index, and I could tell exactly when I was doing that!
  • No more index + 1 and index - 1 all over the code.

So much for my weakness(es). I see the benefits of avoiding primitive obsession, but continue to get stung by it often. Maybe I will be old and wise one day. For now, I will relish my small victories.