Rogish Reading Writing

Software, management, people.

How to Make Remote Teams Work

274 years

The population of Manhattan is roughly 1.5 million people. On the weekend. On a weekday, the population doubles to 3 million people. Almost two million people commute from outside the city. Each work day.

Their commute time is, on average, 48 minutes each way.

For 1.5 million people, who spend 96 minutes a day commuting, that’s 144,000,000 total minutes. 2,400,000 hours. 100,000 days. 274 years.

274 years spent commuting to/from Manhattan each work day

Of course, many of these are retail, service, or support staff who need to be physically located here to perform their job.

What about the rest?

82 years burned every day

Of that number, from labor.ny.gov, we can estimate that roughly 30-40% of them are white collar computer users, or folks that support them. It’s not an exact number, but we’re talking napkin math here. Let’s be conservative and say 450,000 people.

That’s 82 years of completely wasted time every single day. For ~240 work days? A ludicrous 19,680 years every year.

Is this not insane? And this process repeats all over the country, as this chart shows:

There are other costs, too – building giant skyscraper office towers that aren’t getting filled, traffic from delivery vehicles and other support, and increased pollution. Not to mention you need to pay higher salaries to compensate for the extreme cost of NYC living.

Why aren’t these people working from the comfort, quiet, and sanity of their home?

Bright, shiny, work-in-your pajamas future

Working remotely, building remote teams and companies – these are not the “default” ways we’ve been taught to work in companies. But, it’s increasingly the way that some savvy companies are beginning to think, and default.

But for those that aren’t, there are a lot of objections to remote work:

“How can you build culture without seeing everyone each day?”

“How will people communicate and collaborate if they are working from home?”

“How to you make sure people can get their job done from the couch?”

At a half-dozen companies I’ve worked or consulted with, we had high-performing remote teams (either partially co-located/remote, or completely remote). I do not believe that to be successful, you need to cram everyone in one giant open-office nightmare.

The first cut is the deepest

The first step is letting go. Letting go that people need constant oversight. That butts-in-seats-time has a correlation with output. And you have to trust your people to do the right thing.

If you start with this mentality, everything will go a lot better. And even if you don’t manage remote people, this is the right approach in management anyway.

The best managers figure out how to get great outcomes by setting the appropriate context, rather than trying to control their people.

Reed Hastings CEO Netflix

Fighting entropy through facetime

Did I just say facetime isn’t important for results? Yes. But, just like any garden, you have to tend it. Groups take time to gel and until that happens, you’ll have decreased performance. With co-located teams, folks are going to lunch, happy hours, and various other forms of casual interaction. This constant interaction allows people to get to know each other, know the personalities in the group, and helps smooth over any intra-work conflict.

Remote people don’t have that luxury. It’s hard to get to know someone over chat, email, and pull-requests. Without that periodic face-to-face interaction, the team might not ever “gel”..

I highly recommend periodically getting everyone together in one place and time. If you have the budget, fly everyone to one of the cities every 6-8 weeks, for a whole week. Yes, it’s expensive, but it’s necessary to shorten that forming-storming-norming-performing cycle. And, without paying big-city salaries and office rent, you generally still come out ahead.

People

I’ve found that it is a lot riskier to hire people who have never worked from home before. It’s a different work style that some might find uncomfortable or dislike.

You can encourage people to go to a coworking facility to help give them that human interaction if they need it, but some folks will simply not like working remotely.

For folks who have never done it before, I’d suggest starting out on a contract basis in case they find it’s not what they want to do (saves their resume from taking a hit, gives them a reasonable out without needing to quit, etc.).

Tools of the trade

The rest of the tools are pretty straightforward.

Default to asynchronicity in all things.

Don’t have a meeting to discuss something when a pull request or collaborative Google doc will do. Encourage rubber-duck debugging (or slow time).

Default to openness.

