<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6517561437765469293</id><updated>2011-11-27T15:46:21.005-08:00</updated><category term='unit testing'/><category term='separation of concerns'/><category term='maintenance'/><category term='ui'/><category term='dry'/><category term='modality'/><category term='habituation'/><category term='software'/><category term='optimization'/><title type='text'>Standing on the Shoulders of Giants</title><subtitle type='html'>Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away -- Antoine de Saint-Exupéry</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-7098547549786786772</id><published>2011-08-16T19:14:00.000-07:00</published><updated>2011-08-16T19:14:37.998-07:00</updated><title type='text'>Tiny-Type Language Support</title><content type='html'>
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd"&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Tiny-Type Language Support&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
    Tiny-Types are types in object-oriented programming that contain very little data, but still have the benefits of
    objects. The typical example is currency. Tiny-types are
    underused which in part is due to poor language support. Although some of these shortcomings can be solved by code
    generation, it would be beneficial if such friction weren't
    necessary (although &lt;a href="http://www.scala-lang.org/node/258"&gt;Scala case classes&lt;/a&gt; take care of some of these
    concerns). There are several features that are missing in
    mainstream languages that would make using tiny-types easier.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Built-in hash code&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    Many IDEs provide support to generate hash codes automatically. However, this does not stop them from getting out of
    sync, as they are not automatically regenerated when
    the types or number of fields change. This can be provided in an IDE, but it would be easier to just provide this
    mechanism in the language. Say as an alternative to a
    class, one could use the keyword &lt;i&gt;value&lt;/i&gt; that would automatically provide the hash code for you given the
    fields in the type.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Built-in equality&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    Equality is another method that can be generated by the IDE but can become stale when the types or number of fields
    change. This can be implemented by the same mechanism as
    with hash codes. Additionally, there should only be one method/operator that does equality. In Java there is
    .equals() or operator== depending on whether or not the type
    is a class or primitive. In C#, you have to implement both if you want proper functionality as operators are
    overloadable. The in-fix notation, which is used by
    operator==, is more habituated due to the way most of us learned math. Therefore, the method .equals() should be
    eliminated, leaving one place for both primitives (values)
    and classes to define equality.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Built-in JSON/binary serialization&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    Tiny-types are convenient as messages where message passing between processes or threads are used. While
    serialization is not necessary between threads,
    it is essential for communication between processes. Both JSON and some form of standardized language-independent
    binary serialization (perhaps
    &lt;a href="http://msgpack.org/"&gt;Message Pack&lt;/a&gt;, &lt;a href="http://thrift.apache.org/"&gt;Thrift&lt;/a&gt;, or &lt;a
        href="http://golang.org/pkg/gob/"&gt;gobs (but language-independent&lt;/a&gt;?)
    should be generated for value types by default.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;toStr() defaults to JSON&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    String methods are another facility that can be generated by an IDE or by code generation, but again this should be
    unnecessary for value types. The default for toStr()
    method should produce JSON. As with serialization, equality, and hash codes, toStr() should be overrideable.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Immutable&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    Object level immutability is sorely lacking from many mainstream object-oriented languages, with the exception of
    C++. Value types should be immutable, allowing
    for guarantees with intra-process message passing. Immutability is also useful for hashing.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Operator overloading&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
    Operator overloading is very important for tiny-types, particularly for mathematical operations. Anyone who has ever
    used the terrible syntax required by BigDecimals in
    Java can attest to how nice it would be to have operator overloading. One of my main complaints about &lt;a
        href="http://golang.org/"&gt;Go&lt;/a&gt; is the lack of operator overloading.
    I understand why it was left out, but I believe the pros outweigh the cons. C# strikes a nice balance here by
    allowing the overloading of mathematical operators but not
    assignment or arbitrary operators.
&lt;/p&gt;

&lt;p&gt;
    Tiny-type support is lacking in most modern mainstream object-oriented languages. This is unfortunate as it takes
    away from the full benefits of object-orientation and would
    be easy to remedy by language designers.
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-7098547549786786772?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/7098547549786786772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2011/08/tiny-type-language-support.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7098547549786786772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7098547549786786772'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2011/08/tiny-type-language-support.html' title='Tiny-Type Language Support'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4989586084423459875</id><published>2011-05-23T17:52:00.000-07:00</published><updated>2011-05-23T17:52:31.880-07:00</updated><title type='text'>Refactoring: Extract setup and helper methods into test scenario</title><content type='html'>&lt;p&gt;
    In my last post, I discussed being able to implement the entire application-under-test in one line.  This technique is useful at
    more granular levels as well.  In fact, it offers a nice alternative to the idea that &lt;a href="http://blog.jayfields.com/2008/05/testing-duplicate-code-in-your-tests.html"&gt;tests should be wet (not-DRY)&lt;/a&gt;.
    Object-orientation turns out to be a nice solution to duplication in tests.  
&lt;/p&gt;
&lt;p&gt;
    Refactor this:
&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;
[TestFixture]
public class MyObjectTests
{
    // field declarations omitted for brevity

    [SetUp]
    public void Setup()
    {
        _dataStore = new StubDataStore();
        _networkConnection = new StubNetworkConnection();
        _collaborator = new Collaborator();
        _serializer = new Serializer();
    }

    private MyObject CreateSut()
    {
        return new MyObject(_dataStore, _networkConnection, _collaborator, _serializer);
    }

    private static void CustomAssertEquals(IDictionary&amp;lt;string, string&amp;gt; expected,
        IDictionary&amp;lt;string, string&amp;gt; actual)
    {
        // custom assertion
    }

    [Test]
    public void ShouldValidateAdditionalNewFeature()
    {
        var sut = CreateSut();
        sut.LoadDataStore();
        sut.BroadcastStateOnNetwork();

        CustomAssertEquals(_dataStore.Data, _networkConnection.Data);
    }
}
&lt;/pre&gt;
&lt;p&gt;
    Into this:
&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;
public class MyObjectScenario
{
    // field declarations omitted for brevity

    public MyObjectScenario()
    {
        _dataStore = new StubDataStore();
        _networkConnection = new StubNetworkConnection();
        _collaborator = new Collaborator();
        _serializer = new Serializer();
        _sut = new MyObject(_dataStore, _networkConnection, _collaborator, _serializer);
    }

    public void AssertNetworkMatchesDataStore()
    {
        // custom assertion
    }

    public void LoadDataStore()
    {
        _sut.LoadDataStore();
    }

    public void BroadcastStateOnNetwork()
    {
        _sut.BroadcastStateOnNetwork();
    }
}

[TestFixture]
public class MyObjectTests
{
    [Test]
    public void DataBroadcastOnNetworkShouldMatchDataStore()
    {
        var sut = new MyObjectScenario();
        sut.LoadDataStore();
        sut.BroadcastStateOnNetwork();
        sut.AssertNetworkMatchesDataStore();
    }
}
&lt;/pre&gt;
&lt;p&gt;
    Now each test case in the TestFixture is succinct, independent (there are no instance variables in the TestFixture),
    and is very readable.  Additionally, the test cases are DRY and the assertions print out very meaningful error messages which are reusable
    across TestFixtures.  Notice that I am not using a mocking framework for the out-of-process dependencies (network, data store) as this allows me
    to DRY up the behavior I would otherwise have to redundantly put in each setup or test case.  Lastly, these scenarios
    can be chained up to create the whole application-under-test in my previous post, with little duplication.
&lt;/p&gt;
&lt;p&gt;
    It is beneficial to keep your tests DRY.  Tests are code too and reuse is just as helpful in tests as it is in production code.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4989586084423459875?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4989586084423459875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2011/05/refactoring-extract-setup-and-helper.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4989586084423459875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4989586084423459875'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2011/05/refactoring-extract-setup-and-helper.html' title='Refactoring: Extract setup and helper methods into test scenario'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4182114312485632856</id><published>2011-03-26T16:24:00.000-07:00</published><updated>2011-03-26T16:24:38.877-07:00</updated><title type='text'>Can you instantiate your application-under-test in one line?</title><content type='html'>&lt;p&gt;
    Can you instantiate your application-under-test in one line? As in your entire application, with all externally
    facing interactions (threads, GUI, databases, network, etc.) faked out?
&lt;/p&gt;
&lt;p&gt;
    Like this:
&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;
[TestFixture]
public class MyApplicationFunctionalTests
{
    [Test]
    public void ShouldValidateAdditionalNewFeature()
    {
        var sut = new MyApplication();
        sut.DataArrivesOnNetwork("message from another user");
        sut.AssertGuiDisplays("message from another user");
    }
}
&lt;/pre&gt;
&lt;p&gt;
    The ability to instantiate your application-under-test in one line enables you to immediately and easily write a
    test for any new feature or bug fix, and see the effects on the &lt;i&gt;entire&lt;/i&gt; application. The power of this
    technique is difficult to overstate. The true benefits of TDD are much more evident using functional testing with real classes at the
    application level than at the unit test level using a mocking framework.
&lt;/p&gt;

&lt;p&gt;
    I picked up this technique from &lt;a href="http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1301169905&amp;sr=8-1"&gt;
    Growing Object-Oriented Software, Guided By Tests&lt;/a&gt;.  While the authors and I disagree about the effectiveness of
    mocking frameworks (they are the authors of &lt;a href="http://www.jmock.org/"&gt;JMock2&lt;/a&gt;), we certainly agree on the
    use of functional testing at the application level (we also agree on
    &lt;a href="https://groups.google.com/forum/?pli=1#!topic/growing-object-oriented-software/7ymbA2IKTO8"&gt;
    DI containers being detrimental&lt;/a&gt;).  I tried the &lt;i&gt;AUT-in-one-line&lt;/i&gt; technique with a recent greenfield-ish project
    and the results were very positive.  All projects I start going forward will definitely use this pattern.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4182114312485632856?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4182114312485632856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2011/03/can-you-instantiate-your-application.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4182114312485632856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4182114312485632856'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2011/03/can-you-instantiate-your-application.html' title='Can you instantiate your application-under-test in one line?'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-8397277020580056799</id><published>2010-12-03T18:47:00.000-08:00</published><updated>2011-03-26T08:21:25.406-07:00</updated><title type='text'>Chrome Wishlist</title><content type='html'>&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span id="internal-source-marker_0.20004209456965327" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;I am unabashedly a huge fan of Chrome. &amp;nbsp;Minimalism is emphasized throughout its design and it is very fast. &amp;nbsp;However, there are a few small outstanding issues that for some reason have been overlooked.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Wasted space at top of window&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;The following pictures on the top are what Chrome currently looks like. &amp;nbsp;The pictures on the bottom are what Chrome would look like without the extra wasted space at the top (also what it looks like maximized on Windows/Linux). &amp;nbsp;Why is it there? &amp;nbsp;To move the window? &amp;nbsp;How often does that happen? &amp;nbsp;Is it worth all that space? &amp;nbsp;There still would be plenty of space around the min/max/close buttons to perform such a rare operation.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;img height="39px;" src="https://lh4.googleusercontent.com/tR2-ylXWOeMWCwLutgQ9qmO1d2OndnY-i6Vr2Vce1ws5IEUo8cJp_kaYVciSx2-Ngwm8Px-hmxujNoZE31HTJb3Bs5N7OvR4qG569MHLAmuUrhK2XQ" width="576px;" /&gt;&lt;img height="25px;" src="https://lh4.googleusercontent.com/PoTR1lGcdTi1OQ6uES6YAA2OXk0y5ayYhxoT2YHC4iLSPnYuvWxnq6pGDpuOlPCyvvfI7FK0rzjU14rwjYHUoVrr1ItD-4HZdLjBZPuamaDHYs5Zsg" width="574px;" /&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Windows 7&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;img height="42px;" src="https://lh5.googleusercontent.com/fqcIi1Zg1cWysMDnPf8UHjH2uz5-1ZDL3ko9fLWl_-09pRT4T7rjgjdyqjV1cmwFqsMiacvG_Zx3dE7DRP8V43kXnYRGpbitmnWNpE83S6P2cyoivQ" width="634px;" /&gt;&lt;img height="25px;" src="https://lh3.googleusercontent.com/poNDekrUtZgiO_82mUfdOwr0xErQ9acLgqwWqC_tlY9VyxsC8sDGNmPrd1zhX6JqF4DsDE-440KYe8YuUrYxexndK0xrt24ZpnlfGnWwGnP78-hNWg" width="634px;" /&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Ubuntu&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;img height="34px;" src="https://lh5.googleusercontent.com/qyeO-bGvFw4mqeiPO9L3HZ5zdVAu9QPmvL4JgRecEKxYA_02EwNEqQgXO01Zz5udxSIDiOyh1R8QmDXTNvdTT4qn4HrxN975WHx47wFPKqjUMonZcQ" width="634px;" /&gt;&lt;img height="24px;" src="https://lh3.googleusercontent.com/t3jxcGNWPDKpRcyFrE5Cmn6wWISHzmQ9a79NJs1JXNpGirg2eGsJfVi1dqwx06HHpCyccBnXqQKZ6BoQbL5e5D6L2ehbWpWIwb2O-mghGNibRfqyEA" width="634px;" /&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Mac OS X&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: italic; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Inconsistent keyboard shortcuts between platforms&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;On the Mac, the Bookmark Manager shortcut is Alt+Command+B. &amp;nbsp;On Windows/Linux, it is completely missing. &amp;nbsp;On Windows/Linux, the Task Manager shortcut is Shift+Esc, on Mac, it is completely missing. &amp;nbsp;Why the inconsistency?&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Remove bookmark bar&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;The bookmark bar is not useful. &amp;nbsp;If there are a few bookmarks that are often used then the sites will readily come up in the omnibar. &amp;nbsp;In keeping with Chrome's minimalism, it should be removed.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Sync search engines&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Many pieces of data are synchronized via Google Chrome. &amp;nbsp;One thing that is definitely missing is synchronization of search engines.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;b&gt;Add bookmark search engine in omnibar&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; font-size: medium; font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; white-space: normal;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px; white-space: pre-wrap;"&gt;&lt;br&gt;The search engine support in the omnibar is very useful.  It would be more efficient if I could search just my bookmarks via the same mechanism, instead of having to open up the bookmark manager page.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-8397277020580056799?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/8397277020580056799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/12/chrome-wishlist.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/8397277020580056799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/8397277020580056799'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/12/chrome-wishlist.html' title='Chrome Wishlist'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-6179261004687781103</id><published>2010-09-29T08:57:00.000-07:00</published><updated>2010-09-29T08:57:00.359-07:00</updated><title type='text'>Retlang Documentation Improved</title><content type='html'>&lt;div style="background-color: transparent; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span id="internal-source-marker_0.942544600693509" style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Now that &lt;a href="http://code.google.com/p/retlang/"&gt;Retlang&lt;/a&gt; has reached 1.0 status, the next task was to clean up the documentation. &amp;nbsp;Several areas have been improved.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;ul&gt;&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Obsolete documentation has been removed. &amp;nbsp;Majority of “getting started” information is now directly on the front page.&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;a href="http://dl.dropbox.com/u/2053101/Retlang%20and%20Jetlang.mov"&gt;Video/presentation&lt;/a&gt; of graphical guide to Retlang is posted and linked on the front page.&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;Classes and interfaces have been renamed in order to more easily grok the library. &amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;a href="http://groups.google.com/group/retlang-dev"&gt;Google Group&lt;/a&gt; has been cleaned up. &amp;nbsp;Spammers have been removed and all posts are now moderated before appearing.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"&gt;Please let me know (via the &lt;a href="http://groups.google.com/group/retlang-dev"&gt;user group&lt;/a&gt; or this blog post) of any other improvements that could be made.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-6179261004687781103?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/6179261004687781103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/09/retlang-documentation-improved.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6179261004687781103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6179261004687781103'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/09/retlang-documentation-improved.html' title='Retlang Documentation Improved'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-9097651866059245540</id><published>2010-07-09T17:57:00.001-07:00</published><updated>2010-07-09T18:03:31.433-07:00</updated><title type='text'>Next Project</title><content type='html'>&lt;div style="background-color:transparent;margin-left:0px;margin-right:0px"&gt;&lt;span id="internal-source-marker_0.15735871344804764" style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;I have been working on one large project for a few years now, and while we have done a pretty good job in keeping the code as clean as possible, there are still some endemic characteristics I would like to change if I were to start over.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;No DI Framework&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;We started with &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://www.springframework.net/"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Spring.NET&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, but then ran into the usual XML problems (renames, namespace changes, ugly factory syntax, ugly generics syntax). &amp;nbsp;So then we moved to &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://code.google.com/p/spring-recoil/"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Spring-Recoil&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, a programmatic abstraction over &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://www.springframework.net/"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Spring.NET&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;. &amp;nbsp;Unfortunately, the following are still painful:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color:transparent;margin-left:0px;margin-right:0px"&gt;&lt;ul&gt;&lt;li style="background-color:transparent;color:#000000;font-style:normal;list-style-type:disc;vertical-align:baseline"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Missing constructor arguments are run-time errors.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color:transparent;color:#000000;font-style:normal;list-style-type:disc;vertical-align:baseline"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Conditionally loading containers (DI frameworks are declarative).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color:transparent;color:#000000;font-style:normal;list-style-type:disc;vertical-align:baseline"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Custom object life cycles.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="background-color:transparent;color:#000000;font-style:normal;list-style-type:disc;vertical-align:baseline"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Substitution of individual classes within a container (useful for creating integration test harnesses).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Yes there are other DI frameworks out there, but they all still suffer from the above. &amp;nbsp;While dependency injection is invaluable, using a DI framework is more trouble than it&amp;rsquo;s worth. &amp;nbsp;As a coworker recently said: &amp;ldquo;Spring is training wheels for learning dependency injection.&amp;rdquo; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Enforce no more than 4 arguments per method/constructor&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;I picked this one up from &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1278087530&amp;amp;sr=8-1"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Clean Code by Uncle Bob&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;. &amp;nbsp;This is an easy, concrete way to enforce small class/method sizes and &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Single Responsibility&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;. &amp;nbsp;Vastly superior than line count. &amp;nbsp;A reflective automated test will keep this enforced.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Virtually no mocks&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;There is no easier way to make a brittle test whose functionality has no bearing on the functionality of the system than mocks. &amp;nbsp;Mocks are for testing how exactly one object interacts with another. &amp;nbsp;This not useful information. &amp;nbsp;I want to know the result. &amp;nbsp;If there is interaction with another object, and I want to isolate the system-under-test, then I will use a stub, hand-rolled if I need a little functionality. &amp;nbsp;However, I usually prefer to use as many real classes as possible, as I am more closely matching the functionality of the real system (in which case &amp;quot;unit&amp;quot; testing is not the best label).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Enforce a test class for virtually every class&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;I have tried to religiously practice &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;TDD&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, but still haven&amp;rsquo;t gotten there. &amp;nbsp;For me TDD is more helpful for ensuring correctness than for design as I rarely come back to a class I have trouble testing. &amp;nbsp;An automated test to reflect through the code and enforce the existence of a class named &lt;i&gt;&lt;font face="&amp;#39;Courier New&amp;#39;"&gt;$class.name$Tests&lt;/font&gt;&lt;/i&gt; should do the trick, as I am pretty good at keeping the build green. &amp;nbsp;For classes where this is unnecessary, I will add a white list. &amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Web UI&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;a href="http://www.google.com/chrome/"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Google Chrome&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt; has recently advanced to the point of being able to provide parity with fat client applications. &amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Svg"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;SVG&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/HTML_canvas"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;Canvas&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Websockets"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;WebSockets&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://www.css3.info/"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;CSS3&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;, etc. allow for rich user interaction. &amp;nbsp;Coupled with the vast performance gains in the &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Webkit"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;WebKit&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt; rendering engine and the &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/V8_(JavaScript_engine)"&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000099"&gt;&lt;u&gt;&lt;font size="2"&gt;V8&lt;/font&gt;&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-style:normal;vertical-align:baseline"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt; Javascript engine, Chrome is quite fast as well. &amp;nbsp;Now that it matches fat clients in terms of speed and richness (in most cases, hardware acceleration is still lacking), the advantages of cross platform and central deployment that thick clients lack make web apps the clear winner. &amp;nbsp;Note this isn&amp;rsquo;t appropriate for all applications, but is for the domain in which I work.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-9097651866059245540?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/9097651866059245540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/07/next-project.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9097651866059245540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9097651866059245540'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/07/next-project.html' title='Next Project'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-1697717581340498788</id><published>2010-06-23T21:18:00.000-07:00</published><updated>2010-06-23T21:18:43.226-07:00</updated><title type='text'>Retlang 1.0.1 Released</title><content type='html'>This is the final scheduled release. &amp;nbsp;No known bugs or further optimizations exist and the library has been used extensively in production.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Targets .NET Framework 4.0 (&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/clr/thread/dd66d965-73cc-4d7d-9fe6-3b9bd3c55c57"&gt;generic bug&lt;/a&gt; fixed).&lt;/li&gt;
&lt;li&gt;Lists are recycled between executors and fibers, instead of creating new arrays on each execution.&lt;/li&gt;
&lt;li&gt;StubFiber now has ExecutePendingImmediately defaulted to false.  The new default more closely resembles how real fibers execute.  Also it matches &lt;a href="http://code.google.com/p/jetlang/"&gt;Jetlang&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;StubFiber now executes pending actions in FIFO (as opposed to LIFO) order when actions enqueue other actions.  In previous releases this was an issue only when ExecutePendingImmediately was set to true.&lt;/li&gt;
&lt;li&gt;Additional constructors for DispatcherFiber and ThreadFiber.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Get it &lt;a href="http://code.google.com/p/retlang/downloads/list?saved=1&amp;amp;ts=1277219898"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-1697717581340498788?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/1697717581340498788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/06/retlang-101-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/1697717581340498788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/1697717581340498788'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/06/retlang-101-released.html' title='Retlang 1.0.1 Released'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-5470775806508624467</id><published>2010-02-20T10:16:00.001-08:00</published><updated>2010-02-25T07:34:09.381-08:00</updated><title type='text'>Missteps in the Design of the C# Language</title><content type='html'>C# &lt;i&gt;as a language&lt;/i&gt; has many benefits over Java.&amp;nbsp; Some of the more noticeable include a proper implementation of generics, anonymous delegates and lambdas, and niceties such as the var keyword, IDisposable, and LINQ expressions.&amp;nbsp; However, there are several parts of the C# language that are poor, and would have been (are) easy to fix.&lt;br&gt;&lt;b&gt;&lt;br&gt; Enumerations&lt;/b&gt;&lt;br&gt;&lt;br&gt; Why can I not add methods to enumerations as I can in Java?&amp;nbsp; The only time I use C# enumerations anymore is for DTOs.&amp;nbsp; Otherwise, I know from experience that I am going to end up with a switch statement on the enumeration when I should be using polymorphism.&amp;nbsp; See below:&lt;br&gt;&lt;pre class="csharp" name="code"&gt;enum Fruit { Apple, Orange }&lt;br&gt;&lt;/pre&gt; vs.&lt;br&gt;&lt;pre class="csharp" name="code"&gt;class abstract Fruit&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static readonly Fruit Apple = new Apple(1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static readonly Fruit Orange = new Orange(2);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected Fruit(int id)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _id = id;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Id&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;get { return _id; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public abstract virtual void Peel();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private class Apple : Fruit&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Apple(int id) : base(id)&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void Peel()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // omitted for brevity&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // rest omitted for brevity&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;b&gt;Events&lt;/b&gt;&lt;br&gt;&lt;br&gt; Events are probably the worst offender.&amp;nbsp; Why is there an event keyword?&amp;nbsp; Why not just use the already existing multicast delegate?&amp;nbsp; Is not having to encapsulate the field really worth the confusion it causes?&amp;nbsp; Public events appear to be able to be referenced by outside classes.&amp;nbsp; This is however not the case, some methods can only be accessed by the owner class.&amp;nbsp; For even more fun try passing an event to a method.&amp;nbsp; Also why not use the null object pattern with events instead of forcing me to do this every time:&lt;br&gt;&lt;pre class="csharp" name="code"&gt;public event EventHandler ButtonPushed = delegate {};&lt;br&gt;&lt;/pre&gt; An argument against this is that invoking a null event should result in a null reference because it was never allocated.&amp;nbsp; Well then why can I append to it?&amp;nbsp; I can&amp;#39;t add an element to a null list reference, then why can I append an EventHandler to a null event?&amp;nbsp; The most consistent solution would be to require allocation before appending.&lt;br&gt;&lt;br&gt;&lt;b&gt;Structs&lt;/b&gt;&lt;br&gt;&lt;br&gt; It is very useful to be able to allocate data on the stack.&amp;nbsp; Unfortunately if you have any references to classes, then your struct gets boxed and goes on the heap.&amp;nbsp; Structs should have been named value, so as not to confuse them with the unrelated C++ structs and to be more intention revealing.&amp;nbsp; Also the compiler should prevent you from referencing any classes, as to preserve the benefits of stack allocation.&lt;br&gt;&lt;pre class="csharp" name="code"&gt;// this shouldn&amp;#39;t compile&lt;br&gt;struct Currency&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Dollars;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Cents;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Symbol;&lt;br&gt;}&lt;br&gt;&lt;br&gt;// this should compile&lt;br&gt;value Currency&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Dollars;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Cents;&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;&lt;b&gt;Nullable&amp;lt;T&amp;gt;&lt;/b&gt;&lt;br&gt;&lt;br&gt; A coworker introduced me to this one inspired by his learning of &lt;a href="http://www.haskell.org/" id="ryln" title="Haskell"&gt;Haskell&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Monad_%28functional_programming%29#Maybe_monad" id="i8lt" title="Maybe monad"&gt;Maybe monad&lt;/a&gt;.&amp;nbsp; References to classes should be NOT nullable by default.&amp;nbsp; References to classes that can be null should be marked with a ?.&amp;nbsp; Imagine how useful it would be to know which variables could be null and the convention was enforced by the compiler?&lt;br&gt;&lt;pre class="csharp" name="code"&gt;public static void MethodToCall(RequiredArg reqArg, OptionalArg? optional);&lt;br&gt;&lt;br&gt;// should not compile&lt;br&gt;MethodToCall(null, null);&lt;br&gt;&lt;br&gt;// should compile&lt;br&gt;MethodToCall(new RequiredArg(), null);&lt;br&gt;&lt;br&gt;&lt;/pre&gt; While C# as a a language definitely has its benefits over Java, there are still some warts that could definitely be fixed.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-5470775806508624467?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/5470775806508624467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/02/missteps-in-design-of-c-language.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5470775806508624467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5470775806508624467'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/02/missteps-in-design-of-c-language.html' title='Missteps in the Design of the C# Language'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-7875646055428070888</id><published>2010-01-16T11:44:00.001-08:00</published><updated>2010-01-16T11:46:23.279-08:00</updated><title type='text'>StubFiber: How to Deterministically Test Concurrent Code</title><content type='html'>Writing correct concurrent code is considered by many to be one of the more difficult areas of computer science.&amp;nbsp; Verifying the correctness of concurrent code is deemed even more difficult.&amp;nbsp; Ask most developers how to verify the correctness of concurrent code deterministically, and you will be often met with a blank stare.&amp;nbsp; Even books such as &lt;a title="Clean Code" href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1263152214&amp;amp;sr=8-1" id="hpum"&gt;Clean Code&lt;/a&gt;, an otherwise worthwhile read, is incredibly disappointing when it comes to testing concurrent code.&amp;nbsp; An entire chapter and appendix is dedicated to the topic of clean concurrent code.&amp;nbsp; The recommendation comes down to abstracting away threading (but with no examples of how to do this) and using third party tools to alter the thread scheduler to introduce artificial pauses in the hopes that they will expose bugs.&lt;br&gt;
&lt;br&gt;
It turns out that writing correct concurrent code and testing it deterministically is actually not that difficult.&amp;nbsp; As the saying goes, if it hurts, you are doing it wrong.&amp;nbsp; The first step is architectural.&amp;nbsp; Instead of using shared-state concurrency with all the perils of &lt;a title="nested locking" href="http://en.wikipedia.org/wiki/Lock_%28computer_science%29" id="zil1"&gt;nested locking&lt;/a&gt;, use &lt;a title="message based" href="http://en.wikipedia.org/wiki/Message_passing" id="g:xa"&gt;message based&lt;/a&gt; concurrency.&amp;nbsp; Keep unparallalizable mutable state in a single thread and then communicate with other such threads via immutable messages.&amp;nbsp; Two libraries written by &lt;a title="Mike Rettig" href="http://www.jroller.com/mrettig/" id="t_g0"&gt;Mike Rettig&lt;/a&gt;, called &lt;a title="Retlang" href="http://code.google.com/p/retlang/" id="d3p9"&gt;Retlang&lt;/a&gt; (for C#) and &lt;a title="Jetlang" href="http://code.google.com/p/jetlang/" id="t1.v"&gt;Jetlang&lt;/a&gt; (for Java) greatly assist with message based concurrency by introducing the Fiber and Channel abstractions.&amp;nbsp; Fibers are abstractions for threads and Channels are abstractions for the conduit through which Fibers send and receive messages from other Fibers.&amp;nbsp; Since a Fiber is inherently synchronous with itself, it processes all of its messages in order, eliminating the concern of one message handler interrupting another.&lt;br&gt;
&lt;br&gt;
By relying on the Fiber abstraction instead of threads themselves, &lt;a title="ThreadFibers" href="http://code.google.com/p/retlang/source/browse/trunk/src/Retlang/Fibers/ThreadFiber.cs" id="pn6_"&gt;ThreadFibers&lt;/a&gt; or &lt;a title="PoolFibers" href="http://code.google.com/p/retlang/source/browse/trunk/src/Retlang/Fibers/PoolFiber.cs" id="hmfp"&gt;PoolFibers&lt;/a&gt; can be substituted with &lt;a title="StubFibers" href="http://code.google.com/p/retlang/source/browse/trunk/src/Retlang/Fibers/StubFiber.cs" id="t81v"&gt;StubFibers&lt;/a&gt; to obtain synchronous deterministic tests.&amp;nbsp; Any race conditions between threads can be made explicit in a test and thus correct execution can be validated for all interleaves of the thread schedule.&amp;nbsp; Below is an example in Retlang (C#):&lt;br&gt;
&lt;pre class="csharp" name="code"&gt;&lt;br&gt;public class Runner()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly Channel&amp;lt;CalculationResult&amp;gt; channel = new Channel&amp;lt;CalculationResult&amp;gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly Channel&amp;lt;object&amp;gt; requestChannel = new Channel&amp;lt;object&amp;gt;();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly StubFiber fiberOne = new StubFiber { ExecutePendingImmediately = false; };&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly CalculatorOne calculatorOne;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly StubFiber fiberTwo = new StubFiber { ExecutePendingImmediately = false; };&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly CalculatorTwo calculatorTwo;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly ResultAggregator resultAggregator;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Runner()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;calculatorOne = new CalculatorOne(fiberOne, channel, requestChannel);&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;calculatorTwo = new CalculatorTwo(fiberTwo, channel, requestChannel);&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;resultAggregator = new ResultAggregator(new StubFiber(), channel, requestChannel);&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void ExecuteAllPendingOnFiberOne()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fiberOne.ExecuteAllPending();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void ExecuteAllPendingOnFiberTwo()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;fiberTwo.ExecuteAllPending();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void StartCalculations()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;resultAggregator.StartCalculations();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public CombinedResult CombinedResult&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;get { return resultAggregator.Result; }&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br&gt;}&lt;br&gt;&lt;br&gt;[Test]&lt;br&gt;public void FiberExecutionOrderShouldNotChangeResult()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var runner = new Runner();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;runner.ExecuteAllPendingOnFiberOne();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;runner.ExecuteAllPendingOnFiberTwo();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Assert.AreEqual(CombinedResult.Expected, runner.CombinedResult); &lt;br&gt;}&lt;br&gt;&lt;br&gt;[Test]&lt;br&gt;public void SecondFiberExecutionOrderShouldNotChangeResult()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var runner = new Runner();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;runner.ExecuteAllPendingOnFiberTwo();&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;runner.ExecuteAllPendingOnFiberOne();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Assert.AreEqual(CombinedResult.Expected, runner.CombinedResult); &lt;br&gt;}&lt;br&gt;&lt;/pre&gt;

