Hiltmon

On walkabout in life and technology

Estimating Software Like It Is

Software estimates are hard. Clients expect things to take little time (see It Should Only Take You a Few Hours…) and cost little money. But the reality is that software is hard, there is lots to do, lots of work over and above just programming and it takes a lot more time and money to make good product. Most people underestimate the work to be done, or try to make the estimates look good, so most projects run over time and over budget because of this.

It’s bad for clients.

It’s bad for your reputation.

It’s bad for the industry at large.

You should estimate software as it is, because it’s always better to set the right expectations to your clients.

I just sent off an estimate for some iOS work to a potential client. But instead of estimating the work like it could be (and thereby misrepresenting the work involved), I estimated it like it is. In other words, I sent out a true project estimate, one that will probably not go over time or over budget, one that includes all the work involved, not just programming. But unfortunately, one that will not get me the work as the price is too high compared to the how it could be estimates they have received from others.

Let me throw out some numbers. The engagement is to create a simple flash card style game. I’ve done these before, and can whip a new one out in, lets say, 8 days pure programming time. From “Create Project” in Xcode to having the whole thing run from end to end, 8 days. Most software people would estimate 8 days times 8 hours times their hourly rate and be done with it.

That would be wrong. That is estimating software how it could be. How it could be if there was only programming involved, and all the art was done, and the product mechanics, experience and feel completely understood, tested, and worked out, all those involved had done several of the same kind of product before, and the program does not need testing as it works the first time.

How it could be is not real. It’s not even close. But unfortunately how most seem to send as estimates.

In reality, the product is not yet designed, the art not yet done, the client is new to creating software product, this is the first of their products to be developed, no code has yet been written for reuse, and no other product exists that works like it, feels like it, and has it’s same experience. In reality, there is a huge learning curve ahead for all.

When estimating how it is, at least the following additional work (and hence developer time) is required:

  • Design the game scenes and game mechanics to match the nuances of this flash card game. This requires several meetings with the client, where you print out wireframes and play the game using paper cutouts to get a feel for the experience you desire.
  • Create the placeholder assets and work with the graphic designer to create the real assets, in the right Slicy Photoshop format so that the developer spends less time generating and regenerating game assets. Include time to create the icon and iTunes store art as well as store text and screenshots. Include more time as artwork changes over the life of the development and more alpha releases need to be made and sent out.
  • Double the development time because the first cut of the game with the first cut artwork never works, never feels right, it’s never fluid, the mechanics are wrong, and only by playing the earlier iterations of the product can you get a feel for where the polish and additional animations and interactions are needed, or where to try new ideas, all of which add time and effort.
  • Add time for a proper beta test, sending the product out, answering questions, updating for bugs, and tuning for performance.
  • Add time to finalize the game, install the final artwork, polish the final rough edges and get it ready for App Store release. And create the screencast and the web site and PR and generate buzz on Twitter and Facebook.

There is no way, under the how it could be estimate, that all these things can be done in 8 days of work as well as doing all the programming. Not going to happen. Not if you want a properly designed, polished, reliable, fast and good game, even though the mechanics are simple.

The how it is estimate for this game, excluding designer time, is really at least 24 days of work. That is how it is, at least three times the how it could be time estimate. Given past performance on similar products, we’re looking at close to the minimum right amount of time this can be made with an experienced crew (remember - it’s a simple flash card game).

You’ll note that I keep saying “at least” in the how it is estimate and all estimates are in terms of work and not duration. The art will take longer than you expect, and will require more iterations than you expect. The product will iterate through more versions and experiments more times before the mechanics, interaction and feel became “right” than you expect. Most of the time, you are learning what works for this product each time. And as you learn, things change.

So please, folks, when estimating software next time, take the time to add in all the peripheral stuff that increases work on the project like design and testing, take into account the learning experience, take experimentation and iteration into account, even take how the last project really went into account, and estimate software how it is.

You may not get the work. But at least you are not misrepresenting what will happen to client if they go with the wrong estimate, and you can sleep peacefully at night.

And when you do get the work, clients will remember that your estimates and your delivery were close, were real, and true. And that’s how you build a better reputation for yourself, which leads to more work, and more great products, and more delighted customers.

Kinds of Files in a Project Folder

In preparation for a client call, I wrote a quick and dirty script to count the kinds of files in a project folder to show them what’s involved. I wanted a nice presentation, and the files grouped into categories. I also added parameters to exclude certain folder patterns from the counter.

