The Practice of Programming by Brian Kernighan

Parker Klein ✌️
TwosApp
Published in
3 min readFeb 15, 2022

Remember the book you read with Twos ✌️ (CLICK HERE)

Simplicity keeps programs short and manageable

Clarity makes sure they are easy to understand, for people as well as machines

Generality means they work well in a broad range of situations and adapt well as new situations arise

Automation lets the machine do the work for us, freeing us from mundane tasks

The purpose of style is to make the code easy to read for yourself and others, and good style is crucial to good programming

Code should be clear and simple — straightforward logic, natural expression, conventional language use, meaningful names, neat formatting, helpful comments — and it should avoid clever tricks and unusual constructions

The broader the scope of a variable, the more information should be conveyed by its name

Use descriptive names for globals, short names for locals

Use active names for functions

The goal is to write clear code, not clever code

If you work on a program you didn’t write, preserve the style you find there. When you make a change, don’t use your own style even though you prefer it. The program’s consistency is more important than your own, because it makes life easier for those who follow

Comment anything unusual or potentially confusing, but when the comment outweighs the code, the code probably needs fixing

When you change code, make sure the comments are still accurate

If the problem involves modest amounts of data, choose simple techniques; if the data could grow, eliminate designs that will not scale up to large inputs

The design of the data structures is the central decision in the creation of a program. Once the data structures are laid out, the algorithms tend to fall into place, and the coding is comparatively easy

Choosing simple algorithms and data structures, the simplest that will do the job in a reasonable time for the expected problem size

An interface must provide straightforward access to the components while hiding details of the implementation so they can be changed without affecting users

The implementation behind the interface should be hidden from the rest of the program so it can be changed without affecting or breaking anything

As a general principle, errors should be detected at as low a level as possible, but handled at a high level. In most cases, the caller should determine how to handle an error, not the callee

Techniques that help reduce debugging time include good design, good style, boundary condition tests, assertions and sanity checks in the code, defensive programming, well-designed interfaces, limited global data, and checking tools

Debugging techniques: look for familiar patterns, examine the most recent change, debug now, not later, explain your code to someone else

Make the bug reproducible, divide and conquer, draw a picture, display output to localize your search

Debugging is what you do when you know that a program is broken. Testing is a determined, systematic attempt to break a program that you think is working

Testing can demonstrate the presence of bugs, but not their absence

Defensive programming: making sure that a program protects itself against incorrect use or illegal data

Finally, put yourself in the shoes of the person who receives your report. You want to provide the owner with as good a test case as you can manage

Make sure the bug is new. Do you have the latest version of the program?

Thinking about testing as you write a program will lead to better code, because that’s when you know best what the code should do. If instead you wait until something breaks, you will probably have forgotten how the code works

The intent of regression testing is to make sure that the behavior hasn’t changed except in expected ways

Self-contained tests that carry their own inputs and expected outputs provide a complement to regression tests

Whenever a feature is added or a bug is fixed, new tests are added to verify correct operation

Keep a record of bugs, changes, and fixes; it will help you identify old problems and fix new ones

A profile is a measurement of where a program spends its time. Profiling is an effective tool for finding hot spots in a program, the functions or sections of code that consume most of the computing time

Precompute results

Shared from Twos ✌️

--

--

Parker Klein ✌️
TwosApp

Former @Google @Qualcomm @PizzaNova. Building Twos: write, remember & share *things* (www.TwosApp.com?code=baller)