Message based concurrency is vastly superior to shared state concurrency.&amp;nbsp; Not only is the resulting design significantly easier to understand, it also has the nice side effect of being able to be tested deterministically.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-7875646055428070888?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/7875646055428070888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/01/stubfiber-how-to-deterministically-test_16.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7875646055428070888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7875646055428070888'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/01/stubfiber-how-to-deterministically-test_16.html' title='StubFiber: How to Deterministically Test Concurrent Code'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-6552601977093731210</id><published>2010-01-09T13:13:00.001-08:00</published><updated>2010-01-09T17:20:33.349-08:00</updated><title type='text'>Circuit Breakers</title><content type='html'>It is extremely difficult to write bug-free software.&amp;nbsp; Even if you managed to acquire the most talented developers in the world, gave them plenty of time to release, allowed them to use the best suited methodologies for the project, and had well-specified requirements, I'm confident the resulting software would still have bugs.&amp;nbsp; There are many reasons behind this unfortunate truth.&amp;nbsp; According to Fred Brooks in  &lt;a title="The Mythical Man Month" href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1263069971&amp;amp;sr=1-1" id="uceu"&gt;The Mythical Man Month&lt;/a&gt;, software construction is probably one of the most complex endeavors yet undertaken by human beings.&lt;br&gt;
&lt;br&gt;
Many techniques are helpful to reduce the amount of bugs in a codebase.&amp;nbsp; Writing clean readable code is probably the easiest.&amp;nbsp; Several levels of testing (unit, integration, functional, user, load, performance, etc.) are the most obvious.&amp;nbsp; In &lt;a title="Facts and Fallacies of Software Engineering" href="http://www.amazon.com/Facts-Fallacies-Software-Engineering-Robert/dp/0321117425/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1263069939&amp;amp;sr=8-1" id="q-ox"&gt;Facts and Fallacies of Software Engineering&lt;/a&gt;, Robert Glass shows that code inspection (which includes &lt;a title="pair programming" href="http://www.infoq.com/articles/adopting-pair-programming" id="xrnw"&gt;pair programming&lt;/a&gt;) when done frequently and in small groups is also an effective way to reduce bugs.&amp;nbsp; Unfortunately, all of these techniques will only reduce the number of bugs, not guarantee the elimination of all of them.&amp;nbsp; As developers we have to accept that we will ship software with bugs.&lt;br&gt;
&lt;br&gt;
The question is what can we do as developers to reduce the impact of bugs as much as possible given that we know they will occur in production.&amp;nbsp; Michael Nygard, in his book &lt;a title="Release It!" href="http://www.amazon.com/Release-Production-Ready-Software-Pragmatic-Programmers/dp/0978739213/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1263070200&amp;amp;sr=1-1" id="katp"&gt;Release It!&lt;/a&gt;, introduces what he calls the Circuit Breaker pattern.&amp;nbsp; The software pattern matches very closely to the real world pattern.&amp;nbsp; No circuit in your house should draw more current than it is rated to handle.&amp;nbsp; Of course at some point, somewhere, someone will plug in enough power hungry devices to overload a circuit.&amp;nbsp; Before circuit breakers, this would cause a fire.&amp;nbsp; With circuit breakers, the circuit is broken, and the house remains safe.&lt;br&gt;
&lt;br&gt;
This technique involves more than a simple try-catch block. &amp;nbsp;It involves keeping timeouts for interactions with external systems. &amp;nbsp;It involves limiting the total number of times an operation will be retried before alerting the user to the problem. &amp;nbsp;It involves monitoring resources such as disk space or memory and terminating non-essential actions until the resources are freed.&amp;nbsp; It involves limiting the number of rows that can return from a database query.&lt;br&gt;
&lt;br&gt;
While every reasonable effort should be made to eliminate bugs, as a professional developer you have to admit that bugs are not 'ifs' but 'whens'.&amp;nbsp; Circuit Breakers are an excellent defense against the intractable reality of software bugs.&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-6552601977093731210?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/6552601977093731210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2010/01/circuit-breakers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6552601977093731210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6552601977093731210'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2010/01/circuit-breakers.html' title='Circuit Breakers'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-9201762671422891509</id><published>2009-12-09T16:11:00.001-08:00</published><updated>2009-12-10T07:12:07.165-08:00</updated><title type='text'>The Benefits of Unstructured Data</title><content type='html'>In the book The Pragmatic Programmer, an entire section is dedicated to "The Power of Plain Text".&amp;nbsp; The section lists integration (the UNIX tool chain being the canonical example), insurance against obsolescence, and easier testing as motivations for using plain text.&amp;nbsp; There is another significant advantage to plain text that is often overlooked: it lacks rigorous structure.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;MongoDB&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
There has been a trend recently against relational databases that has been coined &lt;a title="NoSQL" href="http://en.wikipedia.org/wiki/Nosql" id="esl9"&gt;NoSQL&lt;/a&gt;.&amp;nbsp; Not to say that relational databases are always a bad idea, just that they are not the best tool for every job.&amp;nbsp; Personally, I have all too often encountered the "I need to persist data so I must use a relational database" mentality.&amp;nbsp; Avoiding &lt;a title="RDBMS" href="http://en.wikipedia.org/wiki/Relational_database_management_system" id="so41"&gt;RDBMS&lt;/a&gt; allows for avoiding schemas.&amp;nbsp; Database schemas are a pain because they have to stay synchronized with all of the applications that access it.&amp;nbsp; Typically this also involves going through a DBA group, which adds a hop that impedes rapid and frequent deployment.&amp;nbsp; &lt;a title="Ruby on Rails" href="http://rubyonrails.org/" id="wc7d"&gt;Ruby on Rails&lt;/a&gt; has a facility called &lt;a title="migrations" href="http://api.rubyonrails.org/classes/ActiveRecord/Migration.html" id="w3a-"&gt;migrations&lt;/a&gt; to help deal with such pain points, but avoiding schemas removes this problem altogether.&amp;nbsp; Furthermore Rails maintains referential integrity at the application layer, making an RDBMS largely overkill.&amp;nbsp; Although my experience with non-relational data stores is far from comprehensive, my favorite so far is &lt;a title="MongoDB" href="http://www.mongodb.org/display/DOCS/Home" id="wtyx"&gt;MongoDB&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
The first thing to notice about MongoDB is the API.&amp;nbsp; The API is very simple and has little if any accidental complexity.&amp;nbsp; There are named collections and you can store dictionaries (or nested dictionaries) in those collections.&amp;nbsp; Each dictionary within a collection can have a different number and types of key-value pairs, and they can be nested.&amp;nbsp; Simple.&lt;br&gt;
&lt;br&gt;
The benefit of not having schemas is that the application can be upgraded before the data store is ready.&amp;nbsp; Just deploy the application upgrade into production and start storing the new data.&amp;nbsp; Separate applications can in most cases be upgraded independently.&amp;nbsp; If previously stored data needs to be normalized, this can happen separately, before or after the application upgrade occurs.&lt;br&gt;
&lt;br&gt;
In addition to avoiding schemas, an unstructured approach yields two other benefits.&amp;nbsp; Want access to the data independent of MongoDB?&amp;nbsp; The data is all stored in &lt;a title="binary JSON" href="http://en.wikipedia.org/wiki/BSON" id="zvd2"&gt;binary JSON&lt;/a&gt;, and therefore is accessible from other languages and applications that have no knowledge of MongoDB.&amp;nbsp; Another benefit of MongoDB made possible by its non-relational nature is support for &lt;a title="auto-sharding" href="http://www.mongodb.org/display/DOCS/Sharding" id="bwmd"&gt;auto-sharding&lt;/a&gt; and &lt;a title="MapReduce" href="http://www.mongodb.org/display/DOCS/MapReduce" id="gcif"&gt;MapReduce&lt;/a&gt;.&amp;nbsp; These features make MongoDB scale significantly better than RDBMS solutions.&amp;nbsp; MongoDB nicely fills niches on both sides of RDBMS in the size-of-data spectrum.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Wikis&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Wikis are an excellent way to share content and communicate.&amp;nbsp; Wikis are superior to other solutions, such as &lt;a title="SharePoint" href="http://en.wikipedia.org/wiki/Sharepoint" id="mu5l"&gt;SharePoint&lt;/a&gt;, because they are akin to a version controlled notebook that everyone can view/edit from their browser.&amp;nbsp; Notebooks impose no structure, nor require a separate context to view or edit (such as Word).&amp;nbsp; Many wikis have macros for tables and other formatting but these are all optional.&amp;nbsp; The wiki will not complain if you leave something out.&amp;nbsp; Wikis can make an excellent replacement for documentation, forums, task lists, release notes, etc.&amp;nbsp; One of the more recent items I have replaced with a wiki is &lt;a title="Mingle" href="http://www.thoughtworks-studios.com/mingle-agile-project-management" id="vkt-"&gt;Mingle&lt;/a&gt;, a software project management tool.&amp;nbsp; Having used several project management tools, I find a wiki to be a better choice due to their lack of structure.&amp;nbsp; The model imposed by project management software never quite fits or is too heavy handed, forcing me to either make my process match the tool, or spend more time than it is worth to coerce the tool to fit my process.&amp;nbsp; Lastly, searching is significantly easier with a wiki because the data is all text.&amp;nbsp; Searching in &lt;a title="SharePoint" href="http://en.wikipedia.org/wiki/Sharepoint" id="md41"&gt;SharePoint&lt;/a&gt; is frustrating in comparison.&lt;br&gt;
&lt;br&gt;
The "Power of Plain Text" is understated.&amp;nbsp; Rigorous structure is not always a good thing when it comes to data, and less stringent solutions should be considered first, as they are often more flexible and require less developer overhead.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-9201762671422891509?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/9201762671422891509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/12/benefits-of-unstructured-data.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9201762671422891509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9201762671422891509'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/12/benefits-of-unstructured-data.html' title='The Benefits of Unstructured Data'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-1669619916652650407</id><published>2009-10-24T11:13:00.001-07:00</published><updated>2011-05-30T09:54:45.966-07:00</updated><title type='text'>Encapsulate Collections and Primitives</title><content type='html'>I recently came across an article entitled &lt;a title="Object Calisthenics" href="http://www.amazon.com/ThoughtWorks-Anthology-Technology-Innovation-Programmers/dp/193435614X/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1256404406&amp;amp;sr=8-1" id="eiy:"&gt;Object Calisthenics&lt;/a&gt; by Jeff Bay.&amp;nbsp; The purpose of the exercise is to show the effects of following object-orientation rigorously on a small greenfield project.&amp;nbsp; After the calisthenics are practiced as rules, they are to be relaxed and used as guidelines in production code.&amp;nbsp; Two of these exercises are of particular interest.&lt;br&gt;
&lt;h4&gt;Rule 3: Wrap all primitives and strings&lt;/h4&gt;
As referenced above, the goal of rule 3 is not to preclude the use of naked primitives and strings altogether, but to learn when it is appropriate to encapsulate them.&amp;nbsp; Interestingly, the language of choice affects the overhead of encapsulating primitives and strings.&lt;br&gt;
&lt;br&gt;
In Java a wrapped primitive must be an object, thereby adding work for the garbage collector.&amp;nbsp; Secondly, Java does not allow operator overloading thus adding a lot of ceremony to otherwise simple mathematical operations.&amp;nbsp; Anyone who has suffered through the use of BigDecimals has experienced this pain.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
In C#, primitives can be wrapped as structs and therefore be allocated on the stack, making GC performance less of a concern.&amp;nbsp; Also, C# allows for operator overloading of arithmetic operators, eliminating the ugliness of using BigDecimal.&amp;nbsp; C# also supports implicit casting, making conversion between primitives and a wrapped class succinct, though I have to admit I never use implicit casting because I am always worried it will cast unexpectedly.&lt;br&gt;
&lt;br&gt;
Moving past language support, when are the appropriate times to encapsulate strings and primitives?&amp;nbsp; Type safety in statically typed languages is the first that comes to mind.&amp;nbsp; Both for mathematical operations and argument passing.&amp;nbsp; If a method takes two different doubles, it can be refactored so it takes two separate types.&amp;nbsp; This helps eliminate the mistake of transposing the arguments.&amp;nbsp; Another advantage of type safety is to restrict mathematical operations to only a subset of types.&amp;nbsp; F# does a good job of this with its units library.&amp;nbsp; Below is a trivial example using C#.&lt;br&gt;
&lt;pre class="csharp" name="code"&gt;// Mechanics.cs&lt;br&gt;public Mass Calculate(Force f, Acceleration a)&lt;br&gt;{&lt;br&gt;   return f/a;&lt;br&gt;}&lt;br&gt;&lt;br&gt;// MechanicsTests.cs&lt;br&gt;private readonly Force f = new Force(12);&lt;br&gt;private readonly Acceleration a = new Acceleration(4);&lt;br&gt;private readonly Mass m = new Mass(3);&lt;br&gt;&lt;br&gt;[Test]&lt;br&gt;public void ForceShouldBeMassTimesAcceleration()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Assert.AreEqual(m, new Mechanics().Calculate(f, a));&lt;br&gt;}&lt;br&gt;&lt;br&gt;[Test]&lt;br&gt;public void WillNotCompileButWouldUsingPrimitives()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Assert.AreEqual(a, new Mechanics().Calculate(f, m));&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/pre&gt;The method &lt;i&gt;Calculate&lt;/i&gt; could have a better name, but type safety makes it largely redundant.&amp;nbsp; Type safety also makes it safer than a more intention revealing method name as the compiler does not enforce the intent of method names.&lt;br&gt;&lt;br&gt;Another reason to encapsulate a primitive is when the entire range of values for the primitive is not valid for an argument.&amp;nbsp; Enumerations are a good example of such an encapsulation, as they are really just a subset of integers mapped to meanings.&amp;nbsp; As an aside, Java allows the addition of methods and thereby a kind of polymorphism to enums making them superior to C# enums.&lt;br&gt;
&lt;br&gt;
Strings are always objects.&amp;nbsp; This has different memory implications for managed vs. unmanaged languages.&amp;nbsp; Type safety for argument passing and range of values both apply here as well, though obviously not mathematical operations.&amp;nbsp; A good example is file system paths.&amp;nbsp; Several characters are not allowed in file system paths, and the object itself should enforce such restrictions.&lt;br&gt;
&lt;h4&gt;Rule 8: Use first class collections &lt;/h4&gt;
 Rule 8 should be more than an exercise.&amp;nbsp; A mutable collection should almost never be passed between classes without being wrapped.&amp;nbsp; Any operations performed on the collection should be extracted into methods and added to the wrapped collection.&amp;nbsp; Encapsulating collections adds minimal coding and memory overhead to most languages, and greatly increases readability and encapsulation.&lt;br&gt;&lt;br&gt;Applying the idea of calisthenics to programming is an interesting idea.&amp;nbsp; As with physical calisthenics, object calisthenics are helpful to the entire spectrum of developers.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-1669619916652650407?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/1669619916652650407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/10/encapsulate-collections-and-primitives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/1669619916652650407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/1669619916652650407'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/10/encapsulate-collections-and-primitives.html' title='Encapsulate Collections and Primitives'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-9222213868893026617</id><published>2009-06-04T08:33:00.001-07:00</published><updated>2009-06-04T15:10:16.265-07:00</updated><title type='text'>ReSharper Next</title><content type='html'>&lt;a title="ReSharper" href="http://www.jetbrains.com/resharper/index.html" id="mlrh"&gt;ReSharper&lt;/a&gt; (or &lt;a title="IntelliJ" href="http://www.jetbrains.com/idea/" id="ekwa"&gt;IntelliJ&lt;/a&gt;) is an invaluable tool when programming in C# (Java).&amp;nbsp; Proficiency in ReSharper increases productivity by allowing rote refactorings to be performed with a couple of keystrokes.&amp;nbsp; For languages such as C# or Java where ceremony is high, such tools greatly lower the amount of work required to keep code maintainable.&amp;nbsp; I am very happy with ReSharper but I can't help but want more.&amp;nbsp; I think this is a sign of a very good product.&amp;nbsp; It does what it does very well, and therefore I trust &lt;a title="Jetbrains" href="http://www.jetbrains.com/" id="l7q9"&gt;Jetbrains&lt;/a&gt; to be able to add more features with the same elegance. &lt;br&gt;
