Hiltmon

On walkabout in life and technology

TimeToCall - the Effort and the Return

TimeToCall is a simple, universal iOS application I developed to help people choose the best time to call when calling internationally. This is part 1 in a series of posts about the thinking and work done. My goal is to share just how much effort it really does take to craft an iPhone app and ship it. I hope this series helps you to understand why it costs so much and takes so long to create beautiful software.

The Application Scope

TimeToCall is a very simple universal application that contains only four views. Users can create named Times to Call to figure out when it is best to call a set of foreign locations. For more about what the application does, see the TimeToCall product page.

In order to achieve this limited scope, I constructed four views:

The first view, Master, is just a table view with rows for each Time to Call. The second view, Detail, displays all the information we have about a Time to Call and enables the user to ‘play’ with time, the primary action of the app. The third view, Edit, enables the user to change the Time to Call’s location, name and destination. And the final view, Picker, enables the user to browse or search for locations.

Behind that is a simple data model that stores an array of these Time to Call objects. And a data set of places and their timezones.

A simple scope. A simple implementation. How long do you think it would take to do it right?

The Effort

In total, the application, from first blush to submission to the App store took about 100 hours.

Yes, ONE HUNDRED HOURS. I used a timer.

It involved designing, coding, creating artwork, iterating, animating, testing, and then doing that all again for the iPad. And then creating localizations and data files. And fixing bugs and performance problems. And polishing and beta testing.

Sounds like a lot.

The reality is that these 100 hours are just the start for most applications. Most are more complex, have more views, interact with servers and do more things.

Oh sure, you can cut the time down, by not doing a universal version, by not creating any animations, or by not polishing or testing. But if you want people to like, nee love, your app and use it and tell others, you really need to put the effort in.

Lets assume an hourly rate of US$150.00, then 100 hours means a $15,000.00 cost. That seems a lot for a simple app with only four views (and no bugs)! Dropping iPad will maybe save you $3,000.00. Adding features will just increase the time and cost.

The effort shows that creating a polished iOS app is not a quick nor cheap option. Even if the app is so simple.

The Return

Creating the application is the investment, income from sales is the return.

I could put this app up on the store for free. After all, it’s my time, my design, my effort and if you ignore the opportunity cost, that makes it theoretically cost free. The return on investment of a free app is zero. There is none. You’re giving it away.

Free does work for some developers. They want this magical unicorn-like thing called exposure. Or they want bragging rights that they have a large number of users. But in reality, they need to support and update the free app for free. Or, like many, they either choose to ship and stop, or they run out of money and have to get a real job so they stop. No support, no love for their customers, no real way to build a business or a long term relationship.

That is no good. There should be a return. Lets say I price the app at 99c a pop and we run a break-even analysis:

I need to sell 21,429 copies of the app to get my investment back and not lose any money. Given that this is such a simple app, no other price point makes sense, so no need to test them too.

If I sell 30,000 copies, I earn $21,000, or a $6,000 profit. Sounds good. Or 40,000 copies is a $13,000 profit. Sounds better. With numbers like these, it is easy to get starry eyed and forget about rent, food and taxes.

But what is the probability of actually getting these sales numbers? Well, if you Google around, you’ll find an old study that shows more than half of the paid apps on the App Store sell less than 10,000 copies (after they took out outliers). You’ll also find lots of articles on the few outliers who did sell millions and how they are taking a growing lion’s share of revenue out of the App store. And then there are lots of articles containing total download figures that include the millions of free app downloads, so it sorta kinda seems all apps do well.

Within all that noise is this truth. The majority of paid apps on the App Store don’t even get close to 5,000 units sold, never-mind the old study’s 10,000 figure. Which means the probability of TimeToCall achieving less than one third of the sales needed to break even is above 60%. Economically, it’s almost guaranteed to be a disaster, a loss making exercise.

My Expectations

I will sell the app for 99c, I will not give it away. I did spend 100 hours making it.

I expect to sell a couple of hundred units over the next few months as friends and family and some of my readers purchase the app.

I expect to leave the app on the store for at least a year, but do not expect to ever exceed the 5,000 unit mark (50% probability).

I intend to spend more time (and therefore increase the cost and break-even) by supporting the product, issuing bug fixes and adding features.

I do not expect to make a penny in profit off of this app, ever! The chances of getting to even 21,429 units sold is just far too low.

So really, why do it then?

