My learnings from The Pragmatic Programmer

ADARSH KUMAR
5 min readJul 24, 2022

Chapter 1: A Pragmatic Philosophy

The Cat Ate My Source Code: Emphasizes personal responsibility and avoiding blame. Developer blames a cat for losing code instead of taking ownership.
Software Entropy: The concept of “broken windows theory” applied to software, where small issues can lead to major decay if left unaddressed. A messy kitchen analogy to describe how neglecting small cleanups leads to a bigger mess.
Stone Soup and Boiled Frogs:

  • Stone Soup: Soldiers convince villagers to contribute ingredients to a soup they claimed to be making with just a stone, resulting in a delicious communal meal. Small contributions can lead to significant improvements.
  • Boiled Frogs: A frog placed in gradually heated water doesn’t notice the increasing temperature until it’s too late. Be aware of gradual deteriorations and act promptly.

Good-Enough Software: Balancing between over-engineering and under-delivering. Aim for solutions that are good enough rather than perfect.
Your Knowledge Portfolio: Continuously invest in your skills and knowledge as you would in a financial portfolio. Diversify your skill set and stay current with trends.
Communicate: Effective communication is essential. Use documentation, clear speech, and active listening to ensure understanding.

Chapter 2: A Pragmatic Approach

The Evils of Duplication: DRY (Don’t Repeat Yourself) principle. Avoid redundancy to reduce maintenance costs and improve clarity.
Orthogonality: Design systems where components operate independently. This reduces risk and simplifies debugging and testing.
Reversibility: Design with the ability to change your mind. Use version control and modular design to facilitate reversibility.
Tracer Bullets: Develop a working system with minimal functionality first, then iterate and improve. This approach helps verify if you’re on the right track early.
Prototypes and Post-it Notes: Use quick prototypes and simple tools to explore ideas and gather feedback before committing to full-scale implementation.
Domain Languages: Create domain-specific languages or mini-languages that tailor to specific problem domains, enhancing expressiveness and reducing complexity.
Estimating: Improve your ability to estimate time and resources needed for tasks. Use historical data and break tasks into smaller pieces for more accurate estimates.

Chapter 3: The Basic Tools

The Power of Plain Text: Plain text is flexible, easy to edit, and suitable for many tasks. Use it for configurations, logs, and data storage.
Shell Games: Master command-line tools to automate tasks and increase efficiency. Scripts can save time and reduce errors.
Power Editing: Invest time in learning a powerful text editor and its shortcuts to improve productivity.
Source Code Control: Use version control systems like Git to manage changes, collaborate, and maintain a history of your code.
Debugging: Develop systematic debugging techniques. Understand the problem, isolate it, and fix it methodically.
Text Manipulation: Use tools like sed, awk, and regex for powerful and efficient text processing.
Code Generators: Automate repetitive tasks by generating code. This reduces errors and saves time.

Chapter 4: Pragmatic Paranoia

Design by Contract: Clearly define the responsibilities of software components using preconditions, postconditions, and invariants.
Dead Programs Tell No Lies: Systems that fail fast reveal issues early, making them easier to diagnose and fix.
Assertive Programming: Use assertions to validate assumptions in your code. This helps catch bugs early.
When to Use Exceptions: Use exceptions for truly exceptional conditions, not for regular control flow.
How to Balance Resources: Manage system resources carefully. Monitor usage and release resources promptly to avoid leaks and contention.

Chapter 5: Bend, or Break

Decoupling and the Law of Demeter: Reduce dependencies to make your code more flexible and maintainable. A coffee machine analogy illustrating the need to reduce dependencies.
Metaprogramming: Write code that generates other code. This can be a powerful way to reduce redundancy and handle complex tasks.
Temporal Coupling: Avoid designs where components must interact in a specific order. This increases flexibility and reduces bugs.
It’s Just a View: Separate the presentation layer from the business logic. This makes the system easier to maintain and scale.
Blackboards: Use a blackboard system where different components can read from and write to a shared memory space, facilitating collaboration and flexibility.

Chapter 6: While You Are Coding

Programming by Coincidence: Avoid relying on luck or coincidence in your code. Write deliberate and intentional code to ensure reliability.
Algorithm Speed: Understand the time and space complexity of algorithms. Choose appropriate algorithms for the task at hand.
Refactoring: Continuously improve your code by restructuring it without changing its external behaviour. This keeps the codebase clean and maintainable.
Code that’s Easy to Test: Design your code to be testable. This often means creating smaller, loosely coupled modules.
Evil Wizards: Be cautious of tools that generate code or hide complexity, as they can obscure understanding and lead to brittle systems.

Chapter 7: Before the Project

The Requirements Pit: Gather requirements iteratively and be ready for them to change. Focus on understanding the true needs behind the requirements.
Solving Impossible Problems: Break down complex problems into smaller, manageable pieces. Use techniques like rubber duck debugging to gain clarity.
Not Until You’re Ready: Don’t rush into a project without proper preparation. Ensure you have the necessary skills, tools, and understanding.
The Specification Trap: Avoid overly detailed specifications that can limit flexibility. Keep specifications high-level and adaptable.
Circles and Arrows: Use diagrams to communicate complex ideas, but don’t become overly reliant on them. Ensure they add value and clarity.

Chapter 8: Pragmatic Projects

Pragmatic Teams: Build teams with diverse skills and encourage open communication and collaboration. Foster a culture of continuous improvement.
Ubiquitous Automation: Automate everything you can, from builds to tests to deployments. This reduces errors and frees up time for more valuable tasks.
Ruthless Testing: Implement thorough and continuous testing practices. Use unit tests, integration tests, and automated tests to catch issues early.
It’s All Writing: Emphasize the importance of writing clear and concise documentation. Good documentation helps others understand and maintain the code.
Great Expectations: Set and manage realistic expectations for project outcomes. Underpromise and overdeliver to build trust and credibility.

Thanks for reading this article, this is one of most well written book for any aspiring or experienced programmer.

--

--

ADARSH KUMAR
ADARSH KUMAR

No responses yet