Eating Elephants
Maintaing the Sense of Purpose
some problems require quick surface level patch fixes, there focus on reaching
the solution the fastest. diving deep makes sense if the project is for
learning or some deep refactor is required. another solution is to get started
with a quickfix, followed by larger code refactors.
About Mental Models
- make your assumptions about how things work more explisit
- read books learn about different system arcitectures
- perform experiments on the system if it's too large to read in time
- validate assumptions with experiments
- don't fall for 'confirmation bias', try prove it wrong, not right
- test assumptions and find cases where the model doesn't fit the reality
- dev environment is not the same as production, focus on integration more
code is just the textual representation of the mental model of the problem.
so it's wise to focus on the mental model , and not to get lost into the
code. the bug in code is because of some holes in the mental model, so focus
on finding the holes in the mental model first than just fixing the bug.
debugging without looking at the code
code is edited maybe 5 or 10 times in a decade, but it's read thousands of
times, and the readers are trying to understand the mental model which lead to
that code. make sure to write code such that it's easy for others to create a
mental model when they read your code, and their mental models should be close
to yours... it's your responsitility!
Code Documentation
- code tells what not why, self documenting code is a sweet lie
- comments are very important, to tell why that code was written
- implisit assumptions and knowledge is more dangerous than over expln...
- well crafted code reads like prose
let's take a look at a few bits of well written code which reads like prose.
reading the interface definition, i exactly know what it is about and where to
look next.
// The Filter interface represents a process that takes as input a
// sequence of strings from a channel and produces a sequence on
// another channel.
type Filter interface {
// RunFilter reads a sequence of items from Arg.In and produces a
// sequence of items on Arg.Out. RunFilter returns nil on success,
// an error otherwise. RunFilter must #not# close the Arg.Out
// channel.
RunFilter(Arg) error
}
- these code samples belong to
sanjay ghemawat
, a google engineer
- reading other's code helps gain perspectives on good and bad engrg.
- the best code is like a good piece of writing
Rapid Prototyping
hack/prototype a quick end-to-end working solution that touches every part in
a timeboxed setting, hardcode most of it. this way there will be less chances
of running into the unknown and magical surprices.
estimation will be easy as you would know the simple and the complicated
areas. work in small, solid increments to keep yourself motivated and to have
something to show for all that time you spent on the project, one step at a
time and verify the step everytime. this saves hours of painful debugging due
to mixup of changes at different steps.
just reading can be misleading as code is not the same as the state of the
program at a certain point. run the program, attach a debugger and step
through the code to understand what it is doing, how it looks. use callgrind
etc and look at the callgraph maybe.
Reading Code
- read the logs/errors carefully, it's easy to miss something very obvious
- visualizing cleaned-up logs using some script can save hours of labour
- don't rely too much on the system exec state, it's a hand wavy stat
- look for simpler, direct metrics to actually guide your decisions
- learn to speedread code, focus on key areas not impl details, take notes
- custom editors should help navigate the codebase faster
- commit history of a file tells about the evolution of code in that area
- know the tools available around the domain, what and why beind them
- keep checking relevance of the code in the curr context
- avoid mixup of multiple issues in one solution, stay focused on one atat
Reading in General
- the word is not the thing
- reading and getting it is the most important skill, anywhere.
- serious knowledge comes form books/docs/long-articles as they take time
- reading, creating mental mods and finding loopholes is an art in itself
- explore several resources and isolate the ones worth reading
- focus on quality, don't rush and be greedy about reading the next one
- avoid passive entertainment as that messes up with the reward/fear sys
- don't speedread, focus on one word at a time, that's all you need!
- good books require multiple reads before you actually get anything
- don't be too attached to the tools, they are just means, not the path
- learn complex tools slowly, first on small codebases, one command atat
- avoid guis as they hide a lot of details and are often limiting
- observe the experts using the tool to see what it's capable of
- test tools under pressure situations and gain confidence
- printfdebugging is the first tool
- if stdout/stderr cluttered, log to a separate file instead
- print the stack to understand what's going on in the code
- a repl helps look and experiment with the current state of the code
- string based regexp tools also help (find/grep/sed/xargs)
Detailed Logging
- maintain structured logs of everything, what works, what doesn't
- breakdown the problem, approaches, goals... keep focus on the main issue
- have a list of open questions and keep eyes open for clues for answers
- maintain daily logs of approaches, stack traces, what didn't work...
- share notes with others when the task is complete
- freeze the notes with the code changes in the commit message
Sources and Suggested Reads