Author Archives: Ryan Tan

Building with old iPhone SDKs with new XCode versions

If you have recently updated to the latest version of XCode you might be wondering how to get your 6.1 iPhone SDK back. The new XCode versions do not come with previous iPhone SDK’s so we need to obtain them from older XCode (download them from Apple) and symbolic link them to the right place. First, copy the SDK’s from the download and place them somewhere which wouldn’t get replaced on future XCode upgrades. For my case I left them in /SDKs/iPhoneOS.platform/Developer/SDKs. Next, show package contents of your current XCode.app and navigate to Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs, and make the link with this:

sudo ln -s /SDKs/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk iPhoneOS6.1.sdk

Just remember to redo the links whenever you update XCodes.

Collaborative Consumption Reputation

Collaborative Consumption Reputation Score – A way for various platforms to work together?

Think of it as your Klout score, but instead of measuring social influence, it’s a aggregate score of your reputation across various collaborative consumption platforms. Implementation wise it can be as simple as an automatic crawler that collects these statistics from the public profiles from each platform, or having each platform adhere to a standard set of rest endpoints returning the scores for each user in the platform.

It would be a place where people can find out whether you trashed your last AirBnB room, whether you returned the car in proper condition on iCarsClub, whether you provided accurate description on RentTycoons, or even if you did return the items you exchanged on Leendy by the stipulated time. In time, this score might be as, or even more, valuable than your social influence score. Especially when Collaborative Consumption isn’t a trend, it’s a way of life and it’s here to stay.

The score itself might be represented as a percentile within each system. e.g. if the user’s rep is above 75% of all users in AirBnb, his component from AirBnb would be 75, etc. Then each component from different platforms would be normalized by the the number of actions/transactions made on each system, and in time it may be modified with recency as well.

Apps in SG – A showcase of Apps designed and built in Singapore

I realised people outside of the development and entrepreneur circles are often unaware that there are many talented app designers and developers in Singapore. And when I try to show them examples, there isn’t such a list of made in Singapore apps. You either know that autumn dynasty is one of the top selling games made locally, or you don’t.

AppsInSG.com is first and foremost a quick way to showcase beautiful and/or useful apps released by locals, and the talented people and companies behind them. Although the list is heavily biased towards mobile apps at the moment, I’m working to include more web, desktop, and even console apps in the coming weeks. I hope it can grow to provide additional exposure for newly launched apps, inspiration, and eventually a place for developers and designers looking for work at interesting companies.

Know a beautiful or useful app made by Singaporeans? Make a suggestion here.

Parse with deprecated Facebook headers on iOS gives “Semantic Issue” errors

If your app uses the deprecated Facebook headers, i.e. #import "Facebook.h" instead of #import <FacebookSDK/FacebookSDK.h>, importing Parse.h using the standard instructions at https://www.parse.com/apps/quickstart_push would fail your build with multiple errors of

Semantic Issue, Redefinition of enumerator 'FBSessionsStateCreated', 'FBSessionState....', etc.

The issue is that Parse imports the Facebook headers internally. To work around this, open Parse.h and replace

#if __has_include(<FacebookSDK/FacebookSDK.h>)
#import <FacebookSDK/FacebookSDK.h>

with

#if __has_include("Facebook.h")
#import "Facebook.h"

Next, open PFFacebookUtils.h and replace #import <FacebookSDK/FBSession.h> with #import "FBSession.h" and you’re good to go.

MVP vs BVP

The Barely Viable Product

The term minimum viable product shouldn’t be foreign for startups. It represents the fatest route to market, a product that has the minimum set of features that allow the product to be deployed (and gather data), and no more. It’s a simple concept to grasp, with obvious benefits, and most entrepreneurs I know at the prototyping phase use the term as if it’s common sense. Yet, I still see many MVP’s taking double the expected amount of development time, and launching with a feature set that is just shy from version 2.0. Where’s the disconnect?

There is nothing wrong with the term and its definition. The issue doesn’t seem to lie with the intention and sincerity of those using the term as well. The problem seems to lie in the perception of “minimum”. I’ll attempt to illustrate this using a series of grayscale gradients.

This is how the desired features of a product can be listed in an ideal universe. Each feature is easily categorized as essential, or not. In practice, this is hard. The features more than likely appear as the following to a product developer:

And the actual features implemented as the “minimum viable product” usually becomes:

Although this is still much better than implementing all the features and delaying the launch, it is straying quite far from the original intention of a MVP. Remember we are not just comparing time spent developing those extra features, you need to include iterations and testing as well, and each new feature adds to the total time non-linearly. Reflective developers would probably make a note to themselves to stay closer to the objective next time around. Some may kick themselves for failing to do so yet again.