The command is

1
$ ~/Scripts/cfile.rb ~/Projects/Kifu/code/kifu log tmp doc versions

The output is

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Project File Counter v0.1 ©hiltmon.com 2012 https://hiltmon.com

Project: kifu
-------------------------------------------------------
Text Files:
    Markdown              :      1
    Plain Text            :      1
-------------------------------------------------------
Code Files:
    CoffeeScript          :      7
    CSS                   :     10
    ERB                   :    251
    HTML                  :      3
    JavaScripts           :     10
    Ruby                  :    265
    SCSS                  :     10
-------------------------------------------------------
Data Files:
    XML                   :      1
-------------------------------------------------------
Image Files:
    GIF Images            :      2
    Icon Images           :      1
    PNG Images            :    168
-------------------------------------------------------
Configuration Files:
    Configuration         :      3
    Rackup                :      1
    YML                   :      4
-------------------------------------------------------
Other Files:
    Unknown Kind          :      6
    .eot files            :      2
    Locks                 :      1
    Rake                  :      8
    .rdb files            :      1
    Fonts                 :      4
-------------------------------------------------------
TOTAL                     :    760 Files
-------------------------------------------------------

It aint pretty, as it was written very quickly. The script in a gist is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#! /usr/bin/ruby

# cfile.rb
# Hilton Lipschitz
# Use and modify freely, attribution appreciated
#
# This script counts the number and kinds of files in a project. Any additional
# parameters are treated as exclude folder regexes
#
# Requirements:
# 
#
# Examples:
# cfile ~/Folder/DBFS
# cfile ~/Folder/DBFS libs # Will exclude any folders with /libs/
# ~/Scripts/cfile.rb ~/Projects/Kifu/code/kifu log tmp doc versions # To skip all unnecessary rails trees

require 'rubygems'
require 'fileutils'

# No need to report these individually, so merge the counts
@merge_keys = {
  ".xcbkptlist" => ".xcodeproj",
  ".xcscheme" => ".xcodeproj",
  ".xcuserstate" => ".xcodeproj",
  ".pbxproj" => ".xcodeproj",
  ".xcworkspacedata" => ".xcodeproj",
  ".xcsettings" => ".xcodeproj",
  ".scssc" => ".scss",
  ".fnt" => ".ttf",
  ".woff" => ".ttf"
}

# Make nice names for these
@descriptive = {
  ".xcodeproj" => "Xcode Project",
  ".c"       => "C/Objective-C",
  ".h"       => "C/C++ Headers",
  ".m"       => "Objective-C",
  ".pch"         => "Precompiled Headers",
  ".plist"   => "Plists",
  ".png"         => "PNG Images",
  ".txt"         => "Plain Text",
  ".strings"     => "Strings",
  ".coffee"    => "CoffeeScript",
  ".conf"      => "Configuration",
  ".css"       => "CSS",
  ".csv"         => "CSV",
  ".erb"       => "ERB",
  ".gif"         => "GIF Images",
  ".god"         => "GOD Configs",
  ".html"    => "HTML",
  ".ico"         => "Icon Images",
  ".js"          => "JavaScripts",
  ".lock"    => "Locks",
  ".log"         => "Logs",
  ".markdown"  => "Markdown",
  ".old"         => "OLD",
  ".pdf"         => "PDFs",
  ".rake"    => "Rake",
  ".rb"          => "Ruby",
  ".scss"    => "SCSS",
  ".ttf"         => "Fonts",
  ".xml"         => "XML",
  ".yml"         => "YML",
  ".ru"      => "Rackup",
  ".xib"         => "XIBs",
  ".storyboard" => "StoryBoards",
}

# Group the ones we know
@categories = {
  "Code" => [".c", ".h", ".m", ".coffee", ".erb", ".js", ".rb", ".css", ".scss", ".pch", ".html", ".xib", ".storyboard"],
  "Image" => [".gif", ".ico", ".png", ".pdf"],
  "Configuration" => [".xcodeproj", ".plist", ".conf", ".yml", ".ru", "strings"],
  "Data" => [".xml", ".csv"],
  "Text" => [".txt", ".markdown"],
}

@excludes = []
@counter_hash = {}

# Increment the count
def increment_key(key, value = 1)
  if @counter_hash[key].nil?
      @counter_hash[key] = value
  else
      @counter_hash[key] = @counter_hash[key] + value
  end
end