&lt;b&gt;&lt;br&gt;
Coverage&lt;br&gt;
&lt;/b&gt;&lt;br&gt;
I recently got an email from the developers at &lt;a title="NCover" href="http://www.ncover.com/" id="j6-y"&gt;NCover&lt;/a&gt; telling me a new version is ready (a complete rewrite no less).&amp;nbsp; Unfortunately, NCover has yet again missed out on the killer feature for coverage: IDE integration.&amp;nbsp; My favorite version of NCover was the open source version that I could run via TestDriven.Net from the IDE.&amp;nbsp; While bitching about having to pay for a version of NCover I find inferior to the free version, a coworker brought up an even better point.&amp;nbsp; Not only do I want IDE integration, I want it to color my source code in Visual Studio.&amp;nbsp; I want it to slap me in the face with the fact that I have written a line of code that is uncovered.&amp;nbsp; Here is a mocked up example:&lt;br&gt;
&lt;br&gt;
&lt;div id="z8ua" style="text-align: left;"&gt;&lt;div id="aso1" style="text-align: left;"&gt;&lt;img style="width: 720px; height: 272px;" src="http://docs.google.com/File?id=ap74rkbgcbd_81hsvph9c9_b"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;

Given how well ReSharper has done with IDE integration (including unit testing) it would be nice if they would include integrated coverage in the next version as well.&lt;br&gt;
&lt;b&gt;&lt;br&gt;
Metrics&lt;br&gt;
&lt;br&gt;
&lt;/b&gt;Everytime I check in code to the continuous integration server a set of metrics (Cyclomatic Complexity, Lack of Cohesion of Methods, Depth of Inheritance, Coverage, and Duplication) are run.&amp;nbsp; These are arranged into a convenient chart available via a web interface.&amp;nbsp; However, I have to actually navigate to the web interface to see these reports, which makes them easy to ignore.&amp;nbsp; What would be better is if the feedback loop were shorter and I knew while I was working on the code that my Lack of Cohesion of Methods was too high indicating a potential violation of the &lt;a title="Single Responsibility Principle" href="http://en.wikipedia.org/wiki/Single_responsibility_principle" id="wi29"&gt;Single Responsibility Principle&lt;/a&gt;.&amp;nbsp; As with coverage, the results of these metrics being right in front of me while I am coding would have a positive impact on the maintainability of the code. &amp;nbsp; &lt;br&gt;&lt;b&gt;
&lt;br&gt;
Advanced Live Templates: Test Data Builder&lt;br&gt;
&lt;br&gt;
&lt;/b&gt;I recently discovered the pattern of &lt;a title="Test Data Builders" href="http://nat.truemesh.com/archives/000714.html" id="z79y"&gt;Test Data Builders&lt;/a&gt; to help in object construction for testing.&amp;nbsp; It is particularly useful if the object has a lot of constructor arguments, many of which do not change between tests.&amp;nbsp; Test Data Builders require a decent amount of typing and most of it is rote and could be automated.&amp;nbsp; My first thought was to write a custom ReSharper live template.&amp;nbsp; Unfortunately live templates are not powerful enough to do this.&amp;nbsp; One could write a class to code generate it, but it doesn't quite have the same feel as a 'CTRL-T-D-B'.&amp;nbsp; I want to be able to write C# code in live templates, or at the very least provide a built-in template for Test Data Builders.&lt;br&gt;
&lt;br&gt;ReSharper is an excellent tool.&amp;nbsp; I could not imagine coding in C# (or Java with IntelliJ) without it.&amp;nbsp; There is little improvement left for the current feature set.&amp;nbsp; Integrated code metrics and full C# support in live templates would be very beneficial features for the next iteration of ReSharper.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-9222213868893026617?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/9222213868893026617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/06/resharper-next.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9222213868893026617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9222213868893026617'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/06/resharper-next.html' title='ReSharper Next'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4210813500440852723</id><published>2009-03-28T11:21:00.001-07:00</published><updated>2009-03-31T07:09:47.819-07:00</updated><title type='text'>Agile True Believers</title><content type='html'>&lt;div&gt;I recently attended &lt;a id="g_8x" href="http://speakerconf.com/" title="SpeakerConf"&gt;SpeakerConf&lt;/a&gt;, a conference with the intention of only inviting speakers of software related conferences with the idea of "capturing the essence of those productive conference dinners, without having to deal with the rest of the conference" (I'm paraphrasing).  I have never spoken, nor attended, a technical conference, but I do work with one of the organizers &lt;a id="bagm" href="http://blog.jayfields.com/" title="Jay Fields"&gt;Jay Fields&lt;/a&gt;, and he was gracious enough to invite me without having ever spoken at a conference.  I learned a good amount at SpeakerConf, and more importantly met many people I otherwise would not.  I even had the honor of bouncing &lt;a id="tzww" href="http://grahamnash.blogspot.com/2008/07/avoid-inheritance.html" title="my ideas on inheritance"&gt;my ideas on inheritance&lt;/a&gt; off of &lt;a id="gazn" href="http://www.michaelfeathers.com/" title="Michael Feathers"&gt;Michael Feathers&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;At SpeakerConf a speaker explained a term called FDD or Feedback Driven Development, which reminded me of a &lt;a id="b7g6" href="http://grahamnash.blogspot.com/2008/09/agile-lean-feedback.html" title="previous post"&gt;previous post&lt;/a&gt; I wrote about searching for more accurate terms for how I develop.  I started to write that post with a different goal in mind than when I started it.  The original intent of the post was to criticize how I found people using Agile as a catch-all term to describe any development related practice they favored.  Because Agile is such a nebulous term in this context, I questioned the use of a single term to describe a set of nuanced practices.  By the end however, I just came up with a different term, &lt;i&gt;feedback&lt;/i&gt;, and in retrospect I simply replaced one term with another, contradicting the intent of the post.  I have been collecting my thoughts about this topic for a while and finally have my thoughts together enough to correct my stance.
&lt;/div&gt;&lt;div&gt;While I adhere to many of the development practices espoused by this group of well known Agilists, I disagree with many of them on the Agile movement itself.  Mass movements come with zealots, and in my opinion zealots are an easy way to turn off the developers that I want to work with.  Many of them felt zealots were a good way to browbeat the stubborn developers into conversion to Agile development practices.  When it comes to zealotry in the Agile community, Uncle Bob makes &lt;a id="w._2" href="http://blog.objectmentor.com/articles/2009/03/10/lets-hear-it-for-the-zealots" title="this distinction"&gt;this distinction&lt;/a&gt; on his blog:&lt;/div&gt;&lt;div&gt;&lt;i&gt;"&lt;/i&gt;&lt;span&gt;&lt;i&gt;There is a difference between a zealot, and a religious fanatic. A religious fanatic cannot envision themselves to be wrong. We in the agile community may indeed be zealots, but we know we can be wrong."&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Um, really?  There are no "religious fanatics" (a poor choice of words) in the Agile community?  Agreed there are rational people in the Agile community, but to say that all of them argue rationally (we know we can be wrong) instead of emotionally is not true.  Herein lies the danger behind using a mass movement.  Mass movements are often propagated by not just zealots, but what &lt;a id="wp_a" href="http://en.wikipedia.org/wiki/Eric_Hoffer" title="Eric Hoffer"&gt;Eric Hoffer&lt;/a&gt; calls &lt;a id="lipe" href="http://www.amazon.com/True-Believer-Thoughts-Movements-Perennial/dp/0060505915/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1237859232&amp;amp;sr=8-1" title="True Believers"&gt;True Believers&lt;/a&gt;.  Below is my definition which I derived from his book.
&lt;/div&gt;&lt;div&gt;&lt;b&gt;True Believer&lt;/b&gt;&lt;i&gt; - n. a person who joins a mass movement due to lack of confidence in one's abilities and intellect.  By adhering to a simplified and known set of dogma the person becomes a member of a larger entity, providing social camaraderie, a sense of importance, and most importantly lack of personal accountability for failure.  The zeal of the True Believer is proportional to the irrationality of the doctrine.&lt;/i&gt;
&lt;/div&gt;&lt;div&gt;Does the existence of True Believers discredit mass movements in general?  Of course not.  But it does alienate those of us who are turned off by irrational argumentation that is founded on authority, emotion, or other &lt;a id="uwj8" href="http://en.wikipedia.org/wiki/Fallacy" title="ogical fallacies"&gt;logical fallacies&lt;/a&gt; instead of valid evidence.  In fact, many movements are viciously and exclusively defended by fanatics because their doctrine doesn't hold water.  Ideally critical thinkers would investigate deeper, but between skepticism being an essential component of scientific thought, and the sheer amount of utter bullshit espoused by our fellow man, it is understandable that some critical thinkers write off some mass movements without due diligence.
&lt;/div&gt;&lt;div&gt;Agile is not the only victim of True Believers.  &lt;a id="em_s" href="http://en.wikipedia.org/wiki/Getting_Things_Done" title="GTD"&gt;GTD&lt;/a&gt; (note David Allen is an ordained minister of a new age religion) suffers from the very same problem.  Richard Dawkins, in &lt;a id="m5tp" href="http://www.amazon.com/God-Delusion-Richard-Dawkins/dp/0618918248/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1237862919&amp;amp;sr=8-1" title="The God Delusion"&gt;The God Delusion&lt;/a&gt;, purports that churches and religious summer camps should be replaced with organized atheist-friendly political groups and "skeptics camps" for children.  Is there really a difference?  Did Dawkins miss a main motivator behind not having a religion?  The New York Times recently had an &lt;a id="im99" href="http://www.nytimes.com/2009/02/10/science/10essa.html?_r=1&amp;amp;scp=1&amp;amp;sq=darwinism&amp;amp;st=cse" title="op-ed"&gt;op-ed&lt;/a&gt; on how the scientific community should stop using the term Darwinism when referring to biological evolution because it associates an otherwise strong scientific theory with an -ism and an idol.
&lt;/div&gt;&lt;div&gt;What wouldn't spurn away those who think critically?  It is here I would like to return to the initial intent of my original post.  Perhaps marking a way of developing software with a single term like Agile or Feedback is a gross oversimplification.  Instead of mass movements in the software community one could be more granular and debate about the merits of individual practices instead of arbitrary groups of them.  The problem is inherent in coming up with a comprehensive yet numerable set of techniques or mantra for any sufficiently complex intellectual endeavor.  The list will become either overly proscriptive and mechanical with no room for interpretation or will be small and nebulous to the point of being meaningless.  I vote to let each practice stand on its own, without a flag or army, and especially without the pitchforks of the True Believers.
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4210813500440852723?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4210813500440852723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/03/agile-true-believers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4210813500440852723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4210813500440852723'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/03/agile-true-believers.html' title='Agile True Believers'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4855580560553084966</id><published>2009-02-21T06:22:00.001-08:00</published><updated>2009-04-26T18:54:56.895-07:00</updated><title type='text'>Application.Run and Controller-View Separation</title><content type='html'>When starting a new WinForms application, Visual Studio provides you with some defaults to help you get you started.  Two of these are the Program.cs file and a child of the Form class as the project's first window.  In the Main method of Program.cs, you will see the following code:&lt;br&gt;
&lt;pre class="csharp" name="code"&gt;Application.Run(new Form1());
&lt;/pre&gt;It is here that Microsoft starts you off on the wrong foot.  The natural place to start, given this setup, is to add logic to the Form (which is the &lt;a title="View" href="http://en.wikipedia.org/wiki/Model-view" id="e32d"&gt;View&lt;/a&gt;).  By making the View the starting point of the application, proper architecture is discouraged from the beginning.&lt;br&gt;
&lt;br&gt;
All is not lost however.  There is an overload for Application.Run that takes an &lt;a title="ApplicationContext" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext.aspx" id="pmap"&gt;ApplicationContext&lt;/a&gt;.  Simply create a &lt;a title="Controller" href="http://en.wikipedia.org/wiki/Model-view" id="dvq6"&gt;Controller&lt;/a&gt;, that extends ApplicationContext, and have it take a reference to the View.  This design encourages logic to be placed in the Controller which can then drive the View.  &lt;a title="Easier unit testing" href="http://grahamnash.blogspot.com/2009/01/gui-testing-part-i-unit-testing.html" id="s1xc"&gt;Easier unit testing&lt;/a&gt;  is one of many reasons such a design is superior.&lt;br&gt;
&lt;pre class="csharp" name="code"&gt;// Controller.cs
public class Controller : ApplicationContext
{
    private readonly Form1 _view;

