My Sister Paid Progressive Insurance to Defend Her Killer In Court
I’ve been sending out some impertinent tweets about Progressive Insurance lately, but I haven’t explained how they pissed me off. So I will do that here as succinctly as possible. There’s a general understanding that says, “insurance companies— oh they’re awful,” but since Progressive turned their shit hose on my late sister and my parents, I’ve learned some things that really surprised me.
I’ll try to cleave to the facts. On June 19, 2010, my sister was driving in Baltimore when her car was struck by another car and she was killed. The other driver had run a red light and hit my sister as she crossed the intersection on the green light.
How big, important, and addressable is Android as a market?
I have had this question in board meetings, on subways, and product planning sessions, and it’s far from clear.
On the one hand, Android handset sales continue to impress, and provide the only credible current competition to iOS dominance. On the other hand, fragmentation at multiple levels, and different usage habits severely impact the ROI of developing for the platform.
On the Investment side of that, there is OS version fragmentation, device form factor fragmentation, OS customization, and an immature development platform.
On the Return side, there is no single commerce platform with broad reach and adoption (customers with their credit cards already linked and ready), and the number of users seemingly using the devices as application platforms seems shockingly small. As one small data point, our iOS installed base is nearly 10x Android.
There is no question that Android has, for now, become the only secondary mobile application distribution channel, but the ROI of participating is certainly still a question.
Me, I find myself cheering on Microsoft (yes, them), hoping for WinPhone to give us a better development paradigm and unified sales channel, with strong design support to boot. In the mean time, we’ll keep agonizing over it at every juncture, supporting a platform full of promise but painful to work with.
If programming language design is about solving the hard problems with good extensible abstractions, then I want a language to codify “hacks” into a feature.
Coding in the real world, there are constant demands for temporary (and often clearly bounded) subroutines. Handle an edge case in data until we change some client code; work around a slow component until its upgraded, etc.
I continue I wish that I could explicitly mark blocks of code as temporary and bounded in such a way that it would be clear to maintainers what the scope of the “hack” is, and necessary duration. In addition, such annotation would allow a structured approach to sunsetting hacks that have outlasted their usefulness.
For now, we have comments and logging. But I wish there was a better way.
A few months back, we had a candidate for a front-end developer role who we loved. Self taught technologist, easy design sense, great academic pedigree. A work in progress technically, but his potential seemed solid and he met a core need for us at the time. He seemed to click with the team, sounded impressed with our company, and had great things to say.
We made him an offer, and we lost out. It had seemed destined to be. We were crestfallen. What went wrong? Why did he take the other offer (well, to be fair they offered him a lot more money- but we were ready for a fight, and he walked away from the table).
It was one of those galvanizing moments. We sat back, took a new look at our recruiting and interview process, our company culture, and how we sell who we are.
And I won’t say we’ve arrived yet, but I think we’re on a great path now. We’ve made several new (and exceptional) hires since. We’re starting to win people over on culture (and we’ve gone up against some of the best competition that the burgeoning NYC scene has to offer), and vision, and work environment.
How’d we do it? Discipline, or as we like to say here, “rinsing the cottage cheese” (Google it). A better recruiting plan, a better interviewing plan, clear priorities, a polished pitch, and many small ongoing efforts.
So now when I look back, The Candidate was just what we needed. A kick in the pants.
Awhile back, Jacqui Cheng from Ars Technica contacted a bunch of folks (including me) for a story she was putting together about what iOS devs would most like to see from Apple in 2012. Unfortunately I never got around to responding (sorry Jacqui—the holidays were crazy), but if I had, one…
I was inspired to jot this down by this tweet from Chris Dixon:
"I’m still trying to wrap my head conceptually around how getting rid of sql structure helps with sharding / replication."
The answer is data locality. Relational stores, by definition, formalize not just the schema of individual tables but of their relations to each other. The reason they do this, of course, is so that you can run joins, queries that pull related data from multiple tables/collections at once.
And that’s exactly what document stores don’t do. So why is that better for sharding? Because in order to provide efficient access to data in a relational world, you’ll want related data to exist in one location. You’re stuck having to access an unpredictable number of nodes in order to complete a single query. That’s going to hurt a lot.
Document stores ensure that you can only be retrieving a single document at any one time, which means that no matter how your data is portioned across a network, you’ll only be talking to a single node for a single query. This means that any reasonable partitioning scheme that allows you to efficiently map a primary key to a node will give you constant performance in a shared situation.
And because there are no explicit (and thus relied-upon) relationships between documents, replication is as simple as copying individual objects. There are no relationships to maintain and foreign keys to check in the process.
The implications for schema design should be obvious (but took me a long time to fully set in): if there is data you need to retrieve together, that data should reside full in one (or more than one) document. These kinds of schemas are a bit tricky to design well (and require tackling interesting consistency problems), but the payoff in consistent performance a simple sharding is worth it.
Code structure must scale as an organization grows. I’ve said before that Scaling is Performance decoupled from Load, and I think the analogous statement might be that scalable code decouples maintainability from team size.
At an early stage, we’re all just strapping things together with duct tape and working to get our ideas validated by our markets. The pressure on code at this stage is to be minimal and functional, and directions change, as does structure, with great frequency. You’re usually optimizing for a team of 1, maybe 2 at this point, who can know the length and breadth of the code base by rote.
Inevitably there will come a point where you’ve hired 2 more programmers, your customers are clammoring for new features, and you’re still saddled with a code base designed for 1. The next big release goes far beyond its deadline. Programmers complain about APIs. New bugs are cropping up left and right.
What makes code maintainable by a larger group? Standards and well-design interfaces. There are heavy-handed processes you can implement to make sure every line of code is linted, reviewed, etc, but in a startup (even a growing one) your focus should still be individually empowerment and speed to market.
But make sure at least the following are in place:
QA. You’re going to break a lot, do find a detail obsessed person who can tell it like it is.
Naming conventions. The first thing you need to do is get everyone speaking the same language. Semantics is the core of software, so encourage the arguments and negotiation to happen at this level.
Interface design. And I mean interfaces like as in API, not UI. Your senior players are going to have to get good at thinking through interfaces. This requires treating code as a product, and applying UX principles, and thinking about consumption of your APIs by other team members.
Explicit architectural goals. Its probably too soon to have an Architect dedicated role, but your team needs to be able to make sound decisions as they work, in accordance with a set of common principles and roles.
Code review. There’s a whole other post in my head on Scaling Process, but for this one suffice it to say that all of the above will require you to keep yourselves honest, and communicate your progress and standards, and code review is the best way to get it going.
Good luck. This is the fun part.
Maybe. More importantly, what do you need to do to succeed at it if you try?
Programming isn’t something you can take a couple of courses in and become useful. It’s pretty much the opposite of that (bias alert: I never studied CS, and taught myself to code, so there’s that). Programming is a trade. It’s like making shoes, or singing, or playing a sport. You can’t take a class on Soccer and expect to be able to play. You’ve got to get out on the field, and put in the hours of practice.
And I think that there’s a kind of person who is drawn to it, and flourishes in the trade. So here’s my list of what makes that kind of person (and if you’re diving in, what you should aim for to succeed):
Ever watch a programmer at work? She’ll be the one with headphones on not noticing if the ceiling caves in. That’s not just a coincidence, not just nerdiness, it’s a requirement of the job. Programming requires you to contemplate all aspects of a problem at once, and create a little universe of clarity around it. This is shockingly hard, and it’s the reason that (productive) programmers will defend their focus time so strongly, and develop mechanisms (darkness, headphones, isolation, beards) that preserve that focus.
You’ll know you’re on the right track if your friends and loved ones start getting annoyed at how antisocial you’ve become.
A Love of Failure
Your first “hello world” program is going to feel great. Wow, I just made a computer do something! Somewhere shortly after that you’re going to be bludgeoned with failures. Odds are it’ll take multiple attempts to get something that even works in a rudimentary way. A lot of people walk away at this point. It’s demoralizing. But you’ve got to be able to fail over and over, until you find a solution that works. And then you’ve got to be willing to destroy that in favor of finding an even better solution.
Each time you fail, you’ll have learned something, and your next failure will be a more interesting one.
Go forth and write bad code (and yes, it’s going to be terrible). A good programmer would probably laugh (rightfully) at your your whole approach and even your style. But did you make it work? Then good. Now do it again. The only way you’re going to learn how to do things well is to do them badly many many times, and build up the intuitive feel for how to construct programs and solve problems. This doesn’t mean you shouldn’t learn “best practices” and aim for “beautiful” code (both do matter), but don’t let worrying about that slow you down when you’re learning.
All that matters, at the end of the day, is whether your program does what you want.
Programming is an act of pure creation- inside this little digital world, the programmer is God, able to conjure up substance from nothing at all and shape it to her liking. It’s really fun, but also really daunting, to be able to do this. There is no limit on what you can accomplish, but it’s going to be up to you to do it.
There’s no sense worrying about the limits, they’re going to become apparent whether you want them to or not- so aim big.