what I learned over the years

Menu

Month: September 2010

Following the launch, everything started going to shit, and a huge number of challenges to the success of the company had arisen. The biggest of these were the lack of traction from launch, that we had lost the faith of our journalists, and because there were communication issues between Nathan (my co-founder) and I. This combination also killed our motivation.

As a result, I made a carefully thought out decision to shutdown the company, and return as much money as we had left (about 40%) to the investors. Nathan believed the best thing to do would be to pivot our company, and so I agreed to step down to allow him do that. After some work, he agreed that it was best to shut it down (hence the email above), and we are currently going through the steps of winding down the company, and returning the remaining money to investors.

I met Paul and Nathan while they were doing YC, and we dined and talked a couple times. While their original idea for a commenting system for newspapers was not good, they changed their idea quickly to NewsTilt, and seemed to be on their way to making stuff happen. I was rooting for them, as I liked the both of them, and they seemed like pretty good guys.

However, I had no idea about any of these problems between them, and I was surprised as anyone. I appreciate the candor that Paul has in writing it, and it’s often valuable to know why you failed, than to look at why people have succeeded. This is because I think we all often fail in the much the same way, but our successes have more to do with the specific markets, situational opportunities, and problem domains that we’re in.

One of the big lesson I got out of reading it is it matters who your cofounder is and how you and your cofounder interact. It’s been said time and time again. It matters who your cofounder is. Think of it as getting married. And herein lies a problem: most of us try to pick a cofounder before we know what we want and need. Knowing how to pick a cofounder (and for that matter your significant other), requires two things in my mind.

One, knowing yourself, what you value, what you need from another, and what you have to give in return. And two, being able to read others and figure out what motivates them. Both are soft-skills that are a far cry from technical matters, and hence hard to convey in words. It’s only won through being in lots of different social situations, and meeting people from all walks of life and backgrounds. Working with all sorts of personalities in close proximity will bring out these traits and you’ll have to deal with them.

And for any one specific person, you won’t know until you’ve worked with them for a while. Given that, if you wouldn’t marry someone you’ve never dated, you shouldn’t be cofounders with someone you’ve never worked with.

And it may not be someone who you’ve been friends with for a long time. Those that have never worked together or fought together (with each other or along side each other) have never really tested their friendship. That said, not all friendships need to be tested in this way–only those that you intend to go to war with or start a startup with[1].

I started my startup career with a long-time friend. We’d known each other since sixth grade, and always had a tight bond and connection. However, doing a startup together was the wrong thing to do. Our motivations weren’t aligned, our appetite for risk wasn’t the same, and our skills didn’t complement each other. We’re still good friends, but it’s highly unlikely we’ll ever work together again.

Oddly enough, the guy that did end up being my cofounder was someone I had ended up being roommates with first through craigslist. We didn’t decide to start working together until 2 months after being roommates. We ‘dated’ by working together for a couple weeks first on something, and it ends up we’re quite compatible. As with all relationships, you don’t know where it’s going to go, but for now, we’re both cautiously optimistic and constantly work at having a better relationship with each other.

I hope you take your time looking around for cofounders that don’t only have the skills, but someone who can communicate with you, and also is honest and has integrity. That last part is quite important.

To quote Warren Buffet about hiring, but I think it applies equally to cofounders:

“Somebody once said that in looking for people to hire, you look for three qualities: integrity, intelligence, and energy. And if they don’t have the first, the other two will kill you. You think about it; it’s true. If you hire somebody without the first, you really want them to be dumb and lazy.” – Warren Buffett

And people show their integrity when they’re faced with difficult decisions and difficult situations. Do they do what’s right? Or do they do what’s easy? Listen for stories from when your potential cofounder faced these situations and see what they did or didn’t do, and you can probably get a pretty good idea of how they’ll behave when you’re in the trenches with them.

So date your potential cofounder. Do small projects together. Build a twitter clone. Build something that can be done in a weekend or a week. Talk to them about their past. How have they failed? What did they do when they failed? Can they communicate to you their thoughts clearly? Do they listen and process what you have to say? The list goes on, but hopefully, it’ll give you a good start.