# Analyze a file by extension
def analyze_file(source)
  extension = File.extname(source)
#    return if extension.length == 0
  increment_key extension
end

def process_folder(source)

  @excludes.each do |pattern|
      return if source =~ Regexp.new(pattern)
  end

  source_dir = Dir.new(source)
  source_dir.entries.each do |source_file|
      # Skip dot files and hidden files
      next if source_file =~ /^\./
      full_path = File.expand_path(source_file, source_dir.path)
#        puts full_path
      if File.directory?(full_path)
          process_folder full_path
      else
          analyze_file full_path
      end
  end
end

def merge_keys
  @merge_keys.keys.each do |key|
      unless @counter_hash[key].nil?
          increment_key @merge_keys[key], @counter_hash[key]
          @counter_hash.delete(key)
      end
  end
end

if ARGV.length == 0
  puts "USAGE: cfile ~/Folder/DBFS <excludes>"
  exit
end

source = ARGV[0]
if ARGV.length > 1
  @excludes = ARGV[1..(ARGV.length)]
#    puts @excludes
end

unless File.directory?(source)
  puts "  ERROR: Parameter 1 must be a project folder..."
  exit
end

process_folder source

merge_keys

puts
puts "Project File Counter v0.1 ©hiltmon.com 2012 https://hiltmon.com"
puts
puts "Project: #{File.basename(source)}"

used_keys = []
counter = 0
@categories.keys.each do |category|
  array = @categories[category]
  header_printed = false
  @counter_hash.keys.sort.each do |key|
      next if array.index(key).nil?
      unless header_printed
          puts "-------------------------------------------------------"
          puts "#{category} Files:"
          header_printed = true
      end
      used_keys << key if used_keys.index(key).nil?
      descriptive = (@descriptive[key] || "#{key} files").ljust(22)
      puts "    #{descriptive}: #{@counter_hash[key].to_s.rjust(6)}"
      counter = counter + @counter_hash[key]
  end
end

header_printed = false
@counter_hash.keys.sort.each do |key|
  next unless used_keys.index(key).nil?
  unless header_printed
      puts "-------------------------------------------------------"
      puts "Other Files:"
      header_printed = true
  end
  descriptive = (@descriptive[key] || "#{key} files").ljust(22)
  descriptive = "Unknown Kind".ljust(22) if key.length == 0
  puts "    #{descriptive}: #{@counter_hash[key].to_s.rjust(6)}"
  counter = counter + @counter_hash[key]
end

puts "-------------------------------------------------------"
puts "TOTAL                     : #{counter.to_s.rjust(6)} Files"
puts "-------------------------------------------------------"

TextExpander in Terminal

I spend a lot of time in Terminal.app mostly running Rails or Git commands. I am also lazy, so I like to use short macros instead of typing in the same thing over and over again. I used to use bash aliases or functions, but I mostly use TextExpander snippets now because I like to be sure they don’t conflict with internal UNIX commands.

In this post I will show you

  • How to setup a TextExpander Group that only runs in the Terminal
  • Some of the more common snippets I have added to this group

Lets get started.

Setup TextExpander Group for Terminal

If TextExpander is only on your menu bar, click the icon, then choose Open TextExpander. In TextExpander, create a new Group. I called mine HL Terminal Commands. In the Group Settings (see below), choose Only These Applications… and TextExpander will bring up a list of installed applications (see right). Check Terminal only. TextExpander will now only expand these snippets in Terminal.app.

Some core Snippets

Change to Project Folder

One of the first commands I always enter in Terminal is to change to a project folder’s code subfolder. It’s a lot to type cd ~/Projects/Kifu/code/kifu every time, so I created a snippet abbreviated to ;cdki to do it.

  • ;cdki -> cd ~/Projects/Kifu/code/kifu
  • ;cdhi -> cd ~/Projects/HiltmonDotCom/code/hiltmon.com

Git Commands

As we all do, I spend a lot of time typing in Git commands to manage Source Control. Of course, I use git-completion.bash to speed up typing in branch names. Here are some of my snippets for git:

  • ;gs -> git status
  • ;gm -> git merge --no-edit --no-ff (note the space at the end)
  • ;gcd -> git checkout develop
  • ;ga -> git add .
  • ;gb -> git branch
  • ;gcb -> git checkout -b (note the space at the end)
  • ;gpo -> git push origin

One thing I like to do is log all commits to Day One - see Bread Crumbs in Day One. In this case I use a TextExpander cursor position marker to set where I type the commit message, then use it to run a bash macro.

  • ;gca -> gca "%|"

