Startup Journey

 

tl;dr: startup life is a roller-coaster ride with highs, lows & many lessons learnt along the way.

After quitting work in September 2012 this has been my first chance to write about my (limited) startup experience as a struggling entrepreneur and co-founder of Contactable. It has basically been a roller-coaster ride so far, filled with highs and lows that are unpredictable at best. But along the way many lessons have been learnt, and many more to be learnt.

Highs:

  1. Making it to (top 20) interview stage of Startmate – arguably Australia’s leading incubator – only having worked on it for a couple of months while others have worked on it possibly longer.
  2. A sense of accomplishment as I feel like I’m working on something that might make a small dent in the universe (even if it’s a small dent).
  3. A sense of freedom as I get to choose what I want to work on. This comes from having a say in strategic direction and knowing that the input I provide counts.
  4. Staying hungry – it is the adrenaline you get due to a combination of fear of failure & a limited personal runway that seems to become shorter everyday. This feeling of hunger makes you realise that you know that you need to make your idea successful, if not you’ll just be a pauper.

Lows:

  1. Stress (about making money & coming up with a ‘sound’ business model)
  2. Stress (emotional stress I cause on others e.g. girlfriend, co-founder)
  3. Stress (fear of failure)
  4. Stress (working on a problem that matters – is the problem I am working on a ‘blood on the floor’ problem? Should I pivot? Should I consider working on a completely different problem entirely?)

Lessons learnt:

  1. You have to think long and hard about what you are doing and why you are doing it. This matters especially to me as I have a limited personal runway. 
  2. Apply the ‘Lean Startup’ approach whenever possible (primarily testing assumptions at a fast pace) and sometimes taking a ‘leap of faith’ approach.
  3. Learning curve is high so brace yourself as you will be driving at 200+km/h. This includes (but not limited to) learning things like growth hacking (applying analytics), marketing, hustling and pitching.
  4. Being a ‘jack of all trades’ helps in entrepreneurship. So far, this has included coding, doing cold-calls, hustling, dabbling in design as well as a plethora of other activities that will be too long to list down. Luckily, I have an awesome co-founder (Shaon) who has stuck it out with me. The only reason why you have to be this way is you just don’t have enough funds to hire people. I would love to hand-off administrative tasks if possible :-)
  5. Hustling is a very important part of entrepreneurship – on equal par (if not more than) with coding + design. To believe the philosophy: ‘build it and they shall come’ relies on luck and I have seen this not work out in my previous work. I am not great at hustling and have realised this is one of the areas I need to become more proficient at. I am a bit of an introvert and I feel that entrepreneurship will hopefully get me ‘out of my shell’
  6. Pivoting is sometimes inevitable as it’s a manifestation of learning. Not sure where Contactable is headed, but with the recent release of Evernote Hello 2.0 (it has almost all the features we were planning e.g. audio business card exchange + syncing with calendar) it has caused a bit of a low but luckily we have rethought our UVP and are testing some of our assumptions as I’m writing this. 
  7. Long hours is inevitable as a startup entrepreneur as you are smaller than your other competitors. And what makes you great is that you are nimble in nature due to your size and also means you are faster at executing. 
  8. Momentum is important. Every time I hear something that is encouraging, it gives me an extra boost of energy to continue on with my endeavours.
  9. Execution is everything. People are full of ideas, but finding the ‘right’ team to build it and actually building it is the hard part. Hopefully, you will hear more about this in a latter blog post as I believe this is a massive pain point for entrepreneurs :-)
  10. The entrepreneurial community is a very helpful community and one that many people I have seen leverage. More so with the Silicon Beach Australia which has been a very helpful mailing list to date.

These are just some of my thoughts and hopefully I will get time to blog more about this and expand on some of these points more.

How not to display fault exception messages

With the imminent release of the iPhone 4 in Australia, I received an email from Optus to pre-register for the lineup outside the Optus stores.

Unfortunately, when I visit the link: Optus pre-registration I get the following error message:

Hypersite with URL 'https://optusiphone4.com/content/launch?elq=97148e61ae704842868620d3dcf34102' could not be found  (Fault Type: System.ServiceModel.FaultException) - (Fault Code: System.ServiceModel.FaultCode)

