The right way to think about TDD

I've been noticing quite a few posts in the developer community about ways to write better code. In particular, the Code Climate blog has been inspiring. A few days ago, Justin Searls inspired me further with his outstanding post about teaching TDD.

The reason Justin's post resonated with me so much was its relevancy. Just a few days earlier, I had exchanged comments with Bryan from Code Climate about the same thing.

Last week, Bruno (an engineer on our team) and I were talking about the community and the themes you extract from paying attention to the conversation within it. If you're a bystander, you'd probably notice the following rather easily:

If you're not following TDD, you're doing it wrong.

People preach TDD as gospel. It's overwhelming at times.

It's so overwhelming that you can wrongly interpret it. A beginner might think they have to do it all the time to learn programming. Nothing could be further from the truth. When you're first starting out, you're just trying to get things to work. Why should we encourage people to stumble through something that doesn't really help them do that?

The same thing is true for senior developers. If you don't practice TDD, you somehow have a letter tattooed on your chest that labels your code as buggy and awful.

What is our goal as software developers? I hope it's not to have the best test suite. You don't get a special medal for that, and it certainly doesn't imply you've designed and maintained a great code base. If I had a choice between a test suite with 100% coverage or a well-designed code base, I'd choose the latter every time. I can quickly write some high level tests to help me make future changes, but it would take me at least a month to undo years of bad design.

This certainly doesn't mean I don't see the value in testing. I'm simply trying to jump on the bandwagon with these guys - testing needs to be in a different part of the conversation, not at the forefront.

That being said, I've noticed a subset of the community changing the topic of the conversation. No longer is it TDD first. Instead, it's design first. It's writing the code you wish you had. If you design first, nice tests usually follow if you know what you're doing. If you're having trouble writing tests (using too many factories, slow running tests), it's an indication you have poor design.

TDD alone won't save you from violations of the single responsibility principle. It won't save you from poor design choices, and it certainly won't save you from costly refactors. With a little work, I can achieve 100% test coverage and end up with a code base that's messy and not maintainable.

It's bandwagon time. TDD isn't the only way. Don't follow TDD blindly.

Our goal should be writing amazing code. You should feel good about it. Things like the single responsibility principle, the open closed principle, and law of demeter are what you should be studying and applying to your work.

