More on this book
Community
Kindle Notes & Highlights
by
Andy Hunt
Read between
January 17 - January 25, 2021
Programming is a craft. At its simplest, it comes down to getting a computer to do what you want it to do (or what your user wants it to do). As a programmer, you are part listener, part advisor, part interpreter, and part dictator. You try to capture elusive requirements and find a way of expressing them so that a mere machine can do them justice. You try to document your work so that others can understand it, and you try to engineer your work so that others can build on it. What’s more, you try to do all this against the relentless ticking of the project clock. You work small miracles every
...more
Pragmatic Programmers get the job done, and do it well.
We who cut mere stones must always be envisioning cathedrals.
What distinguishes Pragmatic Programmers? We feel it’s an attitude, a style, a philosophy of approaching problems and their solutions. They think beyond the immediate problem, placing it in its larger context and seeking out the bigger picture.
When you find yourself saying, “I don’t know,” be sure to follow it up with “—but I’ll find out.” It’s a great way to admit what you don’t know, but then take responsibility like a pro.
the laws of thermodynamics guarantee that the entropy in the universe tends toward a maximum. When disorder increases in software, we call it “software rot.” Some folks might call it by the more optimistic term, “technical debt,” with the implied notion that they’ll pay it back someday. They probably won’t.
Don’t leave “broken windows’’ (bad designs, wrong decisions, or poor code) unrepaired.
One broken window is one too many.
Keep an eye on the big picture. Constantly review what’s happening around you, not just what you personally are doing.
The scope and quality of the system you produce should be discussed as part of that system’s requirements.
“The meaning of your communication is the response you get.”
There’s one technique that you must use if you want people to listen to you: listen to them.
Good Design Is Easier to Change Than Bad Design
Why is decoupling good? Because by isolating concerns we make each easier to change.
given that you’re not sure what form change will take, you can always fall back on the ultimate “easy to change” path: try to make what you write replaceable. That way, whatever happens in the future, this chunk of code won’t be a roadblock.
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Ask yourself what the comment adds to the code. From our point of view, it simply compensates for some bad naming and layout.
All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.
Make It Easy to Reuse
Don’t rely on the properties of things you can’t control.
Prototyping is a learning experience. Its value lies not in the code produced, but in the lessons learned. That’s really the point of prototyping.
Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be.
You need to be able to manipulate text as effortlessly as possible, because text is the basic raw material of programming.
modern computer systems are still limited to doing what you tell them to do, not necessarily what you want them to do.
“Defensive programming is a waste of time. Let it crash!”
A dead program normally does a lot less damage than a crippled one.
Much of the time, tomorrow looks a lot like today. But don’t count on it.
Coupling is the enemy of change, because it links together things that must change in parallel.
Decoupled Code Is Easier to Change
Meetings where everyone has to attend because no one is sure who will be affected by a change.
Tell, Don’t Ask This principle says that you shouldn’t make decisions based on the internal state of an object and then update that object. Doing so totally destroys the benefits of encapsulation and, in doing so, spreads the knowledge of the implementation throughout the code.
Each piece of global data acts as if every method in your application suddenly gained an additional parameter: after all, that global data is available inside every method.
Our experience has been that reuse should probably not be a primary concern when creating code, but the thinking that goes into making code reusable should be part of your coding routine. When you make code reusable, you give it clean interfaces, decoupling it from the rest of your code. This allows you to extract a method or module without dragging everything else along with it.
You’ll see this problem when you’re writing unit tests for code that uses global data. You’ll find yourself writing a bunch of setup code to create a global environment just to allow your test to run.
If It’s Important Enough to Be Global, Wrap It in an API
Coupled code is hard to change: alterations in one place can have secondary effects elsewhere in the code, and often in hard-to-find places that only come to light a month later in production.
Programming Is About Code, But Programs Are About Data
Inheritance encourages developers to create classes whose objects have large numbers of methods. If a parent class has 20 methods, and the subclass wants to make use of just two of them, its objects will still have the other 18 just lying around and callable. The class has lost control of its interface.
Concurrency is when the execution of two or more pieces of code act as if they run at the same time. Parallelism is when they do run at the same time.
Random Failures Are Often Concurrency Issues
You could also argue that functional languages, with their tendency to make all data immutable, make concurrency simpler. However, they still face the same challenges, because at some point they are forced to step into the real, mutable world.
Testing is not about finding bugs, it’s about getting feedback on your code: aspects of design, the API, coupling, and so on.
When you spot things done in a way that seems strange, jot it down. Continue doing this, and look for patterns. If you can see what drove them to write code that way, you may find that the job of understanding it becomes a lot easier. You’ll be able consciously to apply the patterns that they applied tacitly.
Finding an answer that happens to fit is not the same as the right answer.
67 A Test Is the First User of Your Code
Build End-to-End, Not Top-Down or Bottom Up We strongly believe that the only way to build software is incrementally. Build small pieces of end-to-end functionality, learning about the problem as you go. Apply this learning as you continue to flesh out the code, involve the customer at each step, and have them guide the process.
The beginning of wisdom is to call things by their proper name.
When naming things, you’re constantly looking for ways of clarifying what you mean, and that act of clarification will lead you to a better understanding of your code as you write it.
Programmers Help People Understand What They Want
The secret to solving the puzzle is to identify the real (not imagined) constraints, and find a solution therein.