The bash macro in .bash_profile (OS X) is

1
2
3
4
5
6
function gca(){
  msg=$*
  path=$(pwd)
  ~/scripts/LogtoDayOne.rb "@${path##*/} $msg"
  git commit -am "$msg"
}

So to commit my current branch and merge it into development I could do the following:

1
2
3
4
5
6
7
$ git status
$ git add .
$ git commit -m "Amazing commit message"
$ ~/scripts/LogtoDayOne.rb "@kifu Amazing commit message"
$ git checkout develop
$ git merge --no-edit --no-ff branchname
$ git push origin

or, with TextExpander (showing typing only)

1
2
3
4
5
6
$ ;gs
$ ;ga
$ ;gca "Amazing commit message"
$ ;gcd
$ ;gm branchname
$ ;gpo

to do the same thing, 62 keystrokes instead of 191! Add that up over a day!

SSH to Server

SSH to a server takes too much typing, so I use this:

  • ;sshxxx -> ssh deploy@xxxxxxxx.kifuapp.com

Aside: I like my remote terminals to look different, so I have set the following functions up in my bash profile:

1
2
3
4
5
6
7
8
9
10
11
function tabc() {
  NAME=$1; if [ -z "$NAME" ]; then NAME="Default"; fi
  osascript -e "tell application \"Terminal\" to set current settings of front window to settings set \"$NAME\""
}

# Change the terminal color when remote
function ssh {
  tabc "Hiltmon-Remote"
  /usr/bin/ssh "$@"
  tabc "Hiltmon"
}

Whenever I execute a ssh command, my current terminal gets a new color scheme, which gets restored on exit from the remote session (local to the left, remote to the right).

Open with Editor

Launching an editor, then opening a recent folder or file takes too much effort too. Here are my editor launcher snippets:

  • ;md -> mate . (Opens the current folder in TextMate 2)
  • ;sd -> subl -n . (Opens the current folder in Sublime Text)
  • 'bd -> bbedit . (Opens the current folder in BBEdit)

Looking for more ideas

If you use TextExpander to speed up your use of Terminal, I’d love to hear about it. Link in the comments or DM me on Twitter @hiltmon.

Cheap Programmers Cost More and Ship Less

I’ve been programming for 22 years. When I started Noverse two years ago as a professional software design and development company, I knew I would be competing against younger, cheaper programmers and masses of very cheap outsourced programmers.

A lot has happened over the past two years, and this article is about my own observations regarding the nature of this competition and how things have worked out for a lot of people I have spoken with who have chosen cheap.

tl;dr: They spent a lot more time and money than they ever imagined, and none have shipped a product. That’s right, none of the people I spoke with had shipped. In comparison, Noverse has shipped several client products of equal or greater complexity during the same period.

Setting the scene

A few times a month, I get a call or an email. It’s someone who has heard of me from someone else, knows what I do, has an idea and wants to talk to me about it.

I always take these calls. It’s how I get work. And it does not hurt to spend an hour or two talking to someone new, even if their idea is incomplete and they do not have the funds to execute on it. They tell others, I get more calls.

Most, like 95% of these, are calls by people who have incomplete ideas or no funding. For those whose ideas are incomplete, I spend the time helping them refine the idea, or point them at resources to get them help. Part of providing this advice is altruism, I really want them to succeed, part of it is selfish, if the idea pans out, maybe there’s work for me in it.

For those who have no funding, we talk about time and cost. Software takes a lot of time to make, and there is a lot of work that needs to be done. It needs to be designed, architected, built, debugged and polished. The artwork needs to be created, iterated on and incorporated. You need documentation, a web site, legal help, PR, a means of selling it, and a means of supporting it. This all costs money, usually a lot more than people expect.

Examining the numbers

One option for these potential clients is to go cheap. For the purpose of this article, I will assume cheap programmers mean young, inexperienced programmers or remote outsourced programmers. Let’s compare numbers between a graybeard and a cheap programmer.

Lets say the graybeard could charge $150 per hour for programming. The mathematics are theoretically easy, $150 per hour, 8 hours a day, 220 working days in a year, that’s $264,000 per year before tax. Sounds like a good living, putting them up there with the “greedy rich”. But the truth is that, as an graybeard indie, most only average around 50% time funded, with lots of time spent between client engagements (or in my case, working on the one freebie I do a year). Now we’re looking at about $132,000 per year, before tax (50% utilization). For a 40+ year old married graybeard, that’s a reasonable middle class income.