I wanted to do this for several reasons:

  • I wanted to check and ensure that my project estimations were accurate. Normally when a client requests an estimate, I have incomplete information about the app’s feature set, so I estimate what I know, and add a ‘fudge’ factor for the unknowns. With this app, I knew the full feature set at the start and made an estimate. After creating the app, I realized there were tasks I did not usually include in the estimate and now understand why my estimates are all a tad short. A good learning experience and better for my clients.
  • I needed to update my iOS skills after a year in Rails-land. The last few iOS apps I did were pre-retina, pre-blocks, pre-ARC, on old versions of iOS. I wanted to both learn the newer technologies and also get a feel for how much time they saved. Which is why this app uses Core Animation, ARC, blocks and all the new and cool iOS technologies I could squeeze into it.
  • I needed an app on the App store for portfolio purposes. I had pulled my old apps over a year ago as they did not reflect my current skill-set. And they were not really selling anyway. But clients do ask if there is an app they can download to get a feel for what I can produce.
  • I wanted a real-world but fenced application development process to write about. I feel that there really does need to be a documented real-world example that helps potential clients to understand all that goes in to an app and why it costs what it does and takes as long as it does.

Next: Part 2: Building the Core.


 
TimeToCall can be downloaded from the App Store for 99c.

I hope you enjoy this series of articles on what goes in to the design and development of an iPhone or iPad application, and have a better feel for why these things take so much time and cost so much. If you like them, buy TimeToCall from the App Store, it helps me continue to write, and please tell your friends about these articles and this product.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Time to Call - Coming Soon

“Ring Ring”

“Hmmmm Hello”

“Er Hi Mum”

“Mum”

“MUUUM”

“Do you know what the time is?”

“I know it’s after work in Sydney, but it’s 3AM here in New York”

“Yes I was sleeping”

“No, no, I’m awake now”

“Just please check the time before you call”

Never know when is the best time to call people overseas?

TimeToCall is coming soon for the iPhone and iPad.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Dog With a Bone

I think one thing that is unique about programmers is that we are tenacious about getting a problem solved. As tenacious as a dog with a bone to chew. It irks us when things are not perfect, but instead of ignoring it or putting up with it, we put in the time and effort to solve it. No matter how small the niggle.

Maybe it’s simply because we can. Or maybe we’re anal or crazy. Or maybe we have wolf genes.

I was thinking about this last night at 2AM after a marathon coding and testing session. It all came about because a client mentioned in passing that three memorial dates out of thousands in her copy of Kifu were missing. She assumed that there must have been bad data, and I should not worry about it.

Telling a programmer not to worry about something is like taking a bone away from a dog. It drives us crazy.

So I checked the data, the three people existed, had passed away many years ago, and their passing dates were good. And they did have memorial dates, just a month later, on the next page of the calendar. I could have stopped there, but the client had an expectation that was not being met, maybe, just maybe, there was an edge case here.

So I checked the web and found a reference implementation of religious to secular date conversions, put in these dates and it spat out dates a month earlier than mine. Thousands worked, these three were different. How? See, its fun to try to figure this out.

I spent the night revisiting the code and the conversion rules to find why these three dates were coming out wrong. Finally I found several new edge cases in lunar to secular calendar conversions involving anniversary date shifts on lunar leap years that are followed by lunar short years, and implemented them. Now the three dates came out right. But did I mess up the remaining thousands?

To check, I took it to the next level. I wrote a script to take every date in the past 100 years and test my conversion against the reference, just to be sure that my implementation matched. It ran and ran until 2AM. And finally, it ended. With no mismatches.

I cannot say whether being a perfectionist is a good or a bad thing in life, but it is a necessity when crafting great products. So if there is something in your code-base that irks you, go after it like a dog with a bone and work on it until it is done and done right.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Surface Pro Pricing Madness

I don’t get the pricing for Microsoft’s new Surface Pro.

The basic, bottom spec unit (with no keyboard, tablet form only) is $899.00. Why would you buy it when you can get full-size iPad at $499.00, or even the top-of-the line iPad at $829.00. Why would you buy it if you specifically want a Windows 8 tablet and a Samsung Activ goes for under $699.00 (and includes the keyboard).

And if you do add the keyboard for $120 (which pushes the price over $1,000) to use the Surface as a laptop, why not buy the best laptop ever made, the MacBook Air for $999.00. And if you just have to have Windows 8, Lenovo’s superb Yoga is also faster, better built, bigger and cheaper at $999.00 too (and it’s the most expensive of the bunch!).

