<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>
The Oxford Internet Professionals Meetup
Oxford Tuttle Club

Friends
Freed from the Matrix</description><title>Andy Young's Blog</title><generator>Tumblr (3.0; @apexa)</generator><link>http://insomanic.me.uk/</link><item><title>Problems with Twitter's new Retweet - and a tip/fix</title><description>&lt;p style="text-align: center; font-size: 1.1em; font-weight: bold;"&gt;&lt;strong&gt;“If someone retweets you (new-style), you won’t see it (it’s not in your @-replies &lt;em&gt;or&lt;/em&gt; main feed) - even if you follow them!”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (3 Mar): I was just chatting with my mate &lt;a href="http://twitter.com/lostplan"&gt;Sol from Tweetdeck&lt;/a&gt; and we realised the fix I described here doesn’t work any more.&lt;/strong&gt; Ah well, it was nice while it lasted..&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/andyy"&gt;My twitter feed&lt;/a&gt; is a bit of a mess right now after I discovered a bunch of things in quick succession and typed something wrong initially - so here’s what’s annoying me about &lt;a href="http://blog.twitter.com/2009/11/retweet-limited-rollout.html"&gt;Twitter’s new (built-in) retweet function&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When someone retweets you (new-style), it doesn’t show up in your @-replies list.&lt;/strong&gt; This also means it doesn’t show up in your list of mentions on clients that use Twitter’s mentions feed e.g. Tweetdeck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When someone &lt;em&gt;that you follow&lt;/em&gt; retweets you (new-style), it doesn’t even show up &lt;em&gt;in your own feed&lt;/em&gt;&lt;/strong&gt; i.e on the Twitter.com homepage when you’re logged in, or in your list of “all friends” in clients like Tweetdeck. For example, I follow &lt;a href="http://twitter.com/jake"&gt;Jake&lt;/a&gt; and he &lt;a href="http://search.twitter.com/search?q=jake+andyy"&gt;retweeted me earlier&lt;/a&gt; (another annoyance - I can’t link directly to his retweet of mine, instead the links now point back to my original tweet). However Jake’s RT of mine didn’t appear in my feed, so I didn’t notice until later, by chance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The combination of 1 &amp; 2 mean that &lt;strong&gt;it’s pretty difficult to find out when people retweet you&lt;/strong&gt;, unless you’re really keen to keep checking manually (see below). This means you can’t judge when people are in agreement with you or interested in things you post, even if you’re friends and you follow them. You also can’t discover new people who retweet you - so much for discovering new connections!&lt;/p&gt;