But this graybeard is competing against $50 per hour youngsters (or $88,000 per year at 100% utilization) who live at home, or $15 per hour outsourced folks (or $26,400 per year at 100% utilization) who live in cheap countries.

As you can guess, this graybeard and I lose a lot of potential business to these cheaper resources. The hypothesis is that even if the cheaper resource takes twice as long to do it, it still ends up potentially costing the client less.

Or so you’d think.

Results of going cheap

Fortunately, I have remained in contact with many of the people who I spoke to at the beginning of their experiences, and this is what I have learned from those that went ahead and went cheap:

  • None have yet launched or shipped. Only one of them is close to it. And that’s because they luckily landed a cheap and great programmer, and the chap who’s idea it was is an amazing communicator. Remember, this is over a period of two years of discussions with lots of people!
  • A lot more money has been spent. Some quit when they ran out of cash, others persevered, and have spent many times their original estimates. A few even shared how much. On average, they have spent about what Noverse would have charged, but have nothing to show for it.
  • It has taken way too long. Given that only one is ready to launch in the two years I have been having these conversations, I guess infinite time is certainly too long. What I estimated versus what they were promised versus what happened requires a log scale on the graph.
  • They don’t have time to do anything else. Because they spend their days babysitting programmers. They spend hours every day emailing or talking with their programmers when they could be working on branding, marketing, fundraising, eating and sleeping
  • They made technical decisions without technical knowhow. They chose databases and service providers and technologies based on Google searches, whereas a professional programmer would have advised them what to do. The result is usually suboptimal.
  • What they have received so far is terrible. Lots of badly worded emails, only parts of a product (if any) that looks bad, does not work properly and crashes all the time. A few even got a significant amount of core product written, but finishing it seems to be taking forever.

Part of the reasons we have been in touch is they have either asked me to clean the mess up, or find some way to manage it for them. I did one of these before, it did not end well. The mess was too big and I learned that I did not have the patience or skill to fix it. Lesson learned, will not make that mistake again.

In short, going with cheaper resources has been unsuccessful in that they have no product, have invested huge amounts of their own time and are out a lot of money.

Misconceptions of going cheap

Again, these are my impressions, based on many, many of these conversations:

Misconception: Even if it takes twice the time, it’s still much cheaper.

The reality is that it’s taking 10 times the time, not two times the time, or infinite time since none have shipped. To abuse a cliché, time is money. A lot more time is a lot more money.

And a lot of other costs are being ignored, such as the cost of your time to manage the cheaper resources, the opportunity cost of having a project delivered so much later (or never) and future maintenance and support costs.

Misconception: Fire and forget

Many clients believed that they could treat programming like a fire-and-forget missile, i.e. point the programmer at the target and let them fly. Or in other words, you tell them what the product should do, and leave them alone to make it. And somehow it will happen.

Most cheap resources do not have the knowledge, experience and expertise in product development nevermind your idea for this to be a viable approach. Cheap programmers need to be guided the whole way, to ensure they stay on the track you need. And they need to be watched closely to see that they stay on track.

Even experienced graybeards need guidance along the way. They know they do not understand all the nuances of the idea and that there needs to be discussion and experimentation and learning.

Software crafting is an ongoing conversation between client and developer, requiring time and contribution by both.

Misconception: You’ll get it in the estimated time

Most programmers, including myself, are supremely confident in our abilities, to the point of arrogance. As a result, we’re terrible estimators. Fortunately, most clients are wise to this, and usually double or triple any estimate given to them by programmers.

However, when it comes to cheap programmer resources, most clients get blinded by the cheapness and do not spend time trying to understand the given estimates or the project scope. They think that it’s so cheap, so it does not matter if the estimates are wrong. Several I spoke to never received a Scope of Work or a documented estimate in the first place. So they really had no idea how long it was going to take or cost.

More expensive programmers, like myself, are aware that cost is an issue for our clients. We strive to get the Scope of Work clear, and we use our experience to create better (but unfortunately not perfect) estimates. We also try to remain within the estimated time, often swallowing hours of billable time because we screwed up the estimate.

Misconception: You will get exactly what you need

Cheap programmers, and especially outsourced programmers, deliver what you tell them to deliver. They rarely contribute ideas, or even think about what they are doing. So, if you ask for something silly, they’ll spend the time making it. And when you realize it was silly, they’ll spend the time undoing it, then redoing it another way. More time, more money.

