Article summary
I recently had the opportunity to pair with Scott Vokes on a side project. He had an idea for a simple C program and let me drive while we talked through the design. In a few short hours, I learned a lot more than I expected. I’ll add the list below.
Learning through Paring
At Atomic Object, we’ve been pairing pragmatically on projects as a way of solving problems more effectively. While working with Scott on odo, I was reminded of how how well pairing also works for knowledge transfer. By sitting down for an hour or two and doing the work together, the gaps in my knowledge that were pertinent to problem at hand were quickly exposed. With Scott answering questions based on his experience, I was spared many hours of Googling and weighing different solutions and approaches against each other.
One area I was surprised to find this particularly valuable was when it came to questions of style and project setup. I don’t write a lot of C, so starting on something like this alone would have left me with a lot of anxiety about the right way to do things: what kind of Makefile should I have? Should I be using autotools? Where should I put my brackets? How should I align this block of code? Having an expert there from whom to borrow opinions on these things saved a lot of worry.
As an aside: another place you might look to answer some of these questions for a handful of project types is How I Start. Also, I really like that in the Go programming language, go fmt
eliminates much of this cognitive overhead about formatting.
With these environmental and stylistic issues easily dealt with thanks to Scott’s experience, we were able to talk through the problem and design, and discuss the trade-offs of a couple different approaches to atomicity. For more on that, see Scott’s post on odo.
If you have the time, patience, and a good friend or mentor with the same, I would highly recommend trying out this approach to learning something new.
(By the way, Hacker School students will have the opportunity to pair with Scott in late January, when he will spend a week there as a Hacker School Resident).
What I Learned
Here are a few of the things I learned while pairing with Scott.
More about Emacs
(I usually use Vim, but recently forked Scott’s Emacs config):
- How to maintain a 2-window split and flip quickly between recently active buffers
- How to use built-in hooks for make
- Efficient patterns of use:
- Open what docs/files you need, let midnight mode clean things up later
- Using bindings that can toggle between buffers (e.g. C-z for shell or last buffer)
- Which parts of Scott’s config don’t work for me (e.g. bindings that make more sense on Dvorak)
More about Makefiles
- How to set compiler flags
- When it’s not yet necessary to have a Makefile
More about C
- Style preferences (more on this later)
- Easy typos to make (e.g. ‘=’ for ‘==’) and how to catch errors
- E.g. There is a style that makes assignment in place of equality checks a syntax error
- But you can also just turn on more compiler warnings & test to catch it
- Pointer / dereferencing syntax is confusing, and I shouldn’t feel bad for thinking that
- This is one of those thing you end up just internalizing after spending a lot of time in the language
- More examples of why working with pointers and pointer math can be dangerous
- How to organize small programs (e.g. start by describing internal API in a .h file)
More about syscalls
- Wow! Man pages for syscalls are full of really useful info!
- Also: the Stevens book is great
- Also: compare different OSes for interesting differences (the FreeBSD docs site has a good collection of docs for various OSes in the Unix family)
mmap
is really powerful (and dangerous). Wow.- Error checking/handling patterns (not entirely unlike what I’ve seen in Go…)
More about (using) C compilers
- Systems programming has its own yaks to shave
- I’m used to dealing with Ruby’s “dependency hell” but had idealized systems programming as yak-free
- It turns out that there are plenty of incidental complexities around C programming, too.
- e.g. trying to find out about support for compiler-provided features (e.g. Atomic CAS) can be hard
- Compiler-provided features are totally a thing