That means all conversations and meetings should happen out in the open – in the chat room or a recorded video chat (and the video pasted into the chat room or wiki). If someone happens to be asleep or otherwise not around, the recording or chat scrollback will allow them to get up to speed when they return.

Speaking of being away from the keyboard – communicate your schedule when you “start” work for the day, so I can plan anything I might need. If I know you’re seeing a movie with your family at 2PM, I can make sure to get what I need from you ahead of time. As they say, a failure to plan on my part does not constitute an emergency on yours.

Discourage 1-on-1 conversation

Provide for individual conversation (Skype, GChat, whatever) but only for highly specific things that are not appropriate for a larger audience. Hardly ever use email. Do not collect team member’s phone numbers or make available to the group (if you want to share your mobile # with the rest of the team, that’s up to them).

Checkin Periodically

We don’t want to silo person-to-person communication except for periodic one-on-ones. I like to do weekly (or bi-weekly) one-on-ones with each person in the team.

Automate everything

If there is any process that relies on a person doing it, find a way to automate it. This includes deployments, CI, new developer onboarding, test/staging server refreshes, etc.

Did I mention CI? You should have it, and everything should grind to a halt if it fails.

Centralize the centralizable

Any company assets should be centralized in something like DropBox, Google Drive, a git repo, or the like. If someone needs an asset (logo), they should know exactly where to look for it. Their inbox is not that place.

Trust the process

Lots and lots of people have made this work. You can do it, too! Individual tools may come and go, but enter remote work with the right philosophy, and you’ll very likely be successful.

How to Interview Programmers Part 2

In a previous post, I outlined a general strategy to interview programmers. Today, I’ll be more specific, including examples and rationales, on how to hire Ruby/Rails developers.

To keep things simple, I’ll assume you have some sort of inbound funnel that delivers developers into your pipeline. I’ll discuss in a later post how to fill that funnel.

Pre-Screen

Talk to each candidate for 30-40 minutes, outline the current state of your company, product, team, etc. – over communicate – and check for immediate deal-breakers. For example, if you require pair programming and the candidate hates it, there’s no sense in wasting your and their time interviewing if they will not be a culture fit.

If you are operating at next-level Jedi stuff, you can record a video of you explaining all of this and having candidates watch it as a form of self-screening.

In either case, over communicate! It makes no sense to hide what you do, your culture, or your process. The last thing you want is to spend time and money hiring someone only for them to find out after they start that they are not a cultural fit and they quit.

After this, send the candidate a list of questions that you want them to answer. They should be designed to get a sense of the depth and breadth of the candidate – to help discover their “T-Shape”. Clarify with candidates the goal is to not “cheat” and discover the answers and that dishonesty will only hurt them, as it’ll become evident later.

Alternately, you can schedule an additional phone screen to answer them in real-time, but I’ve often found that most candidates are trustworthy enough to save you the time.

First Phone Screen

Provided the candidate exhibits none of the deal-breakers you have (you do have your deal-breakers defined, right?) then schedule a 45-60 minute phone conversation.

I start with some small self-contained Ruby problems adapted from RubyQuiz. I provide them with a github repo that has a bunch of the problems, have them pull the repo, get rspec running (e.g. just run bundle, then rspec), then make the tests pass for as many of the ones as they can do in 45 minutes (leave 10-15 for Q&A). I do this in a screenshare. The idea is to get them to do something more complicated than FizzBuzz but not something that should take more than 15-20 minutes, so they can do a few of them.

They are somewhat complicated but you also have access to a lot of solutions, so you can study ahead of time and help guide them if necessary. Since there are so many of them, you can slowly continue to add them to your repository — and if you are so lucky to be a famous place people want to work, it’s no worry if someone happens to get a copy of your repo because there are way too many to cram ahead of time and “cheat”.

I suppose if someone could study all 100 or so RubyQuizzes and recite them all from memory, I might want to hire them just for that.

You should pick ones that are close to your problem domain or create a few of your own, featuring APIs you use, or particular problems you’ve had to solve. This should not be very difficult and you should be able to have a large library of standardized, work-related problems.

The tests should be comprehensive but incomplete, so they are forced to do TDD. A good thing to look for is if they identify the cases you haven’t covered with tests and add them. This suite will allow you to conduct post-mortems and identify which tests are most diagnostic, removing the rest, leaving you with a repeatable, scalable, representative test suite.

Most of the time you don’t need to review their code, since you were watching it, but you could have them commit and push to your repo (set them up with a fork ahead of time). You can review, and if they pass, move them forward.

Second Phone Screen

I start with an OO theory problem; design a moderate but understandable domain in plain old Ruby. They should be able to do this in 30-40 min, with some time to answer questions at the end. Review and talk through the OO problem.

The example I used to use is model a deck of cards in Ruby (using however many classes, helpers, whatever you want). Talk through it. How would you shuffle the deck? What if you didn’t have Array.shuffle? (This is a personal favorite of mine – how to randomize an array in Ruby if you don’t have shuffle). There is a giveaway answer if the candidate knows it, so have a few other hard questions up your sleeve if they did their homework.

I have never found someone who had never seen a deck of cards, so there’s no risk in a candidate going “I have no idea what a deck of cards are” and giving you a false negative.

You also could do a parking lot with cars. How do you represent the lot? How do you represent cars? Owners? Is it important to have owners?

Bonus points if you can come up with an example that is used in your line of business. You always run the risk of the candidate getting it wrong because of a lack of understanding instead of incompetence, and leading to a false-negative.

Have them commit and push the code to a repo you give them access to, so others can review. If they pass, you’ll use it in the in-person.

Again, conduct post-mortems and reviews to ensure the problems you give are diagnostic.

In-Person

In the morning, do the “Welcome to YourCompany, have some coffee”, warm them up by introducing to people, talk to the CEO, etc. Then after about 30-45 minutes, so they’re warmed up and not too jittery, have them build a Rails app from scratch (or maybe from a skeleton repo you provide with rspec, etc.) that allows the user to take that deck of cards and play War) with another player (or, whatever it is that extends your basic object lesson from the second phone screen – if it’s the parking lot, have them build the interface that the attendant would use for a multi-level parking garage).

