Pages

Tuesday, 9 August 2011

My Blog Has Moved

My blog has now moved to WordPress and can be found at this address...

http://goodcoffeegoodcode.wordpress.com

All new articles will be will be posted there.

Monday, 13 June 2011

Windows Azure Usage Gotcha for BizSpark Members

If you have an MSDN subscription then you'll also get some Azure benefits. These have even been increased recently. PhotoPivot is a BizSpark member so we get access to MSDN Ultimate which entitles us to 1500 hours of Small compute instances per month.


Be warned: THESE BENEFITS ARE NOT INTERCHANGEABLE!

What I mean is, if you're on Ultimate you can use 1 Small compute for 1500 hours or 2 Small computes for 750 hours each etc. What you cannot do is use an Extra Small compute for 1500 hours or 1 Medium compute for 750 hours. The benefit is SPECIFIC to the exact type of compute size.

We got slightly stung this month, but we've learnt our lesson. Learn from our mistake, not your own!

Friday, 13 May 2011

Inside PivotViewer v2. Episode 1, Legacy Support

Welcome to the first in a series of video blog posts where we'll be looking at what's new for PivotViewer v2 in Silverlight 5.

In this episode we'll take a deep-dive into PivotViewer v2 and look at what legacy support is available to all those that have created static, server-side cxml collections. We'll also see some great dynamic benefits that can be applied to these existing collections with v2.

Please leave comments, feedback and any suggestions for things you'd like to see in this series.

Inside PivotViewer v2. Episode 1, Legacy Support from Chris Arnold on Vimeo.


Here are the links to the references I make at the end of the video:

Tony Champion (.Net Rocker)
http://tonychampion.net

Xpert360
http://xpert360.com

Kingsley Uyi Idehen
http://twitter.com/kidehen

Friday, 15 April 2011

Making 3rd-party API Libraries more Robust

In this post we'll be combining Generics, Functions and Actions with the Decorator Pattern to solve the following problem:

"Network requests are flaky"

Every time you make a call "across the wire" you've got to provision for errors. Everything from gateway timeouts, server faults right down to your toddler pulling the lan cable out. If it can happen, at some point, it probably will.

Most solutions are very ad-hoc and resemble this:
using (var wc = new WebClient())
{
  for (int i = 0; i < 5; i++)
  {
    try
    {
      wc.DownloadFile(source, target);
      break;
    }
    catch (Exception e)
    {
      Thread.Wait(200);
    }
  }
}

This approach is fine if you only have a couple of calls in your application. In today's hyper-connected world, however, it's more likely that you'll be making lots of these requests with wildly differing signatures. Very quickly your code will become unreadable as you battle to trap all the possible exceptions and manage the retries. What we need is a pattern for easily applying this retry mechanism to any call whilst keeping our client code clean.

Real-world Example

There are a myriad of 3rd party libraries that allow you to target platform APIs e.g. Twitter, Facebook etc. At PhotoPivot.com we rely heavily on Sam and Tim's great FlickrNet library to perform an enormous number of calls to Flickr. Here's a greatly simplified bit of production code from our server-side application:
public class FlickrPhotoDataDownloadService
{
  private readonly IFlickr _flickr;

  public FlickrPhotoDataDownloadService(IFlickr flickr)
  {
    _flickr = flickr;
  }

  public void GetPhotoDataForUser(string userId)
  {
    var photoCollection = _flickr.PhotosGetAllNotInSet();

    foreach (var photo in photoCollection)
    {
      var photoInfo = _flickr.PhotosGetInfo(photo.PhotoId);
      var exifs = _flickr.PhotosGetExif(photo.PhotoId);

      // Do something with the data...
    }
  }
}
Potentially, any of the calls to the IFlickr interface can result in a sporadic network error. This is a serious pain if it happens inside the foreach loop when the routine is 90% through a list of 10,000 photos. If we implemented the ad-hoc solution at the start of this post the GetPhotoDataForUser method would become very untidy and a developer's ability to read it would lessen. So, let's look at some of the related classes. Below you can see the interface that the service uses to describe its requirements. We then used the Adapter Pattern to "bring in" the interface to the main FlickrNet class.
public interface IFlickr
{
  PhotoCollection PhotosGetAllNotInSet();
  PhotoInfo PhotosGetInfo(photo.PhotoId);
  ExifTagCollection PhotosGetExif(photo.PhotoId);
}
public class FlickrEx : FlickrNet.Flickr, IFlickr
{
}
The client code that uses the service looks like this:
var flickr = new FlickrEx();
var service = new FlickrPhotoDataDownloadService(flickr);
service.GetPhotoDataForUser(userId);
So, how do we encapsulate all the methods, or at least the methods we need, in the main Flickr class? We can't rely on just extending the class as it, or its methods, might be sealed. Let's start by creating a class that can keep track on failed attempts and whether a retry is possible.
using System;
using System.Threading;