The key issue is that you think you are communicating effectively when telling the programmer what you need. But if they have a different mentality, or do not understand you and where you are coming from, they invariably misunderstand what you need, and deliver on that misunderstanding. Happens all the time.

People like me, who buy-in to a project, who have passion for it, contribute more than just code. We offer insight, advice, we think about the feature set and focus our efforts on making a great product for you. We make sure we understand. Then we make what you need.

Misconception: Misunderstandings are easy to fix

A common thread in all these discussions was that the programmer was told what to make, and they somehow made something else. As a result, the client had to spend hours and hours explaining what they had told the programmer to do and what needed to be done to fix it. And, after several days of programming, it was still not right, requiring another iteration, more time and more cost to fix things.

Some clients learned the hard way to communicate more explicitly, the remainder failed to learn this skill. Explicit clear communication is very very hard. Those that did learn had to struggle to find the right things to say to the programmer, living in fear that no matter how good the communication was, they’d still have to iterate several times on fixes, and pay for more hours. The remainder gave up.

This is how it should work:

Communicate the overall vision of what you’re trying to create for your customers, and any programmer worth their salt will bring their A-game to solve it from that shared understanding.

John Larson JPL Consulting

Misconception: You will get a quality product

Most laypeople believe that if a program works, that’s good enough. Cheap, outsourced programmers do make things that work, and they do so cheaply, so that must be good enough. What a misconception.

Those of us who have been through the grinder know different. Software that works in one case does not work in all cases. It probably does not scale. It’s probably not maintainable or extensible. It’s probably not secure.

Software has an ongoing lifecycle. You do not build it and it’s done. You build it, ship it, fix it, maintain it, ship some more, extend it, enhance it and support it. A few users may grow into thousands. A single server may grow into hundreds. It may evolve in many ways. But the work never ends.

What you need for complex software is people who understand this and build an architecture to support this. You need people who take the long view, not the daily coding needs into account.

Misconception: Hang in there, it will work out

I sure hope so, but based on these conversations, it has certainly not done so for the people I have been taking with. Some are persevering, and I sure hope they succeed. But at some point, you need to ask if you are just throwing good money after bad.

So expensive is obviously better?

Um, no. If it were, Noverse would be charging $1,000 per hour, and I would not be shooting myself in the foot right now.

All kidding aside, really, the answer is still no. It’s not about the per hour rate.

Finding the right skills and the right kind of people is better.

The Hiltmon Now

Then pay them what they ask. Here is what to look for:

  • Passion: A person who assembles Ikea tables is not a carpenter, a person who creates tables from raw wood is. A programmer who treats programming like any normal day job will produce code, but will not help you make a great product.
  • Buy-in: A programmer who likes the idea of the product is more likely to ‘get’ the product and produce something nice versus the programmer who is just doing it for the money.
  • Pride: A programmer that takes pride in their craft is one who will deliver good code and good product. A programmer who does it as a day job will deliver whatever code they can get away with.
  • Problem Solving: A programmer who helps you solve problems, advises you on how things should be done, explains why things are, and interrogates you to ensure they have a proper understanding. Look for a thinker, not a doer, a collaborator, not a worker bee.
  • Feedback: Programers have very logical minds, they see things differently and have completely different life experiences. A programmer who proffers ideas and feedback on your ideas is better than one that just does what you tell them to do.
  • Opinionated: Look for programmers who offer their own opinions. These are the ones who will collaborate with you, not just work for you. Programmers with opinions seem quite annoying at times, but the work they do is so much better.
  • Accuracy: Listen to how the programmer speaks. If they seek accuracy in your communications with them, and speak to you in very accurate terms, it means they are thinking and understanding. If they respond monosyllabically or in general terms, it usually means they do not understand you, or are not listening.
  • Experienced: A programmer who has failed, made mistakes, and learned from them. One thing that completely boggles my mind is that for programmers, companies look for young, inexperienced, cheap resources, and get rid of them when they gain experience and cost more, thereby losing all the knowledge and experience gained. Can you imagine if we did that with doctors?
  • A shipping mentality: Look for a programmer who wants the project to finish and ship. Most programmers don’t worry about polishing up and finishing the product, they just program. As long as they are programming, they are happy. Seek out one that wants to ship your product, it’s the only way it will get finished.