Things to look for:

War: How do you persist the game state if you wanted to load it later? Just freeze the array? Represent a row in a table somewhere? Should you persist it at all? Is there a better way?

Parking lot: how to represent a parking garage? Different levels? How would you make it multi-tenant? Should # of levels be configurable? etc.

Continue to dig into the problem, extending it, evolving it toward some goal. Look for things that are both cultural fit designators (do they write tests first? Tests at all?), code quality, and refactoring.

Try this on your own to get a sense of how long it takes, but with both of those examples there’s clearly many hours of work there, if you want to let it go that far. You should stop around lunchtime.

Take them out to lunch. You’d be surprised the number of companies that don’t bother to give the candidate the common courtesy of buying their lunch. Some even schedule interviews through lunch, which is a certain sort of jerkitude and has to lead to false negatives.

If they passed the first half you can move them to the follow-up. If not, take them to lunch and have that be the end of it. This way, you’ve got an out so if someone is completely a no-hire there’s no need to waste the rest of the day. You can easily communicate this ahead of time and say “Let’s block out the whole day, sometimes we go that long, sometimes, not, really depends who is in the office, etc.”, so it’s not super obvious that they bombed and allows them to save face.

After lunch, pair with them on an open source lib you use and release the code back, proving you do open source, and set aside example projects similar to the phone screens. Have each developer know which project they will use and what they are looking for in the pair session.