This is a SOAP exception error and indicates this site uses M$ ASP.NET.I am dumbfounded that this error message is not more properly handled (as indicated by MSDN FaultException better fault handling should occur via using a FaultContractAttribute) and a more intuitive web page is provided e.g. a web page with “Thankyou for your interest but currently we are overloaded. Please try again later” or even cooler a Twitter version of a Fail Whale will suffice , though I suspect they did not expect this level of interest for the release of the iPhone 4 in Australia.

Quirks of PHPUnit & Xdebug setup in Ubuntu 9.10 (Karmic Koala)

PHPUnit is a good Unit Testing framework for PHP and works well with the Zend framework.

Setup Quirks for PHPUnit & Xdebug

It is especially easy (installing & configuring via PEAR – PHP equivalent of CPAN for Perl) [thank you Sebastian for the update]:

>sudo apt-get install php-pear
>sudo pear upgrade-all PEAR
>sudo pear channel-update PEAR
>sudo pear channel-discover pear.phpunit.de
>sudo pear install pear.phpunit.de/phpunit

Install the xdebug libraries as well:

>sudo apt-get install php5-dev
>sudo pecl install xdebug

Edit the file /etc/php5/apache2/php.ini and add the following two lines to the bottom of the file:

[xdebug]
zend_extension="/usr/lib/php5/20060613+lfs/xdebug.so"

(Note that the xdebug.so file might be located in a different directory. Please double check this).

PHPUnit Code Coverage Memory Quirk

Another quirk is a memory hog issue that exists with the code coverage reporting done by PHPUnit.

As PHPUnit is run from the command line, you will need to modify the ‘cli’ version of the php.ini file than rather apache2 directory version.

> vim /etc/php5/cli/php.ini

And look for the memory_limit variable and set it to 512 Mb (Yes, it does take a lot memory!!).

>memory_limit = 512 M

This is recommended by Jeffrey Sambells

PHPUnit erroneous package Quirk

It appears that PHPUnit uses YUI for the javascript even though t is disabled in /usr/share/PHPUnit/TextUI/TestRunner.php ($arguments[‘reportYUI’] = FALSE;)

The error message being reported is the same as reported on Ubuntu launchpad:

# phpunit --coverage-html coverage-html application
 PHPUnit 3.3.16 by Sebastian Bergmann.
Time: 0 seconds
OK (0 tests, 0 assertions)
Generating code coverage report, this may take a moment.
 Warning: copy(/usr/share/php/PHPUnit/Util/Report/Template/container-min.js): failed to open stream: No such file or directory in /usr/share/php/PHPUnit/Util/Report.php on line 242
Call Stack:
 0.0008      95544   1. {main}() /usr/bin/phpunit:0
 0.4147    6243128   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:52
 5.0970    6249232   3. PHPUnit_TextUI_TestRunner->doRun() /usr/share/php/PHPUnit/TextUI/Command.php:128
 5.0979    6263480   4. PHPUnit_Util_Report::render() /usr/share/php/PHPUnit/TextUI/TestRunner.php:424
 5.0989    6268848   5. PHPUnit_Util_Report::copyFiles() /usr/share/php/PHPUnit/Util/Report.php:115
 5.1511    6272616   6. copy() /usr/share/php/PHPUnit/Util/Report.php:242
Warning: copy(/usr/share/php/PHPUnit/Util/Report/Template/yahoo-dom-event.js): failed to open stream: No such file or directory in /usr/share/php/PHPUnit/Util/Report.php on line 242
Call Stack:
 0.0008      95544   1. {main}() /usr/bin/phpunit:0
 0.4147    6243128   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:52
 5.0970    6249232   3. PHPUnit_TextUI_TestRunner->doRun() /usr/share/php/PHPUnit/TextUI/Command.php:128
 5.0979    6263480   4. PHPUnit_Util_Report::render() /usr/share/php/PHPUnit/TextUI/TestRunner.php:424
 5.0989    6268848   5. PHPUnit_Util_Report::copyFiles() /usr/share/php/PHPUnit/Util/Report.php:115
 5.1743    6272616   6. copy() /usr/share/php/PHPUnit/Util/Report.php:242"