internal abstract class RetryableBase
{
  private readonly int _maxAttempts;
  private readonly TimeSpan _delay;
  private int _attempts;

  internal RetryableBase(int maxAttempts, TimeSpan delay)
  {
    _maxAttempts = maxAttempts;
    _delay = delay;
  }

  protected bool CanRetry(Exception e)
  {
    _attempts++;

    Thread.Sleep(_delay);

    return (_attempts < _maxAttempts);
  }
}
Next we'll extend this and, by leveraging C#'s Func<> capabilities, create a couple of classes that can wrap a function in some standardised retry routines.
using System;

internal class RetryableFunc<TResult> : RetryableBase
{
  private readonly Func<TResult> _func;

  public RetryableFunc(Func<TResult> func, int maxAttempts, TimeSpan delay)
  : base(maxAttempts, delay)
  {
    _func = func;
  }

  public TResult Call()
  {
    TResult result = default(TResult);

    bool success = false;

    while (!success)
    {
      try
      {
        result = _func();
        success = true;
      }
      catch (Exception e)
      {
        if (!CanRetry(e))
          throw;
      }
    }

    return result;
  }
}

internal class RetryableFunc<T, TResult> : RetryableBase
{
  private readonly Func<T, TResult> _func;

  public RetryableFunc(Func<T, TResult> func, int maxAttempts, TimeSpan delay)
  : base(maxAttempts, delay)
  {
    _func = func;
  }

  public TResult Call(T t)
  {
    TResult result = default(TResult);

    bool success = false;

    while (!success)
    {
      try
      {
        result = _func(t);
        success = true;
      }
      catch (Exception e)
      {
        if (!CanRetry(e))
          throw;
      }
    }

    return result;
  }
}

You will, unfortunately, need to create a new class for each signature function call needed. For instance, the one's above will work for calls that match Func<TResult> or Func<T, TResult> only. Func<T1, T2, TResult> will need another class. Functions that don't return anything are Actions<>. You'll need separate classes for these also. Once done, though, the ROI will be huge.

We now have the capability to make calls robust but how do we 'invisibly' add this to someone else's class? We'll use the Decorator Pattern to create a new class that "is a" IFlickr but also "has a" IFlickr. By initially abstracting our service's needs to an interface we have enabled ourselves to do this very easily.
public class RetryableFlickrEx : IFlickr
{
  private readonly IFlickr _flickr;

  public RetryableFlickrEx(IFlickr flickr)
  {
    _flickr = flickr;
  }

  public PhotoCollection PhotosGetAllNotInSet()
  {
    var retry = new RetryableFunc<PhotoCollection>(_flickr.PhotosGetAllNotInSet);

    return retry.Call();
  }
  public PhotoInfo PhotosGetInfo(string photoId)
  {
    var retry = new RetryableFunc<string, PhotoInfo>(_flickr.PhotosGetInfo);

    return retry.Call(photoId);
  }
  public ExifTagCollection PhotosGetExif(string photoId)
  {
    var retry = new RetryableFunc<string, ExifTagCollection>(_flickr.PhotosGetExif);

    return retry.Call(photoId);
  }
}
Now that we have all our pieces in place the ONLY change we need to make to our entire application is one line in the client. The service still gets the IFlickr it requires and simply doesn't care about the implementation:
var flickrBase = new FlickrEx();

// New line: Use the Decorator Pattern to extend functionality at runtime...
var flickr = new RetryableFlickrEx(flickrBase);

var service = new FlickrPhotoDataDownloadService(flickr);
service.GetPhotoDataForUser(userId);

Please leave comments if you can see a way of enhancing this idea.

Friday, 14 January 2011

The Biggest Challenge Faced by Technical Founders

When someone technical decides to step off the cliff and become a founder of a startup there are always going to be challenges. Most programmers and developers believe that these will come from areas outside of their comfort zone - sales, marketing, taxes, fund-raising, design and even just networking! This is why the standard co-founders model partners someone technical with someone more 'businessy'. The reality, however, is very different.

For me the biggest challenge I face as a technical founder is programming. To be more specific: stopping programming. For years I have measured my progress by ticking off features delivered, bugs fixed or user stories completed. It's a well understood system and it's easy to track, but that's not what I should be doing. My job as a founder is to find a repeatable business model that will make money, and the only route to achieving this is via validated learning.

Here's an example:

Earlier this week I was building some new server functionality for @photoPivot. I found myself working through the options of how and where to host a service and what type of communications medium was going to be the absolute best for this. Eventually I realised "Who cares? It doesn't matter!". All I needed to do was test my idea in the quickest way possible. Just stick it in a console app and off we go (sneakernet style!).

Now, this doesn't mean that you should write bad, unmanageable code. You can still test your ideas in a way that isn't going to back you into a nasty corner in the future. Just be a little pragmatic. Do enough to get it working, then step away. I know how difficult it is to know that you could make something better - it's very hard to resist being the perfect craftsman. Once you've proven your idea then you can make it elegant; but why waste your time polishing something that you don't know people want?