[1] I’m not trying to imply starting a startup is like going to war. Only that the trust in the guy that’s suppose to have your back in war is the same trust you need in doing a startup.

The other time, I talked about picking the right problem. The other half of getting to MVP is the emotional factor, which often times, is fear. Often times, this fear will manifest itself as excuses you make to yourself. It’s not ready to launch because we need that one feature, because the design’s not presentable, because we only get one shot. In fact, it’s just the fear.

What is there to fear? As adults, many of us don’t make things like we did in grade school, so it’s easy to forget the fear that comes with creating things. To start, there’s the fear of negative feedback.

You are not your creation.

Before the days of mass production, it was much more obvious the personal touch and personality that was imbued in anything that was created. The curve of a brush strokes or wood planes of a carver were fingerprints of their interpretation of their craft. Nowadays, machines create the curves in our objects, but the process of creation is still deeply personal.

While the machines stroke the lines, it is still we who delineate and decide upon those lines. Everything we make has design decisions that must be made beyond what it looks like. And whether conscious or not, these design problem is an interpretation of its creator and how they see the world, what they envision is a solution, and an invocation of their creativity. Great creations and great products have the personality and interpretation of a solution that shines through from their creator. How can it not be personal?

And yet, in the process of creation, you need to separate yourself from your product. You are not your product. If it fails, it does not mean you’ve failed as a person [1]. If people hate it, it does not mean human beings don’t like you. I imagine it’s a bit like being a parent: you can teach the child all you want, but in the end he or she has its own will and will make its own way in the world. Once you accept this, it’s much easier to take criticism and negative feedback in stride, because hey, people are mad at the product, not me. And products are much easier to change than yourself.

Good visions aren’t static

Sometimes, there is a fear of launching because there’s a fear of the negative feedback that would shatter your vision for the product. When we start brainstorming about our ideas, we imagine possibilities of how we’d change the world. However, when doing startups, you need to check these possibilities with reality. Would people really want to take notes on other people? Would people want to have social networks for their dogs? Would people want to write emails to themselves?

Good visions are always changing in response to what you’re learning about what people want. When you first get started, you don’t know much about the shape of the problem and which aspect of it people want. As you get feedback, talking to people, and seeing how they use your product, you get a much better idea of what the true limitations are and where the interesting things in that space are. Think of it as an experiment. You have hypothesis, and you test it out in the real world, drawing conclusions, which will probably raise more questions to answer. That will usually lead you somewhere far grander than your imagination.

You can always improve it later

I have less to say about this one, since it’s been talked about a lot elsewhere, but if you’re not embarrassed by what you put out, you’ve launched too late. The nature of deploying software is different than it use to be. Most of us aren’t doing life critical pieces of software, and we can deploy on the web. That means you can always improve on it after you launch. Launching is the first step, not the last. The advantage of launching is only that you get to test your assumptions against the real world, which is an extra helping hand in guiding your design decisions.

There’s almost always more potential early users

This is more applicable to consumer products then enterprise products, but there’s often the fear that users are like firecrackers–you only get to use it once and it’s gone. It is true that for any one particular user, they’re only going to check out your site once, maybe twice. But that’s just one user! There are always more potential early users. Of course, in the beginning of a startup, you’ll always be in a niche, but that niche should be big enough that there’s always more potential users can you hit up for a first impression.

The key realization with MVP is that once you hit upon that single, naked, simple, core value that users want, they’ll forgive all sorts of unpolish. Design sucks? No problem because it’s useful. Don’t have a lot of features? No problem because it solve a raging problem I have. As long as you keep iterating and keep making them happier with the value they’re getting, they will stick with you.

And lastly, it might help to think of your MVP just as a glorified email list. You’re creating something that is one single unit of usefulness, and by signing up users, you’re getting permission from them to contact them when you have something more for them to solve the problem that they were sold on by your landing page.

So for the last couple of months, I’ve been using posterous to post to blogger. I’ve finally decided to make the move entirely to Posterous. It was their autopost feature that made me switch. But to be honest, I don’t really like their editor. It’s not very conducive to posts about code, since you don’t edit HTML by default, and the editor munges your HTML.

