Posts

The Right Customers

After reading and following the startup space for a long time, I have come to two rather obvious conclusions:

  1. Making a product that people will use is hard.
  2. Making a product that people will stop at nothing to have is much harder.

Both aren’t impossible. I have a list of companies that do both of these things extremely well.

All of these companies have figured out who the right customers are in their early stages. Further more, they have been able to talk to these customers to figure out if their product is something people want.

Talking to customers is the major starting point of most startup resources. Everyone makes it sound so easy.

Write code and
Talk to customers

It is the mantra of Y-Combinator. So how do you find the first set of customers that you want to talk to? And how do you know they are the right customers?

Can you tell if they are giving you feedback that applies to your product or if they just aren’t the correct target?

I’ve asked a few different people this and it feels like there isn’t a straight forward answer. More to come on this.

On RubyMotion

Having written two RubyMotion iOS apps, it became clear that it was time to put down some thoughts on using RubyMotion in anger. RubyMotion changes the iOS development toolchain to a Ruby like language and a bunch of tools that all run from the command line. It moves the focus of iOS development from XCode to Vim/Emacs/editor of your choice. And significantly improves the readability of the git log and makes it easier to reason about iOS code in general.

When you use Vim every day for roughly 12 - 16 hours per day it becomes second nature. When asked to switch to another environment, it is like going back to learning to walk as a toddler, even when you know how to run as an adult. Trying to build something in XCode feels like this and even though the outcome is an amazing app the process is like wading through molasses. Languages aren’t very scary compared to having to switch environments. RubyMotion allows a Ruby programmer to stick to the toolchain that they have spent the last few years with. And in most cases provides a joyful environment to do so.

Being a stickler for the story that a git log presents means that project files and nib files ruin a development environment. Particularly when they can change just by opening them. Rails has a similar problem with schema.rb where running a migration will re-order or adjust the spacing for schema.rb even though you weren’t the user who created it. The only reason I commit these files that are autogenerated is because of convention in the community. If these files go away then it is a massive improvement for the readability of the git log because doing --stat doesn’t end up listing files that aren’t integral to the commit.

Promotion, Motion-kit, Sugarcube and Bubblewrap are great libraries. They make building iOS apps much more convenient. More libraries in this vein for
Objective C/Swift would greatly improve the composability of apps. There are some choices around Ruby constructs that aren’t great in these libraries so they are far from perfect. But the spirit is great.

The community of RubyMotion developers is intimate and hungry for people. This has the benefit of people who are eager to help and make things better but suffers having less content to other communities.

Giving RubyMotion a try has been a surprising experience that has torn down the barrier to shipping iOS apps that are functional, fast and have code that is pretty easy to reason about. If you are someone that uses Vim/Emacs and spends a lot of time in the console, you will find RubyMotion matches your way of working more than the traditional ways of developing iOS apps.

As an aside, trying to adapt RubyMotion’s project/build management to Swift so that you can write Swift without XCode/AppCode is a very interesting approach that could change the way a lot of developers write iOS apps.

Commits that No One Reads

Does your commit log look like this?

* 245754d - work in progress

* d15cf15 - Handled a particular error.

* 2b55942 - One more time, but with feeling.

This is really frustrating because:

  • It takes a lot of commands to view the change;
  • And a very long time to understand what has changed;
  • And you still have no idea why the change was made.

These problems get worse over time.

It would be amazing if you could do:

git log --oneline

And understand:

  • The history of the code.
  • How the team works together.
  • Coding standards that a used;
  • And most importantly, why each of the changes were made.

6 Years Ago

Tim Pope came up with a good system of formatting git commits:

Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together.

Write your commit message in the imperative: “Fix bug” and not “Fixed bug” or “Fixes bug.” This convention matches up with commit messages generated by commands like git merge and git revert.

Further paragraphs come after blank lines.

  • Bullet points are okay, too
  • Typically a hyphen or asterisk is used for the bullet, followed by a single space, with blank lines in between, but conventions vary here
  • Use a hanging indent

A Note About Git Commit Messages

One of the most important elements of style presented here is that git commits should be written in the present tense. Doing this matches the output of commands like git merge and git revert.

Taking this a step further you can drill into the first line. It is the most important part of a git commit because all git tools focus on it.