It all boils down to care. If the programmer is just doing a job, they do not care about the product. If the programmer has passion, buy-in, is proud of what they do, involves themselves in solving product problems, contributes their ideas, offers opinions (even argues with you), seeks clarity and accuracy and wants to ship as much as you do, you’ve found one that cares about what they do and about the your product.

To it, then

You may find care in a 22-year old for $50 an hour, or a grizzled veteran for $250 per hour. It’s not about the money. It’s about finding the right programmer to turn your idea into a viable and successful product, a product that works, is reliable, scaleable, useable, and maintainable, and then shipping it, supporting it and getting a return on your investment on it. And it’s about reducing the risk that the product will never get built, never finish, never be debugged, never be polished and never ship.

I am sure this has been done with cheap resources, look at most startups these days. But how many of these have released a successful product, or any product at all, without massive VC funding?

Based on my limited network, going cheap has not been a successful or even a viable strategy for the people I speak to. For them, going cheap simply cost more, took more time and none of them have a product at the end of all this to show for it.

Noverse does not compete on price. We care about our clients and the products we make for them. We have shipped and we continue to ship great products for them, and we do so at a fair and viable rate. Everybody wins.

Kifu v1.0 Released

Noverse LLC (my company) and the The Shukai Company LLC, is very pleased to announce that Kifu v1.0.0 has shipped. And our first customers are already happily using Kifu in production. We want to thank all our beta testers and beta clients for testing Kifu and helping us make such a great product.

Kifu is an intuitive, easy-to-use software product for small non-profits and community organizations to easily manage their community and its events. Kifu has a comprehensive people database and implements membership, communications, billing, statements, payments, and donations, all in a single integrated environment available on the web. For more see the Kifu web site and play with the demo.

But we’re not stopping or even slowing down. We have the core platform, and we know it works. We also have many, many ideas and features we wish to add to help you maximize the value you get from Kifu in your small non-profit. We’re starting on the v1.1 tasks today, we have a v1.2 plan and lots, lots more to come.

Over the next few weeks, we’ll be bringing the remainder of our beta customers on board, and adding new customers that registered during the beta. We believe that it’s important to ensure that all new customers have a pleasant first experience with Kifu, so we’re doing the migrations for them first. Once that backlog is cleared, we’ll enable online sign-up for new clients.

If you have any questions, please do not hesitate to email us at contact@kifuapp.com or contact@shukaico.com.

Noverse LLC is a New York independent software designer and developer, established in 2010 by Hilton Lipschitz (@hiltmon) to craft brilliant web, iOS and Macintosh software. If you are looking for someone to craft a product as great as Kifu, feel free to contact me at contact@noverse.com.

Building and Dismantling the Windows Advantage

Horace Dediu, of the excellent Asymco blog, presents some interesting Mac vs PC stats in Building and dismantling the Windows advantage.

Take a look, then come back, I’ll wait.

In 1984, Windows was outselling Mac at 6 to 1. In 2004, it was an incredible 56 to 1. Microsoft was killing it. Microsoft had won.

But then Apple turned around. By 2010, the number had dropped to 20 to 1, still strongly in Microsoft’s favor, unless you add iPhone and iPad into the mix. Then, it drops to below 2 to 1.

Considering the near future, it’s safe to expect a “parity” of iOS+OS X vs. Windows within one or two years. The install base may remain larger for some time longer but the sales rate of alternatives will swamp it in due course.

My take: It’s a very, very good time to be an indie iOS and Mac dev. Especially one with experience and has capacity to take on a few more consulting or development engagements. Email me at hiltmon@noverse.com.

Great Since Day One

Marco Arment nails it in Great since day one:

I never make technology-buying decisions based on future promises, rumors, or potential.

and

I buy things that are great today. They’re usually things that have been great since day one. And, more often than not, they’re Apple products.

I agree with Marco, I buy what I need now, so I can be productive now.

I do not understand how folks can put up with the frustration with what they have, the inability to get things done or the doing without by waiting for something that may never happen. In my case, not waiting led to:

  • The best laptop ever, the Titanium PowerBook, purchased a few weeks before the Aluminum PowerBooks were announced, because I needed a new laptop, 6 years excellent service.
  • My favorite monitor, the Apple 23" Cinema HD, purchased a few months before the new Apple metal monitors were announced in 2004, because I needed an bigger and better display. I am still using it today to write this post. Apple has since released the 24", the 27", the 30", the mini-displayport ones and the thunderbolt one, but this monitor is still going strong.