The fix for this is relatively straightforward, though having an updated package should alleviate this. Doing a bit of googling showed there is a patch. Looking at the patch it was a simple case of editing /usr/share/php/PHPUnit/Util/Report.php and removing the offending javascript lines from the php script:

-- /usr/share/php/PHPUnit/PHPUnit/Util/Report.php
+++ /usr/share/php/PHPUnit/PHPUnit/Util/Report.php
@@ -230,12 +230,10 @@
 'chameleon.png',
 'close12_1.gif',
 'container.css',
-          'container-min.js',
 'glass.png',
 'scarlet_red.png',
 'snow.png',
 'style.css',
-          'yahoo-dom-event.js'
 );

Hope this helps whoever comes across the same quirks when setting up PHPUnit.

Python – 2 legged OAuth Woes

While I have been programming with Python I have found the following intricacies with the OAuth 2-legged approach, in regards to using web based APIs (all the examples are in Python & refer to the Vimeo API).

Note I don’t believe this is well documented, and have at times found the following confusing:

  1. When using Web based APIs, one does not need to be concerned about the concept of ‘tokens’ if you are using a 2-legged OAuth approach (even though alot of sites proclaim that one should always be requesting for tokens, and even the python OAuth APIs that exist in github.com don’t really indicate that one does not need tokens). This basically means you do not need a token if you are doing a HTTP ‘GET’ request (depending which web based API you are using).
  2. When using 2-legged OAuth (or 3-legged for that matter), you must indicate all the parameters that are going to be sent using the HTTP ‘GET’ request (equally this should apply for ‘POST’ requests as well) before you generate a ‘signature method’.
  3. As of OAuth Standard 1.0a I believe there is a slightly broken nature in how OAuth is used and believe it is actually a flaw in the OAuth protocol, which I discovered by accident. When using a 2-legged approach (refer to example below), this method will ‘intermittently’ work, when I first tested this (using the vimeo API), it actually worked for the 1st iteration, but failed consecutively for 3 iterations before working again and then intermittently after that:
#Using Leah Culver’s Python library @ http://github.com/leah/python-oauth
#Note I have deliberately left out my API key and secret for the purposes of this blog post
consumer = oauth.OAuthConsumer(VIMEO_API_KEY, VIMEO_API_SEC)
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url=VIMEO_API_URL)
oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1() , consumer, None)
#After I sign the request then I form the other parameters with the corresponding values:
http_request = ‘http://vimeo.com/api/rest/v2?’ + ‘apiMethod’ + ‘param_value’ + str(oauth_request.to_postdata())

I originally thought it was a bug on the web API provider’s end, but it turned out to be a bug on how I perform the OAuth signing request. Basically, the bug was that I was signing the request before setting/applying the web API methods/parameter values I wanted (which obviously changed the hash of the signing request method). However, I believe that because it does not require a token, you can ‘brute force’ it to intermittently work if you call it enough times (possibly because the hash code for the request signature matches once in a while).

However, with a bit of help from using the php example provided by vimeo for their OAuth API, I figured out that one had to encode the parameters before signing the request:

consumer = oauth.OAuthConsumer(VIMEO_API_KEY, VIMEO_API_SEC)

oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url=VIMEO_API_URL)

oauth_request.set_parameter(‘format’, ‘json’)

oauth_request.set_parameter(‘method’, ‘vimeo.videos.getByTag’)

oauth_request.set_parameter(‘tag’, tagname)

oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1() , consumer, None)

http_request = ‘http://vimeo.com/api/v2?’ + str(oauth_request.to_postdata())

Note: you could manually identify each OAuth required parameter without using the method: ‘from_consumer_and_token()’ but I found it easier to use it to save some code space (though I think the name is somewhat counterintuitive) as a non-token http url needs to be specified and is used for 2-legged OAuth.

Hope this helps anyone else who is trying to figure out how to use 2-legged OAuth (whether using Python or not) and is using examples from the web or from examples in an OAuth library, though I believe all examples I found only covered 3-legged approach, which requires an actual token request! I don’t believe a wrapper needs to be written for the 2-legged approach but there needs to be better examples to help facilitate developers understanding the 2-legged approach.

iPhone 3.0 GM Seed Installation