Have them pair with everyone on the team, maybe 1-2 hrs each (depends on # of people).

This is the least objective part of the interview and you have to be very careful not to pick up false signals (positive or negative).

Send them on their way around 4p, have the team huddle at 4:05 and give them a go/no go, and have the offer (or rejection) to them by 4:30.

Post-Mortems and Retrospectives

I can’t tell you the number of places I’ve seen where they have the same script and examples from 2004, using outdated techniques and libraries. If they even have a script (most likely I see folks winging it).

After every hire (or fire), and periodically (quarterly is about right) throughout the year, conduct a post-mortem or retrospective to see what needs to change in the process. Is the suite still representative of your work environment? Did you recently tackle a hard problem that should be added?

Like any other project, if you let entropy take over it’ll win and you’ll end up with a rusty pile of code that ceases to be useful. It requires care and feeding but will pay off with consistent, repeatable, diagnostic interviews and great hires.

What’s in your interview toolkit?

Automatically Maintaining and Improving Code Quality

New software projects start the same way: clean, well-tested, and fresh in everyone’s minds. Over time, however, the knowledge fades as little-visited parts of the code aren’t touched, folks move to other projects, and new developers come on board. Test coverage drops. Mass hysteria.

Without automated, enforced quality and test coverage metrics, entropy wins and you get stuck in a vicious cycle.

We have some tools in our arsenal to help prevent code rust: we can institute code reviews, we can pair program, or folks can “lunch-n-learn” to demo code. All these are well and good, but require active effort to maintain quality. What if there were automated methods to help ensure code quality that didn’t require manual intervention?

I’m a big believer in automating all the things and code inspection is something you should strive to automate. Static code analysis allows us to enforce code standards (no spaces after parens! Two spaces, not tabs! and other holy wars), catch potential bugs or security problems, and improve code quality.

But if it’s outside of your normal day-to-day development routine you’ll forget to check it. And, like the bad old days of waterfall development, if your code gets thrown over a wall and the analysis runs long after you’ve written the code, it merely introduces more inefficiency and churn. If you integrate static code analysis into your automated testing, actual metrics prove your code is improving as you red/green/refactor.

In a Ruby/Rails project, you have several tools to help maintain code quality:

Setup

You should integrate this into your specs to run when you execute all your tests:

Rakefile
1
task default: :all_specs

and

lib/tasks/spec.rake
1
2
3
4
5
task all_specs: :environment  do
  ['rubocop -R', 'rails_best_practices', 'rspec'].each do |task|
    sh task
  end
end

Rails Best Practices

Rails Best Practices performs typical ruby checks but integrates it into a Rails environment. For example, if you have an unreachable route, it’ll report that, or report if you miss an index on a foreign key. It’s super valuable for onboarding new developers to Rails, too. Yes, they should read a Rails book, but if they inadvertently violate one of the many norms of Rails, this gem will catch it.

Rubocop

RuboCop is similar to RBP except focused on Ruby specifically. Things like spaces instead of tabs, methods and classes that are too long or complex, etc.

SimpleCov

SimpleCov allows you to lock the minimum amount of test coverage and also refuse a test coverage drop. You should define a low water line to ensure coverage does not drop below some number (90%?)

spec/spec_helper.rb
1
2
3
4
5
require 'simplecov'

SimpleCov.start 'rails'
SimpleCov.minimum_coverage 90
SimpleCov.refuse_coverage_drop

CodeClimate

CodeClimate ties these all together and has their own flavor of Ruby/Rails linters, along with JavaScript/Node.JS. CodeClimate can plug into your rspec and along with SimpleCov, report code coverage in the tool. More valuable, though, is security monitoring which reports vulnerabilities in your particular version of Ruby/Rails and when you introduce security problems in your code.

CircleCI

CircleCI is a fantastic SaaS CI provider I’ve used for a few years now. Not only are the founders super responsive, their massive parallelization functionality allows us to focus on writing code and tests and not worrying about how long they take to run.

You can combine CodeClimate and CircleCI to get test coverage reports in CC and notified of test coverage regressions in Circle.

Using all these tools, you too can have a non-trivial app that is well-tested, easy to maintain, and a joy to work with.

What tools do you use to improve the quality of your code?