But nonetheless, I think it’s time to retire this blog. It’s been fun y’all, but I think it’s time to move to another phase. I think I was more prolific before, since I was learning a lot. Nowadays, I’m still learning, but have been less inclined to write about it. But, I’m breaking that habit and making it a point to write again. If you’d like to follow me over, I’m at:

NOTE: Titanium 1.5+ has come out and some of the gotchas listed below may have been fixed. So you should consult the Titanium documentation and community for updates!

The other day, I wrote about the little gotchas to getting started with Titanium. And don’t get me wrong, I think things like Titanium and Corona are great. They decrease developer time by getting the native code with all the calls and memory management right once, and then spending the rest of the time tying all the pieces together in Javascript and Lua respectively.

However, with Titanium (as of this writing, Titanium SDK 1.4.0), the abstraction is still leaky and you can waste hours when you stumble upon one of the leaky abstractions. You either have to not be afraid to dive down into the native code to see what it’s doing, or have the right mental model in your head.

The biggest leaky abstraction is Titanium.include(), or Ti.include() for short. It doesn’t behave at all like include or require in other languages, and it will fuck you up if you think it does. To save you time and sanity, I go over the gotchas of Ti.include() below that wasn’t at all obvious to me when I started. The short version of it if you don’t want to read all of this, is Titanium.include() is more like a cut and paste macro, than a true include or require. If you think of it that way, you’ll be fine.

What’s an execution context?

Execution context is probably the biggest thing you need to understand when doing Titanium apps. When you start the app, the main file is under the /Resources directory and it’s called app.js. The code in app.js is running in an execution context, much like a thread with a certain scope. When you create a child window in app.js, you get a child window that the Titanium guys call ‘lightweight’,

var contactsWin = Ti.UI.createWindow({
title:'Contacts'
});

This lightweight window is running in the same execution context as app.js, meaning that you can access all variables created in the app.js file. However, if you create a window that uses a different file, aka, with the ‘url’ option, you create a child window that’s ‘heavyweight’:

And the code for this new window in the file (contacts_index.js) will be run in a different execution context. That means none of the variables in the parent window will be available to you. Anything you want to use in that execution context will need to be included again. [1]

What is the scope for the files that are included?

Let’s say app.js includes utilities.js. The variables that you create in utilities.js are available in the app.js. So if utilities.js defines a variable named ‘foo’ at its top level, then it will also be available to all code in app.js following the line where utilities.js was included.

What is the current directory for include?

With the two concepts above in mind, we’re ready for the first leaky abstraction of include. We ask: What is the current directory “./” for Ti.include()? If you write:

Ti.include('utilities.js');

Does it include utilities.js from the root path from which it is run, or does it include utilities.js from the directory that this file resides in?

The answer is neither. The current directory for include is the directory that the top level file of the current execution context.

Let’s do an example. Suppose you have this directory structure where the includes in each file is:

app.js [ includes utilities.js ]

lib

utilities.js [ includes ajax.js ]

ajax

ajax.js

windows

contacts_list.js [ includes utilities.js ]

app.js is the top level main file, and the windows/contacts_list.js is the code that’s run when app.js opens a new child heavyweight window. Thus the include statements each file should be:

app.js [ Ti.include(“./lib/utilities.js”); ]

lib

utilities.js [ Ti.include(“./lib/ajax/ajax.js”); ]

ajax

ajax.js

windows

contacts_list.js [ Ti.include(“../lib/utilities.js”); ]

Notice that app.js is in a different execution context then contacts_list.js, and therefore, contact_list include’s current directory for includes is in windows/ unlike app.js, which is in the root directory.

For the astute amongst you, you’ll notice that this example doesn’t actually work! The idea is correct, but the layout of the files in the directories is wrong. This is because utilities.js assumes that it’ll always be included by execution contexts with files at the root level. When app.js includes utilities.js, all is fine! But when contacts_list.js includes utilities.js, utilities.js turns around and tries to include “./lib/ajax/ajax.js”, which it won’t find, because it’s actually looking for “/windows/lib/ajax/ajax.js”.

Thus, I structure my files so all the includes happen in the execution contexts in windows/, and I only use app.js to instanciate these execution contexts in windows/

app.js [ ]