Its easy to attribute this to greediness and lack of discipline, but I feel its more likely due to the ambiguous nature of the term “minimum” – where do you draw the line in the grey area? Any feature seems just as a good fit under the minimum label as the other. Therefore I am proposing a new term to help product developers deal with the idea of minimum – the Barely Viable Product.

The term barely inherently denotes a much less greedy approach to selection – you are not even selecting what’s minimum, you just want it to be barely viable. I hope this conjures such an image when translated into my greyscale gradient:

Much better isn’t it?

The barely viable product isn’t a replacement for the ideas and concepts behind the original term, but a new guide when picturing the minimum viable product. I hope this simple alias would help startups form a bettre mental picture of what they are trying to achieve. The truth is, product developers would still stray, but hopefully much less. This change of perception is a kind of reverse of the aim-for-the-stars-and-reach-the-moon way of thinking, it’s more like the experts’ way of packing for a trip – pack what you need then throw out a third.

Perception aside, startups need to be reminded to use BVP in conjunction with the underlying aim of learning about customers, not just early releases. It is definitely helpful to release and start gathering customer feedback but make sure what you are releasing allows you to do that. In the end its more about customers than your product, you’ll still need to figure out a balance yourself.

Beta Testing for Leendy

After 3 months of weekend development sessions, I’m excited to finally start the beta testing phase for Leendy. I’ve even squeeze out time to do up the website and Facebook page!

Leendy is the easiest way to share and swap things among friends while saving the earth. It is based on the collaborative consumption philosophy of sharing to cut down on resource wastage and allow everyone to enjoy more value out of existing items. If you have an iPhone and some free time, why not register as a tester?

Running manage.py locally with auto pythonpath

While trying to run my manage.py locally to syncdb, it complains that my project’s .settings isn’t in the sys.path. Instead of setting it manually, I decided to add it into the manage.py script itself:


from os.path import abspath, dirname
sys.path.insert(0, dirname(dirname(abspath(__file__))))

This works perfectly in Django 1.6 on Python 2.7+

Drupal 7 – Debugging Illegal offset type in isset or empty in … and other errors

Though the title mentions Drupal 7, this article is really about the debugging technique and so is applicable to general php as well. I want to share a recent bug we had to solve at work. Though experienced developers would usually have an idea what new code is breaking, mysterious warnings and errors sometimes do slip through while working in teams (even when having a proper svn system in place!). You check with your co-developers and the one who broke it have no idea where this might be coming from, or worse: they have seen and have been ignoring this error for some time because they felt it didn’t matter. What do you do then?

Read the error
The error message “Illegal offset type in isset or empty in…” points to an illegal type used in a call to isset or empty, and it conveniently points you to the offending line – but with Drupal’s (and most of today’s frameworks’) complex page execution flows, it is hard to spot where is the real source of error, especially if the line is in one of the framework’s frequently called core routines (in my case it was in user_access). Since this is not much help in trying to deduce the real source, I resort to setting my own error handler (temporarily overriding Drupal’s) so that I can do a debug_back_trace().

To set your own error handler, define a function and feed the name to php’s set_error_handler():
[php]
// Your custom handler
function my_error_handler($errno, $errstr, $errfile, $errline
, array $errcontext)
{
// error was suppressed with the @-operator, ignore
if (0 === error_reporting()) {
return false;
}

// print the backtrace
echo ‘<pre>’.print_r(debug_backtrace(),true).'</pre>’;

// throw an error exception if you want to catch it at the caller
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}

// Back at the offending line:
set_error_handler(‘my_error_handler’);

try {
// original code
}
catch (ErrorException $e) {
// print your own debug log or what not
}

// Restore Drupal’s own error handler. You don’t want a backtrace
// on every other E_USER_NOTICE’s do you?
restore_error_handler();

[/php]

While you may find it useful to convert every error into an exception, note that even E_USER_NOTICE would then halt your page execution, so please use with care (refer to php manual on the ErrorException class for a handler that ignores non-fatal errors).

Now, what’s left is to carefully read through the debug backtrace and spot the problem. For my case, it was a line of code someone embedded in a view context. Hope this helped, share your own debugging methods and opinions in the comments.

End note
Some people may feel that my style of debugging isn’t very ‘elegant’ but my experience is that the fastest way to find the problem isn’t necessarily the most elegant way. Rather than going through hours of deducing which functions might or might not be involved, and later realising the problem was in one of those functions that “logically shouldn’t have mattered in this case”, I find that getting a solid backtrace – after a quick deduction fails – is usually my best bet in the long run.