One of the often under appreciated situations in web development today are thing inherent to the process that create blockers inefficiencies when a developer is doing his or her day-to-day work. I am firm believer that inefficiencies are in fact blockers. and you should work hard to eliminate them. Although this might be difficult for ‘the business’ (managers, stakeholders) to understand, these things should be treated with the same importance as a “blocker” that you might bring up at stand-up. Failure to treat inefficiencies compound the problem, eventually leading to waste. Here are 9 things that make teams slow, and what you should do to address them on your team.
1. Fast deployment to QA servers
You should deploy your branch to a QA instance. Ideally, when you deploy you will squash & rebase master against your branch first, bringing your code current with master. Then, your test cycle on your QA instance is truly running against what the code will look like when it goes to Production. Nothing is worse than merging code into master only to have some unseen logic conflict cause bugs. (And by ‘unseen’ I mean something that doesn’t show up in a git merge conflict and doesn’t show up in a test failure. If this happens occasionally, squashing & rebasing and testing on a QA instance is your prevention to catch those integration bugs. If it happens a lot to you, you need to be writing better tests.
2. Fast & fail-safe deployment to Production Servers (ideally with zero-downtime)
Zero-downtime is an illusive goal. In reality, database migrations mean you almost always have some downtime. (There are ways to write additive-only db migration, but I find that strategy to be impractical). The shortest downtime you can possibly get is ideal. Less than 60 seconds is what you should aim for. Your deployment strategy, amount of time it takes your app to boot, etc, will all affect this.
Perhaps this goes without saying, but your deployment should never fail and leave your website broken. If that’s happening to you, fix that right away.
3. Tests that run quickly
Tests that run fast are essential to a tight TDD cycle. I know many devs who try to write tests without loading Rails (practical for unit tests, impossible for integration tests). Running only a subset of your tests locally (really fast) and then running the full suite on a CI (continuous integration) system is a good idea.
4. Continuous Integration Setups linked to your Github pull requests (Semaphore, TDDium)
If you aren’t using continuous integration you should be. Period. When set up to work correctly, the CI system will run your suite against each and every git commit, and send a ping back to Github telling Github the SHA is passed, failed, or pending. You should see this in your Github pull request, with a Pending (orange), Pass (green), or Failure (red) message at the bottom of your pull request. If your CI server is running correctly but you don’t see green check marks next to your commits on Github or at the bottom of your pull requests, you haven’t given the remote CI system “commit status” permission on your Github account. Try unlinking and re-linking your Github account, or contact the CI system help team to figure out what is wrong.
5. Don’t get stuck starting up your server (web, database, redis, resque workers, etc) in development
If you have issues starting, stoping, or configuring your local dev environment, fix them.
6. Don’t get stuck by your dev environment (homebrew, gcc, using rvm, building libraries)
This can be painful, and can sometimes take days and days even for an experienced developer. (For example, it took me about 2-3 days of futzing with my tools after a recent upgrade to Mavericks.)
7. Using Dev Tools when Debugging (browser-based or Ruby debuggers)
Use and learn Chrome dev tools.
For Ruby 1.9, use pry for debugging. For 2.0, use byebug.
For packet sniffing, check out Charles Proxy
Take the time to learn these tools.
Also check out this post I wrote about debugging start-up issues in your Rails app, or this post I wrote about debugging Capybara Javasript.
Finally, in Ruby, you can figure out where in the code a method is defined using source_location on an invocation to the method object itself (which you get by calling .method() and passing the name of the method you are curious about as a symbol). For example, if you don’t know where the bar method gets defined on your object foo:
8. Reduce “wait states” when working with others on the team
This is more of a team processing concern, but it affects your development speed greatly. A lean team practicing daily stand-up as a built-in process for dealing with this. Indeed, this is much of the core of what a lean process teaches. Put pressure on the stakeholders, design, marketing, etc to deliver what you need and give you feedback quickly, preferably face-to-face. Avoid any kind of ‘throw it over the wall’ approach to back-and-forth process when working with other departments. Although most dev teams that use a project management tool (like Tracker or Jira) have some kind of system for denoting “waiting for design,” if this happens a lot and those wait period happen after a developer has started on the story, this is invariably leading to waste on your team. Identifying those bottlenecks and eliminating them is key to creating a better process for yourself.
9. Get early feedback on your code
This is perhaps a personal pet peeve of mine, and varies based on your team and how you are supervising the more junior developers. Many teams have a “+1” system for marking eachother’s code as “good to go.” (On Github, you type :+1: and your +1 will turn into a thumbs-up icon.) One less-than-ideal workflow is the following: Dev writes code, dev pushes code to QA instance, QA happens and signs off on the code (or there is back-and-forth), dev submits pull request, another dev marks it +1 and it is merged into master. Sounds like it makes sense, but this can create a serious inefficiency if your code is not likely to get +1ed. For example, after you refactor based on the feedback you got, you then have to go back and re-QA the refactor. Either you waste the QA people’s time by having them QA more than once, or you waste the other engineers’ time by having them give you feedback more than once. There is no easy solution, but my best advice is to get the dev feedback early in the process as possible. No one wants to have their work pass QA, be signed off by stakeholders, be ready for deployment, and then be told that it has a serious architectural problem that should be fixed before it is deployed.
A lot of this has to do with the skill level of the developer. For people newer to the team or to Ruby, I recommend that you actually do two rounds of +1ing- one at the start of your work to get a “architectural OK” to make sure you’re going in the right direction and another just before you’re done to get a final sign-off. Of course if you have serious questions about architecture of a new developer’s work, you should probably be pairing with that developer to bring him or her up to speed.
10. Git diff before git commit!
Get in the habit of reading your own code changes before you commit them. Either by doing a quick git diff before you commit or when you submit a pull request, re-read the code you’re about to submit to make sure you haven’t left any debugging statements or extra stuff. Better yet, re-read it both before committing and when you submit a pull request.