lib

utilities.js [ Ti.include(“../lib/ajax/ajax.js”); ]

ajax

ajax.js

windows

contacts_list.js [ Ti.include(“../lib/utilities.js”); ]

models

contact.js [ Ti.include(“../lib/utilities.js”); ]

And any includes first go up a directory and then go down, so regardless of the execution context, the paths will always be correct.

If a file gets included twice, does the code actually get executed twice?

The answer is a disappointing yes. If you have a library or utility file that is included in different files, it will get executed twice. And no, there’s no preprocessor like in C to detect whether you’ve already included a file or not. However, you can detect whether a variable is defined or not and decide whether or not to execute the file contents.

If you include utilities.js, it will probably have to do something like this:

Finally, if you’re reading this to figure out whether you should use Titanium or not, I’d say, give it a shot. It does speed up your development time. For me, it sped it up about 3x. What use to take three weeks now took one. However, don’t expect everything to work in javascript world. If something breaks, be prepared to dive down into the Objective-C or Java depths below.[2] Really, I wish Titanium was more mature, as they’ve been at it for 2 years now, but I guess the more eyeballs there are, the better software gets.

After promising myself to blog more, I ended up with my head down programming. But I’m back to let you know what I learned! About a week or two back, I got started using Appcelerator’s Titanium. It’s basically a framework that lets you to write native mobile apps in javascript that you can compile across multiple mobile platforms.

Titanium is actually set up like Shoes. Most of the application code is written in javascript, and then some of this code delegates its execution to Objective-C, like how in Shoes, it’s Ruby up top, and for slow parts, the execution is proxy-ed to C. Therefore Titanium doesn’t really “compile” to native Objective-C code, but rather, it’s written in native Objective-C and uses the already built-in javascript to tie things together at the top application layer. On android, just replace Objective-C above with “Java”.

I think it’s a much better idea to have a scripting language on top of native code to tie things together at the application layer. Developer time goes much faster, and you definitely make less mistakes with memory management. However, there’s a bunch of gotchas in getting started with Titanium. And while their marketing copy makes it seem like it’s pretty painless, there’s actually enough potholes in the way to stop you from even getting started.

To start, you need the correct combination of the iPhone SDK and the Titanium SDK in order to get it started and working. So make sure you have the latest SDK. I’m on the iPhone 4.0 SDK and Titanium Developer 1.2.1 with Titanium SDK 1.4.0. For those of you wondering, you can compile with a iPhone 4.0 baseline, but still compile to a lower iOS. I have a 2G iPhone running 3.1.3 firmware, and it runs fine since I’m not using any new APIs.

The other gotchas have to do with the javascript API. For example, when creating a button, we do something like this:

Seems pretty easy, except the documentation doesn’t mention that while you can have left and right co-exist to set left and right margins, you can’t actually have both top and bottom co-exist to set top and bottom margins. If you do, it simply won’t display your button, and you have no idea why.

Alternatively, there is no mention of what are required options and what are optional options. For example, for textfields:

It seems pretty elementary, but it’s required that you specify the borderStyle, or else your button and textfield will simply not be displayed with no error. Buttons and textfields also require a height, otherwise, the chosen default is the full size of the screen! That doesn’t make any sense. Also, when using tableViewRows, all rows with a different layout need to have a different className, for the native app to be able to conserve memory.

None of these gotchas are intuitive, and confuses the heck out of people, but I realize they’re obvious to those that have first worked in Objective-C and then in Titanium. Given the goal of Titanium is to provide web devs an “in” to writing native apps without writing in native code, I’d say it’s not there yet. Titanium is at best a leaky abstraction on top of the native code.

The worst part about using Titanium is its include mechanism. It isn’t at all like include or require in other languages. It’s actually more basic then that–essentially just a cut and paste of code. After I realized it’s not a mature javascript development environment that you might be use to with in-browser javascript or node.js, things went a lot smoother. In a later post, I’ll talk about Ti.include() and the follies that come with it, so you save yourself some headaches down the road.

About me

I'm a entrepreneur and programmer currently working on Cubehero, collaboration software for 3D printable projects. I'm available for freelancing or consulting about the growing 3D printing market.