    public Controller(Form1 view)
    {
        _view = view;
    }   
}

// Program.cs

// in Main
Application.Run(new Controller(new Form1());

&lt;/pre&gt;This simple change in default setup has a dramatic architectural effect on the application going forward.  While many experienced developers will invert the default relationship, as shown in the snippet above, it leads novice .NET developers down the wrong path unnecessarily.  Why make a superior architecture available but not make it the default?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4855580560553084966?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4855580560553084966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/02/applicationrun-and-controller-view.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4855580560553084966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4855580560553084966'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/02/applicationrun-and-controller-view.html' title='Application.Run and Controller-View Separation'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-299715576607236077</id><published>2009-02-15T10:21:00.001-08:00</published><updated>2009-04-26T18:51:55.991-07:00</updated><title type='text'>The Costs of Emotional Immaturity</title><content type='html'>I was following the &lt;a title="XHEO controversy" href="http://ayende.com/Blog/archive/2009/02/02/open-letter-to-xheo-that-is-not-a-good-way.aspx" id="k59l"&gt;XHEO controversy&lt;/a&gt;  recently on &lt;a title="Ayende's blog" href="http://ayende.com/blog/" id="lg6b"&gt;Ayende's blog&lt;/a&gt;  when I happened upon a comment instructing the XHEO executive to learn something about customer service from &lt;a title="Joel Spolsky" href="http://www.joelonsoftware.com/" id="fb45"&gt;Joel Spolsky&lt;/a&gt;.  I find Joel to be hit and miss, especially when it comes to &lt;a title="technical content" href="http://www.joelonsoftware.com/items/2008/03/17.html" id="wg40"&gt;technical content&lt;/a&gt;  and &lt;a title="workspace layout" href="http://www.joelonsoftware.com/articles/BionicOffice.html" id="qupl"&gt;workspace layout&lt;/a&gt;.  However, his entry on &lt;a title="customer service" href="http://www.joelonsoftware.com/articles/customerservice.html" id="wxv3"&gt;customer service&lt;/a&gt;  is spot on.  In particular I find the following passage very important:&lt;br&gt;
&lt;br&gt;
&lt;span style="font-style: italic;"&gt;“Ah. It’s my fault,” he said.&lt;/span&gt;&lt;br&gt;
&lt;span style="font-style: italic;"&gt;And suddenly, I wasn’t mad at all.&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br&gt;
Mysteriously, the words “it’s my fault” completely defused me. That was all it took.&lt;/span&gt;&lt;br&gt;
&lt;p&gt;For some reason, some adults have a very difficult time admitting they are wrong, especially in front of a group.  This is perplexing, all people make mistakes, to not admit when one is wrong is delusional, and therefore I would argue immature and unprofessional.  Stubbornly holding a position against a group of adults who know that the offender is attempting to save face instead of arrive at the best solution is not a good way to earn the respect of those in the room, regardless of age, tenure, or rank.  &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Not only is it a sure way to lose respect, it is a timesink.  When such an incident happens in a meeting, the offender generally must be pulled aside individually so their ego can be placated in a one-on-one environment.  Then a third meeting must be called with the original group where the original solution is covered again, except the offender does not raise any objections this time, thereby demonstrating consensus.  This is a waste of two entire meetings and everyone's time who has to attend.  All because one person isn't comfortable publicly admitting they are human.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;These timesinks add up over time.  My current group doesn't experience this problem at all, and our velocity is noticeably higher than groups that refuse to mitigate the problem.  The culture is to admit when one is wrong, publically if that happens to be the context at the time, as soon as one realizes it.  We work on very difficult problems, leading people to be wrong frequently.  This is expected, and because everyone in the group is emotionally mature enough to admit it immediately, we discard subpar solutions as quickly as possible.  If anything, we all respect each other more because we readily admit when we are wrong.    &lt;/p&gt;&lt;p&gt;Not every discipline has this luxury.  Software development is a fairly objective area of study.  CPU and memory footprint, testability, and &lt;a title="maintainability" href="http://grahamnash.blogspot.com/2008/07/maintenance-first.html" id="xe.u"&gt;maintainability&lt;/a&gt;  are all measurable, so long as the group agrees on the definitions.  Leverage the relative objectivity of software development to your advantage.  Encourage a scientific culture, one where skepticism, dissent, falsifiability and correctness are emphasized above shielding everyone's inner child.  Next time someone proves your stance incorrect logically or empirically, think twice before &lt;a title="arguing from emotion" href="http://en.wikipedia.org/wiki/Appeal_to_emotion" id="h-2w"&gt;arguing from emotion&lt;/a&gt;.  It might save the group time and increase your respectability amongst coworkers.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-299715576607236077?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/299715576607236077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/02/costs-of-emotional-immaturity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/299715576607236077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/299715576607236077'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/02/costs-of-emotional-immaturity.html' title='The Costs of Emotional Immaturity'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-9205104244271693670</id><published>2009-01-31T14:57:00.001-08:00</published><updated>2011-01-08T15:25:02.355-08:00</updated><title type='text'>Unit Testing GUIs</title><content type='html'>A couple of years ago I was doing mostly GUI programming.&amp;nbsp; At around the same time I starting getting into unit testing.&amp;nbsp; Unit testing soon became an invaluable way to validate my implementation and drive my design, but I found it difficult to apply to GUIs.&amp;nbsp; I scoured Amazon and Google trying to find anything that would help me out.&amp;nbsp; Most of what I found was along the lines of "GUI testing is a hard problem that is largely unsolved."&amp;nbsp; Very discouraging results.&lt;br /&gt;
&lt;br /&gt;
After a while, I did find one pattern that looked like it had potential: &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html" id="dnxz" title="Passive View"&gt;Passive View&lt;/a&gt;.&amp;nbsp; The original web page is a little rough and difficult to read, but after going through it a couple of times it clicked (later I found an easier to read version of same pattern which the author calls &lt;a href="http://www.atomicobject.com/files/PresenterFirstAgile2006.pdf" id="s56d" title="Presenter First"&gt;Presenter First&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Passive View is a version of Model-View-Presenter.&amp;nbsp; The distinction between Model-View-Presenter and Model-View-Controller depends on whom you ask; you can follow the Passive View link if you are curious.&amp;nbsp; Passive View is different from other implementations of MVP in that there is no coupling between Model and View.&amp;nbsp; The goal of Passive View is testability.&amp;nbsp; If you are unsure if you are properly following Passive View, ask yourself "Is what I am about to code difficult to test?"&amp;nbsp; If the answer is yes, then you are not following Passive View.&amp;nbsp; Below are the guidelines to follow for Passive View:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Keep the View as thin and logic free as possible.&lt;/li&gt;
&lt;li&gt;Put as much of the presentation logic as possible in the Presenter instead of the View.&lt;/li&gt;
&lt;li&gt;Only the Presenter should reference the View.&lt;/li&gt;
&lt;li&gt;The View should not reference any other objects, including the Model.&lt;/li&gt;
&lt;/ul&gt;The View should implement an interface on which the Presenter should depend.&amp;nbsp; This allows for substituting the real View with a &lt;a href="http://www.martinfowler.com/bliki/TestDouble.html" id="ti13" title="test double"&gt;test double&lt;/a&gt;  view while testing the Presenter, via &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection" id="k2_j" title="Constructor Injection"&gt;Constructor Injection&lt;/a&gt;.&amp;nbsp; Because the vast majority of the implementation is contained in the Presenter, the GUI code is now easy to test.&amp;nbsp; Below is an example using C# 3.5 and &lt;a href="http://ayende.com/projects/rhino-mocks.aspx" id="bu67" title="Rhino Mocks 3.5"&gt;Rhino Mocks 3.5&lt;/a&gt;.&lt;br /&gt;
&lt;pre class="csharp" name="code"&gt;public interface IView
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;FlexGrid Grid { get; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;event RowColEventHandler CellChanged;

&amp;nbsp;&amp;nbsp;&amp;nbsp; string SaveButtonText { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;bool SaveButtonEnabled { get; set; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; event EventHandler SaveButtonClicked;
}

public partial class MyView : Form, IView
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;private Button _saveButton;
&amp;nbsp;&amp;nbsp; &amp;nbsp;private FlexGrid _grid;
&amp;nbsp;&amp;nbsp; &amp;nbsp;
&amp;nbsp;&amp;nbsp; &amp;nbsp;public FlexGrid Grid
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;get { return _grid; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;public Color SaveButtonColor
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;get { return _saveButton.BackgroundColor; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;set { _saveButton.BackgroundColor = value; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;public bool SaveButtonEnabled
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;get { return _saveButton.Enabled; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;set { _saveButton.Enabled = value; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;public event EventHandler SaveButtonClicked
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;add { _saveButton.Click += value; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;remove { _saveButton.Click -= value; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
}

public class MyPresenter
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly IView _view;
&amp;nbsp;&amp;nbsp; &amp;nbsp;private readonly IModel _model;

&amp;nbsp;&amp;nbsp; &amp;nbsp;public MyPresenter(IView view, IModel model)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view = view;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_model = model;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.SaveButtonClicked += SendChangesToModel;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.CellChanged += EnableSaveButton;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;private void SendChangesToModel(object sender, RowColEventArgs e)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_model.ChangeInfo(_view.Grid[e.Row, "Author"], _view.Grid[e.Row, "Book"]);
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.SaveButtonEnabled = false;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.SaveButtonColor = Colors.Gray;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;private void EnableSaveButton(object sender, EventArgs e)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.SaveButtonEnabled = true;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view.SaveButtonColor = Colors.Firebrick;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
}&lt;/pre&gt;Notice button properties are delegated-to in the View, but with the FlexGrid only events are redirected.&amp;nbsp; This is because if the button were exposed directly or through an adapter with an interface so it could be mocked, one would have to create two mocks and have one return the other.&amp;nbsp; It is easier to "denormalize" as many of the properties as possible to one interface.&amp;nbsp; The exception to this technique is with a heavily normalized and complex class like FlexGrid.&amp;nbsp; It would be very cumbersome to delegate all of the methods to an adapter class or on the Form.&amp;nbsp; Instead a real FlexGrid is returned, generally one generated by the real Form so that it is properly configured (columns are already set up).&amp;nbsp; The same could be done with the Button, but not being able to use the events on the button itself is confusing, so the previous technique should be used only if necessary.&amp;nbsp; Neither event is subscribed to directly because it is required to be able to fire these while testing.&amp;nbsp; Putting the events on interfaces allows them to be fired with Rhino Mocks like so:&lt;br /&gt;
&lt;pre class="csharp" name="code"&gt;[TestFixture]
public class MyPresenterTests
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; [Test]
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void ButtonClickShouldSendChangesToModel()
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var view = MockRepository.GenerateMock&amp;lt;IView&amp;gt;();
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var model = MockRepository.GenerateMock&amp;lt;IModel&amp;gt;();
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var grid = new MyView().Grid;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.Stub(v =&amp;gt; v.Grid).Return(grid);
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var underTest = new MyPresenter(view, model);
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; grid[1, "Author"] = "Carl Sagan";
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; grid[1, "Book"] = "A Demon Haunted World";
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;view.Raise(x&amp;nbsp;=&amp;gt;&amp;nbsp;x.SaveClicked&amp;nbsp;+=&amp;nbsp;null,&amp;nbsp;view,&amp;nbsp;new RowColEventArgs(1, 0));

&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; model.AssertWasCalled(m =&amp;gt; m.ChangeInfo("Carl Sagan", "A Demon Haunted World");
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.AssertWasCalled(v =&amp;gt; v.SaveButtonEnabled = false);
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; view.AssertWasCalled(v =&amp;gt; v.SaveButtonColor = Colors.Gray);
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
}&lt;/pre&gt;Lastly if a view or presenter gets too large but you want to keep the window together, simply break up the interface into pieces and have the same Form implement all of them.&amp;nbsp; Lastly create smaller presenters that have a common presenter connecting between them.&lt;br /&gt;
&lt;pre class="csharp" name="code"&gt;public interface IGridView
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;FlexGrid Grid { get; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;event RowColEventHandler CellChanged;
}

public interface IControlPanelView
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;string SaveButtonText { get; set; }
&amp;nbsp;&amp;nbsp; &amp;nbsp;bool SaveButtonEnabled { get; set; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; event EventHandler SaveButtonClicked;
}

public class MyView : Form, IGridView, IControlPanelView
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;// implementation left out for brevity
}

public class GridPresenter : IGridPresenter 
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;private IGridView _view;

&amp;nbsp;&amp;nbsp; &amp;nbsp;public GridPresenter(IGridView view)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view = view;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;// implementation left out for brevity
}

public class ControlPanelPresenter : IControlPanelPresenter
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;private IControlPanelView _view;

&amp;nbsp;&amp;nbsp; &amp;nbsp;public ControlPanelPresenter(IControlPanelView view)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_view = view;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;// implementation left out for brevity
}

public class CommonPresenter
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;private IGridPresenter _grid;
&amp;nbsp;&amp;nbsp; &amp;nbsp;private IControlPanelPresenter _controlPanel;

&amp;nbsp;&amp;nbsp; &amp;nbsp;public CommonPresenter(IGridPresenter grid, IControlPanelPresenter controlPanel)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_grid = grid;
&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;_controlPanel = controlPanel;
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;// implementation left out for brevity
}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-9205104244271693670?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/9205104244271693670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2009/01/gui-testing-part-i-unit-testing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9205104244271693670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/9205104244271693670'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2009/01/gui-testing-part-i-unit-testing.html' title='Unit Testing GUIs'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-5359078368057693827</id><published>2008-12-20T09:00:00.000-08:00</published><updated>2009-04-26T18:47:04.810-07:00</updated><title type='text'>Why is CreateHandle protected?</title><content type='html'>In WinForms, there is a method on Form called CreateHandle that is protected.  The method simply forces the Form to create a handle.  An exception is thrown if you attempt to modify the form before a handle is created.&lt;br&gt;
&lt;br&gt;
In most cases calling CreateHandle is not necessary.  When you open the Form, a handle is created automatically.  However there are times when I want to modify the Form before the user opens it.  To do this I have a couple of choices.  I can inherit from Form and expose CreateHandle in a new base class.  I can individually expose CreateHandle in every Form for which I want to have this ability.  My last choice is to use reflection to gain access to the protected method.   Some people will mention that you can simply query the Handle property and that will create a handle.  This is not quite true, when using this technique a handle is not created for children of the parent Form:&lt;br&gt;
&lt;br&gt;
&lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.control.createcontrol.aspx" target="_blank"&gt;http://msdn.microsoft.com/en-&lt;wbr&gt;us/library/system.windows.&lt;wbr&gt;forms.control.createcontrol.&lt;wbr&gt;aspx&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
I do not like any of these options.  In fact this is an example of why I do not think protected is a valid level of encapsulation at all.  If the functionality is useful, make it public.  If it breaks encapsulation, then make it private.  Protected is an annoyance that sort of sits between encapsulated and not.  Why favor inheritance, a technique that is usually &lt;a href="http://grahamnash.blogspot.com/2008/07/avoid-inheritance.html"&gt;inappropriate and brittle&lt;/a&gt;, when composition would be a better choice.  The use of the protected keyword pushes me towards inheritance as a design choice even though it is inferior.&lt;br&gt;
&lt;br&gt;
If I were to design an object-oriented language, I wouldn't include the protected level of encapsulation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-5359078368057693827?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/5359078368057693827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/12/why-is-createhandle-protected.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5359078368057693827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5359078368057693827'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/12/why-is-createhandle-protected.html' title='Why is CreateHandle protected?'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-5282519289200042283</id><published>2008-10-22T19:40:00.000-07:00</published><updated>2009-04-26T18:46:00.484-07:00</updated><title type='text'>Rhino Mocks 3.5</title><content type='html'>&lt;span&gt;I had a chance to upgrade to Rhino Mocks 3.5 recently.  While I won't go over all of the new features I will go over the ones I have found most useful.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;br&gt;
Static creation methods&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
CreateMock is deprecated. Use StrictMock instead. StrictMocks create brittle tests and therefore usage is discouraged.  A better route is to forgo using an instance of a MockRepository altogether. Instead two static creation methods are available:&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
var mock = MockRepository.GenerateMock&amp;lt;IMock&amp;gt;(); // same as DynamicMock
var stub = MockRepository.GenerateStub&amp;lt;IStub&amp;gt;()
&lt;/pre&gt;Compare with:&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
MockRepository mocks = new MockRepository();
IMock mock = mocks.DynamicMock&amp;lt;IMock&amp;gt;();
IStub stub = mocks.Stub&amp;lt;IStub&amp;gt;();
&lt;/pre&gt;Note the terms "Mock" and "Stub" instead of DynamicMock and Stub. This is to be more in line with &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;popular test double terminology&lt;/a&gt; which carries the benefit of being more intention revealing.  Mocks should use Expect with constraints (using Arg&amp;lt;T&amp;gt;) before exercise of the unit-under-test (and VerifyAllExpectations after) or AssertWasCalled and AssertWasNotCalled after the exercise.  Stubs should use the Stub method to return canned data which should be called before exercising the unit-under-test.  Both Stub and Expect can be used on mocks, if you want to mix and match, but it makes the code less clear.  Only Stub can be used on stubs.  All properties on Stubs are defaulted to UsePropertyBehavior as with the old API.  Note that Stubs cannot make the test fail.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Goodbye record-playback&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
The explicit phases of record and playback (and the &lt;span style="font-style: italic;"&gt;using&lt;/span&gt; scopes along with them) is no longer necessary. The idea here is to simplify mocking. The new technique is called &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/24/arrange-act-assert-and-bdd-specifications.aspx"&gt;Arrange, Act, Assert&lt;/a&gt; or AAA for short.&lt;br&gt;
&lt;ul&gt;&lt;li&gt;  Arrange - set up the unit under test&lt;/li&gt;&lt;li&gt;Act - exercise the unit under test, capturing any resulting state&lt;/li&gt;&lt;li&gt;Assert - verify the behavior through assertions&lt;br&gt;
&lt;/li&gt;&lt;/ul&gt;This is a long-winded way of saying exercise the unit under test and then verify the results, effectively making unit tests that use test doubles as succinct as those that don't.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Inline constraints&lt;/span&gt;&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
var view = MockRepository.GenerateMock&amp;lt;IPassiveView&amp;gt;();
// exercise unit-under-test
view.AssertWasCalled(x =&gt; x.SetSaveButtonState(
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;string&amp;gt;.Matches(t =&gt; t.StartsWith("Saved")),
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;bool&amp;gt;.Is.Equal(true),
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;Color&amp;gt;.Is.Anything));
&lt;/pre&gt;or&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
var view = MockRepository.GenerateMock&amp;lt;IPassiveView&amp;gt;();
view.Expect(x =&gt; x.SetSaveButtonState(
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;string&amp;gt;.Matches(t =&gt; t.StartsWith("Saved")),
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;bool&amp;gt;.Is.Equal(true),
&amp;nbsp;&amp;nbsp;&amp;nbsp;Arg&amp;lt;Color&amp;gt;.Is.Anything)).Return(true);
// exercise unit-under-test
view.VerifyAllExpectations();
&lt;/pre&gt;This used to require creating a separate custom delegate for each different signature and then an assertion for each argument within the callback. The new syntax saves a lot of keystrokes.  Note that with assertions no explicit verification is necessary.  If there are expectations, they are to be verified on a per mock basis.  This encourages using few mocks, however if multiple are used, the granularity of verification is smaller and cleaner.  This was available in the previous API but had an uglier syntax before &lt;a href="http://en.wikipedia.org/wiki/Extension_method"&gt;extension methods&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;New event raising syntax&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
I find this new API call particularly useful with the &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;PassiveView&lt;/a&gt; pattern to simulate the firing of UI events.&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
view.Raise(x =&gt; x.SaveClicked += null, view, EventArgs.Empty);
&lt;/pre&gt;Compare with:&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
view.SaveClicked += null;
IEventRaiser buttonClick = LastCall.IgnoreArguments().GetEventRaiser();
buttonClick.Raise(view, EventArgs.Empty);
&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;WhenCalled instead of CallBack&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
WhenCalled is a cleaner replacement for CallBack.  It allows access to all of the arguments and the return value through the invocation object.  It should not be used for validating arguments, use the Arg constraint instead.  It is useful for keeping what is passed in or setting certain state when a particular method is called.  For example:&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
var wasFired = false;
var buttonText = string.Empty;

view.Stub(x =&gt; x.SetSaveButtonText(Arg&amp;lt;string&amp;gt;.Is.Anything))
&amp;nbsp;&amp;nbsp;&amp;nbsp;.WhenCalled(invocation =&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buttonText = (string)invocation.Arguments[0];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wasFired = true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&lt;/pre&gt;The new 3.5 syntax is vastly superior to an already useful API. It is more succinct and expressive, lowering the barrier for entry and making code much more readable for the maintainer of the tests.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-5282519289200042283?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/5282519289200042283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/10/rhino-mocks-35.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5282519289200042283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5282519289200042283'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/10/rhino-mocks-35.html' title='Rhino Mocks 3.5'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4325760646803552980</id><published>2008-09-27T07:38:00.000-07:00</published><updated>2009-04-26T18:42:27.279-07:00</updated><title type='text'>SVN Renames</title><content type='html'>&lt;span&gt;I am a huge fan of &lt;/span&gt;&lt;a  href="http://en.wikipedia.org/wiki/Subversion_%28software%29"&gt;Subversion&lt;/a&gt;&lt;span&gt;.  Maybe it is because the first SCM I used professionally was &lt;/span&gt;&lt;a  href="http://en.wikipedia.org/wiki/StarTeam"&gt;StarTeam&lt;/a&gt;&lt;span&gt;, for which gzip and email provides a better solution, but that is probably a different discussion. &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span&gt;To be honest it is probably because svn provides atomic commits, cheap copies, a good CLI, has a single responsibility, optimistic locking, has tools that provide &lt;/span&gt;&lt;a  href="http://www.visualsvn.com/"&gt;good IDE&lt;/a&gt;&lt;span &gt; and &lt;/span&gt;&lt;a href="http://tortoisesvn.tigris.org/"&gt;file system integration&lt;/a&gt;&lt;span&gt;, is free, and my favorite feature svn:externals which saves immense amount of time when used for binary dependencies. &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span&gt;Every piece of software has its warts, and svn is no different.  While good at branching, historically svn has lacked an easy way to merge.  Version 1.5.0 introduced merge tracking to allow for easier merging. &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span&gt;I was really looking forward to this feature, not because I branch a lot, but when I do, creating pre and post tags is tedious.  I usually take care of this problem with a Ruby script, but a solution that works well with IDE and file system integration would be nice. &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span&gt;As noted by the svn developers themselves, merge tracking is not complete as of 1.5.2, however one bug in particular is a deal breaker for me.  Merge tracking does not play well with &lt;/span&gt;&lt;a href="http://subversion.tigris.org/issues/show_bug.cgi?id=3128"&gt;renaming files&lt;/a&gt;&lt;span&gt;. &lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span&gt;The problem with renames in svn annoys me the most.  In svn renames are not atomic.  Instead they are composed of a copy and delete.  It is unfortunate that the &lt;/span&gt;&lt;a href="http://subversion.tigris.org/issues/show_bug.cgi?id=898"&gt;request&lt;/a&gt;&lt;span&gt; for fixing this problem early was dismissed.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;At this point, most developers are probably saying, svn is open source, go check it out and fix it yourself.  Well I did check out the svn code and I looked in to fixing it.  But between the complexity of the change (it requires a change in the schema) and my rusty C skills, I don't think I have much of a shot of pulling it off.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;So this is a call to the svn developers out there.  Please fix the rename problem and the possibly related merge tracking problem soon.  I rename classes and subsequently files frequently and while the lack of atomicity normally has not gotten in the way, it is a roadblock to adopting the 1.5.x line and subsequently taking advantage of merge tracking.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4325760646803552980?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4325760646803552980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/09/svn-renames.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4325760646803552980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4325760646803552980'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/09/svn-renames.html' title='SVN Renames'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-5942513284766410443</id><published>2008-09-20T08:22:00.001-07:00</published><updated>2009-04-26T18:41:43.661-07:00</updated><title type='text'>Agile -&gt; Lean -&gt; Feedback</title><content type='html'>&lt;span &gt;A colleague of mine recently lampooned the Agile (proper) movement.  The explanation behind his iconoclasm was eye-opening.  In his presentation he listed a set of practices that our group considered Agile such as continuous integration, unit testing, acceptance testing, separation of concerns, discouraging singletons, sprints, stories, etc.  Right next to this list he displayed the &lt;/span&gt;&lt;a  href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt;&lt;span &gt;.  There was a serious disconnect.  Not so much that the lists conflicted, as much as the Agile Manifesto is wildly open to interpretation.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;While certainly a step forward when it originated, Agile has become a brand name in the development community, and after the aforementioned presentation, I am not sure if it is meaningful in and of itself.  Agile has become the software equivalent of the &lt;/span&gt;&lt;a  href="http://en.wikipedia.org/wiki/Interstate_commerce_clause"&gt;Interstate Commerce Clause&lt;/a&gt;&lt;span &gt;.  Unfortunately due to its popularity and nebulous definition, Agile is sometimes used to label any practice that an advocate finds desirable.  Opponents are then often written off for attacking an Agile practice, instead of on the merits of the actual criticism.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;In an effort to move back to analytical review, instead of emotional attacks by &lt;/span&gt;&lt;a  href="http://www.amazon.com/True-Believer-Thoughts-Movements-Perennial/dp/0060505915/ref=pd_bbs_sr_3?ie=UTF8&amp;amp;s=books&amp;amp;qid=1221925818&amp;amp;sr=1-3"&gt;True Believers&lt;/a&gt;&lt;span &gt;, I looked for a new label to use in place of Agile that is more descriptive of my favorite practices.  &lt;/span&gt;&lt;a  href="http://en.wikipedia.org/wiki/Lean_software_development"&gt;Lean&lt;/a&gt;&lt;span &gt; is a newer label adopted from Toyota manufacturing that comes closer to getting the job done.  Waste is the ultimate evil and continuous monitoring and elimination of waste is paramount to Lean development.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;Like most attempts to make parallels between traditional engineering disciplines and software development, I think Lean also comes up short.  This is due to the significantly higher level of complexity of software and the subsequent organic/iterative process that is required to develop it.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;After examination of the practices listed above that I find most useful, I think "shortening the  feedback loop" is a better mantra.  Pair programming introduces code inspection as the code is written.  Unit tests give the developer design and correctness feedback as the tests are written, and maintainers feedback when they break current functionality.  Continuous integration lets the developer know as soon as possible that the build does not compile, the tests do not pass, or a metric has breached a threshold.  Stand-ups and retrospectives find impediments early and provide a means to fix them.  Sprints and stories give the stakeholders feedback on what they thought they asked for, and how long it will take to finish.&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span &gt;"Shortening the feedback loop" is a much more intention revealing goal than "Agile".  It disarms some of the religious fervor of modern software practices, clarifies what is useful, and gives helpful practices a more analytical base on which to stand.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-5942513284766410443?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/5942513284766410443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/09/agile-lean-feedback.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5942513284766410443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/5942513284766410443'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/09/agile-lean-feedback.html' title='Agile -&gt; Lean -&gt; Feedback'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-4903336134051363937</id><published>2008-08-24T10:09:00.000-07:00</published><updated>2009-04-26T18:40:11.876-07:00</updated><title type='text'>History Is Written By The Victors</title><content type='html'>&lt;span   &gt;Every once in a while, the software field makes a wrong turn.  One of these decisions was &lt;a href="http://en.wikipedia.org/wiki/Mutual_exclusion"&gt;mutual exclusion&lt;/a&gt; over &lt;a href="http://en.wikipedia.org/wiki/Message_passing"&gt;message passing&lt;/a&gt; for concurrency.  I contend another is &lt;a href="http://en.wikipedia.org/wiki/C%2B%2B"&gt;C++&lt;/a&gt; over &lt;a href="http://en.wikipedia.org/wiki/Obj-c"&gt;Obj-C&lt;/a&gt;.  C++ is taught in universities and &lt;/span&gt;&lt;span   &gt;is arguably the de facto general programming language in the field.  &lt;/span&gt;&lt;span   &gt;Obj-C is used by Apple.  I always found it strange that Apple, during its scariest period, decided to go with the unpopular Obj-C over the very popular C++ as the language of choice on its brand new platform.  It turns out this decision was made at &lt;a href="http://en.wikipedia.org/wiki/NeXT"&gt;NeXT&lt;/a&gt;, the company who wrote the predecessor to OS X.  But why did NexT choose Obj-C over C++?  Maybe they made the right decision...&lt;br&gt;
&lt;br&gt;
What are the benefits of Obj-C over C++?  The primary reason is that Obj-C is a &lt;span style="font-weight: bold;"&gt;simple&lt;/span&gt; extension to C, a language that is also simple.  C++ is however far from simple.  C can be picked up in a &lt;a href="http://www.amazon.com/Programming-Language-Prentice-Hall-Software/dp/0131103628/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217988312&amp;amp;sr=1-1"&gt;weekend&lt;/a&gt;.  Mastery of the arcane C++ requires no less &lt;a href="http://www.amazon.com/C-Programming-Language-Special-3rd/dp/0201700735/ref=pd_bbs_sr_3?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217988187&amp;amp;sr=8-3"&gt;than&lt;/a&gt; &lt;a href="http://www.amazon.com/C-Standard-Library-Tutorial-Reference/dp/0201379260/ref=pd_bbs_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217988215&amp;amp;sr=1-1"&gt;all&lt;/a&gt; &lt;a href="http://www.amazon.com/Effective-Specific-Addison-Wesley-Professional-Computing/dp/0321334876/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217988240&amp;amp;sr=1-1"&gt;of&lt;/a&gt; &lt;a href="http://www.amazon.com/Template-Metaprogramming-Concepts-Techniques-Depth/dp/0321227255/ref=pd_bbs_sr_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217988257&amp;amp;sr=1-2"&gt;these&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
The designers of Obj-C also made some design decisions that are superior to those of C++.  Obj-C does not allow &lt;a href="http://en.wikipedia.org/wiki/Multiple_inheritance"&gt;multiple inheritance&lt;/a&gt; or operator overloading and has &lt;a href="http://en.wikipedia.org/wiki/Dynamic_typing#Dynamic_typing"&gt;dynamic typing&lt;/a&gt;.  It also has categories (like extension methods in C#), protocols (like interfaces in Java/C#), and reflection.  Reflection is almost indispensible for dependency injection, test discovery, and UI development.&lt;br&gt;
&lt;br&gt;
To boot, Obj-C 2.0 allows for optional &lt;a href="http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29"&gt;garbage collection&lt;/a&gt;, although this is on the C++ road map as well.&lt;br&gt;
&lt;br&gt;
However, as usual, Obj-C is not perfect.  Obj-C lacks namespaces entirely.  In fact most classes start with NS, such as NSObject, which stands for NexTStep to obviate the need for namespaces.  Another oddity is that there is no private modifier, only public and protected, making the &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open-Closed Principle&lt;/a&gt; difficult.&lt;br&gt;
&lt;br&gt;
Perhaps a more modern question than Obj-C vs. C++ is Obj-C vs. &lt;a href="http://en.wikipedia.org/wiki/Java_%28programming_language%29"&gt;Java&lt;/a&gt;.  Java is a completely managed language, eliminating the common security issue of buffer overflows.  Also, Java is &lt;a href="http://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;JIT&lt;/a&gt;ed via a &lt;a href="http://en.wikipedia.org/wiki/Virtual_machine"&gt;virtual machine&lt;/a&gt;, allowing for both cross platform execution and run-time optimization.  Obj-C being an extension of C provides neither of these benefits.  However what Obj-C does provide is the potential speed of C (when C is actually faster), but with abstraction available when desired.  Garbage collection is optional, dynamic typing is available, but at the same time the range checking of managed languages is not mandatory, and one has access to libraries and hardware interfaces (like &lt;a href="http://en.wikipedia.org/wiki/OpenCL"&gt;OpenCL&lt;/a&gt;) written in C without having to pay the cost of language interop.&lt;br&gt;
&lt;br&gt;
If you write Obj-C applications for the Mac, you also gain all of the benefits of the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_%28API%29"&gt;Cocoa&lt;/a&gt; API.  This gives you access to &lt;a href="http://en.wikipedia.org/wiki/Core_Animation"&gt;Core Animation&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Core_Image"&gt;Core Image&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Core_Video"&gt;Core Video&lt;/a&gt; an&lt;/span&gt;&lt;span   &gt;d a framework that all but mandates &lt;a href="http://en.wikipedia.org/wiki/Model_View_Presenter"&gt;model-view separation&lt;/a&gt; unlike some &lt;a href="http://en.wikipedia.org/wiki/Winforms"&gt;others&lt;/a&gt;.  With Cocoa, cutting edge UI development is possible with Obj-C.&lt;br&gt;
&lt;br&gt;
Should you consider Obj-C over C++?  The gcc compiler supports Obj-C, so you aren't restricted to the Mac platform, though you won't have access to Cocoa (though GNUStep is available).  Also many of my favorite tools, such as an xUnit framework, are not available in Obj-C.  The switch is certainly worth considering though, and with the Mac platform doing so well I anticipate the Obj-C community growing.&lt;br&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-4903336134051363937?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/4903336134051363937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/08/history-is-written-by-victors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4903336134051363937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/4903336134051363937'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/08/history-is-written-by-victors.html' title='History Is Written By The Victors'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-7762164356818682793</id><published>2008-08-07T11:31:00.001-07:00</published><updated>2009-04-26T18:39:24.285-07:00</updated><title type='text'>The B Team</title><content type='html'>&lt;span&gt;Jay Fields, in a recent post titled &lt;/span&gt;&lt;span&gt;&lt;a href="http://blog.jayfields.com/2008/08/elephant-in-server-room.html"&gt;Elephant in the Server Room&lt;/a&gt;, stated that 50% of software developers should find a different line of work.  While this may sound elitist, as &lt;a href="http://www.anexperimentinscotch.com/?p=471"&gt;some&lt;/a&gt; have pointed out, I think Jay's post has merit.  The reason is that the spectrum of talent in software development is very wide.  Robert Glass even attempted to quantify it:&lt;br&gt;
&lt;/span&gt;&lt;span&gt;&lt;br&gt;
"The best programmers are up to 28 times better than the worst programmers, according to 'individual differences' research.  Given that their pay is never commensurate, they are the biggest bargains in the software field."&lt;br&gt;
&lt;br&gt;
&lt;span style="font-style: italic;"&gt;- Robert Glass, Facts and Fallacies of Software Engineering&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
28 times.  That is over an order of magnitude.  Professionally, I have only worked as a software developer, but I find it hard to believe that such a difference exists in other fields.  For instance, how many other professions have a website dedicated to pointing out just how bad some &lt;a href="http://thedailywtf.com/"&gt;coworkers are&lt;/a&gt;?&lt;br&gt;
&lt;br&gt;
For added effect, here is an anecdote I experienced myself with a former coworker:&lt;br&gt;
&lt;br&gt;
I worked with a developer named John (name changed to protect the guilty).  John had a favorite interview question he would ask candidates:&lt;br&gt;
&lt;br&gt;
"How do you reduce the number of buckets in a hash table?"&lt;br&gt;
&lt;br&gt;
Now most of us that passed our sophomore year in college know that this is a silly question.  However John insisted that reducing the number of buckets in a hash table "made it faster."  It did.  Let me explain how.  John was trying to hash up to 10,000 objects each with a unique number from 1 - 10,000.  Most of us would stop right here and just use an array in order to gain constant access.  John however decided he needed a hash table.  He noticed hashing all of these objects was very expensive.  Instead of realizing he was breaking the load factor and initial capacity and adjusting these accordingly in the constructor, he decided to override GetHashCode() as follows:&lt;br&gt;
&lt;pre name="code" class="csharp"&gt;
public override int GetHashCode()
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;return base.GetHashCode()%256;
}&lt;/pre&gt;
So basically he got 10,000 entries to collide over and over again on the first 256 buckets, thus providing O(n/256) or O(n).  Not quite the O(1) hash tables usually provide.  Notice he even used a non-prime number, the worst numerical characteristic for the number of buckets in a hash table.&lt;br&gt;
&lt;br&gt;
Upon pressing John about why his "optimization" "worked" he replied "I do not know Microsoft's implementation."  He was &lt;span style="font-style: italic;"&gt;Programming by Accident &lt;/span&gt;and didn't even know how a hash table worked.  We almost lost a good candidate due to this bogus question.  Additionally, even after the concept of hash tables was explained to John, his "optimization" was still found in code a year later.&lt;br&gt;
&lt;br&gt;
Unfortunately, as the DailyWTF shows, this is a common occurrence.  More importantly this lowers the morale of the developers you actually want to keep around.  Bruce Webster talks about it in &lt;a href="http://brucefwebster.com/2008/04/11/the-wetware-crisis-the-dead-sea-effect/"&gt;The Dead Sea Effect&lt;/a&gt;&lt;/span&gt;&lt;span&gt;.&lt;br&gt;
&lt;br&gt;
The lowering of morale is not limited to software.  Jim Collins attributes the loss of morale to an increase in bureaucracy that is necessary to manage the less competent.&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span id="z8yx8"&gt;"Most companies build their bureaucratic rules to manage the small percentage of wrong people on the bus, which in turn drives away the right people on the bus, which then increases the percentage of wrong people on the bus, which increases the need for more bureaucracy to compensate for the incompetence and lack of discipline, which then further drives the right people away."&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="font-style: italic;"&gt;- Jim Collins, author of Good to Great&lt;/span&gt;&lt;span&gt;&lt;br&gt;
&lt;br&gt;
The gap in talent in software is vast and Jay is not the first to point this out.  Helping some of the lower tiers find new employment might help the industry advance quicker and make the lives of the talented less stressful.  &lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-7762164356818682793?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/7762164356818682793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/08/b-team.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7762164356818682793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/7762164356818682793'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/08/b-team.html' title='The B Team'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-6909492008008062621</id><published>2008-08-05T19:14:00.001-07:00</published><updated>2009-04-26T18:37:10.835-07:00</updated><title type='text'>Avoid Singletons</title><content type='html'>&lt;span  &gt;In part II of the "avoid" series, I am going to discuss the Singleton.  Singleton is not a pattern, it is an anti-pattern.  Singleton is the modern equivalent of global methods/variables in C/C++.  It is diametrically opposed to maintainability because it introduces a strong coupling between classes, the very same problem that &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;IoC&lt;/a&gt; does an excellent job of solving.  For all the good the Gang of Four did with their canonical patterns book, they really shat the bed with the Singleton pattern.&lt;br&gt;
&lt;br&gt;
By Singleton I mean the kind with a static GetInstance() method.  My favorite part of interviews is when the candidate thinks they are being impressive by letting me know the double locking gotcha involved with the GetInstance() method.  In reality they have simply notified me that they write code that I would not want to maintain. An acceptable way to use Singletons is to remove the static GetInstance() method, and instead inject the class with an IoC container.  By using an IoC container, one can still retain singleness while eliminating all the problems with the classic implementation of the Singleton.&lt;br&gt;
&lt;br&gt;
Please if you write code, stop using this "pattern".  Tell your coworkers the same.&lt;br&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-6909492008008062621?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/6909492008008062621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/08/avoid-singletons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6909492008008062621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6909492008008062621'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/08/avoid-singletons.html' title='Avoid Singletons'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-3078584137564733770</id><published>2008-07-24T12:04:00.000-07:00</published><updated>2009-04-26T18:36:23.114-07:00</updated><title type='text'>Avoid Inheritance</title><content type='html'>&lt;span&gt;There are three classic properties of object orientation.  Encapsulation, inheritance, and polymorphism.  At least this is what was drilled in to my head in school.  Over the last several years, I have strived to use all three to make my code more object-oriented, however inheritance is one that I found was being overused, both by myself and others.  The following passage from &lt;a href="http://www.amazon.com/Practices-Agile-Developer-Pragmatic-Programmers/dp/097451408X/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1217185639&amp;amp;sr=8-1"&gt;Practices of an Agile Developer&lt;/a&gt; really brought to light the problem:&lt;br&gt;
&lt;br&gt;
"When using inheritance, ask yourself whether your derived class is substitutable in place of the base class.  If the answer is no, then ask yourself why you are using inheritance.  If the answer is to reuse code in the base class when developing your new class, then you should probably use composition instead."&lt;br&gt;
&lt;br&gt;
The problem was that I was using inheritance mainly for reuse.  The code I wrote usually passed the 'is-a' test, but rarely would I use the child class via a reference of the parent class's type, known as polymorphic substitutability&lt;/span&gt;&lt;span&gt;.&lt;br&gt;
&lt;br&gt;
I have since avoided inheritance unless polymorphic substitution is desired and found that I now almost never use inheritance.  Composition, or &lt;a href="http://en.wikipedia.org/wiki/Delegation_pattern"&gt;delegation&lt;/a&gt;, usually provides a much better alternative, although in languages without &lt;a href="http://en.wikipedia.org/wiki/Mixins"&gt;mixins&lt;/a&gt; (like Ruby), it requires more code.  Note that mixins in Ruby (or &lt;a href="http://en.wikipedia.org/wiki/C_Sharp_%28programming_language%29#Extension_methods"&gt;Extension Methods&lt;/a&gt; in C#) do not completely solve the problem as they cannot contain state themselves.  I prefer maintainability above code brevity, so for me the choice is easy.  If you use a tool like ReSharper (which includes a 'delegate-to' shortcut) the typing overhead is negligible. &lt;br&gt;
&lt;br&gt;
To be clear inheritance does not include interface implementation.  Java separates these two concepts by using two separate keywords: 'extends' for inheriting from a class, and 'implements' for implementing an interface.  In C# both words are replaced by the less expressive ':' but interfaces by convention start with an 'I'.  Both Java and C# use separate 'interface' and 'class' keywords and allow different behavior for each (multiple vs. single).&lt;br&gt;
&lt;br&gt;
C++ however is the worst offender.  It lacks a convention for interfaces, it lacks separate syntax for implementing vs. extending, and most importantly it&lt;/span&gt;&lt;span&gt; lacks different keywords for interfaces and classes.&lt;/span&gt;&lt;span&gt;  I conjecture that this has lead some C++ developers, myself formerly included, to not realize that extending a class and implementing an interface have vastly different maintenance implications.  By not treating interfaces and classes separately, it also required the inclusion of multiple inheritance and other warts such as virtual inheritance that would have been otherwise unnecessary.  C++ does allow for private inheritance, which provides for reuse without being an 'is-a' of the parent, but I fail to see how this is superior to delegation.  Delegation at least provides some explicit scoping.&lt;br&gt;
&lt;br&gt;
So why does improper use of inheritance lead to less maintainable code?  The reason is that inheritance works against encapsulation.  Even if the &lt;a href="http://en.wikipedia.org/wiki/Open_Closed_Principle"&gt;Open-Closed Principle&lt;/a&gt; is closely followed the child class is strongly coupled to the parent class.  This makes testing the child class in isolation from the parent class impossible in most languages.  If the maintainer of the child code is not working closely with the maintainer of the parent code, the child code is now strongly coupled to the whims of the parent implementation.  None of this is necessary with delegation (if the delegated-to-class is &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;injected&lt;/a&gt;).  Protected methods make this worse.  These are special extension points that are not exposed to the outside world, only to child classes.  Often times the &lt;a href="http://en.wikipedia.org/wiki/Template_method"&gt;Template Method&lt;/a&gt; pattern is used here where a parent method calls abstract child methods to complete the behavior of the parent class.  This pattern looks very slick as it is quite DRY, but it leads to improper intimacy of objects creating problems when either class is changed or needs testing.  A better solution to Template Method is to inject the former child class in to the former parent class.  The former parent class can then call the former child class when it needs a specialized implementation, but is only bound to the former child's interface.&lt;br&gt;
&lt;br&gt;
Polymorphism, through interface implementation, is very powerful.  It implies that the class provides a "service".  Having a class reference another class through an interface decouples them, allowing the referencing class to know very little about the referenced class.  In fact the referenced class may be entirely replaced without the referencing class being changed at all.  Depending on interfaces instead of classes allows for decoupled, maintainable code.&lt;br&gt;
&lt;br&gt;
So why was such an easily misused and rarely helpful feature considered one of the pillars of object oriented programming?  I would have preferred mixins or dynamic typing over inheritance.  The less popular &lt;a href="http://en.wikipedia.org/wiki/Obj-c"&gt;Obj-C&lt;/a&gt; has inheritance, but only single, and the language includes dynamic typing.  In fact in dynamically typed languages, where polymorphic substitutability is free, inheritance is almost completely inappropriate.  However you will still find &lt;a href="http://en.wikipedia.org/wiki/ActiveRecord_%28Rails%29"&gt;it&lt;/a&gt; being used by respectable developers.&lt;br&gt;
&lt;/span&gt;&lt;span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-3078584137564733770?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/3078584137564733770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/07/avoid-inheritance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/3078584137564733770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/3078584137564733770'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/07/avoid-inheritance.html' title='Avoid Inheritance'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-3124703239862055668</id><published>2008-07-06T11:38:00.000-07:00</published><updated>2009-04-26T18:34:47.236-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='habituation'/><category scheme='http://www.blogger.com/atom/ns#' term='modality'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><title type='text'>UI Dos and Don'ts</title><content type='html'>&lt;span &gt;For some reason developers think it is difficult to create decent User Interfaces.  &lt;/span&gt;&lt;span &gt;Their difficulty is evident in the high percentage of UIs found in the wild that are difficult to use.    &lt;/span&gt;&lt;span &gt;It is thought that a level of artistry and aesthetic sense is required.  It is true that this helps, but it is not required.  In fact there are a few simple rules I have gleaned from my favorite two UI books: &lt;a href="http://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1215369927&amp;amp;sr=8-1"&gt;Humane Interfaces by Jef Raskin&lt;/a&gt; and &lt;a href="http://www.amazon.com/Designing-Interfaces-Patterns-Effective-Interaction/dp/0596008031/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1215369957&amp;amp;sr=1-1"&gt;Designing Interfaces by Jennifer Tidwell&lt;/a&gt; that will get a UI most of the way there.&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;Avoid modality&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qKmAgg-mh2A/SHdzrUhAZYI/AAAAAAAAAEY/ANhgJ4qDosg/s1600-h/modal2.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp2.blogger.com/_qKmAgg-mh2A/SHdzrUhAZYI/AAAAAAAAAEY/ANhgJ4qDosg/s320/modal2.jpg" alt="" id="BLOGGER_PHOTO_ID_5221769481038095746" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;This is the classic message box.  The problem with message boxes is that they are informational only.  There is no decision to make.  All the user can do is read the message and dismiss the box.  Modal dialog boxes interrupt the user work flow, and cause a user "context switch".  Instead put the message on the status bar, or in the above case, it would have been better to outline the recipient textbox in red with the error message underneath.  &lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;A similar case is the "Are you sure?"  "Are you really sure?"  "Absolutely?" modal window.  Yes I am fucking sure.  That is why I clicked the original action in the first place.  Ok so maybe I didn't.  Maybe I accidently used a short cut key to close the program and I haven't saved a document yet.  If the action is undoable, there is a solution.  Allow undo.  Yes it is more work, but it makes a better UI.  &lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;div style="text-align: center; font-family: georgia;"&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_qKmAgg-mh2A/SHdzk8KgceI/AAAAAAAAAEQ/W_yu5KCXNr0/s1600-h/modal1.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 237px; height: 201px;" src="http://bp0.blogger.com/_qKmAgg-mh2A/SHdzk8KgceI/AAAAAAAAAEQ/W_yu5KCXNr0/s320/modal1.jpg" alt="" id="BLOGGER_PHOTO_ID_5221769371422061026" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: center; font-family: georgia;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_qKmAgg-mh2A/SH6gkQGytTI/AAAAAAAAAF4/otI7Mtkacoc/s1600-h/not-modal.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_qKmAgg-mh2A/SH6gkQGytTI/AAAAAAAAAF4/otI7Mtkacoc/s400/not-modal.jpg" alt="" id="BLOGGER_PHOTO_ID_5223789162455545138" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span&gt;&lt;br&gt;
&lt;br&gt;
Here is an example of two UIs used to find text.  The top one pops up a new window over the text the user is currently reading again interrupting their train of thought.  The bottom instead creates a narrow area that lines up along the bottom of the text, probably away from where the user is rea&lt;/span&gt;ding.  It then &lt;/span&gt;&lt;span style="font-size:100%;"&gt;highlights the text where the user was concentrating.  The bottom example is superior because it doesn't break up the user work flow by avoiding modality.&lt;br&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;User data is sacred&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qKmAgg-mh2A/SHd0JaKEoVI/AAAAAAAAAEw/bbGK7TvClmk/s1600-h/not-sacred1.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 276px; height: 141px;" src="http://bp2.blogger.com/_qKmAgg-mh2A/SHd0JaKEoVI/AAAAAAAAAEw/bbGK7TvClmk/s320/not-sacred1.jpg" alt="" id="BLOGGER_PHOTO_ID_5221769997948592466" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;div style="text-align: left; font-family: georgia;"&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qKmAgg-mh2A/SHdz8cXgInI/AAAAAAAAAEo/yFjMJcTjbcc/s1600-h/not-sacred2.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 280px; height: 141px;" src="http://bp2.blogger.com/_qKmAgg-mh2A/SHdz8cXgInI/AAAAAAAAAEo/yFjMJcTjbcc/s320/not-sacred2.jpg" alt="" id="BLOGGER_PHOTO_ID_5221769775203492466" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span &gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;br&gt;
&lt;br&gt;
Often times error correction is a necessary part of the user interface.  However, even if the user inputs invalid data, one should not throw it out like the example above.  The user may have worked hard for that data, or forgot what they typed to upset the software.  Instead leave the data they typed in and mark it as incorrect.  Then as they correct it themselves, unmark the input.  See below.&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qKmAgg-mh2A/SHd0ScF04LI/AAAAAAAAAE4/QR5PvQn0vx8/s1600-h/sacred.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp2.blogger.com/_qKmAgg-mh2A/SHd0ScF04LI/AAAAAAAAAE4/QR5PvQn0vx8/s320/sacred.jpg" alt="" id="BLOGGER_PHOTO_ID_5221770153086476466" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Habituation&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_qKmAgg-mh2A/SHd0j1_Z2tI/AAAAAAAAAFA/Bb21nTJptDw/s1600-h/not-habituation.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 178px; height: 161px;" src="http://bp1.blogger.com/_qKmAgg-mh2A/SHd0j1_Z2tI/AAAAAAAAAFA/Bb21nTJptDw/s320/not-habituation.png" alt="" id="BLOGGER_PHOTO_ID_5221770452096637650" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_qKmAgg-mh2A/SHd04DTTW3I/AAAAAAAAAFI/Lee4B7j_fKI/s1600-h/habituation.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_qKmAgg-mh2A/SHd04DTTW3I/AAAAAAAAAFI/Lee4B7j_fKI/s320/habituation.jpg" alt="" id="BLOGGER_PHOTO_ID_5221770799267142514" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span&gt;Above are two infamous user interface patterns from MS Office.  The first is what was known as a "personalized menu."  These break what is known as habituation or the formation of habits.  This is because the menus change on the user as you use them which lengthens the time before the location of the menu becomes a habit, thus slowing down the user and requiring more thought.&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span&gt;The second example is the improved UI from a habituation standpoint.  The initial reaction by many users to this new UI was poor.  It is because it is radically different from the previ&lt;/span&gt;&lt;/span&gt;&lt;span &gt;&lt;span&gt;ous UI and thus broke habituation.  However, after becoming acquainted with the new interface it is vastly superior as every item is entirely stationary.  There are no more menus and the items never appear over the document.  Also, they are arranged from left to right and top to bottom (the way English is read) in order of prevalence of usage during user testing.  Size of the targets is also an indicator of prevalence of usage during user testing.  After getting used to this new UI, users are significantly more productive.&lt;br&gt;
&lt;br&gt;
Another common way of breaking habituation is overriding common shortcut chords.  For example do not override ctrl-x, &lt;/span&gt;&lt;/span&gt;&lt;span &gt;&lt;span&gt;ctrl-c, or &lt;/span&gt;&lt;/span&gt;&lt;span &gt;&lt;span&gt;ctrl-v&lt;/span&gt;.&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
Hues and tints&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_qKmAgg-mh2A/SHd1G3kT7BI/AAAAAAAAAFQ/on9f2OKb5-4/s1600-h/nothuesandtints.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 286px; height: 141px;" src="http://bp3.blogger.com/_qKmAgg-mh2A/SHd1G3kT7BI/AAAAAAAAAFQ/on9f2OKb5-4/s320/nothuesandtints.jpg" alt="" id="BLOGGER_PHOTO_ID_5221771053815294994" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qKmAgg-mh2A/SHd1PxWmQnI/AAAAAAAAAFY/DH2DIjrEKTY/s1600-h/huesandtints.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 275px; height: 130px;" src="http://bp2.blogger.com/_qKmAgg-mh2A/SHd1PxWmQnI/AAAAAAAAAFY/DH2DIjrEKTY/s320/huesandtints.jpg" alt="" id="BLOGGER_PHOTO_ID_5221771206765986418" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span&gt;&lt;br&gt;
&lt;br&gt;
The example on the left is slightly contrived, but I have seen examples of such software, I just didn't feeling like taking a screen shot at the time.  The idea here is to pick a color or two (a hue) and then vary other UI elements by various tints on those few hues.  The left window picks too many contrasting hues and no tints which c&lt;/span&gt;&lt;/span&gt;&lt;span &gt;&lt;span&gt;auses cognitive dissonance.  Jennifer Tidwell calls this "fruit salad".  It reminds me of early user pages on My Space.&lt;br&gt;
&lt;br&gt;
This may seem to contrast with the suggestion above regarding coloring incorrect fields, but it does not.  High contrast is useful to get the users attention.  But if there are multiple high contrast items, then the value of contrast is lost and all items become distracting and painful to view.&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
Edges and corners&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_qKmAgg-mh2A/SHd2bluVRQI/AAAAAAAAAFg/UB2d1W49X-c/s1600-h/cornersandedges.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_qKmAgg-mh2A/SHd2bluVRQI/AAAAAAAAAFg/UB2d1W49X-c/s320/cornersandedges.jpg" alt="" id="BLOGGER_PHOTO_ID_5221772509314368770" border="0" /&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;This may seem like a given, but I see many "non-UI" developers forget to properly line up and anchor elements.  Make sure to take the time to line all of the widgets up, and create areas of interest that resemble symmetric, simple shapes (such as rectangles).  Most UI builders help the designer with this task.  Also make sure to eliminate excessive blank space.  Make sure the widgets span almost the entire control, with small equal margins on all sides.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Maintain user focus&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;div style="text-align: left; font-family: georgia;"&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_qKmAgg-mh2A/SIza59imULI/AAAAAAAAAGA/S1cW9L0Hois/s1600-h/okCancel.png"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_qKmAgg-mh2A/SIza59imULI/AAAAAAAAAGA/S1cW9L0Hois/s400/okCancel.png" alt="" id="BLOGGER_PHOTO_ID_5227793956777382066" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_qKmAgg-mh2A/SIza6M_SztI/AAAAAAAAAGI/GIqZjKP9GBk/s1600-h/saveOrNot.png"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_qKmAgg-mh2A/SIza6M_SztI/AAAAAAAAAGI/GIqZjKP9GBk/s400/saveOrNot.png" alt="" id="BLOGGER_PHOTO_ID_5227793960924270290" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span &gt;&lt;br&gt;
&lt;/span&gt;&lt;span &gt;Above there are two windows that are nearly the same.  They differ in how the buttons are labeled.  The first has the usual OK and Cancel, the latter actually describes what the buttons do.  The latter is superior because the user is performing the following steps: (1) reading the message to figure out why the software needs the user to make a decision, (2) moves attention to the buttons to make the decision.  By putting descriptive labels on the buttons, you allow the user to remain focused where they are clicking, instead of rereading the message to figure out what they are OKing or Canceling.&lt;br&gt;
&lt;br&gt;
Another example is the deeply nested windows required to configure wireless networking in Windows XP.  It is possible to get 5 to 7 windows deep and at times making changes at all of these levels.  This requires the user to jump between areas of focus to get a full glimpse of the configuration.  Not a good idea.  &lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
This list is by no means exhaustive, but touches on the majority of UI faux paus I have encountered in the wild.  If you are too lazy, cheap, or busy to read the references above, following these few rules will get a UI most of the way there.&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-3124703239862055668?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/3124703239862055668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/07/ui-dos-and-donts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/3124703239862055668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/3124703239862055668'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/07/ui-dos-and-donts.html' title='UI Dos and Don&apos;ts'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_qKmAgg-mh2A/SHdzrUhAZYI/AAAAAAAAAEY/ANhgJ4qDosg/s72-c/modal2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6517561437765469293.post-6295466964366235543</id><published>2008-07-06T10:49:00.000-07:00</published><updated>2009-04-26T18:32:02.328-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='separation of concerns'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><category scheme='http://www.blogger.com/atom/ns#' term='maintenance'/><category scheme='http://www.blogger.com/atom/ns#' term='dry'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><title type='text'>Maintenance First</title><content type='html'>"Maintenance typically consumes 40 to 80 percent (average, 60 percent) of software costs. Therefore, it is probably the most important life cycle phase of software."&lt;br&gt;
&lt;br&gt;
&lt;span style="font-style: italic;"&gt;- Robert L. Glass, &lt;a href="http://www.amazon.com/Facts-Fallacies-Software-Engineering-Development/dp/0321117425/ref=pd_bbs_sr_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1215366919&amp;amp;sr=1-2"&gt;Facts and Fallacies of Software Engineering&lt;/a&gt;&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
All desirable qualities of software flow from maintainability. If code is maintainable, it is easy for other developers to read, it is testable, it is easy to optimize, it is easy to add features, it is easy to remove features, and it is easy to fix bugs. This is why writing maintainable code is so important. It maximizes software value, as it allows for leverage of an attribute unique and powerful to software: it is malleable. This allows software to be an asset or investment, because the code is not dependent on its original author(s). This is why unmaintainable software is said to have high amounts of "debt". This cannot be stressed enough to managers. If they view software as an investment, then paying up for good developers makes economic sense. It is cheaper to pay fewer developers to maintain an investment than to pay more developers to write new shanties from scratch when the previous shanty collapses.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Readable&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
Many engineers and developers think that writing prose or documentation is not their responsibility. This could not be more false with software. Intention revealing code, with succinct, descriptive, variable and method names is critical for maintainability. Rules that apply to natural languages apply to programming languages as well. Large classes and methods are analogous to run-on sentences and paragraphs. Keeping language constructs small makes them easier for the human brain to digest. For a book on writing succinctly and clearly, I have found no better reference than &lt;a href="http://www.amazon.com/Elements-Style-William-Strunk/dp/0205313426/ref=pd_bbs_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1215366867&amp;amp;sr=8-2"&gt;Strunk and White's Element's of Style&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
This is part of the discussion where some developers talk about commenting code. I want to make something clear, excessive code commenting does not make code easy to read. In fact excessive commenting is a code smell. The code is probably peppered with comments as an inferior substitute for refactoring the code into smaller more readable classes and methods. Also comments can violate the DRY principle because they tend to get out of sync with the code itself. Comments have two legitimate purposes. First, to explain a piece of code that is non-intuitive, probably due to someone else's poor API. Second, &lt;a href="http://www.martinfowler.com/bliki/PublishedInterface.htmlhttp://www.martinfowler.com/bliki/PublishedInterface.html"&gt;published&lt;/a&gt; methods and classes should be commented using baked-in comments so they are available directly within a code-sensing editor.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Testable&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
I am a huge fan of unit testing. Unit tests enforce &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separation of concerns&lt;/a&gt;. Unit tests are &lt;a href="http://en.wikipedia.org/wiki/DRY"&gt;DRY&lt;/a&gt; documentation. Unit tests prevent whack-a-mole bug fixing when changing code. Unit tests keep code in a functional state as the code is written. To get the best results from unit testing, use a continuous build that runs your tests, write the tests as early as possible, and make sure the implementer of the code-under-test is the implementer of the tests themselves.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Easy to Optimize&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
C.A.R. Hoare (or Knuth depending on &lt;a href="http://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/"&gt;whom you ask&lt;/a&gt;) famously said premature optimization is the root of all evil. This is right up there with Glass's quote on maintenance. Start a large code base with nothing but optimization in mind and you will end up with an unmaintainable, sub-optimal mess when you are done. This is because optimization is best done &lt;a href="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori_%28philosophy%29"&gt;a posteriori&lt;/a&gt; instead of &lt;a href="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori_%28philosophy%29"&gt;a priori&lt;/a&gt;. It is difficult to determine in advance which parts of the code will be called most frequently or which methods will be most expensive. These measurements can be taken via monitoring and profiling after the code is written. An easily changeable (i.e. maintainable) piece of code can then be modified to remove the bottlenecks that are empirically discovered.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Add Features&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
Adding features can require changes to existing code because the original code was not written to be used in the new manner. Readable, well tested code, that separates concerns, removes the need to shoe-horn new code where it doesn't fit. The old code can be changed with impunity, without worry about unintended side effects, so that the new code fits nicely.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Remove Features&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
My favorite part of software development is deleting code. Whether it be a feature that is no longer needed, extra operations that proved unnecessary, an uncalled method flagged by static analysis, or even a whole project that was ill-conceived, less code is always better. Less code means less bugs, less to maintain, etc. Don't take this to mean reducing code to the fewest lines possible. Do not sacrifice readability to reduce code, but remove all code that is unnecessary. And do not leave old code as "commented-out". Delete it. If you want it back, use source control. Not using source control? Stop coding.&lt;br&gt;
&lt;br&gt;
&lt;span style="font-weight: bold;"&gt;Fix Bugs&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
When code is easy to read it is easy to find errors. It is difficult to tell if obfuscated code is doing what it is supposed to, let alone doing something it is not. Code with small classes, and small methods, that reads like natural language, and strongly separates concerns is code in which it is easy to isolate bugs. Unit testing is also useful in this regard. Before modifying any code to fix a bug, write a unit test to expose the bug. Then fix the code to make the test pass. Combined with a continuous build, that bug will not crop up again, which commonly happens when trying to fix other bugs or adding features to highly coupled code.&lt;br&gt;
&lt;br&gt;
Here is another quote from the author of my favorite mocking framework, &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt;:&lt;br&gt;
&lt;br&gt;
"If you have an environment that has friction in it, there is an incentive for the developers to subvert the design in order to produce a quick fix or hack a solution to solve a problem. Creating a zero friction environment will produce a system where there is no incentive to corrupt the design, the easiest thing to do is the right thing to do. By reducing the friction in the environment, you increase the system maintainability."&lt;br&gt;
&lt;br&gt;
&lt;span style="font-style: italic;"&gt;- Oren Eini, creator of RhinoMocks, &lt;/span&gt;&lt;a style="font-style: italic;" href="http://www.ayende.com/Blog/archive/2008/05/16/Zero-Friction--Maintainability.aspx"&gt;Zero Friction &amp;amp; Maintainability&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
I wanted to talk about software maintenance in my first post to make clear the essence of my perspective on software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6517561437765469293-6295466964366235543?l=grahamnash.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grahamnash.blogspot.com/feeds/6295466964366235543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grahamnash.blogspot.com/2008/07/maintenance-first.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6295466964366235543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6517561437765469293/posts/default/6295466964366235543'/><link rel='alternate' type='text/html' href='http://grahamnash.blogspot.com/2008/07/maintenance-first.html' title='Maintenance First'/><author><name>gnash</name><uri>http://www.blogger.com/profile/12702643427008702523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