I have found a problem with building in XCode after installing the SDK for the iPhone 3.0 GM Seed on top of the iPhone 3.0 Beta 5 release. When doing a build: Command + Enter, for a project built for iPhone 3.0 Beta 5, an error message pops up that indicates the developer certificate has been added, modified or deleted.

Solution: You have to go back to the target, and then toggle the Code Signing Identity->Any iPhone OS Device to iPhone Developer.

This might be because I had XCode running while doing the installation of the GM Seed and had to use the ‘kill’ terminal command.

Adding icon to iPhone springboard

Adding an icon is pretty easy. Make sure the picture is saved as a *.png.
Drag’n drop this into XCode, underneath your project, under the section/folder Resources.
You will be prompted if you want to copy the file or use the path. Copying is better as the picture will reside with the project. All you have to do then is build’n run.

iPhone 3.0 Beta Environment Setup

This is my first foray into iPhone development (especially with using iPhone beta firmware). This was slightly more challenging, as it required the use of a Beta OS, than rather a released iPhone OS firmware.

Firstly, you will need to enroll into the iPhone dev. This will require an Apple ID. 

From my experience it was easier to enroll as a single developer than rather as a company/business (as it required less documentation) and the turnaround time was 1-2 days (this included acceptance of payment for developing).

Please checkout: http://developer.apple.com/iphone  for further information

Follow the instructions as per the website above. 

Generally, the process is the following:

  1. Download SDK, OS Firmware and iTunes images (these should be in format *.dmg)
  2. Install the software as usual (the OS Beta Firmware is a little different – read next point)
  3. When installing a beta version of the iPhone OS (eg. iPhone 3.0 Beta 5) in iTunes you have to hold the ‘Option’ key and then left mouse click on ‘Restore’. The restore button is located under ‘Devices’ ->your iPhone name->Summary->Version section. I found this counter intuitive and not well documented. This will open a dialog box for you to select your iPhone OS Firmware. Navigate and select the beta OS. Remember this will wipe out all the Apps on the iPhone but will not actually wipe anything else off (as long as you did a backup).
  4. Click on the iPhone Developer Program Portal’ on the right hand pane.  (This took me forever to find!)
  5. Follow the process of creating a team name, developer certificate, App ID and Provision certificates. Note the  developer certificate and provision certificate are most important and have to be installed on both the KeyChain and in XCode Organizer, respectively. 
  6. In XCode, for the respective applications, make sure the Target information is correct. That is:
  • Base SDK = iPhone Device 3.0
  • Code Signing Identity=iPhone <name> (this is the developer certificate name on the Key Chain).
  • Identifier=com.domainname.AppName

When running XCode I had a simple ‘hello world’ app that . However, I ran into a few issues. 

Error: XCode would not build the app as the Identifier: com.domain.AppName was incorrect or could not be recognised.

Fix: The fix was the Provisioning certificate was only dragged into the Provisioning section of the Devices->iPhone Name in XCode Organizer. However, this was NOT the only place to put the provisioning certificate, you also had to drag’n’drop it into IPHONE DEVELOPMENT->Provisioning Profiles as well!

Error:  XCode and A signed resource has been added, modified, or deleted.

Fix: “*If you do not have the WWDR intermediate certificate installed, click here to download now.”

The above link basically downloads the following: AppleWWDRCA.cer (Apple World Wide Relations Certificate Authority). This means that you need two certificates installed on your Mac OS X keychain in order to build the application.  Therefore, your keychain should have the following 2 certificates:

  • iPhone Developer: <name> (this is the one you were told to generate and download via the iPhone portal)
  • Apple Worldwide Developer Relations Certification Authority 

Issue: XCode cannot find the software image to install this version. 

This error can be seen when navigating to the IPHONE DEVELOPMENT->Software Images section as there is no 3.0 Beta version. This does not stop the app to be installed and run, but the ‘Console’ reports of ‘Unknown Kernel [0]‘ messages. 

Fix: Unknown.   The iPhone firmware images are placed at /Users/<username>/Library/iTunes/iPhone Software Updates. Note the firmware has an extension of: *.ipsw. Therefore, open the file iPhone OS 3.0 Beta .dmg and then copy the .ipsw file into the directory mentioned. This DOES NOT remove the message ‘Unknown Kernel [0]’ but it appears to be just a notice message <Debug> and is not an actual error.