<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Minnen Ratta</title>
	<atom:link href="http://minnenratta.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://minnenratta.wordpress.com</link>
	<description>Saving the world, one lame suggestion at a time</description>
	<lastBuildDate>Mon, 28 Nov 2011 12:22:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='minnenratta.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/63f35284b49b23f75a789ea3b97cf228?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Minnen Ratta</title>
		<link>http://minnenratta.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://minnenratta.wordpress.com/osd.xml" title="Minnen Ratta" />
	<atom:link rel='hub' href='http://minnenratta.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Web Apps in TDD, Appendix, the User</title>
		<link>http://minnenratta.wordpress.com/2011/01/02/web-apps-in-tdd-appendix-the-user/</link>
		<comments>http://minnenratta.wordpress.com/2011/01/02/web-apps-in-tdd-appendix-the-user/#comments</comments>
		<pubDate>Sun, 02 Jan 2011 12:22:00 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=298</guid>
		<description><![CDATA[Here&#8217;s the User class and its collaborators as it is right now. It is a bit more evolved than its original form : when I first wrote it all of the logic was in the User itself as I had no need to evaluate Javascript outside of html, later I separated the two responsibilities (parsing [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=298&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the User class and its collaborators as it is right now. It is a bit more evolved than its original form : when I first wrote it all of the logic was in the User itself as I had no need to evaluate Javascript outside of html, later I separated the two responsibilities (parsing xml/html and evaluating Javascript) since I had a need to evaluate Javascript no matter where.</p>
<pre><code>
public class User {
    private final JavaScript javaScript = new JavaScript();
    private final Result result = new Result();

    public User() {
        javaScript.evaluateFile("browser.js");
    }

    public User lookAt(String htmlPage) {
        JavaScriptSource source = new XomJavaScriptSource(htmlPage);
        source.evaluateWith(javaScript);
        triggerOnLoad();
        result.readOutput(javaScript);
        return this;
    }

    public String currentSight() {
        return result.nextValue();
    }

    private void triggerOnLoad() {
        javaScript.evaluateScript("window.onload();", "onload");
    }

}

</code></pre>
<p>And here&#8217;s &#8220;JavaScript&#8221;, which manages everything Rhino-related.</p>
<pre><code>
public class JavaScript {
    private final Context context;
    private final ScriptableObject scope;

    public JavaScript() {
        context = Context.enter();
        scope = context.initStandardObjects();
    }

    public Object valueOf(String variableName) {
        return scope.get(variableName);
    }

    public void evaluateScript(String script, String scriptName) {
        context.evaluateString(scope, script, scriptName, 1, null);
    }

    public void evaluateScript(String script) {
        evaluateScript(script, "script");
    }

    public void evaluateFile(String sourceFileName) {
        try {
            context.evaluateReader(scope, read(sourceFileName), sourceFileName, 1, null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private InputStreamReader read(String sourceFileName) {
        return new InputStreamReader(getClass().getClassLoader().getResourceAsStream(sourceFileName));
    }
}

</code></pre>
<p>This is &#8220;Result&#8221;, which extracts values from the results array in Javascript.</p>
<pre><code>
public class Result {
    private NativeArray output = new NativeArray(0);
    private int current = 0;

    public void readOutput(JavaScript javaScript) {
        output = (NativeArray) javaScript.valueOf("output");
    }

    public String nextValue() {
        return (String) output.get(current++);
    }
}

</code></pre>
<p>Finally, this is the class that hides the fact that scripts are mixed within html.</p>
<pre><code>
public class XomJavaScriptSource implements JavaScriptSource {

    private final Document document;

    public XomJavaScriptSource(String htmlPage) {
        document = parsePage(htmlPage);
    }

    @Override
    public void evaluateWith(JavaScript javaScript) {
        Nodes scriptNodes = document.query("//script");
        for (int i = 0; i &lt; scriptNodes.size(); i++) {
            evaluateNode(scriptNodes.get(i), javaScript);
        }
    }

    private final Document parsePage(String htmlPage) {
        try {
            return new Builder().build(htmlPage, null);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void evaluateNode(Node scriptNode, JavaScript javaScript) {
        if (scriptNode instanceof Element) {
            Attribute sourceAttribute = ((Element) scriptNode).getAttribute(&quot;src&quot;);
            if (sourceAttribute != null) {
                javaScript.evaluateFile(sourceAttribute.getValue());
                return;
            }
        }
        javaScript.evaluateScript(scriptNode.getValue());
    }
}
</code></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/298/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=298&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2011/01/02/web-apps-in-tdd-appendix-the-user/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>Web Apps in TDD, Part 4</title>
		<link>http://minnenratta.wordpress.com/2010/12/17/web-apps-in-tdd-part-4/</link>
		<comments>http://minnenratta.wordpress.com/2010/12/17/web-apps-in-tdd-part-4/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 19:56:02 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=292</guid>
		<description><![CDATA[Multiple buildings! I bet that you can tell where this is going, I&#8217;ve one building, now I want multiple buildings on my page and then finally put the player in the middle. So, I add two more rectangles to my investigation.html. ... var map = new Raphael(0,0,600,400); map.rect(10,10,50,40); map.rect(80,10,30,40); map.rect(10,70,100,40); ... Which produces : Now, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=292&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Multiple buildings!</h1>
<p>I bet that you can tell where this is going, I&#8217;ve one building, now I want multiple buildings on my page and then finally put the player in the middle.<br />
So, I add two more rectangles to my investigation.html.</p>
<pre><code>
            ...
            var map = new Raphael(0,0,600,400);
            map.rect(10,10,50,40);
            map.rect(80,10,30,40);
            map.rect(10,70,100,40);
            ...
</code></pre>
<p>Which produces :</p>
<p><img src="http://minnenratta.files.wordpress.com/2010/11/three-buildings.png?w=575" /></p>
<p>Now, for the test that will lead me to implementing this&#8230;</p>
<pre><code>
    @Test
    public void shouldRenderMultipleBuildings() throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10,10,50,40);
        htmlScreen.addBuilding(80,10,30,40);
        htmlScreen.addBuilding(10,70,100,40);
        User user = new User().lookAt(htmlScreen.render());
        assertThat(user.currentSight(), is("A Rectangle at [10,10], 40px high and 50px wide"));
        assertThat(user.currentSight(), is("A Rectangle at [80,10], 40px high and 30px wide"));
        assertThat(user.currentSight(), is("A Rectangle at [10,70], 40px high and 100px wide"));
    }
</code></pre>
<p>The current result is :</p>
<pre><code>
Expected: is "A Rectangle at [10,10], 40px high and 50px wide"
     got: "A Rectangle at [10,70], 40px high and 100px wide"
</code></pre>
<p>Which is the last building only. This is due to my implementation of the html screen. Which stores the last building and overwrites the previous one. Easy fixed.</p>
<pre><code>
    private String renderBuildings() {
        String renderedBuildings = "";
        for (Building building : buildings) {
            renderedBuildings += building.render(vectorGraphics);
        }
        return renderedBuildings;
    }

    public Screen addBuilding(int x, int y, int width, int height) {
        buildings.add(new Building(x, y, width, height));
        return this;
    }
</code></pre>
<pre><code>
function Raphael(x, y, width, height){

    this.rect = function(x, y, width, height) {
        output[invocations++] = "A Rectangle at [" + x + "," + y + "], " +
                    height + "px high and " + width + "px wide";
    }

}

var output = [];
</code></pre>
<pre><code>
    public String currentSight() {
        return (String) output.get(current++);
    }
</code></pre>
<p>Now, for the real-life test</p>
<pre><code>
    public static void main(String... args) throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10,10,50,40);
        htmlScreen.addBuilding(80,10,30,40);
        htmlScreen.addBuilding(10,70,100,40);
        new Boss(11111, htmlScreen);
    }
</code></pre>
<p>But, the very first HtmlScreenBehavior test is not happy, it did expect a rectangle, now that rectangle needs to be added explicitly.</p>
<pre><code>
    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        User user = new User().lookAt(new HtmlScreen().addBuilding(10, 10, 50, 40).render());
        assertThat(user.currentSight(), is("A Rectangle at [10,10], 40px high and 50px wide"));
    }
</code></pre>
<p>Now it passes. All tests are green.</p>
<p>I&#8217;m so glad it&#8217;s time to refactor, because my tests are looking very bad. For instance, have a look at the test just after the one I just modified :</p>
<pre><code>
    @Test
    public void shouldRenderTheBuildingWithTheRightPositionAndDimensions() {
        User user = new User().lookAt(
        		new HtmlScreen().addBuilding(50, 30, 80, 40).render());
        assertThat(user.currentSight(),
        		is("A Rectangle at [50,30], 40px high and 80px wide"));
    }

</code></pre>
<p>Yes, they are the same, the only difference is in the values. This is pretty much the only instance were I do consider erasing a test without a change in features : when it says exactly the same thing as another test.</p>
<p>So, adieu! I delete the second one, as I like the first one&#8217;s name better.</p>
<p>What else? Well, I&#8217;m growing bored of typing all of these &#8220;A Rectangle&#8230;&#8221;.</p>
<pre><code>
    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        User user = new User().lookAt(new HtmlScreen().addBuilding(10, 10, 50, 40).render());
        assertThat(user.currentSight(), is(aRectangle(10, 10, 50, 40)));
    }

    @Test
    public void shouldRenderMultipleBuildings() throws Exception {
        HtmlScreen htmlScreen = new HtmlScreen();
        htmlScreen.addBuilding(10, 10, 50, 40);
        htmlScreen.addBuilding(80, 10, 30, 40);
        htmlScreen.addBuilding(10, 70, 100, 40);
        User user = new User().lookAt(htmlScreen.render());
        assertThat(user.currentSight(), is(aRectangle(10, 10, 50, 40)));
        assertThat(user.currentSight(), is(aRectangle(80, 10, 30, 40)));
        assertThat(user.currentSight(), is(aRectangle(10, 70, 100, 40)));
    }

    private String aRectangle(int x, int y, int width, int height) {
        return "A Rectangle at [" + x + "," + y + "], " +
        			height + "px high and " + width + "px wide";
    }
</code></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/292/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/292/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/292/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=292&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/12/17/web-apps-in-tdd-part-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2010/11/three-buildings.png" medium="image" />
	</item>
		<item>
		<title>Web Apps in TDD, Part 3</title>
		<link>http://minnenratta.wordpress.com/2010/12/06/web-apps-in-tdd-part-3/</link>
		<comments>http://minnenratta.wordpress.com/2010/12/06/web-apps-in-tdd-part-3/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 22:01:29 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=283</guid>
		<description><![CDATA[Rendering a building What&#8217;s next on the todo list? I want a rectangle to appear on the screen to show a building. Google tells me there&#8217;s a nice javascript library to draw vector graphics on a browser. I think I&#8217;ll try it, it&#8217;s called Raphael. So I write an html file using this library to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=283&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Rendering a building</h1>
<p>What&#8217;s next on the todo list? I want a rectangle to appear on the screen to show a building.<br />
Google tells me there&#8217;s a nice javascript library to draw vector graphics on a browser. I think I&#8217;ll try it, it&#8217;s called Raphael.<br />
So I write an html file using this library to draw a rectangle :</p>
<pre><code>
&lt;html&gt;
&lt;head&gt;
    &lt;script type="text/javascript" src="raphael-min.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" charset="utf-8"&gt;
        window.onload = function() {
            var map = new Raphael(0,0,600,400);
            var building = map.rect(10,10,50,40);
        };
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>And with this I get :</p>
<p><img src="http://minnenratta.files.wordpress.com/2010/11/investigation.png?w=575" /></p>
<p>A real beauty. The building is the small rectangle top left.</p>
<p>Now I would like my HtmlScreen to return that.</p>
<h2>Testing the behavior</h2>
<p>I could write a test like this :</p>
<pre><code>
    @Test
    public void shouldRenderABuildingAsARectangle() {
        assertThat(new HtmlScreen().render(), is("&lt;html&gt;\n" +
                "&lt;head&gt;\n" +
                "    &lt;script type=\"text/javascript\" src=\"raphael-min.js\"&gt;&lt;/script&gt;\n" +
                "    &lt;script type=\"text/javascript\" charset=\"utf-8\"&gt;\n" +
                "        window.onload = function() {\n" +
                "            var map = new Raphael(0,0,600,400);\n" +
                "            var building = map.rect(10,10,50,40);\n" +
                "        };\n" +
                "    &lt;/script&gt;\n" +
                "&lt;/head&gt;\n" +
                "&lt;body&gt;\n" +
                "&lt;/body&gt;\n" +
                "&lt;/html&gt;"));
    }
</code></pre>
<p>But it would be awfully fragile. More to the point : it would not declare what I&#8217;m interested in.<br />
What is it I&#8217;m interested in? If this were a test for some internal functionality it would be easier, you just have to think at what the clients of an object expect from it. Here the client of the rendering from the HtmlScreen is the user : the biped that is looking at the computer screen.</p>
<p>What I would really like to write in my test is :</p>
<pre><code>
    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        User user = new User().lookAt(new HtmlScreen().render());
        assertThat(user.currentSight(), is("A Rectangle at [10,10], 40px high and 50px wide"));
    }
</code></pre>
<p>Then I think I&#8217;ll write exactly this and I&#8217;ll find a way to make it work. A solid, meaningful test is definitely worth the effort.</p>
<p>The are three pretty separate issues here :</p>
<ul>
<li>The user should be able to look at the rendering and extract the parts of it which are meaningful for it, right now that means the javascript.</li>
<li> The user should be able to evaluate those meaningful parts and get me a short description of the final result.</li>
<li>HtmlScreen should return the correct html with the script needed to satisfy the user</li>
</ul>
<p>Before attacking any of this I put my html inside a string within the test itself and I pass it to the user, I want to make sure that when my user will work I will know.</p>
<pre><code>
    @Test
    public void shouldRenderABuildingAsARectangle() throws Exception {
        String html = "&lt;html&gt;" +
                "&lt;head&gt;" +
                "    &lt;script type=\"text/javascript\" src=\"raphael-min.js\"&gt;&lt;/script&gt;" +
                "    &lt;script type=\"text/javascript\" charset=\"utf-8\"&gt;" +
                "        window.load = function() {" +
                "            var map = new Raphael(0,0,600,400);" +
                "            map.rect(10,10,50,40);" +
                "        }" +
                "    &lt;/script&gt;" +
                "&lt;/head&gt;" +
                "&lt;body&gt;" +
                "&lt;/body&gt;&lt;/html&gt;";
        User user = new User().lookAt(html);
        assertThat(user.currentSight(),
        	is("A Rectangle at [10,10], 50px high and 40px wide"));
    }
</code></pre>
<p>Now, on with the implementation of my user.<br />
The first problem is quickly solved, I&#8217;ll have the user parse the received html and extract all scripts. The second problem is partially solved by using Rhino to evaluate the scripts.</p>
<p>There&#8217;s one thing that hangs : provided I can run the javascript in my user, that javascript does not produce a fancy (and easy to check) text description of what the user sees, it calls Raphael which performs some vector graphics magic.</p>
<p>Luckly, stubbing objects and whole libraries in javascript is trivial. In my tests I&#8217;ll replace the Raphael library with this file :</p>
<pre><code>
    function Raphael(x, y, width, height){
        this.rect = function(x, y, width, height) {
           output += "A Rectangle at [" + x + "," + y + "], " + height + "px high and " + width + "px wide";
        }
    }

    var output = "";
</code></pre>
<p>I run this and the test is still red, Rhino says that there&#8217;s no window object available. Indeed the window object is provided by the browser. I&#8217;ll just make sure that my user executes a browser.js file before everything else when evaluating the HtmlScreen :</p>
<pre><code>
    function Window() {}
    var window = new Window();
</code></pre>
<p>The test is green.</p>
<p>I move the html to HtmlScreen, this test is green but the old one is red, remember the first test for HtmlScreen?</p>
<pre><code>
    @Test
    public void shouldRenderAnHtmlDocument() {
        assertThat(new HtmlScreen().render(), is("&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;"));
    }
</code></pre>
<p>That&#8217;s definitely not true any longer. Is interpolating the microdivergence between these two tests going to help my design? Maybe, but I&#8217;ve added a lot for this last test, I don&#8217;t want to follow up with further changes in the production code just to satisfy that old boring test. Moreover, the reason that test is failing is that it is extremely dependent on the actual html string.</p>
<p>That&#8217;s not really good, especially since I&#8217;ve done so much to avoid being dependent to the html string in my latest test. Finally, I&#8217;ve just added a dom library for use inside the user, it&#8217;s really quick to change that test to declaring the same thing without being this fragile :</p>
<pre><code>
    @Test
    public void shouldRenderAnHtmlDocument() throws Exception {
        Document document = new Builder().build(new HtmlScreen().render(), null);
        Element root = document.getRootElement();
        assertThat(root.getLocalName(), is("html"));
        assertThat(root.getChildElements("body").size(), is(1));
    }
</code></pre>
<p>Is it me, or there&#8217;s still no really simple xml library for Java? This is xom, I decided to try it after years of jdom, dom4j and the basic java dom (ugh!) : it has a simple builder, good; poor navigation, bad; and it forces me to pass a null in the builder since I have no base url, very bad.</p>
<p>Anyway, the HtmlScreenBehavior tests are all green. I&#8217;ve one red test, it&#8217;s BossBehavior. It complains that raphael does not exist.<br />
In fact the WebClient performing the http call is parsing the html from the server response and it is calling the server to obtain the raphael-min.js. My server does not currently return static resources.<br />
Even if I have a red test I add a new one into BossBehavior, which is far more focused, that will ensure a clear feedback and also prove my theory on the origin of the error.</p>
<pre><code>
    @Test
    public void shouldReturnAStaticFileWhenAPathIsProvided() throws Exception {
        boss = new Boss(PORT, new BlankScreen());
        assertThat(Http.callOn(PORT, "sample.content.txt"),
		is(HttpAnswer.with("foo content bar").type("text/plain")));
    }
</code></pre>
<p>Inside the sample.content.txt file I got the string &#8220;foo content bar&#8221;.</p>
<p>Indeed the test fails, as expected.</p>
<p>Grizzly has a nifty Adapter ready for this, the StaticResourcesAdapter, but, how to choose between my original adapter and this one? Well, when a resource is required I&#8217;ll use the StaticResourcesAdapter, when no resource is requested it will be my original adapter.<br />
Doesn&#8217;t this sound a lot like mapping?</p>
<pre><code>
public class AlwaysReturn{
	...
        public void service(Request request, Response response) throws Exception {
            String path = request.unparsedURI().toString();
            if(path != null &amp;&amp; !path.equals("/")) {
                filesRetriever.service(request, response);
            } else {
                HttpAnswer.with(screen.render()).writeTo(response);
            }
        }
        ...
}
</code></pre>
<p>The &#8220;filesRetriever&#8221; is the static resources adapter from Grizzly.</p>
<p>I run all tests and they are all green!</p>
<p>I perform a reality check, I launch Boss with its main and I call it with a browser.</p>
<p><img src="http://minnenratta.files.wordpress.com/2010/11/first-building.png?w=575" /></p>
<p>And here it is, the first building of my city.</p>
<p>Yet looking back at the last piece of code I wrote, I don&#8217;t like what I see. Simply put, the service method is a mess : it is performing operations from multiple levels of abstraction, it is meddling with the static adapter while it is also performing actions which are specific to the screen. Finally it belongs to a class &#8220;AlwaysReturn&#8221; whose name has lost all meaning.<br />
I&#8217;ll clean this in a pretty direct way, for now.</p>
<pre><code>
    private static class RootAdapter implements Adapter {
        private final StaticResourcesAdapter resourcesAdapter;
        private final ScreenAdapter screenAdapter;

        public RootAdapter(StaticResourcesAdapter resourcesAdapter,
        				ScreenAdapter screenAdapter) {
            this.screenAdapter = screenAdapter;
            this.resourcesAdapter = resourcesAdapter;
        }

        public void service(Request request, Response response) throws Exception {
            if(pathIsPresentIn(request)) {
                resourcesAdapter.service(request, response);
            } else {
                screenAdapter.service(response);
            }
        }
        ...
    }
</code></pre>
<p>Tests are still green.</p>
<h2>Controlling the building</h2>
<p>I&#8217;ve now the render of a building, but that render is static, I can&#8217;t really control it in any way.<br />
Thus I&#8217;ll add a new test :</p>
<pre><code>
    @Test
    public void shouldRenderTheBuildingWithTheRightPositionAndDimensions() {
        User user = new User().lookAt(new HtmlScreen().addBuilding(50,30,40,80).render());
        assertThat(user.currentSight(), is("A Rectangle at [50,30], 40px high and 80px wide"));
    }
</code></pre>
<p>The test does not compile, I need the method &#8220;addBuilding&#8221;, easy added (empty, of course). Test is now failing, I always get the old rectangle in the old position. Fine.</p>
<p>This code makes all tests pass :</p>
<pre><code>
public class HtmlScreen implements Screen {
    private Building building = new Building(10, 10, 40, 50);

    public String render() {
        String start = "&lt;html&gt;&lt;head&gt;" +
                "    &lt;script type=\"text/javascript\" src=\"raphael-min.js\"&gt;&lt;/script&gt;" +
                "    &lt;script type=\"text/javascript\" charset=\"utf-8\"&gt;" +
                "        window.onload = function() {" +
                "            var map = new Raphael(0,0,600,400);";
        String end = "}&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;";
        return start + building.render() + end;
    }

    public Screen addBuilding(int x, int y, int height, int width) {
        building = new Building(x, y, height, width);
        return this;
    }
}
</code></pre>
<p>This code is ugly. The HtmlScreen is assembling the overall html, importing Raphael and composing the script. Building.render() is also strongly coupled with Raphael. It is also coupled with the fact that the Raphael canvas is named &#8220;map&#8221;, see for yourself :</p>
<pre><code>
    public String render() {
        return "map.rect(" + x + ","+ y + "," + width + "," + height + ");";
    }
</code></pre>
<p>This can&#8217;t do. I want everything related to Raphael to stay isolated and I want the HtmlScreen to focus on assembling the overall html, not the details of the script. I think I need a VectorGraphics object.</p>
<pre><code>
public class HtmlScreen {
    ...
    public String render() {
        return header() +
                vectorGraphics.include() +
                openScript() +
                openFunction() +
                vectorGraphics.init() +
                building.render(vectorGraphics) +
                closeFunction() +
                closeScript() +
                ending();
    }
    ...
}

public class VectorGraphics {

    public String include() {
        return "&lt;script type=\"text/javascript\" src=\"raphael-min.js\"&gt;&lt;/script&gt;";
    }

    public String init() {
        return "var map = new Raphael(0,0,600,400);";
    }

    public String rect(int x, int y, int width, int height) {
        return "map.rect(" + x + ","+ y + "," + width + "," + height + ");";
    }
}

public class Building {
    ...
    public String render(VectorGraphics vectorGraphics) {
        return vectorGraphics.rect(x, y, width, height);
    }
    ...
}
</code></pre>
<p>I don&#8217;t know if this idea of a vector graphics renderer, used by the building and by the HtmlScreen as well, represents a new and lower level of abstraction. In theory it is, as it manages every detail of the use of javascript for graphics, but strong abstractions aren&#8217;t always the most obvious ones, only tests will tell.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/283/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/283/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/283/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=283&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/12/06/web-apps-in-tdd-part-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2010/11/investigation.png" medium="image" />

		<media:content url="http://minnenratta.files.wordpress.com/2010/11/first-building.png" medium="image" />
	</item>
		<item>
		<title>Web Apps in TDD, Part 2</title>
		<link>http://minnenratta.wordpress.com/2010/12/02/web-apps-in-tdd-part-2/</link>
		<comments>http://minnenratta.wordpress.com/2010/12/02/web-apps-in-tdd-part-2/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 20:59:25 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=275</guid>
		<description><![CDATA[Second step The goal is still the same : showing a simple city map with the main character in the middle. I now have made sure I can answer http calls, thus I&#8217;ll pass to declare something about the contents of the answer itself. The simplest version of a city is a building (disclaimer : [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=275&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Second step</h1>
<p>The goal is still the same : showing a simple city map with the main character in the middle. I now have made sure I can answer http calls, thus I&#8217;ll pass to declare something about the contents of the answer itself. The simplest version of a city is a building (disclaimer : Christopher Alexander might not agree).</p>
<p>So, what&#8217;s a building? A rectangle, we said. But not just any rectangle, it should be shown on a browser, so it&#8217;s a rectangle within an html document.</p>
<p>A successful HttpAnswer must thus contain an html document.</p>
<pre><code>
@Test
public void shouldAnswerWithAnHtmlDocument() throws Exception {
    new Boss(PORT);
    assertThat(Http.callOn(PORT), is(HttpAnswer.with("&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;")));
}
</code></pre>
<p>When I run this test though, I get that PORT is already used. This can mean just one thing, my Boss server from the previous test is still running. I must stop it after the test.<br />
Thus I change the previous test as well, to add a stop operation to Boss.</p>
<pre><code>
@Test
public void shouldAnswerHttpCall() throws Exception {
        Boss boss = new Boss(PORT);
        HttpAnswer answer = Http.callOn(PORT);
        boss.stop();
        assertThat(answer, is(HttpAnswer.ok()));
}
</code></pre>
<p>Then I implement it in Boss. This should do it :</p>
<pre><code>
public class Boss {
    private final SelectorThread selector;

    public Boss(int port) throws IOException, InstantiationException {
        selector = new SelectorThread();
        selector.setPort(port);
        selector.setAdapter(new AlwaysReturn(HttpAnswer.ok()));
        selector.listen();
    }

    public void stop() {
        selector.stopEndpoint();
    }
 }
 </code></pre>
<p> Notice how the Grizzly selector now must be a field of Boss.<br />
 The test is still red, but now it&#8217;s not due to the need for the port, but because of this :</p>
<pre><code>
 Expected: is &lt;org.boss.HttpAnswer@7f60c4b0[statusCode=200,payload=&lt;html&gt;&lt;body&gt; &lt;/body&gt;&lt;/html&gt;]&gt;
     got: &lt;org.boss.HttpAnswer@2a114025[statusCode=200,payload=&lt;null&gt;]&gt;
</code></pre>
<p>Which is exactly what I need. I&#8217;ll make this pass then refactor some more.<br />
To make this test pass the obvious thing to do is to let Boss add the html page to each answer.</p>
<pre><code>
public class Boss {
...
    public Boss(int port) throws IOException, InstantiationException {
        selector = new SelectorThread();
        selector.setPort(port);
        HttpAnswer answer = HttpAnswer.with("");
        selector.setAdapter(new AlwaysReturn(answer));
        selector.listen();
    }
...
}
</code></pre>
<p>I should not forget to let my little Http utility class parse the payload back (well, if I forgot my test would stay red, so I would know).</p>
<pre><code>
public class Http {
...
    public HttpAnswer call() throws IOException {
        Page page = client.getPage("http://localhost:" + port);
        int statusCode = page.getWebResponse().getStatusCode();
        String payload = page.getWebResponse().getContentAsString("UTF-8");
        return new HttpAnswer(statusCode, payload);
    }
...
}
</code></pre>
<p>The test is now green, I&#8217;m correctly sending back some basic html component.<br />
Yet, there&#8217;s a surprise, the first test is not passing anymore. The previous test was expecting an empty http answer with just the success code 200.</p>
<p>Now, I might of course erase the old test, reasoning that it was just a stepping stone to the current test, which is, itself, just there to let me get closer to the goal of my first feature: showing the city map with the character in the middle.</p>
<h2>Microdivergence</h2>
<p>Yet I won&#8217;t. I&#8217;ll try to have both tests succeed.</p>
<p>If Boss is the game, then my html declaration is the screen on which the game will appear, and the first test is simply not expecting a screen.</p>
<pre><code>
public class BossBehavior {

    private static final int PORT = 11111;

    @Test
    public void shouldAnswerHttpCall() throws Exception {
        Boss boss = new Boss(PORT, new BlankScreen());
        HttpAnswer answer = Http.callOn(PORT);
        boss.stop();
        assertThat(answer, is(HttpAnswer.ok()));
    }

    @Test
    public void shouldAnswerWithAnHtmlDocument() throws Exception {
        Boss boss = new Boss(PORT, new HtmlScreen());
        HttpAnswer answer = Http.callOn(PORT);
        boss.stop();
        assertThat(answer, is(HttpAnswer.with("&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;")));
    }
}
</code></pre>
<p>Here it is, a new interface, representing the screen on which game objects will appear. The interface is still quite simple :</p>
<pre><code>
public interface Screen {
    String render();
}
</code></pre>
<p>And of course the HtmlScreen renders the html and body tags, while the BlankScreen renders nothing.</p>
<p>Now that all tests are green I&#8217;ll proceed to some more refactoring.</p>
<p>I don&#8217;t like the duplication of the boss.stop() operation I see in the test. I also don&#8217;t like my test to concern itself with two different different levels of abstraction : the overall behavior (it returns an html document) and its implementation (the html document is &lt;html&gt;&lt;body&gt;&#8230;&lt;/html&gt;)</p>
<pre><code>
public class BossBehavior {

    private static final int PORT = 11111;
    private Boss boss;

    @Test
    public void shouldAnswerHttpCall() throws Exception {
        boss = new Boss(PORT, new BlankScreen());
        assertThat(Http.callOn(PORT), is(HttpAnswer.ok()));
    }

    @Test
    public void shouldAnswerWithTheScreenContents() throws Exception {
        Screen screen = new HtmlScreen();
        boss = new Boss(PORT, screen);
        assertThat(Http.callOn(PORT), is(HttpAnswer.with(screen.render())));
    }

    @After
    public void stopBossServer() {
        boss.stop();
    }
}
</code></pre>
<p>Presently I added a new test which is one abstraction level lower than my first test, it&#8217;s not concerned about the whole system, just the game general presentation :</p>
<pre><code>
public class HtmlScreenBehavior {

    @Test
    public void shouldRenderAnHtmlDocument() {
        assertThat(new HtmlScreen().render(), is("&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;"));
    }

}
</code></pre>
<p>Notice how the concept of Screen was born to allow the two tests (&#8220;just return the 200 OK&#8221; and &#8220;return an html document&#8221;) to work at the same time.</p>
<p>The force of two similar-yet-diverging tests makes subsystems spring out. Waiting to have two divergent stories is often too late, while very small steps in a single story generate divergence at will.</p>
<h2>The movement downwards</h2>
<p>Finally, the third test and the Screen interface herald the birth of a gui layer. This is a movement which is very important.</p>
<p>Just as having a first test stating the basic broad facts of a system makes it flexible, using that same level of abstraction to declare all and everything in the system makes the tests rigid and instantly kills the design feedback from tdd.</p>
<p>When the next bit of the story can be declared by using a new, smaller part of the system, we need to focus on declaring it with just that part. If I manage to do it then it means that part has a reason to exist.</p>
<p>There&#8217;s something profoundly wrong in a system where the only useful object is the system itself. This is why acceptance tests have little value as a design tool.</p>
<p>There&#8217;s also something wrong in skipping the first tests of a new system just because that system happens to be a web application. It generates plenty of urban legends on how tdd works only for the business domain.</p>
<p>By the way, what&#8217;s this infamous business domain?</p>
<p>Anyway, let me move on with the next part : showing a building on my screen!</p>
<h2>Reality check</h2>
<p>My very first tests enforce lots of stuff, but I would really like to see how this system works for real. In case I forgot something.<br />
The quickest way to do it is to make it run. I do this by this very complex method in the Boss class :</p>
<pre><code>
public class Boss() {
    public static void main(String... args) throws Exception {
        new Boss(11111, new HtmlScreen());
    }
    ...
}
</code></pre>
<p>Then I fire up my browser and type http://localhost:11111/<br />
Surprise! the browser is not parsing the html!</p>
<p><img src="http://minnenratta.files.wordpress.com/2010/11/plain-text.png?w=575" /></p>
<p>In fact a browser will not parse the html unless the content is declared as being html.<br />
Time to update my tests. I&#8217;ll just include the content type in my definition of correct HttpAnswer:</p>
<pre><code>
    public static HttpAnswer ok() {
        return new HttpAnswer(200,"","text/html");
    }
</code></pre>
<p>Now, when I perform an Http call I&#8217;ll also read the content type and use it to initialize the answer. Result, a red test, the very first one :</p>
<pre><code>
Expected: is ...HttpAnswer...contentType=text/html]
     got: ...HttpAnswer...contentType=text/plain]
</code></pre>
<p>Quick to fix, the HttpAnswer should set the contentType.</p>
<pre><code>
public class HttpAnswer{
...
    public void writeTo(Response response) throws IOException {
        response.setStatus(statusCode);
        response.setContentType(contentType);
        ByteChunk chunk = new ByteChunk(payload.length());
        chunk.setBytes(payload.getBytes("UTF-8"),0,payload.length());
        response.doWrite(chunk);
    }
...
}
</code></pre>
<p>Test green.<br />
Just a little refactoring to clean this code a bit in order to maintain the same level of abstraction throughout the writeTo method :</p>
<pre><code>
    public void writeTo(Response response) throws IOException {
        response.setStatus(statusCode);
        response.setContentType(contentType);
        response.doWrite(payloadAsByteChunk());
    }
</code></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/275/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/275/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/275/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=275&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/12/02/web-apps-in-tdd-part-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2010/11/plain-text.png" medium="image" />
	</item>
		<item>
		<title>From Latex to Html</title>
		<link>http://minnenratta.wordpress.com/2010/11/30/from-latex-to-html/</link>
		<comments>http://minnenratta.wordpress.com/2010/11/30/from-latex-to-html/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 18:16:28 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=272</guid>
		<description><![CDATA[I always loved latex for generating documents. It&#8217;s such an elegant way for a developer to &#8220;develop&#8221; documents! Then I wanted to produce posts from the latex source I had. This is text manipulation, so I picked ruby and started writing a parser. Then I stopped. How many times did I write a parser? Probably [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=272&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I always loved latex for generating documents. It&#8217;s such an elegant way for a developer to &#8220;develop&#8221; documents!</p>
<p>Then I wanted to produce posts from the latex source I had. This is text manipulation, so I picked ruby and started writing a parser. Then I stopped.</p>
<p>How many times did I write a parser? Probably half a dozen times, for different reasons, but nonetheless it always started with text and ended with nodes.</p>
<p>This time I looked around and found <a href="http://treetop.rubyforge.org/">treetop</a>, which lets you write grammars to parse languages into trees and then associate operations to nodes (like converting the node to html).</p>
<p>Of course I could have looked around for a latex-to-html converter or an existing treetop latex grammar, but I wouldn&#8217;t have learnt treetop itself.</p>
<p>I just committed the grammar, the ruby script that generates html from nodes and the ruby script that I used for developing it and that reads a .tex file and converts it to html.</p>
<p>git://github.com/inverno/Treetop-Latex-Grammar.git</p>
<p>The grammar is <strong>very</strong> limited, basically just what I need for my own paper, but, who knows, someone might enjoy playing with it.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/272/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=272&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/11/30/from-latex-to-html/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>Web Apps in TDD, Part 1</title>
		<link>http://minnenratta.wordpress.com/2010/11/28/web-apps-in-tdd-part-1/</link>
		<comments>http://minnenratta.wordpress.com/2010/11/28/web-apps-in-tdd-part-1/#comments</comments>
		<pubDate>Sun, 28 Nov 2010 21:36:32 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=230</guid>
		<description><![CDATA[What&#8217;s this? This is the beginning of the paper I was writing when discussing TDD with Matteo before he kindly invited me to the Italian Agile Day 2010. After the talk, and in the days since, I was asked many times to provide more details and the source code. The first request is certainly best [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=230&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>What&#8217;s this?</h3>
<p>This is the beginning of the paper I was writing when discussing TDD with Matteo before he kindly invited me to the Italian Agile Day 2010.<br />
After the talk, and in the days since, I was asked many times to provide more details and the source code.<br />
The first request is certainly best served by publishing the aforementioned paper : it is not complete, so far it is 20 pages, which were enough for my talk, but I think it will take roughly twice that to describe TDD, the way I do it for web applications.<br />
Nonetheless I&#8217;ll start posting the paper as it is right now, and more, as I continue the development and the paper itself.</p>
<p>I&#8217;ll abide to the second request once the full paper is complete by releasing the full sources along with the pdf version.</p>
<p>So, without further ado, here&#8217;s part one : page 1 to page 4.</p>
<h1>The context</h1>
<p>Here I mean to explain how I use test driven development to help me craft web applications. This is my way of doing it, as it stands now, having evolved during the years through the various systems I had the pleasure to create.</p>
<p>Since I&#8217;ve long wished to create a gta-like web game I&#8217;ll use it as an example for a new web application.<br />
The game name is &#8220;Boss&#8221; and it should be played over a browser with a point-and-click interface.<br />
When Boss is called by http it should offer a bird view of a set of city blocks, with the main character standing in the middle of the map. Each city block should be composed of multiple rectangles representing the various buildings.<br />
The main character, a colored dot, should move in the direction clicked by the user&#8217;s mouse on the map.</p>
<h1>An unusual first step</h1>
<p>I&#8217;ll start with the first feature : when Boss is called by http it should offer a bird view of a set of city blocks, with the main character standing in the middle of the map.</p>
<p>Well, that&#8217;s certainly a lot of stuff to implement and I strongly doubt I&#8217;ll be able to implement it within a few minutes, so I&#8217;ll try to trim down the problem to be able to write the first test and its solution quickly.</p>
<p>With my first test I&#8217;ll just make sure that Boss answers to an http call succesfully. For the sake of brevity I&#8217;ll skip a couple loops and presume that a class &#8220;Boss&#8221; should exist, instead of refactoring it out of the test itself. So, my first test looks like this :</p>
<pre><code>
public class BossBehavior {

    @Test
    public void shouldAnswerHttpCall() throws IOException {
        new Boss(8080);
        WebClient client = new WebClient();
        Page page = client.getPage("http://localhost:8080");
        assertThat(page.getWebResponse().getStatusCode(), is(200));
    }

}
</code></pre>
<p>WebClient comes with the htmlunit framework, which turns out to be a quick way to invoke an http endpoint.</p>
<p>Of course this fails, as expected.</p>
<p>So I&#8217;ll try to make it pass. I don&#8217;t plan to re-implement the http protocol, so I&#8217;ll go shopping for a nice http server. In the past I used Jetty, but this time I&#8217;ll try Grizzly.</p>
<p>After a brief tour on the web I try this :</p>
<pre><code>
public class Boss {

    public Boss(int port) throws IOException, InstantiationException {
        SelectorThread selector = new SelectorThread();
        selector.setPort(port);
        selector.listen();
    }

}
</code></pre>
<p>This returns a nice null pointer exception. To be specific I see this line :</p>
<pre><code>
java.lang.NullPointerException
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:824)
</code></pre>
<p>Hm, well, I didn&#8217;t pass an Adapter to the SelectorThread. Some more reading and I get this :</p>
<pre><code>
public class Boss {

    public Boss(int port) throws IOException, InstantiationException {
        SelectorThread selector = new SelectorThread();
        selector.setPort(port);
        selector.setAdapter(new AlwaysReturn200Ok());
        selector.listen();
    }

    private static class AlwaysReturn200Ok implements Adapter {
        public void service(Request request, Response response) throws Exception {
            response.setStatus(200);
        }

        public void afterService(Request request, Response response) throws Exception {}
    }
}
</code></pre>
<p>It works fine, the test is green.<br />
Now I&#8217;ll proceed to some refactoring, but first, a brief note : is this a unit test?</p>
<p>Actually, I don&#8217;t care. The only thing which I care about is that this test is quick, repeatable, short, simple and it will work everywhere I have port 8080 available.</p>
<p>In fact, port 8080 is quite used nowadays (default tomcat servers for development purposes and so on&#8230;), let&#8217;s change that to 11111 from now on. Just to stay safe.</p>
<h2>And now some refactoring</h2>
<p>First the test, when I switched to port 11111 I forgot to update the url on which WebClient was performing the call, a nice reminder of that clumsy duplication I introduced.<br />
Also, the test is a bit too involved in the details of WebClient, let me fix this before moving to refactoring Boss itself.</p>
<p>I stop when I get to this :</p>
<pre><code>
public class BossBehavior {
    private static final int OK = 200;
    private static final int PORT = 11111;

    @Test
    public void shouldAnswerHttpCall() throws Exception {
        new Boss(PORT);
        assertThat(Http.callOn(PORT), is(OK));
    }
}
</code></pre>
<p>Http contains little special, just the call to WebClient and the extraction of the status code.</p>
<p>Now I&#8217;ll move to Boss. Currently Boss is just a tiny http server which always answers 200 OK. From a responsibility point of view there&#8217;s little to do, but I definitely don&#8217;t like that &#8220;200&#8243; which appears both in the test and the solution.</p>
<p>In the context of my application the code 200 is just a way to say the answer is positive. I don&#8217;t like using primitives to represent high-level concepts, such as &#8220;positive answer&#8221; and I certainly don&#8217;t like duplicated primitive values.</p>
<pre><code>
public class HttpAnswer {

    private final int statusCode;

    public static HttpAnswer ok() {
        return new HttpAnswer(200);
    }

    public HttpAnswer(int statusCode) {
        this.statusCode = statusCode;
    }

    public void writeTo(Response response) {
        response.setStatus(statusCode);
    }
...
}
</code></pre>
<p>While a bit verbose, this class removes the status 200 duplication in test and solution code and it slims down both, while letting me express the intent more clearly. Here&#8217;s the current situation for both test and solution :</p>
<pre><code>
public class BossBehavior {

    private static final int PORT = 11111;

    @Test
    public void shouldAnswerHttpCall() throws Exception {
        new Boss(PORT);
        assertThat(Http.callOn(PORT), is(HttpAnswer.ok()));
    }
}

public class Boss {

    public Boss(int port) throws IOException, InstantiationException {
        SelectorThread selector = new SelectorThread();
        selector.setPort(port);
        selector.setAdapter(new AlwaysReturn(HttpAnswer.ok()));
        selector.listen();
    }

}
</code></pre>
<p>To make the tests assertions work and to get nice messages in the future I&#8217;ll implement equals, hashcode and toString for HttpAnswer. I use the excellent EqualsBuilder, HashcodeBuilder and ToStringBuilder classes from apache.</p>
<pre><code>
public class HttpAnswer {
...
    @Override
    public boolean equals(Object other) {
        return EqualsBuilder.reflectionEquals(this, other);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}
</code></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/230/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/230/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=230&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/11/28/web-apps-in-tdd-part-1/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>The Software Craftsman&#8217;s Guide to the World</title>
		<link>http://minnenratta.wordpress.com/2010/11/23/the-software-craftsmans-guide-to-the-world/</link>
		<comments>http://minnenratta.wordpress.com/2010/11/23/the-software-craftsmans-guide-to-the-world/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 21:04:41 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=214</guid>
		<description><![CDATA[A few weeks ago I started this map after a discussion on the Software Craftsmanship list. The idea is simple : there are developers looking forward to meet others for a discussion or a bit of pairing, there are companies looking forward to welcome people to work with them for a while and share ideas, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=214&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago I started this map after a discussion on the Software Craftsmanship list.</p>
<p>The idea is simple : there are developers looking forward to meet others for a discussion or a bit of pairing, there are companies looking forward to welcome people to work with them for a while and share ideas, there are houses which may offer hospitality to fellow developers, so why not putting them all on a map with contact information?</p>
<p>I mentioned this idea at the Italian Agile Day 2010 and a few people have been asking me for more information, so here it is :</p>
<p><a href="http://maps.google.com/maps/ms?ie=UTF8&amp;hl=en&amp;msa=0&amp;msid=114087136685923801422.0004934ba5dbdca195ead&amp;z=2">The Software Craftsman&#8217;s Guide to the World</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/214/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/214/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/214/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=214&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/11/23/the-software-craftsmans-guide-to-the-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>Speaking about TDD at the Italian Agile Day</title>
		<link>http://minnenratta.wordpress.com/2010/11/20/speaking-about-tdd-at-the-italian-agile-day/</link>
		<comments>http://minnenratta.wordpress.com/2010/11/20/speaking-about-tdd-at-the-italian-agile-day/#comments</comments>
		<pubDate>Sat, 20 Nov 2010 20:43:24 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=210</guid>
		<description><![CDATA[Last Friday I had the pleasure to share with Matteo a session on tdd for web applications at the Italian Agile Day 2010. Here are the slides for my half of the session. Many seemed to enjoy our session a lot, I am overjoyed!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=210&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Last Friday I had the pleasure to share with <a href="http://matteo.vaccari.name/blog/">Matteo</a> a session on tdd for web applications at the Italian Agile Day 2010.</p>
<p>Here are the slides for my half of the session.</p>
<iframe src='http://www.slideshare.net/slideshow/embed_code/5846639' width='575' height='471'></iframe>
<p>Many seemed to enjoy our session a lot, I am overjoyed!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/210/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=210&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/11/20/speaking-about-tdd-at-the-italian-agile-day/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>On prefixes and suffixes</title>
		<link>http://minnenratta.wordpress.com/2010/09/10/on-prefixes-and-suffixes/</link>
		<comments>http://minnenratta.wordpress.com/2010/09/10/on-prefixes-and-suffixes/#comments</comments>
		<pubDate>Fri, 10 Sep 2010 06:27:06 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=185</guid>
		<description><![CDATA[Lately I&#8217;m doing a bit of C# programming, as I&#8217;m having fun with the Unity game engine and suite (and boy, it is cool!). Unity allows you to write game logic in C#, JavaScript and Boo. I started with JavaScript, but then I switched to C#, just for the sake of it. There I had [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=185&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;m doing a bit of C# programming, as I&#8217;m having fun with the <a href="http://unity3d.com/">Unity</a> game engine and suite (and boy, it is cool!). Unity allows you to write game logic in C#, JavaScript and Boo.<br />
I started with JavaScript, but then I switched to C#, just for the sake of it.</p>
<p>There I had quite a surprise. C# base libraries (and thus, I would expect, most of C# code out there) prefix interfaces with &#8220;I&#8221;!!</p>
<p><code><br />
IList, IDictionary, IWhatever.<br />
</code></p>
<p>When C# first came out and later on as new versions appeared I glanced at the language features and I liked what I saw, especially since C# seemed far bolder than Java in updating its syntax to new features, and doing it well (my feelings where kind of confirmed when Neal Gafter moved over to Microsoft to work on .NET).</p>
<p>That said, finding this naming convention so deeply rooted in C# culture pains me to no end.</p>
<p>I&#8217;ve had a look around and I saw quite a few blogs criticizing it, yet the real point about why the &#8220;I&#8221; for Interface is not a good idea didn&#8217;t appear very often, and when it did, it seemed like an afterthought.</p>
<p>I will express this point with a question : &#8220;Why would a client ever need to know that some type it is using is an interface?&#8221;.</p>
<p>&#8220;Client&#8221; here means any bit of code using some other bit of code :</p>
<p><code><br />
oneMethod() {<br />
  IList list = new ArrayList();<br />
</code></p>
<p>In this exemple &#8220;oneMethod&#8221; is the client of the list.</p>
<p><code><br />
anotherMethod(IList list) {<br />
  list.doSomething();<br />
}<br />
</code></p>
<p>Here again, another method is a client of the list.</p>
<p>For the purpose of expressing a problem&#8217;s domain and the logic for solving it, advertising the fact that IList is an interface is uninteresting.<br />
The client code using an interface has no need to know about it, nor the developer reading that code!</p>
<p>What is even more important is that prefixing the interface shows that the interface is considered just a technical &#8220;trick&#8221;, a convenient, but meaningless literal which happens to be part of the language.</p>
<p>Interfaces must always represent the core roles of a system, the main actors on stage. They must do so crisply and unambiguously, as those are the actors we will spend most of our time looking at.</p>
<p>If my system sends payments over the network I do expect that the main roles get first-class names : Payment, Connection, Customer.<br />
If some of these happen to be interfaces I do expect their implementations to get second-class, specific names, since I won&#8217;t look at them often, unless I need to delve one step lower in the details : DirectPayment, DelayedPayment, TCPConnection, BankCustomer, InsuranceCustomer&#8230;</p>
<p>When observing &#8220;I&#8221; infested code I notice that the first-class name (Customer, Connection..) is given to the main implementation of the interface, or, worse, the sole implementation of the interface. In this case the interface is perceived as boilerplate (and it is likely so) : I need to have an interface, so let&#8217;s extract it and put a convenient prefix before it.</p>
<p>Other times the use of prefixes seems to arise from having apparently expended all &#8220;good&#8221; names. I stress the &#8220;apparently&#8221; : I&#8217;ve yet to find a case where it is impossible to give both a meaningful name to the interface, representing the overall concept for the system, and to the implementations, representing the details.</p>
<p>Provided that one stops to think long enough.</p>
<p>Finding good names needs time. A serious naming effort is often the beginning of a new understanding; usually that&#8217;s the understanding that our roles are wrong and we should look for better ones, which leads to further costs.</p>
<p>By using plenty of prefixes and suffixes instead (I, A, Manager, Processor, Decorator, Impl, Service, Factory, Bean&#8230;), we can write code much faster, it spares us much of the thinking, in fact, most of the time we can just stop thinking about names, almost anything can be forced to fall within the range of a random combination of prefixes and suffixes :</p>
<p><code><br />
ITransferManager, ProcessorService, ServiceFactory, ProcessorDecoratorImpl<br />
</code></p>
<p>and, of course, <code>DecoratorProcessorImpl</code> !</p>
<p>While here is a sample of what we might be missing (traslating 1 on 1 to meaningful names) :</p>
<p><code><br />
PostOffice, MailBox, MailAccount, RemoteMailBox, UnsortedMail<br />
</code></p>
<p>By using prefixes and suffixes we are truly wasting the semantic potential of our code.</p>
<p>It&#8217;s the same kind of waste that we could obtain by naming functions after the number of their parameters : setString1(&#8220;&#8221;), setString2(8,&#8221;").</p>
<p>We wouldn&#8217;t dream of not naming the second setString as what it actually is : setSubstring.<br />
Yet we do so all the time with classes.</p>
<p>Often we do this for the sake of &#8220;standardization&#8221;. This a classic of groups where a chief developer puts down the architecture and then enforces a set of rules for class names : &#8220;And thou shall call ye spring initialised objects &#8220;Beans&#8221;, and those which are not shall be &#8220;Factories&#8221;&#8230;&#8221;.</p>
<p>Standardization is nice, and it is perhaps the only positive point I see in pattern-based prefixes and suffixes, but the standardization effort happens long before the real domain of the system is clear and has slowed down evolving; this leaves the standardization authority with pretty few clues on proper names and so it falls back to enforcing technical roles. The developers behind the lead will have one less reason to look for good names : they are not expected to do so.</p>
<p>So, to sum it all up, when prefixes and suffixes see large use, the favoured programming habit is often &#8220;write fast, read slow&#8221;. This is the recipe for huge, bloated code, where technical details get advertised everywhere and arise to prominence in spite of the problem domain. And I don&#8217;t like it.</p>
<p>I&#8217;m looking at you, Controller.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/185/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/185/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/185/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=185&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2010/09/10/on-prefixes-and-suffixes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>
	</item>
		<item>
		<title>A day strolling in town</title>
		<link>http://minnenratta.wordpress.com/2009/10/29/a-day-strolling-in-town/</link>
		<comments>http://minnenratta.wordpress.com/2009/10/29/a-day-strolling-in-town/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 15:20:17 +0000</pubDate>
		<dc:creator>minnenratta</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://minnenratta.wordpress.com/?p=169</guid>
		<description><![CDATA[First and foremost : it is very likely that all of my posts from now on will be in English. During the last year or so, I&#8217;ve felt that during conversations, both face-to-face and online, I needed to point to one of the posts on this blog. I think this is very natural, as I&#8217;ve [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=169&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><font color="#A0A0A0">First and foremost :<br />
it is very likely that all of my posts from now on will be in English.</p>
<p>During the last year or so, I&#8217;ve felt that during conversations, both face-to-face and online, I needed to point to one of the posts on this blog. I think this is very natural, as I&#8217;ve kept adding bits of reasoning to this blog for many years now and, even though my views change and shift, I do happen to repeat myself (far more frequently than anyone would like).</p>
<p>This is all good and nice, except that my Italian-based conversations are just a share of the whole and, while I might expect for an Italian fellow to be able to read English, I can&#8217;t really confide for the opposite to be true.</p>
<p>Hence, from now on, I&#8217;ll stick to English.</p>
<p>Curiously, this post is something I&#8217;ll hardly refer to in a technical context, but I&#8217;ll nonetheless write it in English.<br />
</font></p>
<p>It is now 14:45. I&#8217;m sitting on a bench in Lausanne&#8217;s Riponne plaza.</p>
<p>I&#8217;ve been out and about since this morning, 8:30 am.</p>
<p>I hardly ever quit my routine : work, go home and code/watch movies/talk with gentle wife/stay put. I rarely spend more than a couple hours outdoors and when I do it is usually in the mountains or other very secluded places.</p>
<p>I was astonished at the number of things which happened around me by spending a significant amount of time in a town like this.</p>
<p>First I looked for a parking near the city centre. The concept of a centre in Lausanne is murky. The town stands on multiple hills (pretty steep hills if I may say) on the north shore of Lake Geneva. The morphology has not helped and it took me a while to sort out which was the real city centre.</p>
<p>Anyway, I finally decided that the Riponne parking lot was fine enough for my goals.</p>
<p><img src="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-14-46.jpg?w=400&#038;h=300" alt="Riponne" title="Riponne" width="400" height="300" class="alignnone size-full wp-image-175" /></p>
<p>First of all, I break my fast with a tea and a croissant. Fascinating how a mediocre tea is 3.50 CHF and an excellent croissant is just 1.20.</p>
<p>Then I continued my quest for a pair of good clip-on headphones. Since I&#8217;ll be living in Lausanne from now on, while my wife will stay back at home, I&#8217;ll have to spend long hours in a train heading back home in the week-ends. This is why I sorely need headphones, you wouldn&#8217;t expect me to bother the whole train with a TechQ presentation on domain driven design.<br />
The problem is I hate intra-aural earbuds and almost any full headset which I cared to test would cause long-lasting pain in my ears after a few minutes of use. It is related to the ears being pinched between the two phones. I thought I had found an headset which was gentle enough, but after buying it and using it for more than half-an-hour my ears started aching badly and it lasted for hours after I removed it. So I gifted it to my wife&#8217;s brother.</p>
<p>So now I&#8217;m looking for clip-on headphones, much like <a href="http://reviews.cnet.com/headphones/koss-ksc-75-headphones/4505-7877_7-31495999.html?tag=mncol;lst">these</a>.</p>
<p>I left the patisserie where I had my breakfast and begun by entering a Sony shop. No luck, the Sony guy was astonished I was looking for such a bizarre apparel and mentioned that while he had seen some in the -past- (with the tone you would expect of an elder grandpa talking about the war) he was pretty sure they did not exist anymore, in Switzerland at least.</p>
<p>Then I spotted Fnac, which was cozy and well-appointed as usual, with a vast choice of headsets and earbuds, but no clip-ons.</p>
<p>Anyways, from the top of Fnac I had a commanding view of Flon, it is a former industrial area which sits in between two of Lausanne&#8217;s steep hills. It has now been restructured and a number of shops have opened down there.<br />
Most importantly I spotted a <a href="http://www.pathe.ch/">Pathé</a>! I love the pathé theatres.</p>
<p>After Fnac I tried three different InterDiscounts, MediaMarkt, Bang and Olufssen (yes, they do have 245 CHF earbuds and a 1250 CHF cordless phone, but no clip-ons), the Audio-Center, and the Auditory Area, which turned out to be a clinic specialized in hard of hearing old fellows with a large budget, think Amplifon for rich guys. In there they -did- have clip on headsets, just not the kind which you can jack to a computer.<br />
Finally I went to a nokia shop, where the guy looked at me with an hint of irony and said : &#8220;you know, you should look in shops where they sell computer stuff, did you check Fnac?&#8221;<br />
I answered positively and fell back out in good order.</p>
<p>Thanks to the above-mentioned morphology this search was tantamount to hiking.</p>
<p>Then I visited Lausanne&#8217;s Cathedral. Which, of course, stands on the peak of the tallest hill. In there I found a little presentation on John Calvin, who appears to be the local super-hero when it comes to religion.<br />
There&#8217;s also a medieval building hosting a lycée in the Cathedral Citadel. Full of teenagers of course. The turds did not deserve such a fascinating school building.</p>
<p>I climbed down the citadel just to the bottom, heaven to hell, in Flon, where I bought a couple of ham-filled croissants for five francs.</p>
<p>As I was sitting on a bench eating my croissants a lady approached me and told me she was from Yugoslavia and without a work permit. I gave her ten francs. So she sat beside me and told me about her husband back in Belgium who beat her, and how she was in Switzerland since three weeks, with her little sister and two daughters.</p>
<p>Good lord. I gave her 20 more francs before I could finish my lunch. She was good conversation, except for the repeated petitions for more money, or for work. I very much wished to have a need for an house-cleaner, as she claimed to be quite good at it, having worked in hotels in Belgium.</p>
<p>One of the best moments was when she told me that she earned 1000 euros per month in Belgium, working as a room-cleaner in hotels. I chuckled and I suggested her to not try her luck in Italy, as 1000 euros is standard fare for young developers.<br />
She looked surprised.</p>
<p>After leaving her I asked a nice grandma where was the train station, she told me to take the Metro and showed me to it, just to be sure I would not get lost.<br />
She told me I did not sound like an Italian. I was not surprised, for some reason I don&#8217;t have an Italian accent when I speak French. Years ago I was told I sound Canadian, so I asked her how I did sound to her, and she said she was sure I was from the UK. I thought that, since Canadians can be defined as a mix of french and englishmen, she was not far from the spot, so I told her I agreed with her interpretation and we parted in friendship.</p>
<p>And yes, Lausanne has got two Metro lines. Fascinating. Since the tickets are time-based and allow you to use the metro for half an hour, no matter how many rides you take, it is perfectly wasteful to buy two tickets if you can get to the train station, buy a ticket back to Lugano for your wife and return in less than thirty minutes.</p>
<p>Thus, when I arrived at the train station I was looking for a reason to waste some time and justify my second ticket for the metro.</p>
<p>In the train station there was a pretty complex queue system and a dark-colored fellow asked me how it did work. I told him that I presumed he had picked the wrong queue and that he should be in mine. Then I suggested him to take my place in the queue, since he had arrived before me and, were it not for his mistake, he would be before me.<br />
I stepped back at the beginning of the queue.</p>
<p>But it was of no use, a Swiss queue is often a quick queue, and I had to wait just three more minutes before being able to buy the ticket.<br />
Stupid efficient Swiss cashiers.</p>
<p>I found out that the metro would bring me just where I had parked the car, so I was spared yet another climb up the hill.</p>
<p>So now I&#8217;m back here, I went to the car, took the laptop and the umts key and came to sit on this bench.</p>
<p>Of course it took me some time to write this post, it took even longer than expected because a little pest decided to come by and type all over my keyboard, the mother is still explaining him he should not do that :</p>
<p><img src="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-14-471.jpg?w=400&#038;h=300" alt="The Little Pest and His Mother" title="The Little Pest and His Mother" width="400" height="300" class="alignnone size-full wp-image-176" /></p>
<p>It took so long that I had the time to notice a peculiar phenomenon. Over the hours (it is now 4 pm) that I&#8217;ve been sitting on this bench in Riponne plaza a lot of people with laptops have come to sit beside me on this same bench or the next one.</p>
<p>We are now at my third computer-assisted guest, and I could not spare to take a photo, as sitting by a Tibetan monk with an HP laptop on a bench in Lausanne is something that is worth a photo. See the azure area? That&#8217;s me, and that&#8217;s the monk.</p>
<p><img src="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-15-07.jpg?w=400&#038;h=300" alt="Seven Years in Lausanne" title="Seven Years in Lausanne" width="400" height="300" class="alignnone size-full wp-image-178" /></p>
<p>Most notable is also that the monk was the only one who talked to me :</p>
<p>It seems he could not find Lausanne&#8217;s Wifi. I told him I doubt there is one, as I don&#8217;t get any reading on my Wifi and I&#8217;m connected through umts instead.</p>
<p>He was disappointed and left a few minutes after.</p>
<p>This might explain why many people chose to sit next to me and each one left after a while.</p>
<p>I must look like I&#8217;m sitting in a hotspot.</p>
<p>Time to leave and go collect my wife, she must be almost to the end, where they hang the company owners because they caused the death of a dozen miners.</p>
<p>I suppose.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/minnenratta.wordpress.com/169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/minnenratta.wordpress.com/169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/minnenratta.wordpress.com/169/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=minnenratta.wordpress.com&amp;blog=1748234&amp;post=169&amp;subd=minnenratta&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://minnenratta.wordpress.com/2009/10/29/a-day-strolling-in-town/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ca5608178aa82f1111ed25e7b8d9f8fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">minnenratta</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-14-46.jpg" medium="image">
			<media:title type="html">Riponne</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-14-471.jpg" medium="image">
			<media:title type="html">The Little Pest and His Mother</media:title>
		</media:content>

		<media:content url="http://minnenratta.files.wordpress.com/2009/10/photo-on-2009-10-29-at-15-07.jpg" medium="image">
			<media:title type="html">Seven Years in Lausanne</media:title>
		</media:content>
	</item>
	</channel>
</rss>