It does not make sense to me. I guess Surface Pro buyers must be affected by the nonexistent Microsoft and Windows 8 reality distortion field. Can I get a ‘fanboy’, ooh rah!

Update: Looks like I’m not the only one, MG Siegler also does not understand the pricing. Thanks for pointing it out folks.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Browser Windows on All Desktops

In Being Productive With Virtual Desktops, I talked about how I pin certain applications to certain Mission Control virtual desktops to create context specific environments.

Reader “zharmany” asked what I did with the web browser, since it is needed on many of these desktops for different reasons.

My needs are to have separate browser windows on Desktop 1 / Work for previews, on Desktop 3 / Mail for mail links and on Desktop 4 / Social for looking at tweeted links, so I do not pin Safari. Instead, I open new, blank Safari windows on each of these desktops.

What I used to do is I use the New Window menu item off the Safari dock icon to launch a blank Safari window in the current space.

OS X (or maybe Safari) is smart enough that if there is an open Safari window on the current desktop, then it opens all clicked links in that window as new tabs. It does not jump desktops. Note that I have “Open paths in tabs instead of windows:” set to Automatically in Safari Preferences / Tabs.

What I use now is a Keyboard Maestro macro triggered by ⌃⌥⌘B that creates a new Safari window on the current desktop. I habitually hit ⌃⌥⌘B when I move to a desktop that I wish to browse on. The macro looks like this:

You can setup the same script in Alfred or other launcher, the code is simply:

1
2
3
4
tell application "Safari"
  make new document
  tell application "Safari" to activate
end tell

I usually just leave blank Safari windows open on each Desktop, and as I work and context switch, so the tabs on each desktop fill up with that Desktop’s links.

The main benefit is that a context switch back to work means that the browser on Desktop 1 / Work is not cluttered with mail or social tabs, and remains displaying the last page browsed for work.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Sanity Saver: NoMoreiTunes

Sanity Savers are quick tips that help you stay sane when using your computer.

I really don’t like it when you web browse to the App Store (iOS or Mac), it also launches iTunes or the App Store App on top. If I want to buy the app, I’ll click myself, I do not want my browsing flow to be interrupted by the launch of another application.

The NoMoreiTunes Safari Extension prevents this from happening. You can browse to and look at an app on the web and keep browsing without having new windows getting in the way. Just download and double-click the downloaded file to install it.

I also advise you to open Safari Preferences, go to the Extensions Tab, click on Updates and ensure that “Install Updates Automatically” is checked.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Being Productive With Virtual Desktops

There are a bunch of applications I always want running on my computer, such as Mail.app, OmniFocus, Billings Pro and Tweetbot, but I also do not want to be distracted by them. One option is to hide them using ⌘H on the Mac, the other way is to use virtual desktops.

My goal is to create context-aware desktops where I can stay focussed on the task at hand without distractions, and to be able to switch and restore contexts instantly and predictably, that is most productive.

After much experimentation, I have settled on a five virtual desktop setup in Mission Control, where each serves a specific purpose:

  • Desktop 1: My current workspace, for whatever I am currently doing. All my current working windows are opened here. For example, when programming Kifu, I have BBEdit open for notes, VoodooPad open for project information, TextMate 2 open for coding, several terminal sessions and several browser tabs open on this desktop. For blogging, as now, I have Byword open for writing, a terminal for managing Octopress and a browser window open for preview.
  • Desktop 2: Supporting the current workspace, software and files that are open that support the current task but are not part of it. For example, here I run Acorn or Photoshop for images when developing or blogging.
  • Desktop 3: Mail. I run OS X’s Mail.app here, not in full screen mode so I can have multiple messages open at once.
  • Desktop 4: News and social applications, like Reeder for RSS, Tweetbot for Twitter and Wedge for App.Net.
  • Desktop 5: Out of the way applications, like OmniFocus and Billings Pro. I want these to be always running, a keystroke away, and available to view at a glance, just not in the way.

To enhance productivity, I also set up two things: keyboard shortcuts and pinning.

1. Desktop Keyboard Shortcuts

I can get to any desktop with a single keystroke. ⌃1 to the current workspace, ⌃2 to the alternate, ⌃3 for mail, etc. So, when I have a break working and want to check my mail, I just press ⌃3 and the mail desktop slides in. It is a lot faster than using ⌥⇥ (Option/Alt - Tab) a bunch of times to select mail.app and then wait for the windows to come forward. The best thing is, to get back to work after checking email, ⌃1, the first desktop appears, just as I left it.