The Unreasonable Man

The reasonable man adapts himself to the world: the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man.

George Bernard Shaw Maxims for Revolutionists

Stay hungry, stay unreasonable.

Slicy Photoshop Artwork

I have been using the same process to export application artwork using Adobe Photoshop forever. Most Mac, iOS and Web applications have large numbers of small image files that are used everywhere. They need to be sliced up, scaled and exported into the files and formats needed by the application. Exporting multiple art items in multiple resolutions has been a tedious and time consuming task, a task that had to be repeated manually every time the artwork changed. Until now.

The Old Process

Even to read about it is slow and tedious, and you probably do it the same way. Feel free to skip the next few paragraphs and jump to the new process to stave off boredom.

The first thing I do with all artwork is create a set of Photoshop master files for each major element, such as the splash screen and icon. I then create additional master files for all buttons, another for all icons and more for any additional image elements needed. Since retina came along, my masters are all retina sized.

Then, to create the .png files that I use in the application, I would manually use Photoshop’s Save for Web... dialog to save the retina version, then run it again to to scale it down and save the regular version. That’s fine for one file with one element. But with icon sets or button sets it gets worse.

Say I have five buttons in my button set, each having a standard and pushed version. I’d have a shape layer for the regular state, a shape layer for the pushed state and text layers and image layers for each button variant. I would then create ten layer comps, one for each combination of button layers to reflect each button state image desired. It looks like this:

This works great, all I have to do is change 1 layer and all my buttons get updated. But to export, I would have to have to run Save for Web... twenty times to get the 20 .png files needed, twice for each layer comp (retina and regular). Make one change, 20 more Save for Web... runs. Manual. Slow. Tedious.

I tried using the built-in scripts. Photoshop does have a Layer Comps to Files... script which will dump all comps as .png files. I’d then have to rename all the files, and then open each one in Acorn and resize it for regular size. Hassle factor high, and the quality starts to diminish (not Acorn’s fault, I’m using a bitmap to make another bitmap).

The Slicy way

This week, I needed image buttons for a Cocos2d game I am writing, one button for each of the 9 game levels, with a regular and pushed state. That’s 18 regular images and another 18 retina images (I chose not to create a disabled state as that would increase it from 18 to 27 regular and 27 retina images). I spent less than an hour creating the button regular background layer, pushed state background layer and each button’s face. I then spent another three hours manually exporting 36 images each time, copying them into the application, running it, finding fault, changing one thing in Photoshop, exporting 36 images again by hand, screwing up the file names, and iterating again and again. Ouch.

Aside: In-Game Compositing. I am aware that I could have just created the button background and button pushed state background images and used code to composite the buttons in real time in the game code. Unfortunately, the fonts I need are not licensed for distribution with games, so I needed to create static images here.

When one gets sufficiently frustrated with a process, eventually one goes out and looks for a better solution.

Me Now

And the good people at MacRabbit had just the thing. I have been using their excellent CSSEdit product for years (now merged with Espresso). The product is called Slicy, the idea is simple and the execution is wonderful.

In Photoshop, create layer groups for each element in the file, and name the group with the file name you want it exported as. Like this:

When you want to export the images, drag and drop the .psd file onto Slicy and it creates the images for you. Like magic.

But there’s more. If you name the layer group (file) with the iOS standard @2x syntax, Slicy exports both the retina and regular file versions and names them correctly. Better magic. This is it:

And there is more. Slicy remembers what you did, which means you can repeat the process anytime. And it can create multi-resolution .icns files.

So, from now on, I’ll use layer styles instead of layer comps for each artwork component in Photoshop, label each layer group with the export file name and use Slicy to export all the many artwork files needed in the application automatically with a simple drag-and-drop or repeat.

I’ll save a ton of time and tedium recreating artwork files.

And I’ll ask my graphics designers to make Slicy compatible files from now on, too.

Update 2012-08-01: Layer Cake has been renamed Slicy, thanks to Jan at Macrabbit for telling me about it.

Target the Forward Fringe

Daniel Jalkut, writing on his Red-Sweater blog in Target The Forward Fringe nails who our target market truly is, in discussing whether to retina-ize (HiDPI) our websites and applications.

Because HiDPI customers may be a fringe group, but they are a forward-facing fringe. They represent the users of the future, and the more we cater to them now, the more deeply embedded our products and designs will be in their culture. The future culture.

Guess I need to update my art too, huh.