Three things (I thought) they taught me in school

Morgan Connolly
Engineering @ BuildZoom
8 min readJun 1, 2018

How to debug software

My first experience programing was during freshman year of college, in CS10, The Beauty and Joy of Computing. CS10 is taught in Snap. Snap involves very little typing; to build programs you click and drag pre-defined blocks of “code” together to construct a program and press a “Play” button to run it.

When I started coding in Snap I had no intentions to be a professional developer. Or, even to take another computer science class after finishing CS10. But, sometime into debugging one of my first projects (a hangman game) I found myself thinking that if I could just make this code work I would feel like a wizard.

For me, debugging in Snap typically involved building a fat stack of blocks, then pressing play, and finally staring intently at my Sprites trying to figure out if they were doing exactly what I intended them to do. You might wonder what Sprites are. They are cartoon-like representations of objects, used to make OOP more accessible to beginners.

As you might imagine, this debugging strategy was time consuming and not particularly effective. When the following semester I encountered Python print statements, the insight they provided into the precise inner workings of my code felt like magic. When I met my first command line debugger, jdb, my first thought was “nah man this is harder than writing code”. But the following semester an Operating Systems course in C showed me the light and glory of line-by-line debugging with gdb.

June 2017, when I started working at BuildZoom, I grabbed the two relevant line-by-line debuggers for our stack, “byebug” for the ruby back-end and “debugger” for the AngularJS frontend and cheerfully prepared to annihilate all bugs found in testing quickly and easily ship perfect, bug free code all day every day. Then, reality kicked in.

As you might imagine, my first year working on a living code base within a team of developers has not been bug free. And, I’ve had to build upon the debugging skills I learned in college. Many times I’ve been assigned bugs to fix that are in parts of the code base several BART stops away from anywhere I’ve been before. And sometimes these bugs are reproducible only in a production environment — a situation that, I thought, must exist to frustrate me personally the first time I encountered it. My new favorite debugging techniques are unit tests and grepping logs. And, when I’ve tracked down insidious production bugs or produce working code in record time, I feel distinctly magical. Like that time back in college.

To summarize, I’ve learned that when debugging one should

  • analyze symptoms — this step involves mustering all the information you can gather about the bug. How often has it happened? When did it start? What kind of users does it happen for? This is a good time to leverage logs and any kind of bug reporting system your team uses.
  • understand impact — this usually falls out of analyzing symptoms and is a a critical early step. Because, understanding the impact of a bug allows you to prioritize it.
  • pinpoint the source of the bug — this can be the most time consuming step. Finding the exact code/environment/input tuple that produces a bug is difficult. This is usually the time to break out the line-by-line debugger.
  • Fix the bug, and make a pull request — If you’ve completed the previous three steps this may very well be the easiest and quickest part of the process.

Asking questions

I’ve encountered two big difference between asking questions at school and asking questions at work.

Scope of the questions

Problem sets and projects assigned in courses are, without fail, within the scope of the class. In other words, if you learn all the material presented in the class you will be able to complete the projects and problem sets well. In school, if you’re asking a question, there was probably a way for you to answer the question yourself in approximately the same time as it will take someone to explain the answer to you. For this reason, I avoided asking questions — and the accompanying risk of appearing stupid — by putting hours into a problem before I brought it to an instructor to ask for help. My personal algorithm for seeking help in school was roughly linear and looked something like this: try -> google -> cry -> GSI (graduate student instructor).

In contrast to the limited and well defined scope of a college course, the space of problems you might encounter working in a production code base is vast. Even if a computer science education focused entirely on software development skills (which it most certainly does not) this hypothetical education would not be able to cover the set of problems you might encounter at work. For this reason, there are some problems you should not stare at for several hours before asking for help. For example, when learning a new code base there will probably be conventions you are unfamiliar with. And, someone who is familiar with these conventions can explain them to you far faster than you would be able to figure them out yourself.

Who’s answering the questions

The second big difference between asking questions at school and at work is at school there are people whose job it is to answer your questions. So, if you ask them something you could have googled, then they will probably just be happy that your question wasn’t harder to answer. And, if you ask them a long, rambling question that involves notes spread over several sheets of scratch paper they will probably just be happy you tried to solve the problem on your own before coming to office hours. In contrast, at work every question you ask is taking your coworker’s time away from their own projects. So there’s a much greater opportunity cost to answering questions than during school. If it’s a googlable question, you’re wasting their time. The same is true if the question is not presented concisely.