For technical founders, programming is chicken soup. On difficult days we find comfort there and, by the evening, we've convinced ourselves that, yes, we made good progress today. Don't be fooled by these false metrics. Test your ideas quickly and build your company.

Monday, 20 December 2010

Time to Move On

For the last 9 months I have been a part-time entrepreneur. From 1st January it'll be full-time.

I have now worked at the same software company for 10 years. I started as a developer and worked my way up to become the Development Director. Over the past 2 years I have transformed the company's development department with changes that will continue to help it deliver working software long after my departure. I moved us from a classic waterfall model, with manual deployment, to an Agile process (Scrum) incorporating SOLID principles, unit tests, continuous integration & build servers and, nearly, fully automated deployment of a dozen commercial websites. I am very proud of the changes I have made and I leave a company which now scores 9/12 on the Joel Test.

I'm giving all that up.

My own, personal, transformation didn't stop there though. Over the last year I have become more and more excited by the business side of software development. I spent countless evenings and weekends consuming all I could find from such luminaries as Dharmesh Shah, Seth Godin, Geoffrey A. Moore, Eric Ries etc. The possibility that a 'simple developer' could expand his horizons and create something more than just an application was exhilarating. During 2010 I had, and still have, a hat-full of ideas; one of which bubbled to the top of the stack quite effortlessly. After the creation of an MVP, a few public demos & pitches and some incredible user feedback I'm now ready to go for it. I've learnt all I can without taking that final step off the cliff.

In 2011 I'll be looking for more people to come join me in helping change the way people interact with social media - starting with TweetPivot. If you want to know what that involves you'll have to follow me on twitter or even just come talk with me!

Finally, I'd like to thank some local groups (e.g. Pitch and Mix), some global groups (e.g. Microsoft's BizSpark program) and an innumerable number of individuals who have supported and encouraged me thus far. Almost any hour of the day can feel like a lonely 3am when you're an entrepreneur and having people that can help you refocus is priceless.

So, wish me luck. 2011 is going to be scary-as-hell but, wow, what a sweet looking ride!

Thanks,

Chris

Saturday, 16 October 2010

What are you scared of?

Finding yourself stood in front of Eric Ries can be somewhat daunting. You have the opportunity to ask a question to, arguably, the leading light in the field of Lean Startup. As soon as you start speaking, though, the guy stood behind you in the queue starts getting restless. So, you better make it a good one!

I was unable to attend the Business of Software in Boston last month so was excited to see that Eric was doing a whistle-stop talk last night at TechHub, London. After a, not too inconvenient, train and tube journey I found myself in a vibrant room packed with budding entrepreneurs. The 'formal' part of Eric's talk was mostly content that I'd already seen online, so no major surprises there. What always makes these events unique, though, is the interaction with the people that turn up. The Q and A hand-raising session was very busy but I did manage to talk with Eric afterwards. Here's what I asked him:

Imagine you're back at IMVU circa 2004, but this time you know what you know now. You've created a Minimum Viable Product for just one Instant Messaging network that's already getting good traction. Geoffrey Moore would have probably suggested that you capture your beachhead in that first IM. Would you agree with that or would your next move be to create an MVP for each IM?
As is often the case in this field there was no short, definitive answer! What follows is paraphrased.

Eric: "What are you scared of?"
Me: "Uh, nothing. I'm an entrepreneur creating a startup - by definition am I not fearless?"
Eric: "No. What's your biggest fear?"
Without any prepared answer for this one I said "Well, probably someone else copying us". Eric rocked back, head shaking "No." I got the impression that he hears this 'wrong answer' often.

The gist of Eric's response was that I needed to look at my assumptions. I'd assumed that because my product 'works' for one social network that it will automatically be greeted in the same manner on all the other networks. The way you reassess these assumptions is to do more measuring against hard targets e.g. I'm currently at 10, I think I can get to 20 by time t. If the increments are 10, 12, 14... you're probably gonna make it, but if they're 10, 11, 11.5... you might have a problem. Testing your worst fears early is key.

MBAs are seen as a hindrance in the startup world, but the remainder of Eric's lesson to me did seem to cross a chasm into this territory. The basics of the Lean Startup are pretty straight forward: iterate through 'the loop' as quickly as you can and learn what works. Simple. Once you get into the guts of it, by talking with Eric, it starts sounding a whole lot more complicated. If I wanted an MBA I would have studied for one. I like my vision of the startup as having less politics, less overheard and, by extension, less rigor; but, again, this is an assumption.

I am, however, extremely grateful for the way Eric makes you question all of your assumptions - sometimes to the point of your own existence!

So, what is my biggest fear? After some considerable thought I think it's that people won't like what I do. I fully agree with Eric's observation that the best way to utterly deject developers is to have them spend time and energy creating something only for it to never see the light of day. Lean helps us avoid wasting everyone's time and for that, alone, it is worth pursuing.