Discover more from Engineering Ideas
The Pragmatic Programmer by Thomas & Hunt - notes on the book (part 3)
Scaffold project early, programming language choice, estimation tips, debugging tips, design by contract, take small steps, design data transformations, listen to yourself
Integration tends to take more time than expected, so ensuring the system works end-to-end at the beginning of the project avoids surprises and schedule slip late in the project. In other words, it's one of the Strategies for attacking project risk.
For example, functional language for a compiler, OO language for a game.
Pipe operator in functional PL is a big deal because it lets you think in terms of data transformations.
Use actor model for managing concurrency when actors and state machines match the problem domain language.
Estimate in ranges:
Use PERT, not a single number even for small-scale estimations, particularly in an unknown area.
Base the iteration length on the project experience:
Base the iteration length on the project experience, don't choose arbitrarily. Iterate and refine the project schedule with the code, too.
Turn off auto-repeat in editors and shell to learn how to delete and move the cursor by words and lines. (Note: I actually did that. I like the outcome.)
Store just about everything that defines your machine configuration in version control: user preferences, SSH keys, list of software installed using homebrew, all current projects. Use an old computer to rehearse recovery. (Note: I actually installed Acronis True Image instead, but didn’t verify it is able to restore my entire laptop yet.)
Tracing is more effective than debugging when time itself is a factor: concurrent processes, event-based systems.
Rubber ducking: try to explain what the program is supposed to do out loud. By having to verbalise your assumptions, you may suddenly gain new insight into a problem.
First, explore theories that your code doesn't use the library correctly, than that the library itself is broken. "Select is not broken."
“If it took a long time fixing a bug, ask yourself why. Is there anything you could do to make fixing such bugs easier next time?”
“Alternative to Design by Contract is Program by Coincidence.” (Note: That’s why clojure/spec is huge. I think.)
In requirements work and documents, clearly differentiate between semantic invariants—core, invariable requirements and more situational or potentially changeable policies.
“Any system of agents (services) depends critically on contracts, even if they are dynamically generated.” (Note: reminds me of the OpenAPI initiative.)
If DbC is so powerful, why isn't it used more widely?
No good support in most languages
Doesn't eliminate the need for testing, because blind to consistency and clerical bugs
Benefits come from consistent use, that may feel like a drag on trivial, boilerplate parts of the code (like we are lazy to always check inputs in all code)
Well-specified interface contracts reduce cases when clients intentionally or unintentionally rely on unspecified behaviour.
Take small steps, always. A step is too big when you no longer know or make educated guesses, but need to predict the future.
“Avoid future telling.”
When designing program/system, focus and articulate data transformations (work from requirements), not just draw lines and boxes of components or classes. The structure becomes clearer and error handling more consistent. “Programming is about code, but programs are about data.”
When you have nagging doubts or coding feels more difficult than usual and after every three steps, you slide two steps back, stop and listen to your lizard brain. Is there something the code trying to tell you?
Are the structure and design right?
Is this the right problem to solve?
Aren't you moving in the wrong direction?
Try to pause.
Try to write or tell someone about the problem you are solving.
Thank you for reading!