As any good adventuring party should, the engineering team at BuildZoom has specialists and domain experts. My current help seeking algorithm is significantly more dynamic. And, it benefits dramatically from the wealth of knowledge available a few steps in any direction from my desk.

Building accurate estimates

Making accurate time estimates in school is usually purely for your own benefit. For me, the process of building time estimates for projects and problem sets in school often went something like this

  1. Take number of days between the date the assignment comes out and the date it is due. Divide this number of days by two. Assume you’re working on the assignment for 1.5 hours per day. Call the result course_estimate.
  2. Ask everyone I know who has taken the course to estimate how long the project took them.
  3. Adjust the time estimates from number 2 based on which of the two possible sets of people the estimator comes from: people who code slower than me and liars (joke). Call this list of estimates friend_estimates.
  4. Take the mean of the elements of friend_estimates and course_estimate; the result is approximately the number of hours the assignment should take to complete.

At work, each project is something new. And, fielding reliable estimates necessitates diving deep into the technical nitty-gritty of the assignment. However, this means that if one is making time estimates one is forced to lay out a detailed plan before starting the project. This can be difficult. But, I’ve learned that one shouldn’t start a project until one has a relatively detailed time estimate. If I find that I can’t make a detailed estimate, this is usually a glaring indication that I should not start writing code until I have a better idea of how I’m going to complete the project requirements.

Of course, I sometimes find myself throwing out my careful, broken-down-into-30-or-15-minute-segments time estimate. When this happens, I find myself mourning the lost half an hour taken to craft the estimate. Of course, the time it would have taken to build and test the code would have been far more dear.

To create an estimate

  • break the project down into major parts, e.g. front-end work, back-end work and try to figure out what existing files you’ll be touching. At this point, don’t even try to make time estimates yet. Just figure out what the major parts of the project are.
  • break each major part down into smaller parts, e.g. building a new API call, styling a new button. Try to make time estimates for each of these parts,
  • break any of your estimates that are larger than an hour down into smaller parts.
  • add up your current estimate and budget about 50% of it for QA and unexpected delays.

People would do that? Go on the internet and state their opinions as facts?

My computer science education did not consist of learning anything as an opinion. So, when I set out to learn my first technologies out of school (Ruby and Rails) I was at a bit of a loss to shrewedly consume technical material. RailsGuides taught me about ActiveRecord callbacks (cool!) and later I encountered Destroy All Software screencast. DAS is not a fan of ActiveRecord callbacks. I was skeptical of this opinion. Surely an entire feature of the rails framework couldn’t just be *wrong*. But, eventually I did encounter a nasty callback bug and realized that perhaps the problem with callbacks is that they end up being used where something with easier-to-predict behavior would suffice. Anyone who has spent time learning software development will know that there are bitter and strongly-worded disagreements about the best way to write code. However, I’ve realized that you can take someone’s advice without subscribing to their dogma. And, I think I now understand better why developers state their opinions so strongly. I actually think this tactic is used for two reasons.

1. to say something strongly enough that people remember it and (more importantly)

2. to say something strongly enough to invite disagreement and spark discussion.

tldr;

I have learned much in the past year; I’ve probably learned more interesting, useful, and difficult stuff than I have in any previous year (except perhaps the year I learned how to read). And, I’ve certainly picked up quite a few nice new technical stats.

But, most of the learnings I’ve discussed here are not facts, techniques, technologies or concepts. The learnings I’ve discussed have been more abstract — and correspondingly more difficult to acquire. If I were to purpose these thoughts as advice they would more like a self-help book than documentation. I think this may be because school actually succeeded at teaching me how to to program. I do not claim that school made me a good programmer, you’d have to ask my manager that, but it taught me to be comfortable with coding.

However, school did not teach me how to be a software developer. That is, how to develop and debug in a large production code base, learn from your team, be reliable for the rest of the company and ultimately ship code. And, the first hints of magic I felt when dragging Snap blocks around in CS10 did not prepare me for the camaraderie and satisfaction of shipping code with an awesome team. But, when you think about it, that’s the real magic.

--

--