&lt;p&gt;The flip side of this is that &lt;strong&gt;when you retweet people, they’ll likely not get to know about it&lt;/strong&gt;. So much for subtly attracting someone’s attention..! ;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is a “workaround” however - do a search for your Twitter username and all retweets will show up&lt;/strong&gt; (well, almost - see below). I use Tweetdeck so it was pretty simple just to add a new column with a &lt;a href="http://search.twitter.com/search?q=@andyy"&gt;search for andyy&lt;/a&gt;. The problem with this is that it works &lt;em&gt;most of the time&lt;/em&gt; - but &lt;em&gt;a lot&lt;/em&gt; of people’s tweets are blocked from showing up in twitter search (as I’ve come to discover from the number of people that having problems trying to use my &lt;a href="http://apps.facebook.com/selectivetwitter/"&gt;Selective Twitter Status&lt;/a&gt; app - Twitter seems to have a big problem being overzealous in it’s detection of spam-like activity or something. The end result is that this still doesn’t guarantee to show 100% of retweets.&lt;/p&gt;

&lt;p&gt;I’m actually a big fan of the potential for the new retweet functionality - there’s already some cool stuff if you click on “Retweets” in the right-hand menu on twitter.com - &lt;a href="http://twitter.com/#retweeted_of_mine"&gt;“Your tweets, retweeted”&lt;/a&gt; shows when people retweet you, although it doesn’t show cases where you’ve been the “influencer” - where you retweeted someone else and that was subsequently noticed by people that follow you and retweeted by them. The “&lt;a href="http://twitter.com/#retweets_by_others"&gt;Retweets by others&lt;/a&gt;” that shows tweets that people you follow have retweeted seems a particularly cool way to discover stuff that your friends find interesting. Here’s hoping Twitter manage to get this all worked out soon!&lt;/p&gt;</description><link>http://insomanic.me.uk/post/249361310</link><guid>http://insomanic.me.uk/post/249361310</guid><pubDate>Thu, 19 Nov 2009 06:22:00 +0000</pubDate></item><item><title>PHP Trick: Catching fatal errors (E_ERROR) with a custom error handler</title><description>&lt;p&gt;Implementing a custom error handler using &lt;a href="http://php.net/set_error_handler"&gt;set_error_handler()&lt;/a&gt; in PHP can be a useful technique (&lt;a href="http://www.google.co.uk/search?q=php+custom+error+handler"&gt;Google search for more info/examples&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Unfortunately, set_error_handler() doesn’t catch fatal errors - as the PHP docs say:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Handily, I just discovered it’s possible to catch fatal E_ERROR errors and direct them to your custom error handler using a combination of &lt;a href="http://php.net/register_shutdown_function"&gt;register_shutdown_function()&lt;/a&gt; and &lt;a href="http://php.net/error_get_last"&gt;error_get_last()&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="brush:php"&gt;
set_error_handler('myErrorHandler');
register_shutdown_function('fatalErrorShutdownHandler');

function myErrorHandler($code, $message, $file, $line) {
  ...
}

function fatalErrorShutdownHandler()
{
  $last_error = error_get_last();
  if ($last_error['type'] === E_ERROR) {
    // fatal error
    myErrorHandler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
  }
}
&lt;/pre&gt;

&lt;p&gt;The key is that functions registered with register_shutdown_function() are called even on a fatal error - including out of memory errors. error_get_last() can then be used to detect whether we’re ending the script because of a fatal error, and pass the error info to your custom error handler if so.&lt;/p&gt;</description><link>http://insomanic.me.uk/post/229851073</link><guid>http://insomanic.me.uk/post/229851073</guid><pubDate>Sun, 01 Nov 2009 16:50:00 +0000</pubDate><category>Dev</category><category>php</category></item><item><title>Stickyness and success: Techcrunch has it backwards</title><description>&lt;p&gt;Just read the guest post &lt;a href="http://www.techcrunch.com/2009/10/29/how-to-measure-the-true-stickiness-and-success-of-a-facebook-app/"&gt;How to measure the true stickiness (and success) of a Facebook app&lt;/a&gt; by Nabeel Hyatt from &lt;a href="http://www.conduitlabs.com/"&gt;Conduit Labs&lt;/a&gt; over at Techcrunch.&lt;/p&gt;

&lt;p&gt;Interesting data, but the conclusion is backwards.&lt;/p&gt;

&lt;p&gt;“You would expect stickiness to go down as you get huge”. yes, the table he gives shows this to be TRUE:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://cache0.techcrunch.com/wp-content/uploads/2009/10/conduit1.jpg" alt="" width="500"/&gt;&lt;/p&gt;

&lt;p&gt;An &lt;em&gt;increase&lt;/em&gt; in MAUs between 9/22 and 10/22 (col 4 &gt; col 5) corresponds with a &lt;em&gt;decrease&lt;/em&gt; in DAU/MAU ratio (col 2 &lt; col 3) - and with one exception (RockYou Pets) the opposite is also true - where MAUs went down, stickiness went up.&lt;/p&gt;

&lt;p&gt;In other words, all the apps that got MORE users (grew in size) in the last month became LESS sticky. the last row (Cafe World) is the extreme example - it grew MAUs 15x in the month but went from 92% to 33% stickness.&lt;/p&gt;

&lt;p&gt;The other point - that stickiness and success are correlated - is surely obvious. if you have a stickier app, your users will visit more often, and assuming it is even the smallest bit viral, this means that your users are spending more time being exposed to that virality and so will invite more friends, so over time you’ll get more total MAUs too.&lt;/p&gt;

&lt;p&gt;Put these together and it suggests a different model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;stickiness depends on the individual characteristics of each specific app&lt;/li&gt;
&lt;li&gt;stickiness decreases slowly as apps grow&lt;/li&gt;
&lt;li&gt;apps with more stickiness are more likely to be successful…&lt;/li&gt;
&lt;/ol&gt;</description><link>http://insomanic.me.uk/post/227587734</link><guid>http://insomanic.me.uk/post/227587734</guid><pubDate>Fri, 30 Oct 2009 03:46:00 +0000</pubDate><category>web</category><category>entrepreneurship</category><category>virality</category></item><item><title>1st month as a Spotify premium user</title><description>&lt;p&gt;&lt;img src="http://4.media.tumblr.com/tumblr_krb4blW7Po1qz5fkgo1_100.jpg" alt="" class="left" align="left"/&gt;Spotify founder &lt;a href="http://twitter.com/eldsjal"&gt;Daniel Ek&lt;/a&gt; has just written &lt;a href="http://www.spotify.com/blog/archives/2009/10/08/overnight-success-takes-a-long-time%E2%80%A6/"&gt;a very interesting blog post&lt;/a&gt; to mark the first anniversary of Spotify, giving his views on Spotify’s progress, the music industry, where they’re heading and what the journey will be like.&lt;/p&gt;

&lt;p&gt;It’s now a month since I took the plunge and gave Spotify my credit card details. The tipping point for me was the release of their iPhone app allowing me to stream to my phone, in particular to download entire albums for offline play.&lt;/p&gt;

&lt;p&gt;In the last month I’ve “borrowed” the following albums:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/4A1QN1R8CY6WlMVsxrrR0I"&gt;Tiga - Sexor collector’s edition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/3fcawGlUwJs3MAQuLaKZOf"&gt;Tiga - Ciao!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/0cLZaahA8kJdfQHwD21hME"&gt;Simian Mobile Disco - Temporary Pleasure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/4DIWqOzwfX74Tj2a8MAKma"&gt;Justice - A Cross The Universe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/31U37xLoG3l8JuOGIoBaBL"&gt;2raumwohnung - Kommt Zusammen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/2Oijur4pE7MmCfrHzxYJEZ"&gt;Soulwax - Most of the Remixes…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/3Dp4KWyl2t8KppfFz5tE1E"&gt;DJ Kicks - The Exclusives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/6b26yqVf321OxkkplWjJUY"&gt;Pulp - Different Class (2 CD edition)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/0eFHYz8NmK75zSplL5qlfM"&gt;Muse - The Resistance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/0UH5Q1tgffnQfqj5ZlNeBv"&gt;Snow Patrol - Final Straw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/0vG5hopWlaAp8xus0DuuW0"&gt;Snow Patrol - Eyes Open&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/0nCmFbB1Flri8SwaQXvwmx"&gt;Daft Punk - Alive 2007&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://open.spotify.com/album/6NrLpQCPYrNS3kVWxDgIlg"&gt;Jet - Get Born&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;..as well as a couple of singles, and listed to a bunch of other stuff without saving it for offline play.&lt;/p&gt;

&lt;p&gt;The verdict - in the first month certainly I’ve had fantastic value for money. My £10 has given me repeat listening to a whole bunch of music,  mostly albums I hadn’t heard before and including 2 brand new releases (Muse &amp; Simian Mobile Disco). Sure, this isn’t exactly the same as actually buying a CD or having an MP3, but I’ve not experienced any practical difference.&lt;/p&gt;

&lt;p&gt;We’ll see how it develops, but right now I have to say it comes recommended, at least if you listen to music as much as I do, and particularly since you can cancel at any time..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/209341380</link><guid>http://insomanic.me.uk/post/209341380</guid><pubDate>Sat, 10 Oct 2009 17:24:00 +0100</pubDate></item><item><title>The Alpha Course "Does God exist?" and online poll ethics</title><description>&lt;p&gt;&lt;img src="http://12.media.tumblr.com/tumblr_kr3r7lOJ7u1qz5fkgo1_250.gif" alt="" align="right" class="right"/&gt;The Alpha Course in the UK are running a marketing campaign at the moment with posters asking the question “Does God exist?” followed by empty tick boxes for Yes/No/Probably. They’ve got the same thing on their homepage at &lt;a href="http://uk.alpha.org/"&gt;http://uk.alpha.org/&lt;/a&gt; set up as an online poll, complete with “see results so far” link.&lt;/p&gt;

&lt;p&gt;Problem is..&lt;/p&gt;

&lt;p&gt;Clicking yes always returns 36-34-30.
Clicking no always returns 35-34-30.
Clicking probably always returns 35-34-31.&lt;/p&gt;

&lt;p&gt;The votes are being posted to and the “results” returned by &lt;a href="http://uk.alpha.org/?q=/alpha09/poll&amp;vote="&gt;http://uk.alpha.org/?q=/alpha09/poll&amp;vote=&lt;/a&gt;[yes|no|probably] - view source to see the html returned with the “results”.&lt;/p&gt;

&lt;p&gt;Amusingly you can get the stats as high as 40% “no” by adding lots of votes at once e.g. &lt;a href="http://uk.alpha.org/?q=/alpha09/poll&amp;vote=no&amp;vote=no&amp;vote=no&amp;vote=no&amp;vote=no"&gt;http://uk.alpha.org/?q=/alpha09/poll&amp;vote=no&amp;vote=no&amp;vote=no&amp;vote=no&amp;vote=no&lt;/a&gt; etc. see here: &lt;a href="http://bit.ly/somethingfishygoingon"&gt;http://bit.ly/somethingfishygoingon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course as soon as you vote anything else the numbers return to normal.&lt;/p&gt;

&lt;p&gt;Regardless of your religious beliefs, surely this is pushing the line a bit far in terms of presenting it as a real poll when the results are fixed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don’t mean this to be focused on religion&lt;/strong&gt;. The interesting question to me is “&lt;strong&gt;is it legit to host an online poll backed by a significant ad campaign and present fake results?&lt;/strong&gt;” If it helps, try imagining that this is a poll by some other brand asking “Do you think our product is the best?” and presenting you with what they make out to be what other people think.&lt;/p&gt;

&lt;p&gt;Seems to me like this is deceiving the public. How do poll results (or not) relate to advertising standards laws? Is this legal?&lt;/p&gt;

&lt;p&gt;Say e.g. Apple hosted an online “poll” asking “Are our laptops the best? Yes/No/Probably” with a “see results so far” link. Would that be “just publicity material”? Where would they stand legally?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike me, &lt;a href="http://twitter.com/jamesremuscat"&gt;James&lt;/a&gt; wasn’t too lazy to actually e-mail the webmaster - apparently &lt;a href="http://twitter.com/jamesremuscat/statuses/4736923613"&gt;“the result were being cached - [they] didn’t notice as caching is disabled for registered users.”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The site currently shows a large percentage of noes - hopefully as well as fixing the caching they also ensured that multiple votes in the style of &lt;a href="http://bit.ly/somethingfishygoingon"&gt;http://bit.ly/somethingfishygoingon&lt;/a&gt; are not added to the total!&lt;/p&gt;</description><link>http://insomanic.me.uk/post/205969066</link><guid>http://insomanic.me.uk/post/205969066</guid><pubDate>Tue, 06 Oct 2009 17:51:00 +0100</pubDate></item><item><title>PHP htmlspecialchars()/htmlentities() invalid multibyte/UTF-8 gotcha with display_errors=true</title><description>&lt;p&gt;Here’s a seemingly nonsensical gotcha I just discovered with error handling for htmlspecialchars() and htmlentities() in PHP. &lt;a href="http://www.php.net/releases/5_2_5.php"&gt;Since PHP 5.2.5&lt;/a&gt;, if either of those functions are passed invalid multibyte strings (invalid UTF-8, perhaps containing a truncated multi-byte character after improper use of substr() intead of mb_substr()) then PHP triggers the following error and returns an empty string:&lt;/p&gt;

&lt;p&gt;&lt;code class="brush:php"&gt;
PHP Warning: htmlspecialchars(): Invalid multibyte sequence in argument
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, in general the php ini setting display_errors can be used to control whether errors are output to the browser, the ini setting log_errors can be &lt;em&gt;independently&lt;/em&gt; used to control whether errors are written to logfile, and if a custom error handler has been set with set_error_handler() then this is always called for all errors and can then read the values of display_errors and log_errors along with the value of error_reporting() and take the appropriate course of action, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong!&lt;/strong&gt; In this case, htmlspecialchars() and htmlentities() only trigger the error if the value of display_errors is false. If the value of display_errors is true then no error is triggered at all! This seemingly nonsensical behaviour makes it impossible to detect these errors during debugging with display_errors on.&lt;/p&gt;

&lt;p&gt;Here’s the &lt;a href="http://bugs.php.net/bug.php?id=47494"&gt;bug report, marked as closed - bogus&lt;/a&gt;, &lt;a href="http://cvs.php.net/viewvc.cgi/php-src/ext/standard/html.c?r1=1.125&amp;r2=1.126"&gt;original modification to the PHP source that added this behaviour&lt;/a&gt;, &lt;a href="http://cvs.php.net/viewvc.cgi/php-src/ext/standard/html.c?r1=1.126&amp;r2=1.127"&gt;initial fix for this behaviour&lt;/a&gt; and &lt;a href="http://cvs.php.net/viewvc.cgi/php-src/ext/standard/html.c?r1=1.127&amp;r2=1.128"&gt;subsequent revert of that fix&lt;/a&gt; that I believe was incorrect.&lt;/p&gt;

&lt;p&gt;I’ve contacted the core PHP developers involved but in the meantime this may help anyone searching Google..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/191397106</link><guid>http://insomanic.me.uk/post/191397106</guid><pubDate>Sat, 19 Sep 2009 02:25:20 +0100</pubDate><category>Dev</category></item><item><title>Design by Contract - for efficient coding</title><description>&lt;p&gt;Yesterday I picked up &lt;a href="http://twitter.com/joelg87/status/3769344175"&gt;this tweet&lt;/a&gt; from &lt;a href="http://twitter.com/joelg87"&gt;Joel&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Getting into PHP Exceptions. Very useful :) Example - userExists() function should raise exception when no user passed, not return false!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hang on, should it? While exceptions in programming languages are without doubt a useful tool, his example reminded me of a problematic style of coding I’ve experienced - something I consider an &lt;a href="http://www.c2.com/cgi/wiki?AntiPattern"&gt;Antipattern&lt;/a&gt;. The style I have in mind is when each function starts with code validating the input parameters before the main work of the function is executed. Here’s an example:&lt;/p&gt;

&lt;pre class="brush:php"&gt;function addUserToGroup($user, $group, $done_by) {
  if (!($user instanceof User)) { throw new Exception(..); }
  if (!($group instanceof Group)) { throw new Exception(..); }
  if (!($done_by instanceof User)) { throw new Exception(..); }
  // ok, we're (finally) good to go:
  $ref = new UserGroupRef();
  $ref-&gt;setUser($user);
  $ref-&gt;setGroup($group);
  $ref-&gt;setDoneBy($done_by);
  $ref-&gt;save();
}
&lt;/pre&gt;

&lt;p&gt;If you’d never dream of writing code like this, move along - nothing of interest to see below! If you’re wondering why I think this is a bad approach, though - what’s the problem here?&lt;/p&gt;

&lt;p&gt;The code is verbose - 50% is performing “meta” tasks. This takes time to write and makes it harder to maintain and interpret in the future. (I’m a big believer in &lt;a href="http://c2.com/cgi/wiki?SelfDocumentingCode"&gt;self-documenting code&lt;/a&gt; - key to this is keeping code short and &lt;a href="http://c2.com/cgi/wiki?ReduceUnimportantInformation"&gt;reducing the amount of unimportant information&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The issue gets stronger if we go on to include similar checks in the implementations of UserGroupRef-&gt;setUser(), setGroup() and setDoneBy(). The complete system is now “nice and robust” but has doubled in terms of lines of code, and you can imagine how when the code is executed the same checks are called repeatedly at different levels of the call stack. If those other functions are only ever called by code that has already ensured the parameters passed will be valid, surely all the time and effort to write and maintain the additional checks isn’t strictly necessary..&lt;/p&gt;

&lt;h3&gt;Design By Contract&lt;/h3&gt;

&lt;p&gt;So how do we tell when we need to do this validation? Enter the concept of “&lt;a href="http://en.wikipedia.org/wiki/Design_by_contract"&gt;Design by Contract&lt;/a&gt;” - a “technique to reduce the programming effort for large projects” (&lt;a href="http://www.digitalmars.com/d/2.0/dbc.html"&gt;source&lt;/a&gt;). The basic idea is that each function comes with a “contract” that should be agreed to when calling it, in the same way that two people may have a contract when agreeing to work together in the real world.&lt;/p&gt;

&lt;p&gt;The key elements of Design by Contract are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;Precondition&lt;/strong&gt; - what must be true before the function is called - i.e. the responsibilities of the calling scope. For example, the $user parameter will contain a User object.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;Postcondition&lt;/strong&gt; - what will be true after the function has executed - i.e. the responsibilities of the function itself. For example. $user will be a member of $group.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;Class Invariant&lt;/strong&gt; - what the function guarantees to leave unchanged (for completeness - so we don’t get unexpected side-effects).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The part I want to focus on is the precondition - specifically what parameters the function will be given - values, datatypes etc. &lt;strong&gt;Design by Contract places the responsibility on the calling code to provide valid parameters, not on the called code to validate them&lt;/strong&gt;. The core idea is “fail hard” - if any part of the contract is broken the entire thing is void - and there’s no guarantee what will happen(!)&lt;/p&gt;

&lt;p&gt;That obviously sounds quite scary - I think this interpretation of DBC is a relevant approach only for internal functions within a module or self-contained system. DBC is not a good model for dealing with user input at run-time(!) - and for open-source code or APIs that will be used by other teams or released publicly the extra code to check for and report violation of the contract is probably worth the saving in confusion and support questions.&lt;/p&gt;

&lt;h3&gt;Using Design By Contract for efficient coding&lt;/h3&gt;

&lt;p&gt;So the point is to use DBC as the justification for not filling your classes and methods with code validating input parameters, resulting in lengthy code that’s harder to understand and takes longer to maintain. You just need to ensure that every member of the team writing code that uses a particular module works on the principle that it is the calling code’s responsibility to provide valid parameters, something that is often possible with small teams and bespoke modules. DBC also simplifies debugging and unit testing since the intended behaviour of each routine is clearly specified.&lt;/p&gt;

&lt;p&gt;Back to Joel’s example - should userExists() throw an exception if passed invalid input? The answer really depends on how it will be used, and what the “contract” for function is understood to be. The contract could be written that userExists() &lt;em&gt;will&lt;/em&gt; take responsibility for validating it’s input. However it’s often the case that the calling code will &lt;em&gt;also&lt;/em&gt; need to know if it’s not working with valid data, which indicates that validation is best done at the earliest point in the call stack than repeatedly throughout.&lt;/p&gt;

&lt;p&gt;It’s also important to keep in mind what real-world effect invalid input may have - for some functions it could result in critical data corruption. However the chances are that when testing for the existence of an invalid user, simply returning false will cause the system to function fine as expected. This leads us to one of my favourite concepts of coding - &lt;a href="http://c2.com/cgi/wiki?YouArentGonnaNeedIt"&gt;YAGNI&lt;/a&gt; ;)&lt;/p&gt;

&lt;p&gt;Comments welcome.&lt;/p&gt;</description><link>http://insomanic.me.uk/post/180549381</link><guid>http://insomanic.me.uk/post/180549381</guid><pubDate>Sat, 05 Sep 2009 19:40:00 +0100</pubDate><category>dev</category></item><item><title>Reliability Bug in Facebook PHP API Batching Support</title><description>&lt;p&gt;I recently discovered a bug in the current Facebook API PHP Client library that affects the &lt;a href="http://wiki.developers.facebook.com/index.php/Using_Batching_API"&gt;support for batching calls&lt;/a&gt; which I’ve used for the &lt;a href="http://apps.facebook.com/selectivetwitter/"&gt;Selective Twitter Status&lt;/a&gt; application.&lt;/p&gt;

&lt;p&gt;The bottom line is, sometimes the call to &lt;a href="http://wiki.developers.facebook.com/index.php/Batch.run"&gt;batch.run&lt;/a&gt; within execute_server_side_batch() as called by end_batch() returns an empty string instead of the expected array of results from each of the batched calls. The code has the following test for an exception but this isn’t triggered in it’s current state since no specific FB exception is being returned, just the empty result:&lt;/p&gt;

&lt;pre class="brush: php"&gt;    if (is_array($result) &amp;&amp; isset($result['error_code'])) {
      throw new FacebookRestClientException($result['error_msg'],
                                            $result['error_code']);
    }
&lt;/pre&gt;

&lt;p&gt;The symptom is a bunch of PHP warnings similar to the following as the code attempts to iterate over the empty string as if it was the expected array of results:&lt;/p&gt;

&lt;pre class="brush:php"&gt;PHP Notice:  Uninitialized string offset:  0 in [...]/facebook/facebookapi_php5_restlib.php on line 210
PHP Notice:  Uninitialized string offset:  1 in [...]/facebook/facebookapi_php5_restlib.php on line 210
&lt;/pre&gt;

&lt;p&gt;etc&lt;/p&gt;

&lt;p&gt;In my experience the empty result has been in situations where the requested batch operations haven’t been performed, so the fix is to add a test for the empty result and to treat this as an exception. This was my hack:&lt;/p&gt;

&lt;pre class="brush:php"&gt; if (!isset($result[0])) {
            throw new FacebookRestClientException('Batch call returned invalid result: ' . var_export($result, true) . '; ' . var_export($xml, true), 9999);
    }
&lt;/pre&gt;

&lt;p&gt;As a side note, the batching support as implemented in the current PHP API client is rather limited since if one of the batched functions returns an exception it is thrown immediately, with the result that the return values of subsequent calls are not populated and it’s impossible to know whether they executed successfully. I’ve changed the line that threw the exception to instead set the FacebookRestClientException object as the return value for the relevant call as follows:&lt;/p&gt;

&lt;pre class="brush:php highlight:[6,7]"&gt;    for($i = 0; $i batch_queue[$i];
      $batch_item_result_xml = $result[$i];
      $batch_item_result = $this-&gt;convert_xml_to_result($batch_item_result_xml, $batch_item['m'], $batch_item['p']);
      if (is_array($batch_item_result) &amp;&amp;
          isset($batch_item_result['error_code'])) {
        // PATCH: modify to return the Exception object as the result for this call so we can process all results/exceptions
        $batch_item_result = new FacebookRestClientException($batch_item_result['error_msg'], $batch_item_result['error_code']);
      }
      $batch_item['r'] = $batch_item_result;
    }
&lt;/pre&gt;

&lt;p&gt;Hopefully this  helps anyone searching Google..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/177576827</link><guid>http://insomanic.me.uk/post/177576827</guid><pubDate>Wed, 02 Sep 2009 03:00:00 +0100</pubDate><category>facebookapi</category><category>dev</category></item><item><title>If you can't find yourself in Twitter Search..</title><description>&lt;p&gt;I just came across a &lt;a href="http://help.twitter.com/forums/10713/entries/42646"&gt;recent help page from Twitter&lt;/a&gt; (from June) about what to do if your tweets are not showing up in the twitter search. As it already says on the &lt;a href="http://apps.facebook.com/selectivetwitter/help"&gt;Selective Twitter Status help page&lt;/a&gt;, your tweets not showing in Twitter search is one of the most common reasons for the app not working for you, particularly if it used to work but suddenly stopped.&lt;/p&gt;

&lt;p&gt;To check if your tweets are coming up in Twitter search go to &lt;a href="http://search.twitter.com/"&gt;&lt;a href="http://search.twitter.com/"&gt;http://search.twitter.com/&lt;/a&gt;&lt;/a&gt; and type in your twitter username. For example, my tweets should show up at &lt;a href="http://search.twitter.com/search?q=andyy"&gt;&lt;a href="http://search.twitter.com/search?q=andyy"&gt;http://search.twitter.com/search?q=andyy&lt;/a&gt;&lt;/a&gt;. If your tweets don’t appear, Twitter basically say to check Twitter isn’t having any problems at the moment, and if everything is otherwise fine (and your account is public, of course) then your tweets “have most likely been filtered out of our search index for quality reasons” which sadly isn’t much help (unless you really have been spamming, in which case you just gotta live with it.. ;)&lt;/p&gt;

&lt;p&gt;As I mention on the &lt;a href="http://apps.facebook.com/selectivetwitter/help"&gt;help page&lt;/a&gt;, the last thing to try is to protect your Twitter account and then make it public again. You’ll need to post a new tweet after doing this to check if it worked.&lt;/p&gt;</description><link>http://insomanic.me.uk/post/177557169</link><guid>http://insomanic.me.uk/post/177557169</guid><pubDate>Wed, 02 Sep 2009 02:35:00 +0100</pubDate><category>selective twitter status</category></item><item><title>New website..Tumblr it is</title><description>&lt;p&gt;So, I finally got around to setting up a personal website that I’m not ashamed to show people..&lt;/p&gt;

&lt;p&gt;I don’t really blog, but I wanted a home to stick links to my &lt;a href="http://twitter.com/andyy"&gt;Twitter&lt;/a&gt;, &lt;a href="http://www.facebook.com/andyjy"&gt;FB&lt;/a&gt;, &lt;a href="http://www.linkedin.com/in/andrewyoung"&gt;LinkedIn &lt;/a&gt; profiles etc for people that discover me online, collect links to show off when my projects receive press coverage etc as well as post interesting links and other notes from time to time.&lt;/p&gt;

&lt;p&gt;Features I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy setup, hosted solution, no coding required - I’m lazy, didn’t want to spend time on the technical side of a full Wordpress install etc. &lt;/li&gt;
&lt;li&gt;A service with lots of themes so I could find one I liked and do minimal customisations&lt;/li&gt;
&lt;li&gt;The ability to post stuff with tags, so in future I can set up separate index pages for stuff related to &lt;a href="http://insomanic.me.uk/tagged/GroupSpaces"&gt;GroupSpaces&lt;/a&gt;, &lt;a href="http://insomanic.me.uk/tagged/Selective_Twitter_Status"&gt;Selective Twitter Status&lt;/a&gt;, &lt;a href="http://insomanic.me.uk/tagged/entrepreneurship"&gt;entrepreneurship &lt;/a&gt; etc&lt;/li&gt;
&lt;li&gt;My own domain name&lt;/li&gt;
&lt;li&gt;Suitable cool post-from-email/iphone/etc support&lt;/li&gt;
&lt;li&gt;All the above for free!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I looked at &lt;a href="http://www.posterous.com"&gt;Posterous&lt;/a&gt; first but it doesn’t support all of the above right now. The winner is &lt;a href="http://www.tumblr.com"&gt;Tumblr&lt;/a&gt; which was quick to set up, does all the above plus the following bonus features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designed for minimal blogging (posting short snippets, links and videos rather than extended blog posts) that suits the way I want to post&lt;/li&gt;
&lt;li&gt;Handy powerful iPhone app for posting&lt;/li&gt;
&lt;li&gt;Supports &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; - a handy way of entering formatting quickly as you type&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve also integrated commenting powered by &lt;a href="http://www.disqus.com"&gt;Disqus&lt;/a&gt;, which took only a couple of minutes and has a bunch of powerful features (sign in with Facebook etc). I think the default Disqus interface confuses visitors with too many features and wordy instructions so I’ve hidden some parts of the comments interface and tweaked some other stuff out of the way using custom CSS.&lt;/p&gt;

&lt;p&gt;Let’s see how it goes..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/175076071</link><guid>http://insomanic.me.uk/post/175076071</guid><pubDate>Sun, 30 Aug 2009 01:54:00 +0100</pubDate><category>blog</category></item><item><title>new FB iPhone app fixes Selective Twitter Status issue</title><description>&lt;p&gt;&lt;img src="http://9.media.tumblr.com/tumblr_kp5nq0FG9R1qz5fkgo1_400.jpg" align="right"/&gt;&lt;/p&gt;

&lt;p&gt;The new 3.0 version of the Facebook iPhone app now displays all posts by Selective Twitter Status correctly, even if you have the “show follow link” option turned on in the &lt;a href="http://apps.facebook.com/selectivetwitter/settings"&gt;settings&lt;/a&gt; :)&lt;/p&gt;</description><link>http://insomanic.me.uk/post/174930644</link><guid>http://insomanic.me.uk/post/174930644</guid><pubDate>Sat, 29 Aug 2009 21:44:00 +0100</pubDate><category>Selective Twitter Status</category></item><item><title>European Entrepreneurs Come to Life with their Latest Creations</title><description>&lt;a href="http://www.weblogtheworld.com/united-kingdom/european-entrepreneurs-come-to-life-with-their-latest-creations/"&gt;European Entrepreneurs Come to Life with their Latest Creations&lt;/a&gt;: &lt;p&gt;Features an interview with David about GroupSpaces&lt;/p&gt;</description><link>http://insomanic.me.uk/post/174782662</link><guid>http://insomanic.me.uk/post/174782662</guid><pubDate>Sat, 01 Aug 2009 00:00:00 +0100</pubDate><category>GroupSpaces</category></item><item><title>Warwick Young Entrepreneurs Forum Talk on 98point2.com</title><description>&lt;a href="http://98point2.com/system/2009/03/07/young-entrepreneur-event/"&gt;Warwick Young Entrepreneurs Forum Talk on 98point2.com&lt;/a&gt;: &lt;p&gt;Thanks to Sam Fianu for a write-up of the talk I gave at the Young Entrepreneurs Forum organised by &lt;a href="http://www.warwickentrepreneurs.com/"&gt;Warwick Entrepreneurs&lt;/a&gt; this weekend.&lt;/p&gt;</description><link>http://insomanic.me.uk/post/84774710</link><guid>http://insomanic.me.uk/post/84774710</guid><pubDate>Mon, 09 Mar 2009 03:52:00 +0000</pubDate><category>entrepreneurs</category></item><item><title>Q&amp;A: TechCrunch UK's Editor Mike Butcher talks about the internet startup landscape</title><description>&lt;a href="http://econsultancy.com/blog/3077-q-a-techcrunch-uk-s-editor-mike-butcher-talks-about-the-internet-startup-landscape"&gt;Q&amp;A: TechCrunch UK's Editor Mike Butcher talks about the internet startup landscape&lt;/a&gt;: &lt;p&gt;Mike mentions GroupSpaces as one of the startups really standing out in the UK. Cheers Mike!&lt;/p&gt;</description><link>http://insomanic.me.uk/post/66296716</link><guid>http://insomanic.me.uk/post/66296716</guid><pubDate>Mon, 22 Dec 2008 22:37:00 +0000</pubDate><category>GroupSpaces</category></item><item><title>Where are they now: Ones to Watch 2007</title><description>&lt;a href="http://blogs.freshminds.co.uk/talent/?p=621"&gt;Where are they now: Ones to Watch 2007&lt;/a&gt;: &lt;p&gt;Cheers to Charlie from Freshminds Talent for a write-up of the Spectator piece.&lt;/p&gt;</description><link>http://insomanic.me.uk/post/63929957</link><guid>http://insomanic.me.uk/post/63929957</guid><pubDate>Tue, 09 Dec 2008 17:57:03 +0000</pubDate></item><item><title>2020 Vision: Tomorrow's Stars</title><description>&lt;a href="http://www.spectator.co.uk/business/the-magazine/entrepreneur/3058216/part_3/2020-vision-tomorrows-stars.thtml"&gt;2020 Vision: Tomorrow's Stars&lt;/a&gt;: &lt;p&gt;Featured in Spectator Business Magazine by &lt;a href="http://twitter.com/edielush"&gt;Edie&lt;/a&gt; along with &lt;a href="http://twitter.com/langer"&gt;Langer&lt;/a&gt;, &lt;a href="http://www.linkedin.com/pub/8/ba7/606"&gt;Victoria&lt;/a&gt;, &lt;a href="http://www.oxfordentrepreneurs.co.uk/archive/2007/04/20/rajeeb-dey/"&gt;Raj&lt;/a&gt; and &lt;a href="http://twitter.com/hermioneway"&gt;Hermione&lt;/a&gt;&lt;/p&gt;</description><link>http://insomanic.me.uk/post/63664235</link><guid>http://insomanic.me.uk/post/63664235</guid><pubDate>Mon, 08 Dec 2008 09:19:36 +0000</pubDate></item><item><title>GroupSpaces included in a video montage of “30 Hot UK Web...</title><description>&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/gvRRbQNbnn0&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/gvRRbQNbnn0&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;GroupSpaces included in a video montage of “30 Hot UK Web Companies” created by &lt;a href="http://www.appappeal.com/"&gt;AppAppeal&lt;/a&gt;&lt;/p&gt;</description><link>http://insomanic.me.uk/post/49426203</link><guid>http://insomanic.me.uk/post/49426203</guid><pubDate>Tue, 09 Sep 2008 17:11:00 +0100</pubDate><category>GroupSpaces</category></item><item><title>Three to watch in the student space: GroupSpaces on TCUK</title><description>&lt;a href="http://uk.techcrunch.com/2008/09/04/three-to-watch-in-the-student-space/"&gt;Three to watch in the student space: GroupSpaces on TCUK&lt;/a&gt;</description><link>http://insomanic.me.uk/post/48813163</link><guid>http://insomanic.me.uk/post/48813163</guid><pubDate>Fri, 05 Sep 2008 04:24:00 +0100</pubDate><category>GroupSpaces</category></item><item><title>GroupSpaces featured in the Oxford Times' In Business magazine</title><description>&lt;a href="http://www.theoxfordtimes.net/business/it/display.var.2354794.0.team_spirit.php"&gt;GroupSpaces featured in the Oxford Times' In Business magazine&lt;/a&gt;: &lt;blockquote&gt;&#13;
&lt;p&gt;Andrew Young, the 23-year-old co-founder of Internet company GroupSpaces.com, has a bit of a dilemma.&lt;/p&gt;&#13;
&lt;/blockquote&gt;



&lt;p&gt;Entertaining article. Average number of factual errors per paragraph: 2..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/39337522</link><guid>http://insomanic.me.uk/post/39337522</guid><pubDate>Sun, 22 Jun 2008 02:54:00 +0100</pubDate><category>GroupSpaces</category></item><item><title>Entrepreneurship is in Rude Health</title><description>&lt;a href="http://blogs.telegraph.co.uk/business/yourbusiness/june2008/entrepreneurship-is-in-rude-health.htm"&gt;Entrepreneurship is in Rude Health&lt;/a&gt;: &lt;p&gt;Richard Tyler (Daily Telegraph’s Enterprise Editor) blogs about &lt;a href="http://www.oxfordentrepreneurs.co.uk"&gt;Oxford Entrepreneurs&lt;/a&gt;’ &lt;a href="http://groupspaces.com/oxfordentrepreneurs/item/7162"&gt;100 influential&lt;/a&gt; meal last night..&lt;/p&gt;</description><link>http://insomanic.me.uk/post/37403873</link><guid>http://insomanic.me.uk/post/37403873</guid><pubDate>Fri, 06 Jun 2008 15:42:00 +0100</pubDate><category>entrepreneurs</category></item></channel></rss>
