[Source](https://pragprog.com/the-pragmatic-programmer/extracts/tips "Permalink to List of Tips | The Pragmatic Bookshelf ") # List of Tips | The Pragmatic Bookshelf __ * [Books & Screencasts][1] * [Forums][2] * [Support][3] * [Video Courses][4] * [Become an Author][5] * [Log in][6] * __ [Skip to main content][7] [ ][8] * [Books & Screencasts][1] * [Forums][2] * [Support][3] * [Video Courses][4] * [Become an Author][5] * * [ _ _ Cart (0) ][9] * [Login][6] [ _ _ Cart (0) ][9] ## By developers for developers. **small** **medium** **large** **xlarge** × # List of Tips ![Cover Image For The Pragmatic Programmer…][10] Extracted From _The Pragmatic Programmer_ by Andrew Hunt and David Thomas. Copyright 2000, Addison Wesley. We’ve been busy since we first wrote _The Pragmatic Programmer_ back in 1999. Have you seen all of our [recent books that we’ve written or published][11]? From Agility to Ruby on Rails, project management to debugging your career, we’ve got the titles to help keep you on top of your game. —Andy and Dave * [Browse all titles][11] * [Browse by category][12] #### Pragmatic Software Development Tips **Care About Your Craft** Why spend your life developing software unless you care about doing it well? **Provide Options, Don’t Make Lame Excuses** Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done. **Be a Catalyst for Change** You can’t force change on people. Instead, show them how the future might be and help them participate in creating it. **Make Quality a Requirements Issue** Involve your users in determining the project’s real quality requirements. **Critically Analyze What You Read and Hear** Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project. **DRY—Don’t Repeat Yourself** Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. **Eliminate Effects Between Unrelated Things** Design components that are self-contained, independent, and have a single, well-defined purpose. **Use Tracer Bullets to Find the Target** Tracer bullets let you home in on your target by trying things and seeing how close they land. **Program Close to the Problem Domain** Design and code in your user’s language. **Iterate the Schedule with the Code** Use experience you gain as you implement to refine the project time scales. **Use the Power of Command Shells** Use the shell when graphical user interfaces don’t cut it. **Always Use Source Code Control** Source code control is a time machine for your work—you can go back. **Don’t Panic When Debugging** Take a deep breath and THINK! about what could be causing the bug. **Don’t Assume It—Prove It** Prove your assumptions in the actual environment—with real data and boundary conditions. **Write Code That Writes Code** Code generators increase your productivity and help avoid duplication. **Design with Contracts** Use contracts to document and verify that code does no more and no less than it claims to do. **Use Assertions to Prevent the Impossible** Assertions validate your assumptions. Use them to protect your code from an uncertain world. **Finish What You Start** Where possible, the routine or object that allocates a resource should be responsible for deallocating it. **Configure, Don’t Integrate** Implement technology choices for an application as configuration options, not through integration or engineering. **Analyze Workflow to Improve Concurrency** Exploit concurrency in your user’s workflow. **Always Design for Concurrency** Allow for concurrency, and you’ll design cleaner interfaces with fewer assumptions. **Use Blackboards to Coordinate Workflow** Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants. **Estimate the Order of Your Algorithms** Get a feel for how long things are likely to take before you write code. **Refactor Early, Refactor Often** Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem. **Test Your Software, or Your Users Will** Test ruthlessly. Don’t make your users find bugs for you. **Don’t Gather Requirements—Dig for Them** Requirements rarely lie on the surface. They’re buried deep beneath layers of assumptions, misconceptions, and politics. **Abstractions Live Longer than Details** Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies. **Don’t Think Outside the Box—Find the Box** When faced with an impossible problem, identify the real constraints. Ask yourself: "Does it have to be done this way? Does it have to be done at all?" **Some Things Are Better Done than Described** Don’t fall into the specification spiral—at some point you need to start coding. **Costly Tools Don’t Produce Better Designs** Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits. **Don’t Use Manual Procedures** A shell script or batch file will execute the same instructions, in the same order, time after time. **Coding Ain’t Done ‘Til All the Tests Run** ‘Nuff said. **Test State Coverage, Not Code Coverage** Identify and test significant program states. Just testing lines of code isn’t enough. **English is Just a Programming Language** Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on. **Gently Exceed Your Users’ Expectations** Come to understand your users’ expectations, then deliver just that little bit more. **Think! About Your Work** Turn off the autopilot and take control. Constantly critique and appraise your work. **Don’t Live with Broken Windows** Fix bad designs, wrong decisions, and poor code when you see them. **Remember the Big Picture** Don’t get so engrossed in the details that you forget to check what’s happening around you. **Invest Regularly in Your Knowledge Portfolio** Make learning a habit. **It’s Both What You Say and the Way You Say It** There’s no point in having great ideas if you don’t communicate them effectively. **Make It Easy to Reuse** If it’s easy to reuse, people will. Create an environment that supports reuse. **There Are No Final Decisions** No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change. **Prototype to Learn** Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn. **Estimate to Avoid Surprises** Estimate before you start. You’ll spot potential problems up front. **Keep Knowledge in Plain Text** Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing. **Use a Single Editor Well** The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable. **Fix the Problem, Not the Blame** It doesn’t really matter whether the bug is your fault or someone else’s—it is still your problem, and it still needs to be fixed. **"select" Isn’t Broken** It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application. **Learn a Text Manipulation Language** You spend a large part of each day working with text. Why not have the computer do some of it for you? **You Can’t Write Perfect Software** Software can’t be perfect. Protect your code and users from the inevitable errors. **Crash Early** A dead program normally does a lot less damage than a crippled one. **Use Exceptions for Exceptional Problems** Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things. **Minimize Coupling Between Modules** Avoid coupling by writing "shy" code and applying the Law of Demeter. **Put Abstractions in Code, Details in Metadata** Program for the general case, and put the specifics outside the compiled code base. **Design Using Services** Design in terms of services—independent, concurrent objects behind well-defined, consistent interfaces. **Separate Views from Models** Gain flexibility at low cost by designing your application in terms of models and views. **Don’t Program by Coincidence** Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy coincidence with a purposeful plan. **Test Your Estimates** Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in its target environment. **Design to Test** Start thinking about testing before you write a line of code. **Don’t Use Wizard Code You Don’t Understand** Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project. **Work with a User to Think Like a User** It’s the best way to gain insight into how the system will really be used. **Use a Project Glossary** Create and maintain a single source of all the specific terms and vocabulary for a project. **Start When You’re Ready** You’ve been building experience all your life. Don’t ignore niggling doubts. **Don’t Be a Slave to Formal Methods** Don’t blindly adopt any technique without putting it into the context of your development practices and capabilities. **Organize Teams Around Functionality** Don’t separate designers from coders, testers from data modelers. Build teams the way you build code. **Test Early. Test Often. Test Automatically.** Tests that run with every build are much more effective than test plans that sit on a shelf. **Use Saboteurs to Test Your Testing** Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them. **Find Bugs Once** Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on. **Build Documentation In, Don’t Bolt It On** Documentation created separately from code is less likely to be correct and up to date. **Sign Your Work** Craftsmen of an earlier age were proud to sign their work. You should be, too. | ----- | | [Buy eBook][13] | [Browse Titles][11] | [Discuss!][14] | # Added to your cart Continue Shopping [View Your Cart][9] Yes No ## Customer Service * [Contact][15] * [Privacy][16] * [Legal][17] * [Become an Author][5] * [Security][18] ## Menu * [Categories][19] * [Screencasts][20] * [Video Courses][4] * [Magazine][21] * [Articles][22] * [Forums][23] * [Help Wanted][24] * [Promotions][25] * [About][26] * [Login][6] * __ * __ * [ __ ][27] * [ __ ][28] * [ __ ][29] © 1999–2018 The Pragmatic Programmers, LLC [1]: https://pragprog.com/categories/all [2]: https://forums.pragprog.com/ [3]: https://pragprog.com/frequently-asked-questions/ [4]: https://pragmaticstudio.com [5]: http://write-for-us.pragprog.com/ [6]: https://pragprog.com/login [7]: https://pragprog.com#main [8]: https://pragprog.com/ [9]: https://pragprog.com/cart "Display your cart and proceed to checkout" [10]: https://imagery.pragprog.com/products/59/tpp_largecover.jpg?1339433898 [11]: https://pragprog.com/titles [12]: https://pragprog.com/categories [13]: https://pragprog.com/titles/tpp [14]: http://forums.pragprog.com/forums/tpp [15]: https://pragprog.com/contact [16]: https://pragprog.com/privacy [17]: https://pragprog.com/terms-of-use [18]: https://pragprog.com/security [19]: https://pragprog.com/titles/category/all [20]: https://pragprog.com/screencasts [21]: https://pragprog.com/magazines [22]: https://pragprog.com/articles [23]: http://forums.pragprog.com/ [24]: https://pragprog.com/help-wanted [25]: https://pragprog.com/promotions [26]: https://pragprog.com/about [27]: https://pragprog.com/feed/global/news.rss [28]: https://pragprog.com/frequently-asked-questions/ebooks/sending-ebooks-to-your-dropbox [29]: https://pragprog.com/frequently-asked-questions/ebooks/sending-ebooks-to-your-google-drive