└── readme.md /readme.md: -------------------------------------------------------------------------------- 1 | 2 | This is my summary of the The Pragmatic Programmer, by Andrew Hunt and David Thomas. I use it while learning and as quick reference. It is not intended to be an standalone substitution of the book so if you really want to learn the concepts here presented, buy and read the book and use this repository as a reference and guide. 3 | 4 | If you are the publisher and think this repository should not be public, just write me an email at hugomatilla [at] gmail [dot] com and I will make it private. 5 | 6 | Contributions: Issues, comments and pull requests are super welcome 😃 7 | There is a [Quick Reference](#quick-reference) at the end. 8 | 9 | 10 | # Table of Contents 11 | - [Table of Contents](#table-of-contents) 12 | - [Chapter 1. A Pragmatic Philosophy](#chapter-1-a-pragmatic-philosophy) 13 | - [1.-The Cat Ate My Source Code](#1-the-cat-ate-my-source-code) 14 | - [2.-Software Entropy](#2-software-entropy) 15 | - [3.-Stone Soup and Boiled Frogs](#3-stone-soup-and-boiled-frogs) 16 | - [4.-Good enough soup](#4-good-enough-soup) 17 | - [5.-Your Knowledge Portfolio](#5-your-knowledge-portfolio) 18 | - [6.-Communicate](#6-communicate) 19 | - [Chapter 2. A Pragmatic Approach](#chapter-2-a-pragmatic-approach) 20 | - [7.-The Evils of Duplication](#7-the-evils-of-duplication) 21 | - [8.-Orthogonality](#8-orthogonality) 22 | - [9.-Reversibility](#9-reversibility) 23 | - [10-Tracer Bullets](#10-tracer-bullets) 24 | - [11.-Prototypes and Post-it Notes](#11-prototypes-and-post-it-notes) 25 | - [12.-Domain Languages](#12-domain-languages) 26 | - [13.-Estimating](#13-estimating) 27 | - [Chapter 3. The Basic Tools](#chapter-3-the-basic-tools) 28 | - [14.-The Power of Plain Text](#14-the-power-of-plain-text) 29 | - [15.-Shell Games](#15-shell-games) 30 | - [16.-Power Editing](#16-power-editing) 31 | - [17.-Source Code Control](#17-source-code-control) 32 | - [18.-Debugging](#18-debugging) 33 | - [19.-Text Manipulation](#19-text-manipulation) 34 | - [20.-Code Generators](#20-code-generators) 35 | - [Chapter 4. A Pragmatic Paranoia](#chapter-4-a-pragmatic-paranoia) 36 | - [21.-Design by Contract](#21-design-by-contract) 37 | - [22.-Dead Programs Tell No Lies](#22-dead-programs-tell-no-lies) 38 | - [23.-Assertive Programming](#23-assertive-programming) 39 | - [24.-When to Use Exceptions](#24-when-to-use-exceptions) 40 | - [25.-How to Balance Resources](#25-how-to-balance-resources) 41 | - [Chapter 5. Bend or Break](#chapter-5-bend-or-break) 42 | - [26.-Decoupling and the Law of Demeter](#26-decoupling-and-the-law-of-demeter) 43 | - [27.-Metaprogramming](#27-metaprogramming) 44 | - [28.- Temporal Coupling](#28-temporal-coupling) 45 | - [29.-It's Just a View](#29-its-just-a-view) 46 | - [30.-Blackboards](#30-blackboards) 47 | - [Chapter 6. While you are coding](#chapter-6-while-you-are-coding) 48 | - [31.-Program by Coincidence](#31-program-by-coincidence) 49 | - [32.-Algorithm Speed](#32-algorithm-speed) 50 | - [33.-Refactoring](#33-refactoring) 51 | - [34.-Code That's Easy to Test](#34-code-thats-easy-to-test) 52 | - [35.-Evil Wizards](#35-evil-wizards) 53 | - [Chapter 7. Before the project](#chapter-7-before-the-project) 54 | - [36.-The Requirements Pit](#36-the-requirements-pit) 55 | - [37.-Solving Impossible Puzzles](#37-solving-impossible-puzzles) 56 | - [38.-Not Until You're Ready](#38-not-until-youre-ready) 57 | - [39.-The Specification Trap](#39-the-specification-trap) 58 | - [40.-Circles and Arrows](#40-circles-and-arrows) 59 | - [Chapter 8. Pragmatic Projects](#chapter-8-pragmatic-projects) 60 | - [41.-Pragmatic Teams](#41-pragmatic-teams) 61 | - [42.-Ubiquitous Automation](#42-ubiquitous-automation) 62 | - [43.-Ruthless testing](#43-ruthless-testing) 63 | - [44.-It's All Writing](#44-its-all-writing) 64 | - [45.- Great Expectations](#45-great-expectations) 65 | - [Quick Reference](#quick-reference) 66 | - [Tips](#tips) 67 | - [CheckList](#checklist) 68 | - [Languages To Learn](#languages-to-learn) 69 | - [The WISDOM Acrostic](#the-wisdom-acrostic) 70 | - [How to Maintain Orthogonality](#how-to-maintain-orthogonality) 71 | - [Things to prototype](#things-to-prototype) 72 | - [Architectural Questions](#architectural-questions) 73 | - [Debugging Checklist](#debugging-checklist) 74 | - [Law of Demeter for Functions](#law-of-demeter-for-functions) 75 | - [How to Program Deliberately](#how-to-program-deliberately) 76 | - [When to Refactor](#when-to-refactor) 77 | - [Cutting the Gordian Knot](#cutting-the-gordian-knot) 78 | - [Aspects of Testing](#aspects-of-testing) 79 | 80 | 81 | # Chapter 1. A Pragmatic Philosophy 82 | **Tip 1: Care About Your Craft** 83 | 84 | Why spend your life developing software unless you care about doing it well? 85 | 86 | **Tip 2: Think! About Your Work** 87 | 88 | Turn off the autopilot and take control. Constantly critique and appraise your work. 89 | 90 | ## 1.-The Cat Ate My Source Code 91 | **Tip 3: Provide Options, Don't Make Lame Excuses** 92 | 93 | Instead of excuses, provide options. Don't say it can't be done; explain what can be done to salvage the situation. 94 | 95 | ## 2.-Software Entropy 96 | One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment—a sense that the powers that be don't care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short space of time, the building becomes damaged beyond the owner's desire to fix it, and the sense of abandonment becomes reality. 97 | 98 | **Tip 4: Don't Live with Broken Windows** 99 | 100 | Don't mess up the carpet when fixing the broken window. 101 | 102 | ## 3.-Stone Soup and Boiled Frogs 103 | It's time to bring out the stones. Work out what you can reasonably ask for. Develop it well. Once you've got it, show people, and let them marvel. Then say "of course, it would be better if we added…." 104 | 105 | _People find it easier to join an ongoing success._ 106 | 107 | **Tip 5: Be a Catalyst for Change** 108 | 109 | Most software disasters start out too small to notice, and most project overruns happen a day at a time. 110 | 111 | If you take a frog and drop it into boiling water, it will jump straight back out again. However, if you place the frog in a pan of cold water, then gradually heat it, the frog won't notice the slow increase in temperature and will stay put until cooked. 112 | 113 | Don't be like the frog. Keep an eye on the big picture. 114 | 115 | **Tip 6: Remember the Big Picture** 116 | 117 | ## 4.-Good enough soup 118 | The scope and quality of the system you produce should be specified as part of that system's requirements. 119 | 120 | **Tip 7: Make Quality a Requirements Issue** 121 | 122 | Great software today is often preferable to perfect software tomorrow. **Know When to Stop** 123 | 124 | ## 5.-Your Knowledge Portfolio 125 | _An investment in knowledge always pays the best interest._ 126 | 127 | * Serious investors invest regularly—as a habit. 128 | * Diversification is the key to long-term success. 129 | * Smart investors balance their portfolios between conservative and high-risk,high-reward investments. 130 | * Investors try to buy low and sell high for maximum return. 131 | * Portfolios should be reviewed and rebalanced periodically 132 | 133 | 134 | ### Building Your Portfolio 135 | * Invest regularly 136 | * Diversify 137 | * Manage risk 138 | * Buy low, sell High 139 | * Review and rebalance 140 | 141 | **Tip 8: Invest Regularly in Your Knowledge Portfolio** 142 | 143 | ### Goals 144 | * Learn at least one new language every year. 145 | * Read a technical book each quarter. 146 | * Read nontechnical books, too. 147 | * Take classes. 148 | * Participate in local user groups. 149 | * Experiment with different environments. 150 | * Stay current. 151 | * Get wired. 152 | 153 | You need to ensure that the knowledge in your portfolio is accurate and unswayed by either vendor or media hype. 154 | 155 | **Tip 9: Critically Analyze What You Read and Hear** 156 | 157 | 158 | ## 6.-Communicate 159 | * Know what you want to say. Plan what you want to say. Write an outline. 160 | * Know your audience. (WISDOM acrostic) 161 | * What they **Want**? 162 | * What is their **Interest**? 163 | * How **Sophisticated** are they? 164 | * How much **Detail** they want? 165 | * Who do you want to **Own** the information? 166 | * How can you **Motivate** them to listen? 167 | * Choose your moment: Understanding when your audience needs to hear your information. 168 | * Choose a style: Just the facts, large bound reports, a simple memo. 169 | * Make it look good: Add good-looking vehicle to your important ideas and engage your audience. 170 | * Involve your audience: Get their feedback, and pick their brains. 171 | * Be a listener: Encourage people to talk by asking questions. 172 | * Get back to people: Keep people informed afterwards. 173 | 174 | **Tip 10: It's Both What You Say and the Way You Say It** 175 | 176 | # Chapter 2. A Pragmatic Approach 177 | 178 | ## 7.-The Evils of Duplication 179 | The problem arises when you need to change a representation of things that are across all the code base. 180 | Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. 181 | 182 | **Tip 11: DRY—Don't Repeat Yourself** 183 | 184 | Types of duplication: 185 | 186 | * **Imposed duplication** Developers feel they have no choice—the environment seems to require duplication. 187 | * **Inadvertent duplication** Developers don't realize that they are duplicating information. 188 | * **Impatient duplication** Developers get lazy and duplicate because it seems easier. 189 | * **Interdeveloper duplication** Multiple people on a team (or on different teams) duplicate a piece of information. 190 | 191 | **Tip 12: Make it easy to reuse** 192 | 193 | ## 8.-Orthogonality 194 | 195 | Two or more things are orthogonal if changes in one do not affect any of the others. Also called *cohesion*. 196 | Write "shy" code. 197 | 198 | **Tip 13: Eliminate Effects Between Unrelated Things** 199 | 200 | Benefits: 201 | 202 | * Gain Productivity 203 | * Changes are localized 204 | * Promotes reuse 205 | * M x N orthogonal components do more than M x N non orthogonal components 206 | * Reduce Risk 207 | * Diseased sections or code are isolated 208 | * Are better tested 209 | * Not tied to a product or platform 210 | * Project Teams: Functionality is divided 211 | * Design: Easier to design a complete project through its components 212 | * Toolkits and Libraries: Choose wisely to keep orthogonality 213 | * Coding: In order to keep orthogonality when adding code do: 214 | * Keep your code decoupled 215 | * Avoid global data 216 | * Avoid similar functions 217 | * Testing: Orthogonal systems are easier to test. 218 | * Documentation: Also gain quality 219 | 220 | ## 9.-Reversibility 221 | Be prepared for changes. 222 | 223 | **Tip 14: There are no Final Decisions.** 224 | 225 | ## 10-Tracer Bullets 226 | In new projects, your user's requirements may be vague. Use of new algorithms, techniques, languages, or libraries unknowns will come. An environment will change over time before you are done. 227 | We're looking for something that gets us from a requirement to some aspect of the final system quickly, visibly, and repeatably. 228 | 229 | **Tip 15: Use Tracer Bullets to Find the Target** 230 | 231 | Advantages: 232 | 233 | * Users get to see something working early 234 | * Developers build a structure to work in 235 | * You have an integration platform 236 | * You have something to demonstrate 237 | * You have a better feel for progress 238 | 239 | ### Tracer Bullets Don't Always Hit Their Target 240 | Tracer bullets show what you're hitting. This may not always be the target. You then adjust your aim until they're on target. That's the point. 241 | 242 | 243 | ### Tracer Code versus Prototyping 244 | With a prototype, you're aiming to explore specific aspects of the final system. 245 | Tracer code is used to know how the application as a whole hangs together. 246 | 247 | Prototyping generates disposable code. 248 | Tracer code is lean but complete, and forms part of the skeleton of the final system. 249 | 250 | ## 11.-Prototypes and Post-it Notes 251 | We build software prototypes to analyze and expose risk, and to offer chances for correction at a greatly reduced cost. 252 | 253 | Prototype anything that: 254 | 255 | * carries risk 256 | * hasn't been tried before 257 | * is absolutely critical to the final system 258 | * is unproven 259 | * is experimental 260 | * is doubtful 261 | 262 | Samples: 263 | 264 | * Architecture 265 | * New functionality in an existing system 266 | * Structure or contents of external data 267 | * Third-party tools or components 268 | * Performance issues 269 | * User interface design 270 | 271 | 272 | **Tip 16: Prototype to Learn** 273 | 274 | 275 | Avoid details: 276 | 277 | * Correctness 278 | * Completeness 279 | * Robustness 280 | * Style 281 | 282 | Prototyping Architecture: 283 | 284 | * Are the responsibilities of the major components well defined and appropriate? 285 | * Are the collaborations between major components well defined? 286 | * Is coupling minimized? 287 | * Can you identify potential sources of duplication? 288 | * Are interface definitions and constraints acceptable? 289 | * Does every module have an access path to the data it needs during execution? 290 | 291 | **Never deploy the prototype** 292 | 293 | ## 12.-Domain Languages 294 | 295 | **Tip 17: Program Close to the Problem domain** 296 | 297 | ## 13.-Estimating 298 | **Tip 18: Estimate to Avoid Surprises** 299 | 300 | ### How Accurate Is Accurate Enough? 301 | **First:** Do they need high accuracy, or are they looking for a ballpark figure? 302 | 303 | **Second:** Scale time estimates properly 304 | 305 | | Duration | Quote estimate in | 306 | |------------ |-------------------------------------- | 307 | | 1-15 days | days | 308 | | 3-8 weeks | weeks | 309 | | 8-30 weeks | months | 310 | | 30+ weeks | think hard before giving an estimate | 311 | 312 | ### Where Do Estimates Come From? 313 | Ask someone who's been in a similar situation in the past. 314 | 315 | * Understand What's Being Asked 316 | * Build a Model of the System 317 | * Break the Model into Components 318 | * Give Each Parameter a Value 319 | * Calculate the Answers 320 | * Keep Track of Your Estimating Prowess 321 | 322 | ### Estimating Project Schedules 323 | The only way to determine the timetable for a project is by gaining experience on that same project. 324 | Practice incremental development, repeating the following steps: 325 | 326 | * Guess estimation 327 | * Check requirements 328 | * Analyze risk 329 | * Design, implement, integrate 330 | * Validate with the users 331 | * Repeat 332 | 333 | The refinement and confidence in the schedule gets better and better each iteration 334 | 335 | **Tip 19: Iterate the Schedule with the Code** 336 | 337 | ### What to Say When Asked for an Estimate 338 | **"I'll get back to you."** 339 | 340 | ### Challenges 341 | Start keeping a log of your estimates. For each, track how accurate you turned out to be. If your error was greater than 50%, try to find out where your estimate went wrong. 342 | 343 | 344 | # Chapter 3. The Basic Tools 345 | **Tip 20: Keep Knowledge in plain text** 346 | 347 | ## 14.-The Power of Plain Text 348 | 349 | ### Drawbacks of specific formats 350 | * more space 351 | * computationally more expensive 352 | 353 | ### The Power of Text 354 | * Insurance against obsolescence: you will always have a chance to be able to use text. 355 | * Leverage: Virtually every tool in computing can operate on plain text. 356 | * Easier testing 357 | 358 | ## 15.-Shell Games 359 | **Tip 21: Use the power of command Shells** 360 | 361 | Can't you do everything equally well by pointing and clicking in a GUI? 362 | **No**. A benefit of GUIs is _WYSIWYG_—what you see is what you get. The disadvantage is _WYSIAYG_—what you see is all you get. 363 | 364 | ## 16.-Power Editing 365 | **Tip 22: Use a Single Editor Well** 366 | 367 | ### Editor "must" features 368 | * Configurable 369 | * Extensible 370 | * Programmable 371 | * Syntax highlighting 372 | * Auto-completion 373 | * Auto-indentation 374 | * Initial code or document boilerplate 375 | * Tie-in to help systems 376 | * IDE-like features (compile, debug, and so on) 377 | 378 | ## 17.-Source Code Control 379 | **Tip 23: Always Use Source Code Control** 380 | 381 | ## 18.-Debugging 382 | **Tip 24: Fix the Problem, Not the Blame** 383 | 384 | **Tip 25: Don't Panic** 385 | 386 | ### A Debugging Mindset 387 | Don't waste a single neuron on the train of thought that begins "but that can't happen" because quite clearly it can, and has. 388 | Try to discover the root cause of a problem, not just this particular appearance of it. 389 | 390 | ### Where to Start 391 | * Before you start, address the compiler warnings. 392 | * You first need to be accurate in your observations and data. 393 | 394 | ### Debugging Strategies 395 | #### Bug Reproduction 396 | * The best way to start fixing a bug is to make it reproducible. 397 | * The second best way is to make it reproducible with a _single command_. 398 | 399 | #### Visualize Your Data 400 | Use the tools that the debugger offers you. Pen and paper can also help. 401 | #### Tracing 402 | Know what happens before and after. 403 | #### Rubber Ducking 404 | Explain the bug to someone else. 405 | #### Process of Elimination 406 | It is possible that a bug exists in the OS, the compiler, or a third-party product—but this should not be your first thought. 407 | 408 | **Tip 26: "select" Isn't Broken** 409 | 410 | ### The Element of Surprise 411 | **Tip 27: Don't Assume It—Prove It** 412 | 413 | ### Debugging Checklist 414 | * Is the problem being reported a direct result of the underlying bug, or merely asymptom? 415 | * Is the bug really in the compiler? Is it in the OS? Or is it in your code? 416 | * If you explained this problem in detail to a coworker, what would you say? 417 | * If the suspect code passes its unit tests, are the tests complete enough? What happens if you run the unit test with this data? 418 | * Do the conditions that caused this bug exist anywhere else in the system? 419 | 420 | ## 19.-Text Manipulation 421 | **Tip 28: Learn a Text Manipulation Language** 422 | 423 | ## 20.-Code Generators 424 | **Tip 29: Write Code That Writes Code** 425 | Two main types of code generators: 426 | 427 | * **Passive code generators** are run once to produce a result. They are basically parameterized templates, generating a given output from a set of inputs. 428 | * **Active code generators** are used each time their results are required. Take a single representation of some piece of knowledge and convert it into all the forms your application needs. 429 | 430 | ### Code Generators Needn't Be Complex 431 | Keep the input format simple, and the code generator becomes simple. 432 | 433 | ### Code Generators Needn't Generate Code 434 | You can use code generators to write just about any output: HTML, XML, plain text - any text that might be an input somewhere 435 | else in your project. 436 | 437 | # Chapter 4. A Pragmatic Paranoia 438 | **Tip 30: You can't write Perfect Software** 439 | 440 | No one in the brief history of computing has ever written a piece of perfect software. 441 | Pragmatic Programmers don't trust themselves, either. 442 | 443 | ## 21.-Design by Contract 444 | A correct program is one that does no more and no less than it claims to do. 445 | Use: 446 | 447 | * Preconditions 448 | * Postconditions 449 | * Invariants 450 | 451 | 452 | **Tip 31: Design with Contracts** 453 | 454 | Write "lazy" code: be strict in what you will accept before you begin, and promise as little as possible in return. 455 | 456 | ### Implementing DBC 457 | Simply enumerating at design time: 458 | 459 | * what the input domain range is 460 | * what the boundary conditions are 461 | * what the routine promises to deliver (and what it doesn't) 462 | 463 | ### Assertions 464 | You can use assertions to apply DBC in some range. (Assertions are not propagated in subclasses) 465 | 466 | **DBC enforce Crashing Early** 467 | ### Invariants 468 | * Loop Invariants: Is true before and during the loop therefore also when the loop finishes 469 | * Semantic Invariants: ie the error should be on the side of not processing a transaction rather than processing a duplicate transaction. 470 | 471 | ## 22.-Dead Programs Tell No Lies 472 | All errors give you information. Pragmatic Programmers tell themselves that if there is an error, something very, very bad has happened. 473 | 474 | **Tip 32: Crash Early** 475 | 476 | `A dead program normally does a lot less damage than a crippled one.` 477 | 478 | When your code discovers that something that was supposed to be impossible just happened, your 479 | program is no longer viable. 480 | 481 | ## 23.-Assertive Programming 482 | **Tip 33: If It Can't Happen, Use Assertions to Ensure That It Won't** 483 | 484 | * Assertions are also useful checks on an algorithm's operation. 485 | * Don't use assertions in place of real error handling. 486 | * Leave Assertions Turned On, unless you have critical performance issues. 487 | 488 | ## 24.-When to Use Exceptions 489 | **Tip 34: Use Exceptions for Exceptional Problems** 490 | ### What Is Exceptional? 491 | The program must run if all the exception handlers are removed 492 | If your code tries to open a file for reading and that file does not exist, should an exception be raised 493 | 494 | * Yes: If the file should have been there 495 | * No: If you have no idea whether the file should exist or not 496 | 497 | ## 25.-How to Balance Resources 498 | When managing resources: memory, transactions, threads, flies, timers—all kinds of things with limited availability, we have to close, finish, delete, deallocate them when we are done. 499 | 500 | **Tip 35: Finish What You Start** 501 | 502 | ### Nest Allocations 503 | 504 | * 1.-Deallocate resources in the opposite order to that in which you allocate them 505 | * 2.-When allocating the same set of resources in different places in your code, always allocate them in the same order (prevent deadlocks) 506 | 507 | ### Objects and Exceptions 508 | Use `finally` to free resources. 509 | 510 | # Chapter 5. Bend or Break 511 | ## 26.-Decoupling and the Law of Demeter 512 | ### Minimize Coupling 513 | Be careful about how many other modules you interact with and how you came to interact with them. 514 | 515 | Traversing relationships between objects directly can quickly lead to a combinatorial explosion. 516 | 517 | ```java 518 | 519 | book.pages().last().text(). 520 | 521 | // Instead, we're supposed to go with: 522 | 523 | book.textOfLastPage() 524 | ``` 525 | 526 | Symptoms: 527 | 528 | 1. Large projects where the command to link a unit test is longer than the test program itself 529 | 2. "Simple" changes to one module that propagate through unrelated modules in the system 530 | 3. Developers who are afraid to change code because they aren't sure what might be affected 531 | 532 | ### The Law of Demeter for Functions 533 | 534 | The Law of Demeter for functions states that any method of an object should call only methods belonging to: 535 | 536 | ```js 537 | 538 | class Demeter { 539 | private A a; 540 | void m(B b) { 541 | a.hello(); //itself 542 | b.hello(); //any parameters that were passed to the method 543 | new Z().hello(); // any object it created 544 | Singleton.INSTANCE.hello(); // any directly held component 545 | } 546 | } 547 | ``` 548 | 549 | **Tip 36: Minimize Coupling Between Modules** 550 | 551 | ### Does It Really Make a Difference? 552 | Using The Law of Demeter will make your code more adaptable and robust, but at a cost: 553 | you will be writing a large number of wrapper methods that simply forward the request on to a delegate. imposing both a runtime cost and a space overhead. 554 | Balance the pros and cons for your particular application. 555 | 556 | ## 27.-Metaprogramming 557 | "Out with the details!" Get them out of the code. While we're at it, we can make our code highly configurable and "soft"—that is, easily adaptable to changes. 558 | 559 | ### Dynamic Configuration 560 | **Tip 37: Configure, Don't Integrate** 561 | ### Metadata-Driven Applications 562 | We want to configure and drive the application via metadata as much as possible. 563 | _Program for the general case, and put the specifics somewhere else —outside the compiled code base_ 564 | 565 | **Tip 38: Put Abstractions in Code Details in Metadata** 566 | 567 | Benefits: 568 | 569 | * It forces you to decouple your design, which results in a more flexible and adaptable program. 570 | * It forces you to create a more robust, abstract design by deferring details—deferring them all the way out of the program. 571 | * You can customize the application without recompiling it. 572 | * Metadata can be expressed in a manner that's much closer to the problem domain than a general-purpose programming language might be. 573 | * You may even be able to implement several different projects using the same application engine, but with different metadata. 574 | 575 | ### When to Configure 576 | A flexible approach is to write programs that can reload their configuration while they're running. 577 | 578 | * long-running server process: provide some way to reread and apply metadata while the program is running. 579 | * small client GUI application: if restarts quickly no problem. 580 | 581 | ## 28.-Temporal Coupling 582 | Two aspects of time: 583 | 584 | * Concurrency: things happening at the same time 585 | * Ordering: the relative positions of things in time 586 | 587 | We need to allow for concurrency and to think about decoupling any time or order dependencies. 588 | Reduce any time-based dependencies 589 | 590 | ### Workflow 591 | 592 | Use [activity diagrams](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Activity_conducting.svg/2000px-Activity_conducting.svg.png) to maximize parallelism by identifying activities that could be performed in parallel, but aren't. 593 | 594 | **Tip 39: Analyze Workflow to Improve Concurrency** 595 | 596 | ### Architecture 597 | Balance load among multiple consumer processes: **the hungry consumer model.** 598 | 599 | In a hungry consumer model, you replace the central scheduler with a number of independent consumer tasks and a centralized work queue. Each consumer task grabs a piece from the work queue and goes on about the business of processing it. As each task finishes its work, it goes back to the queue for some more. This way, if any particular task gets bogged down, the others can pick up the slack, and each individual component can proceed at its own pace. Each component is temporally decoupled from the others. 600 | 601 | **Tip 40: Design Using Services** 602 | 603 | ### Design for Concurrency 604 | Programming with threads imposes some design constraints—and that's a good thing. 605 | 606 | * Global or static variables must be protected from concurrent access 607 | * Check if you need a global variable in the first place. 608 | * Consistent state information, regardless of the order of calls 609 | * Objects must always be in a valid state when called, and they can be called at the most awkward times. Use class invariants, discussed in Design by Contract. 610 | 611 | ### Cleaner Interfaces 612 | Thinking about concurrency and time-ordered dependencies can lead you to design cleaner interfaces as well. 613 | 614 | **Tip 41: Always Design for Concurrency** 615 | 616 | ### Deployment 617 | You can be flexible as to how the application is deployed: standalone, client-server, or n-tier. 618 | 619 | 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. 620 | 621 | ## 29.-It's Just a View 622 | ### Publish/Subscribe 623 | Objects should be able to register to receive only the events they need, and should never be sent events they don't need. 624 | 625 | Use this publish/subscribe mechanism to implement a very important design concept: the separation of a model from views of the model. 626 | 627 | ### Model-View-Controller 628 | Separates the model from both the GUI that represents it and the controls that manage the view. 629 | 630 | Advantage: 631 | 632 | * Support multiple views of the same data model. 633 | * Use common viewers on many different data models. 634 | * Support multiple controllers to provide nontraditional input mechanisms. 635 | 636 | **Tip 42: Separate Views from Models** 637 | ### Beyond GUIs 638 | The controller is more of a coordination mechanism, and doesn't have to be related to any sort of input device. 639 | 640 | * **Model** The abstract data model representing the target object. The model has no direct knowledge of any views or controllers. 641 | * **View** A way to interpret the model. It subscribes to changes in the model and logical events from the controller. 642 | * **Controller** A way to control the view and provide the model with new data. It publishes events to both the model and the view. 643 | 644 | 645 | ## 30.-Blackboards 646 | A blackboard system lets us decouple our objects from each other completely, providing a forum where knowledge consumers and producers can exchange data anonymously and asynchronously. 647 | ### Blackboard Implementations 648 | With Blackboard systems, you can store active objects—not just data—on the blackboard, and retrieve them by partial matching of fields (via templates and wildcards) or by subtypes. 649 | 650 | Functions that a Blackboard system should have: 651 | 652 | * **read** Search for and retrieve data from the space. 653 | * **write** Put an item into the space. 654 | * **take** Similar to read, but removes the item from the space as well. 655 | * **notify** Set up a notification to occur whenever an object is written that matches the template. 656 | 657 | Organizing Your Blackboard by partitioning it when working on large cases. 658 | 659 | **Tip 43: Use Blackboards to Coordinate Workflow** 660 | 661 | # Chapter 6. While you are coding 662 | ## 31.-Program by Coincidence 663 | We should avoid programming by coincidence—relying on luck and accidental successes— in favor of programming deliberately. 664 | **Tip 44: Don't Program by Coincidence** 665 | 666 | ### How to Program Deliberately 667 | * Always be aware of what you are doing. 668 | * Don't code blindfolded. 669 | * Proceed from a plan. 670 | * Rely only on reliable things. 671 | * Document your assumptions. [Design by Contract](#21-design-by-contract). 672 | * Don't just test your code, but test your assumptions as well. Don't guess [Assertive Programming](#23-assertive-programming) 673 | * Prioritize your effort. 674 | * Don't be a slave to history. Don't let existing code dictate future code. [Refactoring](#33-refactoring) 675 | 676 | ## 32.-Algorithm Speed 677 | Pragmatic Programmers estimate the resources that algorithms use—time, processor, memory, and so on. 678 | 679 | ### Use: Big O Notation 680 | * **O(1)**: Constant (access element in array, simple statements) 681 | 682 | ```js 683 | bool IsFirstElementNull(IList elements) 684 | { 685 | return elements[0] == null; 686 | } 687 | ``` 688 | 689 | * **O(lg(n))**: Logarithmic (binary search) lg(n) = lg2(n) 690 | 691 | ```js 692 | 693 | Int BinarySearch(list, target) 694 | { 695 | lo = 1, hi = size(list) 696 | while (lo <= hi){ 697 | mid = lo + (hi-lo)/2 698 | if (list[mid] == target) return mid 699 | else if (list[mid] < target) lo = mid+1 700 | else hi = mid-1 701 | } 702 | } 703 | 704 | ``` 705 | 706 | * **O(n)**: Linear: Sequential search 707 | 708 | ```js 709 | 710 | bool ContainsValue(IList elements, string value) 711 | { 712 | foreach (var element in elements) 713 | { 714 | if (element == value) return true; 715 | } 716 | 717 | return false; 718 | } 719 | 720 | ``` 721 | * **O(n lg(n))**: Worse than linear but not much worse(average runtime of quickshort, headsort) 722 | * **O(n²)**: Square law (selection and insertion sorts) 723 | 724 | ```js 725 | 726 | bool ContainsDuplicates(IList elements) 727 | { 728 | for (var outer = 0; outer < elements.Count; outer++) 729 | { 730 | for (var inner = 0; inner < elements.Count; inner++) 731 | { 732 | // Don't compare with self 733 | if (outer == inner) continue; 734 | 735 | if (elements[outer] == elements[inner]) return true; 736 | } 737 | } 738 | 739 | return false; 740 | } 741 | 742 | ``` 743 | * **O(n³)**: Cubic (multiplication of 2 n x n matrices) 744 | * **O(Cⁿ)**: Exponential (travelling salesman problem, set partitioning) 745 | 746 | ```js 747 | 748 | int Fibonacci(int number) 749 | { 750 | if (number <= 1) return number; 751 | 752 | return Fibonacci(number - 2) + Fibonacci(number - 1); 753 | } 754 | ``` 755 | 756 | ### Common Sense Estimation 757 | * Simple loops: O(n) 758 | * Nested loops: O(n²) 759 | * Binary chop: O(lg(n)) 760 | * Divide and conquer: O(n lg(n)). Algorithms that partition their input, work on the two halves independently, and then combine the result. 761 | * Combinatoric: O(Cⁿ) 762 | 763 | 764 | **Tip 45: Estimate the Order of Your Algorithms** 765 | 766 | **Tip 46: Test Your Estimates** 767 | 768 | ### Best Isn't Always Best 769 | Be pragmatic about choosing appropriate algorithms—the fastest one is not always the best for the job. 770 | 771 | Be wary of premature optimization. Make sure an algorithm really is a bottleneck before investing time improving it. 772 | 773 | ## 33.-Refactoring 774 | Code needs to evolve; it's not a static thing. 775 | 776 | ### When Should You Refactor? 777 | * Duplication. You've discovered a violation of the DRY principle ([The Evils of Duplication](#7-the-evils-of-duplication)). 778 | * Nonorthogonal design. You've discovered some code or design that could be made more orthogonal ([Orthogonality](#8-orthogonality)). 779 | * Outdated knowledge. Things change, requirements drift, and your knowledge of the problem increases. Code needs to keep up. 780 | * Performance. You need to move functionality from one area of the system to another to improve performance. 781 | 782 | **Tip 47: Refactor Early, Refactor Often** 783 | 784 | ### How Do You Refactor? 785 | * 1. Don't try to refactor and add functionality at the same time. 786 | * 2. Make sure you have good tests before you begin refactoring. 787 | * 3. Take short, deliberate steps. 788 | 789 | ## 34.-Code That's Easy to Test 790 | Build testability into the software from the very beginning, and test each piece thoroughly before trying to wire them together. 791 | 792 | ### Unit Testing 793 | Testing done on each module, in isolation, to verify its behavior. 794 | A software unit test is code that exercises a module. 795 | 796 | ### Testing Against Contract 797 | This will tell us two things: 798 | 799 | 1. Whether the code meet the contract 800 | 2. Whether the contract means what we think it means. 801 | 802 | **Tip 48: Design to Test** 803 | 804 | There's no better way to fix errors than by avoiding them in the first place. 805 | Build the tests before you implement the code. 806 | 807 | ### Writing Unit Tests 808 | By making the test code readily accessible, you are providing developers who may use your code with two invaluable resources: 809 | 810 | 1. Examples of how to use all the functionality of your module 811 | 2. A means to build regression tests to validate any future changes to the code 812 | 813 | You must run them, and run them often. 814 | 815 | ### Using Test Harnesses 816 | Test harnesses should include the following capabilities: 817 | 818 | * A standard way to specify setup and cleanup 819 | * A method for selecting individual tests or all available tests 820 | * A means of analyzing output for expected (or unexpected) results 821 | * A standardized form of failure reporting 822 | 823 | ### Build a Test Window 824 | 825 | * Log files. 826 | * Hot-key sequence. 827 | * Built-in Web server. 828 | 829 | ### A Culture of Testing 830 | 831 | **Tip 49: Test Your Software, or Your Users Will** 832 | 833 | ## 35.-Evil Wizards 834 | If you do use a wizard, and you don't understand all the code that it produces, you won't be in control of your own application. 835 | 836 | **Tip 50: Don't Use Wizard Code You Don't Understand** 837 | 838 | # Chapter 7. Before the project 839 | 840 | ## 36.-The Requirements Pit 841 | _Perfection is achieved, not when there is nothing left to add, but when there is nothing left to take away…._ 842 | 843 | **Tip 51: Don't Gather Requirements—Dig for Them** 844 | 845 | ### Digging for Requirements 846 | Policy may end up as metadata in the application. 847 | 848 | Gathering requirements in this way naturally leads you to a system that is well factored to support metadata. 849 | 850 | **Tip 52: Work with a User to Think Like a User** 851 | 852 | ### Documenting Requirements 853 | Use "use cases" 854 | 855 | ### Overspecifying 856 | Requirements are not architecture. Requirements are not design, nor are they the user interface. Requirements are need. 857 | 858 | ### Seeing Further 859 | **Tip 53: Abstractions Live Longer than Details** 860 | 861 | ### Just One More Wafer-Thin Mint… 862 | What can we do to prevent requirements from creeping up on us? 863 | 864 | The key to managing growth of requirements is to point out each new feature's impact on the schedule to the project sponsors. 865 | 866 | ### Maintain a Glossary 867 | It's very hard to succeed on a project where the users and developers refer to the same thing by different names or, even worse, refer to different things by the same name. 868 | 869 | **Tip 54: Use a Project Glossary** 870 | 871 | ### Get the Word Out 872 | Publishing project documents to internal Web sites for easy access by all participants. 873 | 874 | ## 37.-Solving Impossible Puzzles 875 | ### Degrees of Freedom 876 | The key to solving puzzles is both to recognize the constraints placed on you and to recognize the degrees of freedom you do have, for in those you'll find your solution. 877 | 878 | **Tip 55: Don't Think Outside the Box—Find the Box** 879 | 880 | ### There Must Be an Easier Way! 881 | If you can not find the solution, step back and ask yourself these questions: 882 | 883 | * Is there an easier way? 884 | * Are you trying to solve the right problem, or have you been distracted by a peripheral technicality? 885 | * Why is this thing a problem? 886 | * What is it that's making it so hard to solve? 887 | * Does it have to be done this way? 888 | * Does it have to be done at all? 889 | 890 | ## 38.-Not Until You're Ready 891 | If you sit down to start typing and there's some nagging doubt in your mind, heed it. 892 | 893 | **Tip 56: Listen to Nagging Doubts—Start When You're Ready** 894 | 895 | ### Good Judgment or Procrastination? 896 | Start prototyping. Choose an area that you feel will be difficult and begin producing some kind of proof of concept, and be sure to remember 897 | why you're doing it and that it is a prototype. 898 | 899 | ## 39.-The Specification Trap 900 | Writing a specification is quite a responsibility. 901 | 902 | You should know when to stop: 903 | 904 | * Specification will never capture every detail of a system or its requirement. 905 | * The expressive power of language itself might not be enough to describe a specification 906 | * A design that leaves the coder no room for interpretation robs the programming effort of any skill and art. 907 | 908 | **Tip 57: Some Things Are Better Done than Described** 909 | 910 | ## 40.-Circles and Arrows 911 | 912 | **Tip 58: Don't Be a Slave to Formal Methods** 913 | 914 | Formal methods have some serious shortcomings: 915 | 916 | * Diagrams are meaningless to the end users, show the user a prototype and let them play with it. 917 | * Formal methods seem to encourage specialization. It may not be possible to have an in-depth grasp of every aspect of a system. 918 | * We like to write adaptable, dynamic systems, using metadata to allow us to change the character of applications at runtime, but most current formal methods don't allow it. 919 | 920 | ### Do Methods Pay Off? 921 | Never underestimate the cost of adopting new tools and methods. 922 | 923 | ### Should We Use Formal Methods? 924 | Absolutely but remember that is just one more tool in the toolbox. 925 | 926 | **Tip 59: Expensive Tools Do Not Produce Better Designs** 927 | 928 | # Chapter 8. Pragmatic Projects 929 | 930 | ## 41.-Pragmatic Teams 931 | Pragmatic techniques that help an individual can work for teams. 932 | 933 | ### No Broken Windows 934 | Quality is a team issue. 935 | 936 | Teams as a whole should not tolerate broken windows—those small imperfections that no one fixes. 937 | 938 | Quality can come only from the individual contributions of all team members. 939 | 940 | ### Boiled Frogs 941 | People assume that someone else is handling an issue, or that the team leader must have OK'd a change that your user is requesting. Fight this. 942 | 943 | ### Communicate 944 | The team as an entity needs to communicate clearly with the rest of the world. 945 | 946 | People look forward to meetings with them, because they know that they'll see a well-prepared performance that makes everyone feel good. 947 | 948 | There is a simple marketing trick that helps teams communicate as one: generate a brand. 949 | 950 | ### Don't Repeat Yourself 951 | Appoint a member as the project librarian. 952 | 953 | ### Orthogonality 954 | It is a mistake to think that the activities of a project—analysis, design, coding, and testing—can happen in isolation. They can't. These are different views of the same problem, and artificially separating them can cause a boatload of trouble. 955 | 956 | **Tip 60: Organize Around Functionality, Not Job Functions** 957 | 958 | * Split teams by functionally. Database, UI, API 959 | * Let the teams organize themselves internally 960 | * Each team has responsibilities to others in the project (defined by their agreed-upon commitments) 961 | * We're looking for cohesive, largely self-contained teams of people 962 | 963 | Organize our resources using the same techniques we use to organize code, using techniques such as contracts (Design by Contract), decoupling (Decoupling and the Law of Demeter), and orthogonality (Orthogonality), and we help isolate the team as a whole from the effects of change. 964 | 965 | ### Automation 966 | Automation is an essential component of every project team 967 | 968 | ### Know When to Stop Adding Paint 969 | 970 | ## 42.-Ubiquitous Automation 971 | ### All on Automatic 972 | **Tip 61: Don't Use Manual Procedures** 973 | 974 | Using _cron_, we can schedule backups, nightly build, Web site... unattended, automatically. 975 | 976 | ### Compiling the Project 977 | We want to check out, build, test, and ship with a single command 978 | 979 | * Generating Code 980 | * Regression Tests 981 | 982 | ### Build Automation 983 | A build is a procedure that takes an empty directory (and a known compilation environment) and builds the project from scratch, producing whatever you hope to produce as a final deliverable. 984 | 985 | * 1. Check out the source code from the repository 986 | * 2. Build the project from scratch (marked with the version number). 987 | * 3. Create a distributable image 988 | * 4. Run specified tests 989 | 990 | When you don't run tests regularly, you may discover that the application broke due to a code change made three months ago. Good luck finding that one. 991 | 992 | **Nightly build** run it every night. 993 | 994 | **Final builds** (to ship as products), may have different requirements from the regular nightly build. 995 | 996 | ### Automatic Administrivia 997 | Our goal is to maintain an automatic, unattended, content-driven workflow. 998 | 999 | * Web Site Generation results of the build itself, regression tests, performance statistics, coding metrics... 1000 | * Approval Procedures get marks `/* Status: needs_review */`, send email... 1001 | 1002 | ### The Cobbler's Children 1003 | Let the computer do the repetitious, the mundane—it will do a better job of it than we would. We've got more important and more difficult things to do. 1004 | ## 43.-Ruthless testing 1005 | Pragmatic Programmers are driven to find our bugs now, so we don't have to endure the shame of others finding our bugs later. 1006 | 1007 | **Tip 62: Test Early. Test Often. Test Automatically.** 1008 | 1009 | Tests that run with every build are the most effective. 1010 | 1011 | The earlier a bug is found, the cheaper it is to remedy. "Code a little, test a little". 1012 | 1013 | **Tip 63: Coding Ain't Done til All the Tests Run** 1014 | 1015 | ### 3 Main aspects: 1016 | 1017 | #### 1.-What to Test 1018 | 1019 | * Unit testing: code that exercises a module. 1020 | * Integration testing: the major subsystems that make up the project work and play well with each other. 1021 | * Validation and verification: test if you are delivering what users needs. 1022 | * Resource exhaustion, errors, and recovery: discover how it will behave under real-world conditions. (Memory, Disk, CPU, Screen...) 1023 | * Performance testing: meets the performance requirements under real-world conditions. 1024 | * Usability testing: performed with real users, under real environmental conditions. 1025 | 1026 | #### 2.-How to Test 1027 | 1028 | * Regression testing: compares the output of the current test with previous (or known) values. Most of the tests are regression tests. 1029 | * Test data: there are only two kinds of data: real-world data and synthetic data. 1030 | * Exercising GUI systems: requires specialized testing tools, based on a simple event capture/playback model. 1031 | * Testing the tests: After you have written a test to detect a particular bug, cause the bug deliberately and make sure the test complains. 1032 | 1033 | **Tip 64: Use Saboteurs to Test Your Testing** 1034 | * Testing thoroughly: 1035 | 1036 | **Tip 65: Test State Coverage, Not Code Coverage** 1037 | 1038 | #### 3.-When to Test 1039 | As soon as any production code exists, it needs to be tested. 1040 | Most testing should be done automatically. 1041 | 1042 | ### Tightening the Net 1043 | If a bug slips through the net of existing tests, you need to add a new test to trap it next time. 1044 | 1045 | **Tip 66: Find Bugs Once** 1046 | 1047 | ## 44.-It's All Writing 1048 | If there's a discrepancy, the code is what matters—for better or worse. 1049 | 1050 | **Tip 67: Treat English as Just Another Programming Language** 1051 | 1052 | **Tip 68: Build Documentation In, Don't Bolt It On** 1053 | 1054 | ### Comments in Code 1055 | In general, comments should discuss why something is done, its purpose and its goal. 1056 | 1057 | Remember that you (and others after you) will be reading the code many hundreds of times, but only writing it a few times. 1058 | 1059 | Even worse than meaningless names are misleading names. 1060 | 1061 | One of the most important pieces of information that should appear in the source file is the author's name—not necessarily who edited the file last, but the owner. 1062 | 1063 | ### Executable Documents 1064 | Create documents that create schemas. The only way to change the schema is to change the document. 1065 | 1066 | ### Technical Writers 1067 | We want the writers to embrace the same basic principles that a Pragmatic Programmer does—especially honoring the DRY principle, orthogonality, the model-view concept, and the use of automation and scripting. 1068 | 1069 | ### Print It or Weave It 1070 | Paper documentation can become out of date as soon as it's printed. 1071 | 1072 | Publish it online, on the Web. 1073 | 1074 | Remember to put a date stamp or version number on each Web page. 1075 | 1076 | Using a markup system, you have the flexibility to implement as many different output formats as you need. 1077 | 1078 | ### Markup Languages 1079 | Documentation and code are different views of the same underlying model, but the view is all that should be different. 1080 | 1081 | ## 45.-Great Expectations 1082 | The success of a project is measured by how well it meets the expectations of its users. 1083 | 1084 | **Tip 69: Gently Exceed Your Users' Expectations** 1085 | 1086 | ### Communicating Expectations 1087 | Users initially come to you with some vision of what they want. You cannot just ignore it. 1088 | 1089 | Everyone should understand what's expected and how it will be built. 1090 | 1091 | ### The Extra Mile 1092 | Give users that little bit more than they were expecting. 1093 | 1094 | * Balloon or ToolTip help 1095 | * Keyboard shortcuts 1096 | * A quick reference guide as a supplement to the user's manual 1097 | * Colorization 1098 | * Log file analyzers 1099 | * Automated installation 1100 | * Tools for checking the integrity of the system 1101 | * The ability to run multiple versions of the system for training 1102 | * A splash screen customized for their organization 1103 | 1104 | ### Pride and Prejudice 1105 | Pragmatic Programmers don't shirk from responsibility. Instead, we rejoice in accepting challenges and in making our expertise well known. 1106 | 1107 | We want to see pride of ownership. "I wrote this, and I stand behind my work." 1108 | 1109 | **Tip 70: Sign Your Work** 1110 | 1111 | 1112 | # Quick Reference 1113 | ## Tips 1114 | **Tip 1: Care About Your Craft** 1115 | Why spend your life developing software unless you care about doing it well? 1116 | 1117 | **Tip 2: Think! About Your Work** 1118 | Turn off the autopilot and take control. Constantly critique and appraise your work. 1119 | 1120 | **Tip 3: Provide Options, Don't Make Lame Excuses** 1121 | Instead of excuses, provide options. Don't say it can't be done; explain what can be done. 1122 | 1123 | **Tip 4: Don't Live with Broken Windows** 1124 | Fix bad designs, wrong decisions, and poor code when you see them. 1125 | 1126 | **Tip 5: Be a Catalyst for Change** 1127 | You can't force change on people. Instead, show them how the future might be and help them participate in creating it. 1128 | 1129 | **Tip 6: Remember the Big Picture** 1130 | Don't get so engrossed in the details that you forget to check what's happening around you. 1131 | 1132 | **Tip 7: Make Quality a Requirements Issue** 1133 | Involve your users in determining the project's real quality requirements. 1134 | 1135 | **Tip 8: Invest Regularly in Your Knowledge Portfolio** 1136 | Make learning a habit. 1137 | 1138 | **Tip 9: Critically Analyze What You Read and Hear** 1139 | Don't be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project. 1140 | 1141 | **Tip 10: It's Both What You Say and the Way You Say It** 1142 | There's no point in having great ideas if you don't communicate them effectively. 1143 | 1144 | **Tip 11: DRY – Don't Repeat Yourself** 1145 | Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. 1146 | 1147 | **Tip 12: Make It Easy to Reuse** 1148 | If it's easy to reuse, people will. Create an environment that supports reuse. 1149 | 1150 | **Tip 13: Eliminate Effects Between Unrelated Things** 1151 | Design components that are self-contained, independent, and have a single, well-defined purpose. 1152 | 1153 | **Tip 14: There Are No Final Decisions** 1154 | No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change. 1155 | 1156 | **Tip 15: Use Tracer Bullets to Find the Target** 1157 | Tracer bullets let you home in on your target by trying things and seeing how close they land. 1158 | 1159 | **Tip 16: Prototype to Learn** 1160 | Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn. 1161 | 1162 | **Tip 17: Program Close to the Problem Domain** 1163 | Design and code in your user's language. 1164 | 1165 | **Tip 18: Estimate to Avoid Surprises** 1166 | Estimate before you start. You'll spot potential problems up front. 1167 | 1168 | **Tip 19: Iterate the Schedule with the Code** 1169 | Use experience you gain as you implement to refine the project time scales. 1170 | 1171 | **Tip 20: Keep Knowledge in Plain Text** 1172 | Plain text won't become obsolete. It helps leverage your work and simplifies debugging and testing. 1173 | 1174 | **Tip 21: Use the Power of Command Shells** 1175 | Use the shell when graphical user interfaces don't cut it. 1176 | 1177 | **Tip 22: Use a Single Editor Well** 1178 | The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable. 1179 | 1180 | **Tip 23: Always Use Source Code Control** 1181 | Source code control is a time machine for your work – you can go back. 1182 | 1183 | **Tip 24: Fix the Problem, Not the Blame** 1184 | 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. 1185 | 1186 | **Tip 25: Don't Panic When Debugging** 1187 | Take a deep breath and THINK! about what could be causing the bug. 1188 | 1189 | **Tip 26: "select" Isn't Broken.** 1190 | 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. 1191 | 1192 | **Tip 27: Don't Assume It – Prove It** 1193 | Prove your assumptions in the actual environment – with real data and boundary conditions. 1194 | 1195 | **Tip 28: Learn a Text Manipulation Language.** 1196 | You spend a large part of each day working with text. Why not have the computer do some of it for you? 1197 | 1198 | **Tip 29: Write Code That Writes Code** 1199 | Code generators increase your productivity and help avoid duplication. 1200 | 1201 | **Tip 30: You Can't Write Perfect Software** 1202 | Software can't be perfect. Protect your code and users from the inevitable errors. 1203 | 1204 | **Tip 31: Design with Contracts** 1205 | Use contracts to document and verify that code does no more and no less than it claims to do. 1206 | 1207 | **Tip 32: Crash Early** 1208 | A dead program normally does a lot less damage than a crippled one. 1209 | 1210 | **Tip 33: Use Assertions to Prevent the Impossible** 1211 | Assertions validate your assumptions. Use them to protect your code from an uncertain world. 1212 | 1213 | **Tip 34: Use Exceptions for Exceptional Problems** 1214 | Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things. 1215 | 1216 | **Tip 35: Finish What You Start** 1217 | Where possible, the routine or object that allocates a resource should be responsible for deallocating it. 1218 | 1219 | **Tip 36: Minimize Coupling Between Modules** 1220 | Avoid coupling by writing "shy" code and applying the Law of Demeter. 1221 | 1222 | **Tip 37: Configure, Don't Integrate** 1223 | Implement technology choices for an application as configuration options, not through integration or engineering. 1224 | 1225 | **Tip 38: Put Abstractions in Code, Details in Metadata** 1226 | Program for the general case, and put the specifics outside the compiled code base. 1227 | 1228 | **Tip 39: Analyze Workflow to Improve Concurrency** 1229 | Exploit concurrency in your user's workflow. 1230 | 1231 | **Tip 40: Design Using Services** 1232 | Design in terms of services – independent, concurrent objects behind well-defined, consistent interfaces. 1233 | 1234 | **Tip 41: Always Design for Concurrency** 1235 | Allow for concurrency, and you'll design cleaner interfaces with fewer assumptions. 1236 | 1237 | **Tip 42: Separate Views from Models** 1238 | Gain flexibility at low cost by designing your application in terms of models and views. 1239 | 1240 | **Tip 43: Use Blackboards to Coordinate Workflow** 1241 | Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants. 1242 | 1243 | **Tip 44: Don't Program by Coincidence** 1244 | Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan. 1245 | 1246 | **Tip 45: Estimate the Order of Your Algorithms** 1247 | Get a feel for how long things are likely to take before you write code. 1248 | 1249 | **Tip 46: Test Your Estimates** 1250 | Mathematical analysis of algorithms doesn't tell you everything. Try timing your code in its target environment. 1251 | 1252 | **Tip 47: Refactor Early, Refactor Often** 1253 | 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. 1254 | 1255 | **Tip 48: Design to Test** 1256 | Start thinking about testing before you write a line of code. 1257 | 1258 | **Tip 49: Test Your Software, or Your Users Will** 1259 | Test ruthlessly. Don't make your users find bugs for you. 1260 | 1261 | **Tip 50: Don't Use Wizard Code You Don't Understand** 1262 | Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project. 1263 | 1264 | **Tip 51: Don't Gather Requirements – Dig for Them** 1265 | Requirements rarely lie on the surface. They're buried deep beneath layers of assumptions, misconceptions, and politics. 1266 | 1267 | **Tip 52: Work With a User to Think Like a User** 1268 | It's the best way to gain insight into how the system will really be used. 1269 | 1270 | **Tip 53: Abstractions Live Longer than Details** 1271 | Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies. 1272 | 1273 | **Tip 54: Use a Project Glossary** 1274 | Create and maintain a single source of all the specific terms and vocabulary for a project. 1275 | 1276 | **Tip 55: Don't Think Outside the Box – Find the Box** 1277 | 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?" 1278 | 1279 | **Tip 56: Start When You're Ready.** 1280 | You've been building experience all your life. Don't ignore niggling doubts. 1281 | 1282 | **Tip 57: Some Things Are Better Done than Described** 1283 | Don't fall into the specification spiral – at some point you need to start coding. 1284 | 1285 | **Tip 58: Don't Be a Slave to Formal Methods.** 1286 | Don't blindly adopt any technique without putting it into the context of your development practices and capabilities. 1287 | 1288 | **Tip 59: Costly Tools Don't Produce Better Designs** 1289 | Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits. 1290 | 1291 | **Tip 60: Organize Teams Around Functionality** 1292 | Don't separate designers from coders, testers from data modelers. Build teams the way you build code. 1293 | 1294 | **Tip 61: Don't Use Manual Procedures** 1295 | A shell script or batch file will execute the same instructions, in the same order, time after time. 1296 | 1297 | **Tip 62: Test Early. Test Often. Test Automatically** 1298 | Tests that run with every build are much more effective than test plans that sit on a shelf. 1299 | 1300 | **Tip 63: Coding Ain't Done 'Til All the Tests Run** 1301 | 'Nuff said. 1302 | 1303 | **Tip 64: Use Saboteurs to Test Your Testing** 1304 | Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them. 1305 | 1306 | **Tip 65: Test State Coverage, Not Code Coverage** 1307 | Identify and test significant program states. Just testing lines of code isn't enough. 1308 | 1309 | **Tip 66: Find Bugs Once** 1310 | 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. 1311 | 1312 | **Tip 67: English is Just a Programming Language** 1313 | Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on. 1314 | 1315 | **Tip 68: Build Documentation In, Don't Bolt It On** 1316 | Documentation created separately from code is less likely to be correct and up to date. 1317 | 1318 | **Tip 69: Gently Exceed Your Users' Expectations** 1319 | Come to understand your users' expectations, then deliver just that little bit more. 1320 | 1321 | **Tip 70: Sign Your Work** 1322 | Craftsmen of an earlier age were proud to sign their work. You should be, too. 1323 | 1324 | ## CheckList 1325 | 1326 | ### Languages To Learn 1327 | Tired of C, C++, and Java? Try the following languages. Each of these languages has different capabilities and a different "flavor." Try a small project at home using one or more of them. 1328 | - CLOS 1329 | - Dylan 1330 | - Eiffel 1331 | - Objective C 1332 | - Prolog 1333 | - Smalltalk 1334 | - TOM 1335 | 1336 | ### The WISDOM Acrostic 1337 | - **W**hat do you want them to learn? 1338 | - What **i**s their interest in what you've got to say? 1339 | - How **s**ophisticated are they? 1340 | - How much **d**etail do they want? 1341 | - Whom do you want to **o**wn the information? 1342 | - How can you **m**otivate them to listen to you? 1343 | 1344 | ### How to Maintain Orthogonality 1345 | - Design independent, well-defined components. 1346 | - Keep your code decoupled. 1347 | - Avoid global data. 1348 | - Refactor similar functions. 1349 | 1350 | ### Things to prototype 1351 | - Architecture 1352 | - New functionality in an existing system 1353 | - Structure or contents of external data 1354 | - Third-party tools or components 1355 | - Performance issues 1356 | - User interface design 1357 | 1358 | ### Architectural Questions 1359 | - Are responsibilities well defined? 1360 | - Are the collaborations well defined? 1361 | - Is coupling minimized? 1362 | - Can you identify potential duplication? 1363 | - Are interface definitions and constraints acceptable? 1364 | - Can modules access needed data – when needed? 1365 | 1366 | ### Debugging Checklist 1367 | - Is the problem being reported a direct result of the underlying bug, or merely a symptom? 1368 | - Is the bug really in the compiler? Is it in the OS? Or is it in your code? 1369 | - If you explained this problem in detail to a coworker, what would you say? 1370 | - If the suspect code passes its unit tests, are the tests complete enough? What happens if you run the unit test with this data? 1371 | - Do the conditions that caused this bug exist anywhere else in the system? 1372 | 1373 | ### Law of Demeter for Functions 1374 | An object's method should call only methods belonging to: 1375 | 1376 | - Itself 1377 | - Any parameters passed in 1378 | - Objects it creates 1379 | - Component objects 1380 | 1381 | ### How to Program Deliberately 1382 | - Stay aware of what you're doing. 1383 | - Don't code blindfolded. 1384 | - Proceed from a plan. 1385 | - Rely only on reliable things. 1386 | - Document your assumptions. 1387 | - Test assumptions as well as code. 1388 | - Prioritize your effort. 1389 | - Don't be a slave to history. 1390 | 1391 | ### When to Refactor 1392 | - You discover a violation of the DRY principle. 1393 | - You find things that could be more orthogonal. 1394 | - Your knowledge improves. 1395 | - The requirements evolve. 1396 | - You need to improve performance. 1397 | 1398 | ### Cutting the Gordian Knot 1399 | When solving _impossible_ problems, ask yourself: 1400 | 1401 | - Is there an easier way? 1402 | - Am I solving the right problem? 1403 | - Why is this a problem? 1404 | - What makes it hard? 1405 | - Do I have to do it this way? 1406 | - Does it have to be done at all? 1407 | 1408 | ### Aspects of Testing 1409 | - Unit testing 1410 | - Integration testing 1411 | - Validation and verification 1412 | - Resource exhaustion, errors, and recovery 1413 | - Performance testing 1414 | - Usability testing 1415 | - Testing the tests themselves 1416 | 1417 | Content from The Pragmatic Programmer, by Andrew Hunt and David Thomas. Visit [www.pragmaticprogrammer.com](http://www.pragmaticprogrammer.com). 1418 | Copyright 2000 by Addison Wesley Longman, Inc. 1419 | --------------------------------------------------------------------------------