The first line of a good git commit should have:

  • What the change is.
  • Where the change is.
  • Why the change is being made.

Below is an example of the first line of a good git commit:

Add notice and example to timeline to improve onboarding.
  • What: Add notice and example
  • Where: to timeline
  • Why: to improve onboarding.

Going a Step Further

Deis has done an amazing job of formalizing git commits. They have come up with the form:

{type}({scope}): {subject}
<BLANK LINE>
{body}
<BLANK LINE>
{footer}

This dramatically increases clarity in the first line. The type can be anyone of the following:

  • feat -> feature
  • fix -> bug fix
  • docs -> documentation
  • style -> formatting
  • ref -> refactoring code
  • test -> adding missing tests
  • chore -> maintenance

The first line needs to be all lowercase without a fullstop at the end. E.g.

feat(timeline): add notice and example to improve onboarding

This makes our example more succinct but keeps the what, where and why in commits.

  • What: feat and “add notice and example”
  • Where: (timeline)
  • Why: to improve onboarding

Taking Care of Commits

Read through formalizing git commits and get into a consistent routine with your commits. Get your team to do the same and in no time your git log will smell like flowers.

Make for Javascript MVC Apps

Minimum Viable Makefile

A makefile is a list of tasks and dependencies for those tasks (called goals in makefile speak). The default filename for a makefile is called Makefile. Tasks are made of:

target: dependencies
[tab] system command

A target can be any name or a filename, dependencies can be the same (except you can have no dependencies as well). Looking at a simple example:

listfiles:
  ls -la

Running make against this Makefile lists the contents of the current directory.

ls -la
total 8
drwxr-xr-x   3 carl  staff  102 20 Sep 22:08 .
drwx------+ 27 carl  staff  918 20 Sep 22:08 ..
-rw-r--r--   1 carl  staff   19 20 Sep 22:08 Makefile

Make runs the first goal by default. Make shows the command that is run by default. You can hide the command from the output by adding a @ to the start of the command:

listfiles:
	@ls -la

Outputs

total 8
drwxr-xr-x   3 carl  staff  102 20 Sep 22:08 .
drwx------+ 27 carl  staff  918 20 Sep 22:08 ..
-rw-r--r--   1 carl  staff   20 20 Sep 22:09 Makefile

Simple

Starting off with copying a html file over to a dist directory:

dist/index.html: app/index.html
	mkdir -p $(dir $@)
	cp $^ $@
  • Ensure that the dist directory exists.
  • Copy the depenency file to the goal name.

In this example:

$^ = app/index.html (The dependency)

and

$@ = dist/index.html (The goal target)

We also introduce a make function here:

$(dir $@)

dir outputs the directory given a file name. In this case it will output dist.

SASS

dist/css/app.css: $(shell find app/sass -name \*.scss)
	mkdir -p $(dir $@)
	sass app/sass/app.scss:$@

This goal gets called when ever any file in the list that is outputted from $(shell find app/sass -name *.scss) changes.

The goal runs the sass command on the app.scss and outputs the result to dist/css/app.css.

Concatenating javascript

JS = $(shell find app/scripts -name \*.js)

dist/scripts/app.js: $(JS)
	mkdir -p $(dir $@)
	cat @^ > $@

woot

JS is a variable that we have introduced. It returns all the .js files under app/scripts. The goal/task here will get called whenever a .js file is changed. It will make the dist/scripts directory, then take all .js files, cat them so they are concatenated and output them to dist/scripts/app.js.

Putting it together

JS = $(shell find app/scripts -name \*.js)

dist/css/app.css: $(shell find app/sass -name \*.scss)
	mkdir -p $(dir $@)
	sass app/sass/app.scss:$@

dist/scripts/app.js: $(JS)
	mkdir -p $(dir $@)
	cat @^ > $@

dist/index.html: app/index.html
	mkdir -p $(dir $@)
	cp $^ $@

all: dist/index.html dist/scripts/app.js dist/css/app.css

.DEFAULT: all

The default goal/task of the makefile has now been set to all so you can now run it by just running: make.

For a full example see https://github.com/carlwoodward/react_with_make_template. If you want to get more into make please read http://www.gnu.org/software/make/manual/make.html.

Awesome

subscribe via RSS