If you're writing code that follows these principles, it's mostly simple. Your classes are responsible for one thing. Your churn is low (your classes don't change often). You don't care much about the rest of the domain (your classes care about themselves). Most of your classes are easy to understand and you can re-use them with ease (they're loosely coupled).

Simply following TDD doesn't give you the beauty of great design. It puts a band-aid on the issue.


Here's how we've been operating as a team.

We don't always write tests first because you don't know what you don't know. The goal is to get nicely written, working code and NOT perfect tests and a badge that says you followed TDD.

We do think about testing as we're designing. If we're creating a new class, a spec file is sure to follow.

We focus on great naming and try to use namespacing. Being able to come up with a good name is a sign you've broken down the problem enough. For example, if we wanted to create a class to notify us about comments on this blog, we'd use "Blog::CommentNotifiers::Email" which would notify us by email. It's simple and it will end up doing one thing: sending an email when a new comment is posted on the blog. Using a callback on the "Comment" model would be a poor design decision and require you to opt-out of the behavior whenever you don't need it.

We focus on unit tests. If we have to stub out all kinds of classes and methods (more than 10 or so), we treat it as a code smell and think about refactoring.

We've learned a lot in the past year about writing better code. When we have to write new code, we write code we wish we had. We don't look for the quickest way to fix the problem (although there are always exceptions). We focus on very clear class names and private methods that read in plain-English. We try to avoid obscure method names. We focus on low-level implementation details last - once we have the design complete.

I highly, highly recommended the following resources to assist you in writing better code:

Bootstrapping is thinking long, not small

Adrian Holovaty, the founder of Everyblock and one of the creators of Django, put up the notes for a talk he gave about how Chicago needs to stop playing by Silicon Valley's rules.

His points are extraordinarily well articulated and he outlines the case for why the Chicago tech community should brand itself as the city for bootstrappers. 

I wanted to just stand up an shout out loud 'THANK YOU THANK YOU THANK YOU' as I read his write up.

I loved just about everything he wrote and a lot of it reminded me of the commentary I had on past hack job press coverage of the Chicago tech scene.

But there's one particularly disturbing thing I noticed happening in conversations after his talk - which is that some people equate bootstrapping to 'thinking small'.

And in fact - bootstrappers often seem to give in and accept the meme that bootstrapping equates to thinking small.

 

But this is wrong.

Bootstrappers don't think small, we think long

This is an important distinction because thinking small implies that you've set limits on your growth and the impact you want to have. I know a lot of bootstrappers, but I know of none who want fewer customers or who care any less about wanting to make their dent in the world.

What we do care about however is how we get those customers, who we have to partner with on our way to acquiring these customers and what kind of day to day existence we have as we build our companies.

This is thinking long, it's not thinking small.

When you start having a time horizon for success that spans 15 or 20 years, you look at the world and the opportunities it presents differently.

You know that in order to be strong you need deep roots, which are unsexy and usually go unnoticed and unappreciated until they finally take hold when suddenly everyone recognizes your 10 year overnight success.

It's silly to accept the notion that bootstrapping is thinking small, especially when the very people who claim that it is are building their products with a framework created by bootstrappers (Rails or Django, take your pick) and committing their code into a central repository created by bootstrappers (GitHub).

Bootstrapping definitely isn't easy, it certainly doesn't hockey-stick and it probably won't save an otherwise worthless portfolio of investment assets.

But to call it small is to misunderstand the very mindset of the bootstrapper.

We think long, not small.

Episode 16: The delusion is that you need a hockey stick to succeed

I was joined by Kevin Finn of Molehill in our latest podcast episode, where we talked at length about how they built their time tracking tool Tick - which also happens to be one of my favorite SaaS products - and their podcasting app Buzzsprout.

I was particularly happy to talk with Kevin because Tick is something I look at and think to myself - this piece of software makes my business better.

Kevin shares some of his insights about making useful products, marketing and the things that make us happy.

Listen below or subscribe to the podcast in iTunes.

Three principles for naming things

There's a saying most of us developers should be familiar with:

There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Naming is hard.

Over time, I've realized you can make it easier on yourself. If you're a beginner, you can follow these three general principles.

It's never ok to use a variable named "p"

Storage space is cheap. You don't need to worry about using short variable names. It's not a valid excuse.

Stop being lazy. If your variable is holding a project, call it project - don't call it "p". You should be able to come back to your code six months later, look at that line, and immediately know that "p" is a project.

So you say you have an amazing memory? It's still not an excuse. Some poor guy will have to read your code in the future and he'll think "p" stands for prick.

It's never ok to use abbreviations

Writing code is all about asking the question, "If I leave this project and come back in six months, will I know what this means?"

It's a constant battle. Another way to win this battle is to stop using abbreviations. Have you ever tried to read someone else's writing where they use a lot of abbreviations? Isn't it hard? Why would you want to use abbreviations for the next poor guy working on your project?

The exception is reserved for conventions.

For example, the HTML standard uses "src" quite a bit which everyone knows to mean source. A common abbreviation in JavaScript is "evt" which obviously stands for event (if you're familiar with JavaScript).

These are conventions which most developers have agreed upon through code review and years of experience. Don't try to invent conventions simply because you're lazy.

Don't feel bad about using variables with long names

Don't worry about long variable names. Usually, the more descriptive you are, the better.

Here's an example. Suppose you query for archived projects and need to store them in a variable. Use "archived_projects" as a name for the variable.

If you broke the rules above, you might try "ap" or "arch_proj" or "a_projects". It might seem obvious to you now, but how will you know what these mean six months from now? It's not worth it.


These principles might seem obvious to you if you've been a developer for years, but it's something we should all keep in mind as we review code and teach others. These principles aren't obvious to beginners.

If you think back to when you first started, you weren't thinking about maintaining your code. You just wanted to get the damn thing working. However, you reach a point where you need to make it easier for yourself and others.

At the very least, if you learn how to be descriptive with names, you'll help everyone around you.

The SaaS products we used in 2013

A while back I wrote a post about some of the tools we use, and I thought an updated list of all the SaaS products we use to run our business might be a nice way to end the year.

We spent just over $12,000 on hosted software in 2013, not counting our Engine Yard server hosting. While this money is a real expense, I find it to be worth every single penny and can't imagine running this business without these great tools. Hopefully there's something in here that you'll find useful too.

Developer Tools

Code ClimateIf I were give out a SaaS product of the year it would probably go to Code Climate. Derek wrote a fantastic blog post about how we use Code Climate so I won't repeat it here. It's difficult to overstate how big of an impact it's had on our team.

GithubWe use github to host most of our code repositories. It's pretty popular and you probably don't need an explanation from us as to what it is.

BeanstalkWe also use beanstalk to host some of our repositories - primarily for the fantastic deployment tools that come with it. Note, if you just need deployment tools, check out dploy.io. It's made by the same fine folks over at Wildbit.

PostmarkOur chosen provider for the transactional email delivery of all our products as well as all of our client projects. Easy to use, with a lovely interface, and built by the team at Wildbit.

Twilo and TropoTwilio and Tropo are pretty big competitors. We use them both to send and receive SMS messages for our products and customer projects alike.

FormstackWhenever we need a form that we don't want to build ourself, we use Formstack. I did a full write up of Formstack a couple years ago that's still pretty relevant.

ChartbeatIf one of our apps has a problem or a spike in users, chartbeat alerts us to this reality. 

SemaphoreHosted Continuous Integration testing for Rails applications. It links up to your Github account and runs your automated tests with every commit.

AirbrakeWhen a user of any product we build gets an error, we're alerted of the error by Airbrake. It's a great way to fix issues fast and we've even had times where we've emailed a customer to tell them we noticed they ran into an error and that it had been fixed before they even had time to email us. 

Project Management and Team Communication

BasecampThe first SaaS product I ever purchased. We still use it every day to manage our projects, communicate as a team, and work with our clients. The iOS app sets a new standard for what business apps can do on the iPhone and the web app is a joy to use. With Jason Zimdars at the helm it's never been better.

Blossom - Blossom is a card based application similar to Trello and other Agile/Kanban type tools, but it's simpler and sort of feels like a 37signals inspired product. We loved the clarity it gave us as to who was working on what, and what development state a feature was in. But we regularly struggled keeping the two in sync. If we only worked on one internal product we may very well have moved to Blossom entirely, but it's file storage and conversation features just aren't powerful enough for what we need considering the number of projects we have.

Hipchat - For group chat needs we left Campfire this year and moved to Hipchat. We like being able to quickly have one on one communications, the ability so set a status, and the desktop and mobile apps are superior than Campfire's. I should note though: there is a very real increase in interruptions with hipchat over campfire and I often consider moving back to Campfire. As of now it's a net win being on Hipchat but it's not without it's tradeoffs.

Google HangoutsWe use Google Hangouts constantly. Whether interviewing job candidates, having team discussions, or just wanting to have a conversation while feeling more connected we use google hangouts.

Sales and Marketing

BiteSize PRThis app is really more of a service powered by humans who look out for reporters who want to interview experts in a particular field. When they find a good fit they write up a pitch that you can approve which gets sent from your email. Super useful and it's how I got profiled in the Chicago Tribune.

ToutWe use tout to send a lot of emails but still sound human. Tout allows you to templatize emails that you send often so you don't have to rewrite the same things over and over again, while still allowing you to customize pieces to individual recipients.

HighriseWe use Highrise to store all customer contact information, email communications, notes and tasks for customer follow-ups.

IntercomIntercom allows you to see how people who try out your software are interacting with your product. It allows you to see who is the most active, least active, likely to convert, etc. You can also use it to message people who meet certain criteria and a host of other things. We probably only use a fraction of it's power but we still find it super useful.

LuckyOrangeA type of analytics tool, Luck Orange lets you watch how users are interacting with the marketing pages on your site so you can see how people are using it, what's working and what isn't.

Heap Analytics and KissMetricsWe used both in 2013 - neither to the extent we should. Hopefully we'll get our analytics act together in 2014 and I'll be able to share something more intelligent here next year.

SquarespaceWe started building a ton of websites for ourselves on Squarespace this year. The Tula blog, Project Idealism and the Tula documentation site are all powered by Squarespace. It's powerful, easy to use, and can be used as a website, blog or e-commerce store. I'm not exaggerating by saying that we turned down tens of thousands of dollars in revenue this year by pointing people to Squarespace because it would serve them better than a custom made website. If you need a website, check them out.

Payment Processing

RecurlyWe use recurly to process all payments that are made for our software products. I like that we aren't reliant on a single gateway for processing payments. They had a major incident this year where they basically locked themselves out from accessing credit card data stored on their systems. The way they handled it made me like them even more. We started using them before Stripe came out and I like them a lot - but if we were starting over today I'm not sure I'd choose them over Stripe.

StripeStripe powers all the credit card payments we conduct inside Tula Software. They are fantastic, and if you need to accept credit cards for anything you should check them out.

SquareSquare allows you to process credit cards with your phone. It's magic. Everyone should have a Square account.

General Business and Miscellaneous

LessAccountingThere are a ton of options for accounting software. We chose LessAccounting because it's easy to use, and the founders are super nice guys who are active in the developer community.

TickWe use tick to track our time, make sure we're hitting budgets and provide clients with detailed history of what we were working on and when we were working on it. 

TgethrTgethr is a group email application that makes it very easy to create a group email address and add people to it. Whenever I need some lightweight way to communicate with a small group of people I use Tgethr.

FreshdeskWe use freshdesk to handle all our customer support requests that come in for Tula. It's very easy to use, integrates very nicely with email, and has helped us provide great support for our Tula customers.

DropboxWe started using Dropbox more than ever this year. (And then basecamp went and built a super nice Google Docs integration so we might be moving in that direction in 2014.)

TeuxDeuxA super simple todo list that doesn't cost much money at all. 

SimplecastWe use simplecast to publish the Project Idealism podcast. I LOVE IT. It's super easy to use and makes creating and publishing a podcast as easy as writing a blog post. If you've ever thought about starting a podcast but didn't know where to start, look no further than Simplecast. 

SaaS is the new rent

When I look at this list, it reinforces my belief that SaaS is the new rent. For every one of these tools I can explain why we use them, why they are worth what they cost and how they help our team to be more efficient. 

I love each and every one of these products because they make our team and our company better.

To all of you - thanks for the great products you put out in the world - our 2013 wouldn't have been as great without you.