To enable this on your Mac, first create each virtual desktop. You do this by launching Mission Control by pressing the F3 key or using four fingers to swipe up. Then move your mouse cursor to the top-right of your screen and click to create new virtual desktops.

I strong recommend opening System Preferences, choosing Mission Control and unchecking “Automatically rearrange spaces based on most recent use” because it causes the desktops to shuffle around annoyingly. See image below right.

You also need to enable the keyboard shortcuts to give you the ability to jump to a virtual desktop in a single keystroke. Open System Preferences, choose Keyboard then Keyboard Shortcuts tab and click on Mission Control. If you scroll down to the right, you should see shortcuts to switch to each created desktop. Make sure they correspond to Control-N where N is the desktop number and they are checked. See image below left.

2. Application Pinning

For the applications that I want to always run on specific desktops, like Mail on Desktop 3, I pin that application to the preferred desktop. The next time that the application launches, it will launch on the pinned desktop and not the current one.

To pin an application to a virtual desktop, make sure the application is not running. Switch to the preferred desktop using the shortcut key, then launch the application. Once the application is running, right-click on it’s icon in the dock, and choose Options / Assign To / This Desktop. Next time this application is launched, it will open its windows on this desktop. Which means all you need to remember is which desktop to switch to for that application.

I do not recommend pinning all applications, for example Finder or Browser windows can and should appear on all desktops. Ideally, Apple will change it so that un-pinned applications will create new windows on desktops where they have none if activated.

The good and the bad

The good of this setup is:

  • I can switch contexts quickly with a single keystroke, to go from work to email, or work to social by just switching desktops.
  • When working in a specific desktop, I am not distracted by non-contextual applications. For example, when processing mail, I do not get distracted by twitter.
  • I can switch back to work without losing my place. ⌃1 back to my work and all windows and applications and cursor positions are exactly as I left them.

The only real bad of this setup depends on your choice in “When switching to an application, switch to a space with open windows for that application” setting in Mission Control preferences. If it is checked then the screen occasionally jumps to another desktop when you quit an application, and OS X jumps you to the frontmost window of the next application on the stack. On the other hand, if it is not checked, then ⌥⇥ becomes quite painful as you switch to an application and nothing appears. Pick your poison, I have it checked and deal with the annoying switches.

I know I have written about this before, but have changed the setup and felt it was better to create a new article than update the old. This truly is one of the best productivity tips, especially since it helps maintain context when switching back to work mode.

See Also: Browser Windows on All Desktops.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

RVM in TextMate 2

I use Ruby Version Manager (rvm) to manage the interpreters and gemsets for all of my projects. But the default install of TextMate 2 uses the system ruby interpreter for internal command execution as well as for external runs. Here is how to use your rvm environment for both.

tl;dr: Set the TM_RUBY variable in preferences or your ~/.tm_properties file to the path returned by which rvm-auto-ruby and restart. That will set the internal runner. For external runs from within TextMate 2, also comment out the shebang in the script before pressing ⌘R (or run from the terminal directly). Sublime Text 2 users, check the end of this post for ⌘B use.

Testing the Internal Command Version

Of course you knew that you can use TextMate 2 to execute arbitrary ruby code in your file. To test which version is being used, create a new Ruby file in TextMate 2 and type: RUBY_VERSION #⇥ which expands to

1
RUBY_VERSION # =>

Then press ⇧⌃⌘E or choose Execute and Update ‘# =>’ Markers from the gear menu. TextMate will run all the text on all lines before the # => marker and place the output to the right. I get the default installed version of ruby:

1
RUBY_VERSION # => "1.8.7"

But if I go to my terminal, I have

1
2
Galileo:~ $ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.0.0]

Setting the Internal Command Version

As per the instructions at rvm’s TextMate page, you need to find the path to rvm-auto-ruby. In a terminal run:

1
2
Galileo:~ $ which rvm-auto-ruby
/Users/Hiltmon/.rvm/bin/rvm-auto-ruby

Set the TM_RUBY variable to this path. You could either do this in TextMate / Preferences in the Variables tab as shown …

… or in your ~/.tm_properties file.

.tm_properties
1
2
3
...
TM_RUBY = "/Users/Hiltmon/.rvm/bin/rvm-auto-ruby"
...

The restart TextMate 2 and run the internal command test again:

1
RUBY_VERSION # => "1.9.3"

It now matches my rvm version.

Testing the External Ruby Run

Create a new ruby file in TextMate 2 as follows:

1
2
3
#!/usr/bin/env ruby -wKU

puts RUBY_VERSION

And hit ⌘R to run it. You should see:

It seems to be using the system ruby.

Using the RVM Ruby

To make this script use the current rvm ruby installation, just comment out the shebang line. It seems that the default TextMate 2 external script wrapper launches a clean shell that uses the shebang to choose the execution environment, but if there is no shebang, TextMate 2 uses the right one. So:

1
2
3
# <— COMMENTED OUT #!/usr/bin/env ruby -wKU

puts RUBY_VERSION

Gives

It is now using the correct rvm version.

Don’t forget to uncomment the shebang line when you are finished.

For Sublime Text 2 Users

If you want Sublime Text 2’s runner ⌘B to use rvm, you need to open ~/Library/Application\ Support/Sublime\ Text\ 2/Packages/Ruby/Ruby.sublime-buildand replace the contents with this using the path returned from which rvm-auto-ruby:

1
2
3
4
5
{
  "cmd": [ "/Users/hiltmon/.rvm/bin/rvm-auto-ruby", "$file" ],
  "file_regex": "^(...*?):([0-9]*):?([0-9]*)",
  "selector": "source.ruby"
}

Note that this will probably get overwritten when the Ruby package gets updated. Note also that neither $HOME or ~ work here, you need the full path.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Back to TextMate 2

I spent the latter half of 2012 trying out new programmer’s editors, getting them set up the way I like and getting productive in them. This was no fly-by-night few-hour test, it was full-monty Rails development work for months. Lots of shell scripts, file manipulations, formats, different programming languages, different platforms, all my programming activities.

I tried BBEdit for programming, and it is good. BBEdit remains my text editing and file manipulation tool of choice and I suspect it always will be. It’s running all the time for me to take notes, scratch around, manipulate data or experiment. But the language grammars, language-in-language syntax highlighting and snippets were not as good as TextMate 1’s for programming. I installed a bunch of tools, wrote a few of my own scripts, but gave up.

I tried and purchased Coda 2, and it is lovely. The integration, editor and product is just beautiful. In my opinion, it is the best IDE-like tool for static HTML5/CSS3 sites, which I occasionally work on. But it does not handle the scripting and Rails workload.

I tried, purchased, configured and used Sublime Text 2 as my sole programming editor for the longest time. I thought this would be it. I proudly wrote about my setup. All the power of bundles and syntax highlighting in a massively extensible tool. I love the multiple themes and the multi-platform use.

But the more I used it, the more I got annoyed with it. Sublime Text 2’s greatest strength, multi-platform, is also, in my opinion, its greatest weakness. As a Mac user who is supremely comfortable with “the Mac way” of doing things, Sublime just looked and felt wrong, out of place on my computer. The centered lookups, non-standard search box, odd default keys and text configuration files are just not right for a graphical programmer’s editor on the Mac.

In the mean time, the alpha of TextMate 2, to my big and pleasant surprise, got more and more reliable. Bugs got squashed, new features added, progress made. The bugs, stability and broken features that triggered my search for a new programmer’s editor were mostly fixed. And updates started flowing in again. It’s still not even beta, or fully featured, or polished. Then again, when I started with TextMate 1, it was in the same state. And it just kept on getting better.

In December, I found that I was using mate . more often than subl -n . to open the Rails folder. I started using rmate to edit files on the Linux servers over ssh. I got used to the new quirks of TextMate 2 very quickly (e.g. no file/new from the file browser, you have to do new/tab instead - what?), and found the old keys and expansions were still to my liking, and better than the other editors’ ones. And the new grammars, better undo and ‘smarts’ are delightful. The next thing I know, I’m using it as my primary editor for Rails and scripts again.

I do miss the multiple themes and multiple panes from Sublime Text 2 (coming in TM2). And I remain a Sublime Text 2 user on all non-Mac platforms, ST2 is still the best out there. I expect to continue to enhance that setup over the next few months.

It may not be cool, it may not be popular, for all I know I’m the only one, but I’m back, all-in, programming using TextMate 2 as my primary programmer’s editor.

And to confirm it to myself, today I reset all my code file associations back to “Open With TextMate…”.

See also My TextMate 2 Setup and TextMate 2 Basics.

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.

Hit by a Bus

What would happen to my clients and my products if I got hit by a bus?

I answer this question in my Noverse (my company) blog in Hit by a Bus.

Did I miss anything?

Follow the author as @hiltmon on Twitter or @hiltmon on App.Net.