Optimizing Tail Call Recursion

I have been familiar with the concept of tail recursion for some time, though I had never explored it in depth. In this post I’ll look at an example of what happens when a tail recursive function is optimized on x86 targeting OS X.

Recursion Limitations

Recursion is common in software, especially in functional programming languages. Unlike iteration (e.g., while or for loops), recursion has the unfortunate side effect of growing the execution stack (a finite region of memory that a program uses during its execution). This can cause problems when many repeated recursive calls are made, as the stack may run out of space. It’s also slower than iteration due to the extra stack frame creation and tear down. Read more on Optimizing Tail Call Recursion…

Breaking Things Is the Best Way to Fix Them

Whenever I’m debugging an issue, I try to model it mentally, hypothesize what could be wrong, and then conduct controlled experiments to narrow down the issue. I trace execution carefully and inspect values.

That usually works well. When it doesn’t work or when I just don’t have many ideas, I often simply smash everything with a hammer (metaphorically speaking). Read more on Breaking Things Is the Best Way to Fix Them…

Test-Driven Infrastructure (TDI)

Atomic really has a passion for writing high quality code and for testing. While our internal server infrastructure has often been maintained in a semi-automated fashion, it has traditionally lagged far behind our development practices in terms of code quality, testing, and continuous integration.

Over the past year, however, Mike English and I have been working to revamp much of our server infrastructure using the Chef configuration management tool. Our goal has become to build a Test-Driven Infrastructure (TDI) in which we first write tests to model and validate the code that we later produce to configure and manage our servers and applications. Read more on Test-Driven Infrastructure (TDI)…

Get Creative with Rubygems and Cocoapods

A lot of people use dependency management tools such as Rubygems or Cocoapods in their applications. These tools make it very convenient to pull in open source libraries and use them in your project without all the hassle of manually downloading projects, copying files, and keeping track of versions. While using these tools to pull in widely used open source libraries is very nice, don’t forget that you can also use them to manage pieces of shared code between your own private applications.

The last few projects that I have worked on included multiple applications that pass data between them in some non-standard way. In order for each application to correctly interpret data from the other, they each had to have a common definition of what structure of that data was — a protocol.

There are many ways of defining a protocol, and I won’t go into those details here, but once you’ve defined a protocol, how do you share it amongst the various parties that use it? Read more on Get Creative with Rubygems and Cocoapods…

Keeping a Development Journal

Life gets crazy, and things slip our minds. A great discovery, a bug, or a general direction we were taking our code can get lost between development sessions.

In my personal projects, where time between development sessions can be days or weeks, I have been keeping a development journal. As much as it takes an additional couple minutes, it allows me to express intent and task my future self with necessary work.

Read more on Keeping a Development Journal…

Interacting with Git: Cryptic RPC Errors, HTTPS, and SSH

In my experience, working with a Git repository hosted by Gitlab, Github, or Gitorious has generally been issue free and enjoyable. Recently, however, three members of my team ran across the same cryptic RPC error when trying to push changes to a remote repository on Gitlab:

error: RPC failed; result=22, HTTP code = 411

In two cases, developers were trying to push new framework libraries (they were moderately sized, 2-9 MB). In the third case, a designer was trying to push a large batch of image assets. In all cases, the problem was caused by using the HTTPS protocol with a server configuration that disallowed individual files larger than 1 MB.

After some basic investigation (thanks Stack Overflow!), we found that using the SSH protocol with Git solved the problem. This type of issue could trip up a new user of Git, so I am going to use this post to briefly describe the problem and summarize the pros/cons of using HTTPS vs. SSH protocols to talk to remote repositories.

Read more on Interacting with Git: Cryptic RPC Errors, HTTPS, and SSH…

Turning Asynchronous Networking Inside-Out

Developing asynchronous networking applications is an interesting problem with unique challenges and no shortage of solutions for, particularly in Python. But the way you’ve traditionally had to write your code to make it work well could leave you with a codebase that, while solid, could be challenging to read or follow.

I’ll take you through a quick introduction to what asynchronous networking is, show you a callback-based asynchronous implementation using the venerable and excellent Twisted, and then finally show you how Python’s new asyncio library uses coroutines to solve the problem in a whole new way.

Read more on Turning Asynchronous Networking Inside-Out…

Sharpen Your Git Saw – Aliases, Selective Staging, & Interactive Rebasing

Git is a powerful tool that we love as developers. It’s also complicated. I consider the bare essentials of Git, the minimum set of features to be familiar with before we can be productive, to be all of this:

  • local interaction: status, add, remove, commit, reset, checkout
  • branch management: checkout, merge
  • remote interaction: clone, fetch, push, pull

Once we’ve learned these basics well, we move onto advanced features and tricks. Read more on Sharpen Your Git Saw – Aliases, Selective Staging, & Interactive Rebasing…

Try All the Easy Fixes First

Even after 10 years, I find I occasionally need a reminder to check all the obvious things when something goes wrong.

I just spent about a day debugging an issue with tests hanging, but only on one machine under continuous integration. The other machines were all fine. I assumed one of my tests was just broken: maybe I was polling for an update in the UI forever or something like that.

I definitely took the long way around trying to debug things. I analyzed which tests were running and how far each was getting by adding print statements that I could view in the CI output. I searched out all the tests that triggered events, just in case my mock event handler was doing Something Strange. Read more on Try All the Easy Fixes First…