The Pragmatic Programmer
Rate it:
Open Preview
Read between May 27 - September 3, 2019
34%
Flag icon
Subclasses must be usable through the base class interface without the need for the user to know the difference.
34%
Flag icon
Without a contract, all the compiler can do is ensure that a subclass conforms to a particular method signature. But if we put a base class contract in place, we can now ensure that any future subclass can't alter the meanings of our methods.
34%
Flag icon
Simply enumerating at design time what the input domain range is, what the boundary conditions are, and what the routine promises to deliver—or, more importantly, what it doesn't promise to deliver—is a huge leap forward in writing better software.
35%
Flag icon
Whatever its choice, this is definitely not sqrt's problem. By expressing the domain of the square root function in the precondition of the sqrt routine, you shift the burden of correctness to the caller—where it belongs. You can then design the sqrt routine secure in the knowledge that its input will be in range.
35%
Flag icon
It's much easier to find and diagnose the problem by crashing early, at the site of the problem.
35%
Flag icon
By the definition of "autonomous," agents are free to reject requests that they do not want to honor.
35%
Flag icon
But if we can't use contracts by hand, we won't be able to use them automatically. So next time you design a piece of software, design its contract as well.
36%
Flag icon
It's easy to fall into the "it can't happen" mentality.
36%
Flag icon
Crash Early
36%
Flag icon
However, the basic principle stays the same—when your code discovers that something that was supposed to be impossible just happened, your program is no longer viable. Anything it does from this point forward becomes suspect, so terminate it as soon as possible. A dead program normally does a lot less damage than a crippled one.
36%
Flag icon
There is a luxury in self-reproach. When we blame ourselves we feel no one else has a right to blame us. • Oscar Wilde, The Picture of Dorian Gray
37%
Flag icon
If It Can't Happen, Use Assertions to Ensure That It Won't
37%
Flag icon
Turning off assertions when you deliver a program to production is like crossing a high wire without a net because you once made it across in practice. There's dramatic value, but it's hard to get life insurance.
37%
Flag icon
This problem is a kind of "Heisenbug"—debugging that changes the behavior of the system being debugged (see [URL 52]).
38%
Flag icon
Assume that an uncaught exception will terminate your program and ask yourself, "Will this code still run if I remove all the exception handlers?" If the answer is "no," then maybe exceptions are being used in nonexceptional circumstances.
38%
Flag icon
Use Exceptions for Exceptional Problems
38%
Flag icon
Finish What You Start
41%
Flag icon
This style of coding dramatically increases the number of classes on which our class depends. Why is this a bad thing? It increases the risk that an unrelated change somewhere else in the system will affect your code.
41%
Flag icon
[1] If n objects all know about each other, then a change to just one object can result in the other n – 1 objects needing changes.
42%
Flag icon
Tip 37 Configure, Don't Integrate
42%
Flag icon
Tip 38 Put Abstractions in Code, Details in Metadata
44%
Flag icon
Tip 40 Design Using Services
45%
Flag icon
Tip 41 Always Design for Concurrency
45%
Flag icon
Going the other way (trying to add concurrency to a nonconcurrent application) is much harder. If we design to allow for concurrency, we can more easily meet scalability or performance requirements when the time comes—and if the time never comes, we still have the benefit of a cleaner design.
46%
Flag icon
Tip 42 Separate Views from Models
46%
Flag icon
Model. The abstract data model representing the target object. The model has no direct knowledge of any views or controllers. View. A way to interpret the model. It subscribes to changes in the model and logical events from the controller. Controller. A way to control the view and provide the model with new data. It publishes events to both the model and the view.
49%
Flag icon
Tip 44 Don't Program by Coincidence
51%
Flag icon
Tip 45 Estimate the Order of Your Algorithms
51%
Flag icon
Tip 46 Test Your Estimates
51%
Flag icon
Best Isn't Always Best
52%
Flag icon
Tip 47 Refactor Early, Refactor Often
52%
Flag icon
Don't try to refactor and add functionality at the same time.
53%
Flag icon
don't live with broken windows.
53%
Flag icon
We want to write test cases that ensure that a given unit honors its contract. This will tell us two things: whether the code meets the contract, and whether the contract means what we think it means.
54%
Flag icon
Tip 48 Design to Test
55%
Flag icon
All software you write will be tested—if not by you and your team, then by the eventual users—so you might as well plan on testing it thoroughly.
55%
Flag icon
Tip 49 Test Your Software, or Your Users Will
55%
Flag icon
Tip 50 Don't Use Wizard Code You Don't Understand
57%
Flag icon
That environment has a requirement to leverage existing skill sets. While slavishly duplicating what already exists doesn't allow for progress, we must be able to provide a transition to the future.
59%
Flag icon
Tip 55 Don't Think Outside the Box—Find the Box
59%
Flag icon
Tip 56 Listen to Nagging Doubts—Start When You're Ready
60%
Flag icon
Tip 57 Some Things Are Better Done than Described
60%
Flag icon
As a Pragmatic Programmer, you should tend to view requirements gathering, design, and implementation as different facets of the same process—the delivery of a quality system. Distrust environments where requirements are gathered, specifications are written, and then coding starts, all in isolation. Instead, try to adopt a seamless approach: specification and implementation are simply different aspects of the same process—an attempt to capture and codify a requirement. Each should flow directly into the next, with no artificial boundaries. You'll find that a healthy development process ...more
60%
Flag icon
Tip 58 Don't Be a Slave to Formal Methods
61%
Flag icon
Tip 59 Expensive Tools Do Not Produce Better Designs
62%
Flag icon
There is a simple marketing trick that helps teams communicate as one: generate a brand. When you start a project, come up with a name for it, ideally something off-the-wall. (In the past, we've named projects after things such as killer parrots that prey on sheep, optical illusions, and mythical cities.) Spend 30 minutes coming up with a zany logo, and use it on your memos and reports. Use your team's name liberally when talking with people. It sounds silly, but it gives your team an identity to build on, and the world something memorable to associate with your work.
62%
Flag icon
Tip 60 Organize Around Functionality, Not Job Functions
63%
Flag icon
Civilization advances by extending the number of important operations we can perform without thinking. • Alfred North Whitehead
63%
Flag icon
Tip 61 Don't Use Manual Procedures
63%
Flag icon
that expense_reports be run at midnight on the first of the month.