<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CallContext</title>
	<atom:link href="http://www.callcontext.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.callcontext.com</link>
	<description>good software is no accident</description>
	<lastBuildDate>Thu, 19 Apr 2012 07:01:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>NHibernate session management in the WCF Web API</title>
		<link>http://www.callcontext.com/2011/11/nhibernate-session-management-in-the-wcf-web-api/</link>
		<comments>http://www.callcontext.com/2011/11/nhibernate-session-management-in-the-wcf-web-api/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 05:59:27 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[.NET Development]]></category>
		<category><![CDATA[ninject]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[wcf web api]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=213</guid>
		<description><![CDATA[Update! This post is still wrong (!!), and no longer relevant with the release of the ASP.NET MVC Web API code. I&#8217;ll provide my updated session handler soon. &#160; As the WCF Web API project is a bit of a...]]></description>
			<content:encoded><![CDATA[<address><strong>Update!</strong> This post is still wrong (!!), and no longer relevant with the release of the ASP.NET MVC Web API code. I&#8217;ll provide my updated session handler soon.</address>
<address></address>
<p>&nbsp;<br />
As the WCF Web API project is a bit of a moving target at the moment, it&#8217;s been hard to try and find a sensible way to handle <a title="NHibernate persistence framework" href="http://nhforge.org/Default.aspx" target="_blank">NHibernate</a> sessions for each resource. They key word there is resource.</p>
<p>If you&#8217;ve ever used NHibernate with WCF before, you&#8217;ve probably organised your session management around the <a title="Session per-request" href="http://richarddingwall.name/2010/08/17/one-nhibernate-session-per-wcf-operation-the-easy-way/" target="_blank">per-request </a>model. That starts to break down with WCF Web APIs. You see, you have to consider how OData is consumed. This is where you have a resource operation that returns an <code>IQueryable&lt;T&gt;</code> that is evaluated after the operation returns. This is a really cool thing, but it breaks if you use a per-request style management method, or if you manually open and close the session for each operation. For example:</p>
<pre class="brush: csharp; highlight: [18]; title: ; notranslate">
[ServiceContract]
public class MyResource
{

    private ISessionManager _sessionManager;
    private IWidgetRepository _widgetRepository;

    // You always inject, right?...
    public MyResource(ISessionManager s, IWidgetRepository r)
    {
        _sessionManager = s;
        _widgetRepository = r;
    }

    [WebGet(UriTemplate = &quot;dtos&quot;)
    public IQueryable&lt;MyDTO&gt; GetAllMyDTOs()
    {
        using(_sessionManager.GetSession())
        {
            return _widgetRepository.Query();
        }
    }
}
</pre>
<p>This is bad/wrong/silly. As the response from <code>GetAllMyDTOs</code> isn&#8217;t actually evaluated until <em>after</em> the operation returns, it will fail, as you&#8217;ve disposed the session it&#8217;s linked to.</p>
<p>The other, &#8220;worserer&#8221; way is to just wait until the garbage collector cleans up your session by itself. I shouldn&#8217;t have to explain why that&#8217;s a <strong>monumentally</strong> stupid thing to do.</p>
<p>So, I had a bit of a think about this problem. While there is the option of <a title="Explanation of message handlers and operation handlers" href="http://codebetter.com/glennblock/2011/05/17/message-handlers-vs-operation-handlers-which-one-to-use-2/" target="_blank">message handlers and operation handlers</a>, they still don&#8217;t give you a way of executing some code before <em>and after</em> an operation (to open and close the session). On top of that, operation handlers are asynchronous, so if you&#8217;re being good and binding your session to a <code>ThreadStatic</code> variable, it won&#8217;t be bound to the same thread your operation will actually execute on.</p>
<p>If you&#8217;re using dependency injection to build your resources (which you should), then you&#8217;ve no doubt used the <code>WebApiConfiguration</code> class and created a method on your class to handle the <code>CreateInstance</code> delegate. This method would locate the requested type in your DI container and return the composed instance.</p>
<p>Well, there&#8217;s a corresponding delegate exposed by <code>WebApiConfiguration</code> called <code>ReleaseInstance</code>. It&#8217;s job is to take an instance and get rid of it.</p>
<p>Now we have two methods, fired at each end of a resource&#8217;s life-cycle. The only concern I had is if, somehow, the create/release methods ran on a different thread to the operation. So I stuck a little logging of the thread ID in there and did a couple of tests. Same thread ID all around! Not only that, each subsequent quasi-simultaneous (because I can&#8217;t think of a better way to describe it) resource request utilised a different thread. At least, that&#8217;s the anecdotal evidence I&#8217;ve&#8230; anecdoted. So each resource would have it&#8217;s own session, as each session is bound to a <code>ThreadStatic</code> variable!</p>
<p>So, at the moment, I have a naïve implementation of session management, scoped per resource, that looks like this:</p>
<pre class="brush: csharp; title: ; notranslate">
public class MyWebApi : System.Web.HttpApplication
{
    public void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute(&quot;{resource}.axd/{*pathinfo}&quot;);

        var config = new WebApiConfiguration
                            {
                                EnableTestClient = true,
                                CreateInstance = Create,
                                ReleaseInstance = Release
                            };
        routes.SetDefaultHttpConfiguration(config);

        routes.MapServiceRoute&lt;MyResource&gt;(&quot;myresourceuri&quot;);
    }

    private object Create(Type t, InstanceContext c, HttpRequestMessage r)
    {
        var sm = Injector.Default.Get&lt;ISessionManager&gt;();
        sm.OpenSession();
        return Injector.Default.Get&lt;t&gt;();
    }

    private void Release(InstanceContext c, object i)
    {
        var sm = Injector.Default.Get&lt;ISessionManager&gt;();
        sm.CloseSession();
    }
}
</pre>
<address><strong>Note:</strong> enabling the test client is fine, for <strong>testing</strong>. Make sure you disable it when you release, otherwise nasty people with bad haircuts and no friends will use it as an instructional guide to ruining your API.</address>
<address></address>
<p>&nbsp;</p>
<p>As I said, this is a very simplified chunk of code. I haven&#8217;t load tested it sufficiently (read: at all) to be able to say with any Jobsian sense of confidence that it&#8217;s flawless. But it gives me the result I want at the moment. Until I find something better&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/11/nhibernate-session-management-in-the-wcf-web-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get your WCF Web API DELETE verb working on IIS6</title>
		<link>http://www.callcontext.com/2011/11/how-to-get-your-wcf-web-api-delete-verb-working-on-iis6/</link>
		<comments>http://www.callcontext.com/2011/11/how-to-get-your-wcf-web-api-delete-verb-working-on-iis6/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 04:51:46 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[.NET Development]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[iis6]]></category>
		<category><![CDATA[wcf web api]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=207</guid>
		<description><![CDATA[I&#8217;ve just had to deal with a problem on Windows Server 2003 (IIS 6.0) where my web API decided not to respond to the DELETE verb. Apparently, this is by design. It doesn&#8217;t happen when you&#8217;re in development mode using...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just had to deal with a problem on Windows Server 2003 (IIS 6.0) where my web API decided not to respond to the <code>DELETE</code> verb. Apparently, this is by design.</p>
<p>It doesn&#8217;t happen when you&#8217;re in development mode using the VS web server, so I didn&#8217;t catch it when I was developing. When I went to put it on the test server, deletes would fail. <a title="Fiddler HTTP debugging proxy" href="http://www.fiddler2.com/fiddler2/" target="_blank">Fiddler</a> would report a <code>501 Not Implemented</code> error was returned by the server. I initially thought I&#8217;d messed up the resource mappings, but it wound up being the server configuration.</p>
<p>Your first response might be to head over to the application configuration on the server and simply add the missing verbs to the existing mappings. But WCF web APIs don&#8217;t have a file type, so there&#8217;s no mapping for you to edit!</p>
<p>To fix it, you need to setup a wildcard mapping on the server. A wildcard mapping allows you to specify an ISAPI handler that is run after every other mapping is attempted. It&#8217;s a kind of catch-all; hence the name.</p>
<p>Here&#8217;s how to set up a wildcard mapping:</p>
<ol>
<li>Open the IIS Manager snap-in.</li>
<li>Use the treeview to navigate to the web site or application hosting your API.</li>
<li>Right-click the application and select <strong>Properties</strong>.</li>
<li>On the <strong>Virtual Directory</strong> tab, click the <strong>Configuration</strong> button.</li>
<li>On the <strong>Mappings</strong> tab, click Insert next to the <strong>Wildcard application maps</strong> list.</li>
<li>In the <strong>Executable </strong>text box, enter the path to the aspnet_isapi.dll version that your API is built for.</li>
<li>Click <strong>OK </strong>to close the mapping dialog.</li>
<li>Click <strong>OK </strong>to close the <strong>Application Configuration</strong> dialog.</li>
<li>Click <strong>OK </strong>to close the properties dialog.</li>
<li>Go delete something!</li>
</ol>
<p>It&#8217;s not hard to fix the problem, in the end.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/11/how-to-get-your-wcf-web-api-delete-verb-working-on-iis6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subclassed singleton instance</title>
		<link>http://www.callcontext.com/2011/10/subclassed-singleton-instance/</link>
		<comments>http://www.callcontext.com/2011/10/subclassed-singleton-instance/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 06:30:51 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[.NET Development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ninject]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=193</guid>
		<description><![CDATA[I couldn&#8217;t really think of a good explanatory title for this post, so I guess I&#8217;ll just have to explain. I&#8217;m setting up a dependency injection resolver using NInject, and I&#8217;m trying to centralise the implementation so it can be...]]></description>
			<content:encoded><![CDATA[<p>I couldn&#8217;t really think of a good explanatory title for this post, so I guess I&#8217;ll just have to explain. I&#8217;m setting up a dependency injection resolver using <a title="NInject IoC Container" href="http://ninject.org/" target="_blank">NInject</a>, and I&#8217;m trying to centralise the implementation so it can be reused in the various layers of the application, but I want each application to be able to configure it in isolation of every other layer. I&#8217;m still not quite sure that I&#8217;m explaining what I want correctly, so let me try explaining it this way.</p>
<p>In <code>App.Core</code>. I want to create the <code>InjectorBase</code> class that every injection implementation derives from. Then, for example, in the <code>App.UI</code> I want to create a <code>UserInterfaceInjector</code> that descends from <code>InjectorBase</code>, but I only want the subclass to supply configuration. Then in <code>App.Services</code> I can create a <code>ServicesInjector</code> that also descends from <code>InjectorBase</code>, and again, only supplies configuration.</p>
<p>The next trick to this is, I want the dependency injection to be through a singleton. Yes, yes, <a title="The Evil Singleton...Oooooh" href="http://c2.com/cgi/wiki?SingletonsAreEvil" target="_blank">singletons are evil</a> etc. In this case, it&#8217;s being used for what I consider a correct purpose (as a service locator), and not some sort of global variable hold-all. So, in some random piece of code in <code>App.Services</code>, I want to be able to do something like this:</p>
<pre class="brush: csharp; title: ; notranslate">
public void SomeMethodThatDoesSomethingTo(Some variable)
{
    var aRepository = ServicesInjector.Default.Get&lt;IARepository&gt;();
    aRepository.Add(variable);
}
</pre>
<p>And, conversely, in the App.UI I want to be able to do this:</p>
<pre class="brush: csharp; title: ; notranslate">public void SomeMethodThatLocatesAServiceImplementation()
{
    var aService = UserInterfaceInjector.Default.Get&lt;IAService&gt;();
    aService.DoSomethingMostLikelyAsynchronously();
}
</pre>
<p>It all seems fairly straight forward, yes? Well, it winds up not being too difficult, but one of the first problems you&#8217;ll run into relates to inheritance and the static keyword. Basically, you can&#8217;t. Which actually makes sense if you care to try and understand it. Anything static is of the class, not of an instance of the class. If you create a subclass, it&#8217;s new class, so the static thing doesn&#8217;t follow you. Why do we need the static keyword? The singleton. Here&#8217;s an example (simple) singleton implementation.</p>
<pre class="brush: csharp; title: ; notranslate">
public class MySingleton
{
    private static MySingleton _default;

    public static MySingleton Default
    {
        get { return _default ?? _default = new MySingleton(); }
    }

    public string SayHello()
    {
        return &quot;Hello!&quot;;
    }
}
</pre>
<p>In order to supply a reference to an instance without maintaining that reference in another class, we have to use a static field (to hold the reference) and a static property (to get at the static field).</p>
<p>Where I wanted to take this that was a bit out of the ordinary, is I wanted the singleton in the base class so implementors didn&#8217;t have to think about all that plumbing. This means making the base class abstract (so it can&#8217;t be directly instantiated) and then providing an abstract method that returns a container configuration. Then all the subclasses have to do is inherit from the base class and then provide an implementation of the abstract method.</p>
<p>The next problem is, the configuration method is an abstract method of the base class, and not static, but the point of creation of the class is in a static property get method. How do you call an instance method of a class to obtain configuration you need at creation time without an instance of the class? Well, you can&#8217;t. Now, obviously I&#8217;ve solved this problem, otherwise we&#8217;d be at the end of this post.</p>
<p>The gist of it involves breaking a cardinal rule of C# object creation: Don&#8217;t call virtual methods in a constructor. The reasoning behind this is C# initialisers (initializers for the Americans amongst us) run in order of farthest child back up to the base class, but the constructors run from the base class to the farthest child. <a title="Virtual method calls from constructors = Bad" href="http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor">Here&#8217;s a bit more information</a>. The trick to overcoming the actual problem was to use the <code>Activator</code> class. This involves a bit of genericism of the base class to ensure the child class is being instantiated, which then allows us to call the virtual method with abandon. So the base class now looks like this:</p>
<pre class="brush: csharp; title: ; notranslate">
abstract class BaseClass&lt;T&gt; : IHello where T: IHello
{
    private static IHello _default;
    private readonly string _message = &quot;Hello from the base class.&quot;;

    public static IHello Default
    {
        get { return _default ??
                    (_default = Activator.CreateInstance&lt;T&gt;()); }
    }

    protected BaseClass()
    {
        _message = GetMessage();
    }

    public void SayHello()
    {
        Console.WriteLine(_message);
    }

    public abstract string GetMessage();
}
</pre>
<p>Here&#8217;s <code>IHello</code>, in case you couldn&#8217;t figure it out:</p>
<pre class="brush: csharp; title: ; notranslate">
interface IHello
{
    void SayHello();
}
</pre>
<p>Finally, here&#8217;s how the implementors of the base class look:</p>
<pre class="brush: csharp; title: ; notranslate">
class ChildClass : BaseClass&lt;ChildClass&gt;;
{
    public sealed override string GetMessage()
    {
        return &quot;Hello from the child class.&quot;;
    }
}
</pre>
<p>You can tie all this together in a console application with a bit of this magic:</p>
<pre class="brush: csharp; title: ; notranslate">
class Program
{
    static void Main(string[] args)
    {
        ChildClass.Default.SayHello();
        Console.ReadKey(true);
    }
}
</pre>
<p>I&#8217;m about to roll this into the code. The spike seems to work without any problems (other than ReSharper warning me about my virtual method call in the constructor), but until I put it into the application code I won&#8217;t really know if it&#8217;s 100%. Let me know if you spot anything silly, won&#8217;t you?</p>
<p>Oh, here&#8217;s a <a href="http://www.callcontext.com/wp-content/uploads/2011/10/SingletonInheritanceCreationTest.zip">link to the sample code</a> if you want it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/10/subclassed-singleton-instance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Resolving an existing instance with Ninject</title>
		<link>http://www.callcontext.com/2011/10/resolving-an-existing-instance-with-ninject/</link>
		<comments>http://www.callcontext.com/2011/10/resolving-an-existing-instance-with-ninject/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 06:34:22 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ioc]]></category>
		<category><![CDATA[ninject]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=182</guid>
		<description><![CDATA[Today I was looking for a way to allow a type to resolve to a specific instance that I had already created &#8211; something not known at the time the Ninject kernel is initialised. There is no method of a...]]></description>
			<content:encoded><![CDATA[<p>Today I was looking for a way to allow a type to resolve to a specific instance that I had already created &#8211; something not known at the time the <a title="Ninject IoC Container" href="http://ninject.org/" target="_blank">Ninject</a> kernel is initialised. There is no method of a Ninject binding that explicitly handles this kind of thing.</p>
<p>The trick is to use the <code>ToMethod</code> method. <code>ToMethod</code> takes a lamda as a parameter. It&#8217;s defined as:</p>
<pre class="brush: csharp; title: ; notranslate">
ToMethod(Func&lt;IContext, IInstance&gt; method)
</pre>
<p>This means <code>ToMethod</code> takes a function that accepts the injection context and returns an instance of the type being bound to. We can now use this to return our specific instance:</p>
<pre class="brush: csharp; title: ; notranslate">
myKernel.Bind&lt;IMyInstance&gt;.To(context =&gt; anInstanceOfMyInstance);
</pre>
<p>The gotcha being that any <code>Get</code> of <code>IMyInstance</code> will result in a reference to the original <code>anInstanceOfMyInstance</code>. You have to be careful of lifetime, and therefore scope, and any changes to state.</p>
<p>I&#8217;m not convinced that this is actually a good idea, but it solves my immediate problem.</p>
<p><a href="http://www.callcontext.com/wp-content/uploads/2011/10/NInjectExistingInstanceTest.zip">NInjectExistingInstanceTest</a></p>
<p><sub><em>(And yes, this represents yet another return to blogging in some more regular form&#8230; I do intend to come through with the previously promised goods, just not in any specific order&#8230;)</em></sub></p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/10/resolving-an-existing-instance-with-ninject/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gimp window focus</title>
		<link>http://www.callcontext.com/2011/04/gimp-window-focus/</link>
		<comments>http://www.callcontext.com/2011/04/gimp-window-focus/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 03:55:24 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[gimp]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[inkscape]]></category>
		<category><![CDATA[x11]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=162</guid>
		<description><![CDATA[&#160; I&#8217;ve been using a combination of The Gimp and Inkscape to handle my artwork needs of recent. As I&#8217;m running them in OS X, they need to use the X11 environment. One of the annoyances I have been having with...]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<div class="mceTemp">
<dl id="attachment_65" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.callcontext.com/wp-content/uploads/2011/02/KylieInOnslow1.jpg"><img class="size-medium wp-image-65" title="Mixing Console" src="http://www.callcontext.com/wp-content/uploads/2011/02/KylieInOnslow1-300x200.jpg" alt="" width="300" height="200" /></a></dt>
</dl>
</div>
<p>I&#8217;ve been using a combination of <a title="The Gimp Homepage" href="http://www.gimp.org/" target="_blank">The Gimp</a> and <a title="Inkscape Homepage" href="http://inkscape.org/" target="_blank">Inkscape</a> to handle my artwork needs of recent. As I&#8217;m running them in OS X, they need to use the <a title="X.org Homepage" href="http://www.x.org/wiki/" target="_blank">X11 environment</a>. One of the annoyances I have been having with the Gimp is every window has needed an extra click just to focus it.</p>
<p>It turns out the fix is not difficult. I initially thought it might involve turning on the &#8220;focus follows mouse&#8221; option, but instead it was this:</p>
<p><a href="http://www.callcontext.com/wp-content/uploads/2011/04/Screen-shot-2011-04-13-at-12.32.24-PM.png"><img class="aligncenter size-full wp-image-164" title="X11 Preferences" src="http://www.callcontext.com/wp-content/uploads/2011/04/Screen-shot-2011-04-13-at-12.32.24-PM.png" alt="X11 Preferences" width="564" height="410" /></a></p>
<p>So if you&#8217;re using an X11 application and find yourself dealing with weird focus issues, try turning on &#8220;Click-through Inactive Windows&#8221;. It did the trick for me.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/04/gimp-window-focus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Who gets it perfectly right the first time?</title>
		<link>http://www.callcontext.com/2011/04/who-gets-it-perfectly-right-the-first-time/</link>
		<comments>http://www.callcontext.com/2011/04/who-gets-it-perfectly-right-the-first-time/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 03:07:58 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Fundamentals]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[planning]]></category>
		<category><![CDATA[rants]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=154</guid>
		<description><![CDATA[There was an interesting argument I was a witness to a few days ago. The basic premise was, a developer was complaining about the lack of thought that went into a particular area of a particular piece of software. He...]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_64" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><img class="size-medium wp-image-64" title="Karatha Roadsign" src="http://www.callcontext.com/wp-content/uploads/2011/02/KarathaRoadsign1-300x200.jpg" alt="A roadsign on the way to Karatha, Western Australia." width="300" height="200" /></dt>
</dl>
</div>
<p>There was an interesting argument I was a witness to a few days ago. The basic premise was, a developer was complaining about the lack of thought that went into a particular area of a particular piece of software.</p>
<p>He was right. The most basic amount of thought had been put into it, and the thought that had been put into it was wrong. It was causing him some distress (shall we say&#8230;) and the conversation was getting quite heated.<span id="more-154"></span></p>
<p>At this point in time, one of the company principles came out of his office, and in defense of the software said something along the lines of, and I&#8217;m paraphrasing, &#8220;Nobody ever gets it perfectly right the first time. I suppose you always get things right the first time, yes?&#8221;.</p>
<p>He was right as well. Nobody ever gets it right the first time. We all have to make decisions based on what we know at the time, and then we have to live with the consequences.</p>
<p>However, there&#8217;s not getting it perfectly right the first time, and there&#8217;s <em>really</em> not getting it right the first time. In considering this, I arrived at the following long-winded and possibly pointless analogy:</p>
<blockquote><p>Lets say one day you decided to be a furniture mover. You decide, based on nothing other than the fact you like the colour, (and that it&#8217;s got an MP-3 CD player, built-in GPS, and self-parking) that you&#8217;ll use a <a title="Hyundai i30 Brochure Site" href="http://worldwide.hyundai.com/showroom/passenger-cars/i30-focus.html" target="_blank">Hyundai i30</a>. When you get to your first job, things start out well enough. You&#8217;re able to pack a couple of boxes onto the back seat, you get a hatstand in the front passenger seat, and some clothes get shoved into the boot.</p>
<p>At this point, the home-owner comes out and asks how you plan on moving her 24-foot long, solid marble dining table. In a burst of inspiration, you hire a boilermaker and weld a bunch of steel tubing onto the car making a nice flat area on top. With a great deal of effort, you get the dining table onto the roof, and the car&#8217;s wheels bury themselves into the wheel arches.</p>
<p>With the car fully loaded, you decide to set off for the next house. Except you can&#8217;t open the drivers door. There&#8217;s a steel support strut welded to it now, holding up the dining table on the roof. No problem though, you just smash out the windscreen and climb in over the dash.</p>
<p>You buckle in, turn the engine over, put the automatic transmission into drive, depress the accelerator and&#8230; nothing. The engine is revving, you can hear the transmission straining, but the car doesn&#8217;t move. Not a problem, you decide. You climb back out the windscreen, jump in a cab and dash to the Hyundai service centre. &#8220;Three i30 engines, please!&#8221;, you ask confidently. (Let&#8217;s just imagine this is possible, for the sake of artistic license&#8230;) The smiling and helpful service manager drops three new engines into the back of your cab, and you head back to the house.</p>
<p>You stand back and admire yours and your boilermaker&#8217;s skill. You&#8217;ve removed the engine from under the bonnet, and bolted an engine to each wheel. Magically, (because this is an analogy &#8211; I think&#8230;) all the engines hook up to the cars controls perfectly. You climb back in over the dash and fire them all up. Delicately, you squeeze down on the accelerator and the car pulls away from the curb. At this point in time, the heavens open up and a storm like you&#8217;ve never seen pounds the car with water droplets the size of dachshunds.</p>
<p>You jam  on the breaks, praying that the dining table doesn&#8217;t slide off the front of the jury-rigged assembly holding it up. You reach into the boot and grab one of the shirts. Handing it to the boilermaker you say, &#8220;Every ten meters, wipe my face with this.&#8221;. At this point, the boilermaker turns to you and says &#8220;You didn&#8217;t put much thought into this, did you. You should&#8217;ve just got a truck with a pan&#8230;&#8221;. But he doesn&#8217;t get to finish the sentence as you cut him off with a tirade about how little he knows about the moving business, and how he should think twice before telling you anything about moving because you&#8217;re the moving expert. Etcetera.</p>
<p>Now, let&#8217;s do the alternate universe. You&#8217;ve decided to be a furniture mover. So, you sit down and thing, &#8220;What kind of vehicle will I need to help me carry around furniture?&#8221;. Logic dictates that you scribble down a list of things you think people might ask you to move for them &#8211; televisions, beds, lounges, fridges, dining tables, boxes, small dogs &#8211; and you decide that a medium sized truck with a 20-foot long pantech would be what you want.</p>
<p>You turn up for the first job and the owner mentions they&#8217;ve got a 24-foot long, solid marble dining table. Being a reasonable person, you realise you may have made a mistake with the size of the pantech. A quick call to the pantech supermart confirms that they have a 30-foot long one there that they can swap out with yours in about 30 minutes. You tell the owner that it&#8217;s not a problem and you&#8217;ll be back in an hour.</p>
<p>An hour later you return with your 30-foot long pantech, fit all the owner&#8217;s belongings &#8211; including the dining table &#8211; and are able to drive to the new house even though it&#8217;s bucketing down.</p></blockquote>
<p>I&#8217;m sorry that this has been quite a long and seemingly senseless exposition, but my point is, while nobody ever gets it perfect the first time, you can come close with a little bit of thought.</p>
<p>In the software world, it&#8217;s impossible to think of every possible variable that will impact the development and operation of any software you&#8217;re going to write. You can, however, still take a reasoned and logical approach and consider a fairly significant proportion of the important things. Using that list, you&#8217;re then able to formulate an approach for what you have to do based on actual requirements and logic. Not to mention, with some idea of the scope of the problem, you can then consider applying best-practises and industry norms to help speed up the process.</p>
<p>Without making these considerations, you&#8217;ll wind up trying to move a 24-foot long dining table with a small Korean hatchback. Justifying your mistake by telling yourself that you made the best decision at the time based on nothing other than ego, or a desire for the shiny-new, or factory options, is ridiculous.</p>
<p>Making an informed decision based on reality and a pre-existing body of knowledge will always mean that, even if you get it wrong, it may be good enough for now, and it will be a lot easier to move it closer to what you really need later on. Don&#8217;t be afraid of your limitations, be open about what you know, and be willing to accept you&#8217;re wrong. Then fix it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/04/who-gets-it-perfectly-right-the-first-time/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>First blood!</title>
		<link>http://www.callcontext.com/2011/03/first-blood/</link>
		<comments>http://www.callcontext.com/2011/03/first-blood/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 03:47:25 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[LiveTrax Pro]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[livetrax pro]]></category>
		<category><![CDATA[support]]></category>
		<category><![CDATA[thanks]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=143</guid>
		<description><![CDATA[Wow. I mean, I realise the whole point of putting something in the app store is to get it into other people&#8217;s hands, but wow. After finally getting the contracts sorted out (still a GST issue, but that&#8217;s a simple...]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_60" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.callcontext.com/wp-content/uploads/2011/02/Bee1.jpg"><img class="size-medium wp-image-60" title="Bee" src="http://www.callcontext.com/wp-content/uploads/2011/02/Bee1-300x200.jpg" alt="Bee" width="300" height="200" /></a></dt>
</dl>
</div>
<p>Wow. I mean, I realise the whole point of putting something in the app store is to get it into other people&#8217;s hands, but wow. After finally getting the contracts sorted out (still a GST issue, but that&#8217;s a simple thing), <a title="LiveTrax Pro Backing Track Player for iPad" href="http://www.livetraxpro.com" target="_blank">LiveTrax Pro</a> went live.</p>
<p>To be perfectly honest, I didn&#8217;t think (and really, I still don&#8217;t think) that there&#8217;s any kind of huge market for LiveTrax Pro. The &#8220;back-of-a-napkin&#8221; math went something like this. X million iPads sold (let&#8217;s say 10 &#8211; I know it&#8217;s more, but humour me&#8230;). Number of performers who own iPads would be X percent of that (let&#8217;s say 5% &#8211; 500k&#8230;). X percent of those would consider using their iPad live (let&#8217;s say 5% again &#8211; 25k&#8230;). Standard conversion rates for app sales are somewhere around 1%, so that leaves 250 people who may buy my app. But that&#8217;s not why I wrote it.<span id="more-143"></span></p>
<p>It&#8217;s a niche app I designed to fill a need I personally had. It&#8217;s very focused in its design, and function has been put before form. All that aside, it has been bought buy a few awesome individuals. Perhaps surprisingly (or not, considering everything), a lot of the sales have come from non-English speaking countries.</p>
<p>When I set out to scratch this itch, one of the considerations of the design of the UI was that I wanted it to be simple and clear for everyone, not just the English speakers out there. Now, I only really speak one language. I know some colourful words in a smattering of others, and I learned how to say &#8220;Thank you&#8221;, &#8220;Passenger&#8221;, and &#8220;Seat&#8221; in when I went to Sabah (Borneo).</p>
<p>The easiest way to achieve that was through the use of symbology. I have worked hard on the design to remove any text from the UI. The buttons all use well known symbology that follows what you&#8217;d find on a tape transport control, and they all behave in a natural and expected way. The only notable exceptions being the set timer reset button, and the repurposing of the skip-to-end symbol as the symbol for the autoskip functionality.</p>
<p>I&#8217;m proud of the app as it stands, but I&#8217;ve still got more ideas for it and I&#8217;m going to keep improving it as much as I possibly can. To that end, I&#8217;m working on fixing the product website to help explain how the app works (it&#8217;s pretty simple, really), and I&#8217;m setting up some forums on the company website so that I can hopefully start a dialog with the people using the application. I want to provide simply awesome support because I&#8217;m grateful that someone has decided my app was worth their money and time. Stay tuned.</p>
<p>So, to those people; thanks. <img src='http://www.callcontext.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/03/first-blood/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Seal of Approval!</title>
		<link>http://www.callcontext.com/2011/02/seal-of-approval/</link>
		<comments>http://www.callcontext.com/2011/02/seal-of-approval/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 13:36:34 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[LiveTrax Pro]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[livetrax pro]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=140</guid>
		<description><![CDATA[It appears I have been granted access to that exclusive club, the App Store. Today I received the fantastic news that LiveTrax Pro has been approved for sale! Unfortunately, right now you won&#8217;t be able view it as I am...]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_58" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.callcontext.com/wp-content/uploads/2011/02/BendigoCathedraFront1.jpg"><img class="size-medium wp-image-58" title="Cathedral in Bendigo" src="http://www.callcontext.com/wp-content/uploads/2011/02/BendigoCathedraFront1-300x200.jpg" alt="Cathedral in Bendigo" width="300" height="200" /></a></dt>
</dl>
</div>
<p>It appears I have been granted access to that exclusive club, the App Store. Today I received the fantastic news that <a title="LiveTrax Pro Backing Track Player for iPad" href="http://www.livetraxpro.com" target="_blank">LiveTrax Pro</a> has been approved for sale!</p>
<p>Unfortunately, right now you won&#8217;t be able view it as I am still waiting on an ABN number before my contract is complete. If you think waiting for app approval from Apple can take a long time, trying getting something out of the Australian government&#8230;</p>
<p>Anyway,  good news for now. Time to fix up the websites while I&#8217;m waiting for my mark of the beast&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/02/seal-of-approval/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s coming up, or &#8220;Keeping myself honest&#8221;.</title>
		<link>http://www.callcontext.com/2011/02/whats-coming-up-or-keeping-myself-honest/</link>
		<comments>http://www.callcontext.com/2011/02/whats-coming-up-or-keeping-myself-honest/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 16:27:09 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[motivation]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=107</guid>
		<description><![CDATA[In the interests of providing some impetus for myself, I thought I&#8217;d detail a few ideas of the posts I want to write. Some of them I&#8217;ve been wanting to write for a while, others are new ideas that have...]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_56" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.callcontext.com/wp-content/uploads/2011/02/Hedge1.jpg"><img class="size-medium wp-image-56" title="Hedge" src="http://www.callcontext.com/wp-content/uploads/2011/02/Hedge1-300x200.jpg" alt="Hedge" width="300" height="200" /></a></dt>
</dl>
</div>
<p>In the interests of providing some impetus for myself, I thought I&#8217;d detail a few ideas of the posts I want to write. Some of them I&#8217;ve been wanting to write for a while, others are new ideas that have come about from my recent journey to the &#8220;other side&#8221; (read: Apple).</p>
<p>Writing like this is quite new for me, and I know that I&#8217;ll be more focused if I put myself under a little bit of pressure by detailing what I&#8217;m thinking about. As I write them, I&#8217;ll try and update the list to link to the specific articles.<span id="more-107"></span></p>
<h2>Windows Communication Foundation</h2>
<ul>
<li>Authentication architecture patterns and implementations.</li>
</ul>
<h2>Silverlight</h2>
<ul>
<li>Automatic runtime configuration of WCF endpoints.</li>
<li>Uploading files.</li>
<li>A deep dive into MVVM.</li>
</ul>
<h2>iOS</h2>
<ul>
<li>Working with XIB files and code.</li>
<li>Populating grids.</li>
<li>Custom drawing grid cells.</li>
<li>Playing music from the iPod library.</li>
<li>Memory management in iOS.</li>
<li>Building applications with XCode 4.0.</li>
</ul>
<h2>Graphic Design for Developers</h2>
<ul>
<li>Understanding the basic tenets of graphic design.</li>
<li>Understanding colour.</li>
<li>Laying out data entry forms.</li>
<li>Adding some pizazz to your forms.</li>
<li>Design inspiration.</li>
</ul>
<p>That&#8217;s all I can think of off the top of my head. There are quite a few more. I&#8217;ve actually got some half-started posts lying about that will have to remain on hold until the NDA for XCode 4.0 is lifted. Hopefully this list will provide inspiration to get started.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/02/whats-coming-up-or-keeping-myself-honest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LiveTrax Pro is pending review</title>
		<link>http://www.callcontext.com/2011/02/livetrax-pro-is-pending-review/</link>
		<comments>http://www.callcontext.com/2011/02/livetrax-pro-is-pending-review/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 16:10:39 +0000</pubDate>
		<dc:creator>Geoff</dc:creator>
				<category><![CDATA[LiveTrax Pro]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[livetrax pro]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://www.callcontext.com/?p=104</guid>
		<description><![CDATA[After a little bit of mucking about, I&#8217;ve finally submitted my first application to the Apple App Store. (Hence the lack of posting for a few days&#8230;) I have to say, the process seems a little convoluted, but that&#8217;s most likely...]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_55" class="wp-caption alignleft" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.callcontext.com/wp-content/uploads/2011/02/Tree1.jpg"><img class="size-medium wp-image-55" title="Just a tree" src="http://www.callcontext.com/wp-content/uploads/2011/02/Tree1-300x200.jpg" alt="Just a tree" width="300" height="200" /></a></dt>
</dl>
</div>
<p>After a little bit of mucking about, I&#8217;ve finally submitted my first application to the Apple App Store. (Hence the lack of posting for a few days&#8230;) I have to say, the process seems a little convoluted, but that&#8217;s most likely because of the need to grab a certificate to sign the code.</p>
<p>Now, in fairness to Apple, I did recently upgrade to XCode 4.0, which means that the instructions detailed in the iTunes Connect site weren&#8217;t aimed at me. It took me a little bit of mucking about to find some of the things that need to be found, and I&#8217;m pretty sure I&#8217;ve still not got the actual distribution build settings quite right. XCode 4.0 has some pretty cool features around build configuration that aren&#8217;t clear to me yet.</p>
<p>Anyway, now the long wait begins. They say their typical turn-around is about two weeks. All things considered, I&#8217;m expecting a fairly quick response and a rejection seeing as it&#8217;s my first submission. Let&#8217;s see how that pans out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.callcontext.com/2011/02/livetrax-pro-is-pending-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

