- There is no such thing as a best solution, be it a tool, a language, or an operating system. There can only be systems that are more appropriate in a particular set of circumstances.
- You shouldn’t be wedded to any particular technology, but have a broad enough background and experience base to allow you to choose good solutions in particular situations.
- Care about your craft.
- We feel that there is no point in developing software unless you care about doing it well.
- Think about your work.
- In order to be a Pragmatic Programmer, we’re challenging you to think about what you’re doing while you’re doing it.
- Never run on autopilot. Constantly be thinking, critiquing your work in real time.
- Over the long term, your time investment will be repaid as you and your team become more efficient, write code that’s easier to maintain, and spend less time in meetings.
- Within the overall structure of a project there is always room for individuality and craftsmanship.
- Great lawns need small amounts of daily care, and so do great programmers.
- “Kaizen” is a Japanese term that captures the concept of continuously making many small improvements.
- Every day, work to refine the skills you have and to add new tools to your repertoire.
- Learning is a continuous and ongoing process.
- We can be proud of our abilities, but we must be honest about our shortcomings--our ignorance as well as our mistakes.
- Responsibility is something you actively agree to.
- When you do accept the responsibility for an outcome, you should expect to be held accountable for it. When you make a mistake (as we all do) or an error in judgment, admit it honestly and try to offer options.
- 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 to salvage the situation.
- When disorder increases in software, programmers call it “software rot.”
- There are many factors that can contribute to software rot. The most important one seems to be the psychology, or culture, at work on a project.
- Don’t live with broken windows.
- Don’t leave “broken windows” (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered. If there is insufficient time to fix it properly, then board it up. Perhaps you can comment out the offending code, or display a “Not Implemented” message, or substitute dummy data instead. Take some action to prevent further damage and to show that you’re on top of the situation.
- Work out what you can reasonably ask for. Develop it well. Once you’ve got it, show people, and let them marvel.
- People find it easier to join an ongoing success.
- Be a catalyst for change.
- Remember the big picture.
- It’s easier to ask forgiveness than it is to get permission.
- Constantly review what’s happening around you, not just what you personally are doing.
- All systems must meet their users’ requirements to be successful.
- Make quality a requirements issue.
- Surprisingly, many users would rather use software with some rough edges today than wait a year for the multimedia version.
- Great software today is often preferable to perfect software tomorrow. If you give your users something to play with early, their feedback will often lead you to a better eventual solution.
- Don’t spoil a perfectly good program by over embellishment and over refinement.
- An investment in knowledge always pays the best interest.
- Your knowledge and experience are your most important professional assets.
- Your knowledge becomes out of date as new techniques, languages, and environments are developed.
- As the value of your knowledge declines, so does your value to your company or client.
- You must invest in your knowledge portfolio regularly.
- The more different things you know, the more valuable you are.
- The more technologies you are comfortable with, the better you will be able to adjust to change.
- Invest regularly in your knowledge portfolio.
- Learn at least one new language every year.
- Read a technical book each quarter.
- Read nontechnical books too.
- Don’t forget the human side of the equation.
- Isolation can be deadly to your career; find out what people are working on outside of your company.
- The process of learning will expand your thinking, opening you to new possibilities and new ways of doing things.
- Talking to other people will help build your personal network, and you may surprise yourself by finding solutions to other, unrelated problems along the way.
- Always have something to read in an otherwise dead moment.
- Critically analyze what you read and hear.
- Know exactly what you want to ask, and be as specific as you can be.
- Frame your question carefully and politely.
- Once you’ve framed your question, stop and look again for the answer.
- Finally, please be sure to thank anyone who responds to you.
- A good idea is an orphan without effective communication.
- When you’re faced with an important meeting or a phone call with a major client, jot down the ideas you want to communicate, and plan a couple of strategies for getting them across.
- You’re communicating only if you’re conveying information.
- The WISDOM acrostic--understanding an audience: what, interest, sophisticated, detail, own, motivate.
- What do you want them to learn?
- What is their interest in what you’ve got to say?
- How sophisticated are they?
- How much detail do they want?
- Whom do you want to own the information?
- How can you motivate them to listen to you?
- Make what you’re saying relevant in time, as well as in content.
- Adjust the style of your delivery to suit your audience.
- There is no excuse today for producing poor-looking printed documents.
- If possible, involve your readers with early drafts of your document.
- There’s one technique that you must use if you want people to listen to you: listen to them.
- Encourage people to talk by asking questions, or have them summarize what you tell them.
- Always respond to emails and voice mails, even if the response is simply “I’ll get back to you later.”
- It’s both what you say and the way you say it.
- Our e-mail tips are simple:
- Proofread before you hit send.
- Check the spelling.
- Keep the format simple.
- Plain text is universal.
- Check your list of recipients before sending.
- Archive and organize your email--both the important stuff you receive and the mail you send.
- Try to give the same attention and care to email as you would to any written memo or report.
- We feel that the only way to develop software reliably, and to make our developments easier to understand and maintain, is to follow what we call the DRY principle: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
- DRY--Don’t Repeat Yourself.
- Good code has lots of comments. Bad code requires lots of comments.
- The DRY principle tells us to keep the low-level knowledge in the code, where it belongs, and reserve the comments for other, high-level explanations.
- Use the header files to document interface issues, and the implementation files to document the nitty-gritty details that users of your code don’t need to know.
- Where possible, always use accessor functions to read and write the attributes of objects.
- Make it easy to reuse.
- If it isn’t easy, people won’t do it.
- Two or more things are orthogonal if changes in one do not affect any of the others.
- Non-orthogonal systems are inherently more complex to change and control.
- Eliminate effects between unrelated things.
- We want to design components that are self-contained: independent, and with a single, well-defined purpose. When components are isolated from one another, you know that you can change one without having to worry about the rest.
- You get two major benefits if you write orthogonal systems: increased productivity and reduced risk.
- You can get an informal measure of the orthogonality of a project team’s structure. Simply see how many people need to be involved in discussing each change that is requested. The larger the number, the less orthogonal the group.
- Don’t rely on the properties of things you can't control.
- When you bring in a toolkit (or even a library from other members of your team), ask yourself whether it imposes changes on your code that shouldn’t be there.
- Write shy code--modules that don’t reveal anything unnecessary to other modules and that don’t rely on other modules’ implementations.
- If you need to change an object’s state, get the object to do it for you.
- Every time your code references global data, it ties itself into the other components that share that data.
- In general, your code is easier to understand and maintain if you explicitly pass any required context into your modules.
- Duplicate code is a symptom of structural problems.
- Get into the habit of being constantly critical of your code. Look for any opportunities to reorganize it to improve its structure and orthogonality. This process is called refactoring.
- Module level (or unit) testing is considerably easier to specify and perform than integration testing.
- We suggest that every module have its own unit test built into its code, and that these tests be performed automatically as part of the regular build process.
- Tag bug fixes when you check the code back in after testing. You can then run monthly reports analyzing trends in the number of source files affected by each bug fix.
- Nothing is forever--and if you rely heavily on some fact, you can almost guarantee that it will change.
- Requirements, users, and hardware change faster than we can get the software developed.
- There are no final decisions.
- If something is added automatically, it can be taken out automatically as well.
- Use tracer bullets to find the target.
- Once you’re on target, adding functionality is easy.
- The most daunting piece of paper is the one with nothing written on it.
- 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.
- It’s the same with tracer code. You use the technique in situations where you’re not 100% certain where you’re going.
- A small body of code has low inertia--it is easy and quick to change.
- Prototyping generates disposable code. Tracer code is lean but complete, and forms part of the skeleton of the final system.
- Post-it notes are great for prototyping dynamic things such as workflow and application logic.
- 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.
- Prototype to learn.
- A high-level scripting language lets you defer many details (including specifying data types) and still produce (albeit incomplete or slow) piece of code.
- Scripting languages work well as the “glue” to combine low-level pieces into new combinations.
- Computer languages influence how you think about a problem, and how you think about communicating.
- Program close to the problem domain.
- By coding at a higher level of abstraction, you are free to concentrate on solving domain problems, and can ignore petty implementation details.
- Data languages produce some form of data structure used by an application.
- Imperative languages take this a step further. Here the language is actually executed, and so can contain statements, control constructs, and the like.
- Given that most applications exceed their expected lifetimes, you’re probably better off biting the bullet and adopting the more complex and readable language up front.
- By learning to estimate, and by developing this skill to the point where you have an intuitive feel for the magnitudes of things, you will be able to show an apparent magical ability to determine their feasibility.
- Estimate to avoid surprises.
- To some extent, all answers are estimates. It’s just that some are more accurate than others.
- One of the interesting things about estimating is that the units you use make a difference in the interpretation of the result.
- Choose the units of your answer to reflect the accuracy you intend to convey.
- We find that often the only way to determine the timetable for a project is by gaining experience on that same project.
- Iterate the schedule with the code.
- What to say when asked for an estimate? You say “I’ll get back to you.”
- Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be.
- Always be on the lookout for better ways of doing things.
- Let need drive your acquisitions.
- We need to be comfortable beyond the limits imposed by an IDE.
- We believe that the best format for storing knowledge persistently is plain text.
- Plain text is made up of printable characters in a form that can be read and understood directly by people.
- Plain text doesn’t mean that the text is unstructured; XML, SGML, and HTML are great examples of plain text that has a well-defined structure. You can do everything with plain text that you could do with some binary format, including versioning.
- The problem with most binary formats is that the context necessary to understand the data is separate from the data itself.
- Keep knowledge in plain text.
- Human-readable forms of data, and self-describing data, will outlive all other forms of data and the applications that created them.
- Virtually every tool in the computing universe, from source code management systems to compiler environments to editors and stand-alone filters, can operate on plain text.
- All software becomes legacy as soon as it’s written.
- If you use plain text to create synthetic data to drive system tests, then it is a simple matter to add, update, or modify the test data without having to create any special tools to do so.
- You need to ensure that all parties can communicate using a common standard. Plain text is that standard.
- If you do all your work using GUIs, you are missing out on the full capabilities of your environment.
- The shell commands may be obscure or terse, but they are powerful and concise.
- Use the power of command shells.
- Gain familiarity with the shell, and you’ll find your productivity soaring.
- The GNU General Public License is a kind of legal virus the Open Source developers use to protect their (and your) rights.
- Whenever you derive a work from a GPL’d work, your derived work must also be GPL’d.
- You need to be able to manipulate text as effortlessly as possible, because text is the basic raw material of programming.
- We think it is better to know one editor very well, and use it for all editing tasks: code, documentation, memos, system administration, and so on.
- Use a single editor well.
- Choose an editor, know it thoroughly, and use it for all editing tasks.
- Ideally, the shell you use should have key bindings that match the ones used by your editor.
- Using only keystrokes for common editing operations is more efficient than mouse or menu-driven commands, because your hands never leave the keyboard.
- With a properly configured source code control system, you can always go back to a previous version of your software.
- Always use source code control.
- Make sure that everything is under source code control--documentation, phone number lists, memos to vendors, makefiles, build and release procedures, that little shell script that burns the CD master--everything.
- There is a tremendous hidden benefit in having an entire project under the umbrella of a source code control system: you can have product builds that are automated and repeatable.
- Don’t forget that an SCCS is equally applicable to the things you do outside of work.
- No one writes perfect software, so it’s a given that debugging will take up a major portion of your day.
- Embrace the fact that debugging is just problem solving, and attack it as such.
- It doesn’t really matter whether the bug is your fault or someone else's. It is still your problem.
- Always try to discover the root cause of a problem, not just this particular appearance of it.
- Before you start to look at the bug, make sure that you are working on code that compiled cleanly--without warnings.
- It doesn’t make sense to waste time trying to find a problem that the compiler could find for you!
- You may need to interview the use who reported the bug in order to gather more data than you were initially given.
- You must brutally test both boundary conditions and realistic end-user usage patterns.
- The best way to start fixing a bug is to make it reproducible. After all, if you can’t reproduce it, how ill you know if it is ever fixed?
- A very simple but particularly useful technique for finding the cause of a problem is simply to explain it to someone else.
- The simple act of explaining, step by step, what the code is supposed to do often causes the problem to leap off the screen and announce itself.
- The amount of surprise you feel when something goes wrong is directly proportional to the amount of trust and faith you have in the code being run.
- Don’t assume it--prove it.
- When you come across a surprise bug, beyond merely fixing it, you need to determine why this failure wasn’t caught earlier.
- Learn a text manipulation language.
- It is good OO-programming style to restrict access to an object’s properties, forcing external classes to get and set them via methods.
- Write code that writes code.
- Passive code generators are run once to produce a result.
- Active code generators are used each time their results are required.
- Whenever you find yourself trying to get two disparate environments to work together, you should consider using active code generators.
- You can’t write perfect software.
- It is the caller’s responsibility to pass good data.
- If a routine’s preconditions are met by the caller, the routine shall guarantee that all post-conditions and invariants will be true when it completes.
- Design with contracts.
- Inheritance and polymorphism are the cornerstones of object-oriented languages and an area where contract can really shine.
- Subclasses must be usable through the base class interface without the need for the user to know the difference.
- The greatest benefit of using DBC may be that it forces the issue of requirements and guarantees to the forefront. 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.
- It is often at eh boundary between your code and the libraries it uses that the most problems are detected.
- Languages that feature built-in support of DBC check pre- and post-conditions automatically in the compiler and runtime system.
- For Java, there is jContract. It takes comments (in JavaDoc form) and generates a new source file with the assertion logic included.
- Thus if there is any explicit checking of parameters to be done, it must be performed by the caller, because the routine itself will never see parameters that violate its precondition.
- Shift the burden of correctness to the caller--where it belongs.
- It’s much easier to find and diagnose the problem by crashing early, at the site of the problem.
- A loop invariant is a statement of the eventual goal of a loop, but is generalized so that it is also valid before the loop executes and on each iteration through the loop.
- Be sure not to confuse requirements that are fixed, inviolate laws with those that are merely policies that might change with a new management regime.
- Crash early
- One of the benefits of detecting problems as soon as you can is that you can crash earlier. And many times, crashing your program is the best thing you can do.
- 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.
- If it can’t happen, use assertions to ensure that it won’t.
- Whenever you find yourself thinking “but of course that could never happen,” add code to check it. The easiest way to do this is with assertions.
- The condition passed to an assertion should not have a side effect. Also remember that assertions may be turned off at compile time--never put code that must be executed into an assert.
- In reality, for any complex program you are unlikely to test even a minuscule percentage of the permutations your code will be put through.
- One of the problems with exceptions is knowing when to use them. We believe that exceptions should rarely be used as part of a program’s normal flow; exceptions should be reserved for unexpected events.
- Use exceptions for exceptional problems.
- An error handler is a routine that is called when an error is detected.
- Finish what you start.
- The routine or object that allocates a resource should be responsible for deallocating it.
- The finish what you start tip tells us that, ideally, the routine that allocates a resource should also free it.
- Deallocate resources in the opposite order to that in which you allocate them. That way you won’t orphan resources if one resource contains references to another.
- When allocating the same set of resources in different places in your code, always allocate them in the same order. This will reduce the possibility of deadlock.
- When a try block contains a finally clause, code in that clause is guaranteed to be executed if any statement in the try block is executed.
- Organize your code into cells (modules) and limit the interaction between them. If one module then gets compromised and has to be replaced, the other modules should be able to carry on.
- Systems with many unnecessary dependencies are very hard (and expensive) to maintain, and tend to be highly unstable.
- Configure, don’t integrate.
- Use metadata to describe configuration options for an application: tuning parameters, user preferences, the installation directory, and so on.
- program for the general case, and put the specifics somewhere else--outside the compiled code base.
- Put abstractions in code, details in metadata.
- We recommend representing configuration metadata in plain text--it makes life that much easier.
- Unplanned, spur-of-the-moment configuration of existing software is a powerful concept.
- We need to allow for concurrency and to think about decoupling any time or order dependencies.
- Analyze workflow to improve concurrency.
- Design using services.
- Always design for concurrency.
- Separate views from models.
- Use blackboards to coordinate workflow.
- Developers who don’t actively think about their code are programming by coincidence--the code might work, but there’s no particular reason why.
- Something that should be in the back of your mind whenever you’re producing code is that you’ll someday have to test it.
- we suggest that you should be careful of tools that write reams of code on your behalf unless you understand what they’re doing.
- We should avoid programming by coincidence--relying on luck and accidental successes--in favor of programming deliberately.
- Accidents of implementation are things that happen simple because that’s the way the code is currently written.
- The boundary condition you rely on may be just an accident.
- Undocumented behavior may change with the next release of the library.
- Additional and unnecessary calls make your code slower.
- For routines you call, rely only on documented behavior.
- Don’t program by coincidence.
- Always be aware of what you are doing.
- Attempting to build an application you don’t fully understand, or to use a technology you aren’t familiar with, is an invitation to be misled by coincidences.
- Document your assumptions.
- Don’t let existing code dictate future code. All code can be replaced if it is no longer appropriate.
- Normally, the size of this input will affect the algorithm: the larger the input, the longer the running time or the more memory used.
- The O() notation is a mathematical way of dealing with approximations.
- Think of the O as meaning “on the order of”. The O() notation puts an upper bound on the value of the thing we’re measuring (time, memory, and so on).
- Sometimes we come up with fairly complex O() functions, but because the highest-order term will dominate the value as n increases, the convention is to remove all low-order terms, and not to bother showing any constant multiplying factors.
- Whenever algorithms start looking at the permutations of things, their running times may get out of hand. This is because permutations involve factorials.
- Estimate the order of your algorithms.
- Test your estimates.
- You also need to be pragmatic about choosing appropriate algorithms--the fastest one is not always the best for the job.
- Also be wary of premature optimization. It’s always a good idea to make sure an algorithm really is a bottleneck before investing your precious time trying to improve it.
- Code need to evolve; it’s not a static thing.
- Rewriting, reworking, and re-architecting code is collectively known as refactoring.
- Refactor early, refactor often.
- Don’t try to refactor and add functionality at the same time.
- Make sure you have good tests before you begin refactoring. Run the tests as often as possible.
- Take short, deliberate steps.
- If you keep your steps small, and test after each step, you will avoid prolonged debugging.
- Like are hardware colleagues, we need to build testability into the software from the very beginning, and test each piece thoroughly before trying to wire them together.
- A software unit test is code that exercises a module.
- We want to write test cases that ensure that a given unit honors its contract.
- We want to test that the module delivers the functionality it promises, over a wide range of test cases and boundary conditions.
- Once the subcomponents have been verified, then the module itself can be tested.
- Design to test.
- For small projects, you can embed the unit test for a module in the module itself. For larger projects, we suggest moving each test into a subdirectory.
- A test harness can handle common operations such as logging status, analyzing output for expected results, and selecting and running the tests.
- Test harnesses should include the following capabilities:
- A standard way to specify setup and cleanup.
- A method for selecting individual tests or all available tests.
- A means of analyzing output for expected (or unexpected) results.
- A standardized form of failure reporting.
- Tests should be composable; that is, a test can be composed of subtests of subcomponents to any depth.
- If the code broke once, it is likely to break again. Don’t just throw away the test you created; add it to the existing unit test.
- Log messages should be in a regular, consistent format; you may want to parse them automatically to reduce processing time or logic paths that the program took.
- 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.
- Testing is more cultural than technical; we can instill this testing culture in a project regardless of the language being used.
- Test your software, or your users will.
- Don’t use wizard code you don’t understand.
- Don’t gather requirements--dig for them.
- A requirement is a statement of something that needs to be accomplished.
- It’s important to discover the underlying reason why users do a particular thing, rather than just the way they currently do it.
- There’s a simple technique for getting inside your users’ requirements that isn’t used often enough: become a user.
- Work with a user to think like a user.
- While slavishly duplicating what already exists doesn’t allow for progress, we must be able to provide a transition to the future.
- Don’t be a slave to any notation; use whatever method best communicates the requirements with your audience.
- A big danger in producing a requirements document is being too specific. Good requirements documents remain abstract. Where requirements are concerned, the simplest statement that accurately reflects the business need is best.
- Abstractions live longer than details.
- The key to managing growth of requirements is to point out each new feature’s impact on the schedule to the project sponsors.
- Create and maintain a project glossary--one place that defines all the specific terms and vocabulary used in a project.
- Use a project glossary.
- The secret to solving the puzzle is to identify the real (not imagined) constraints, and find a solution therein. Some constraints are absolute; others are merely preconceived notions. Absolute constraints must be honored, however distasteful or stupid they may appear to be. On the other hand, some apparent constraints may not be real constraints at all.
- The key to solving puzzles it 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.
- Don’t think outside the box--find the box.
- When faced with an intractable problem, enumerate all the possible avenues you have before you. Don’t dismiss anything, no matter how unusable or stupid it sounds. Now go through the list and explain why a certain path cannot be taken.
- Many times a reinterpretation of the requirements can make a whole set of problems go away.
- Listen to nagging doubts--start when you’re ready.
- When you feel a nagging doubt, or experience some reluctance when faced with a task, heed it.
- A technique that has worked for us in these circumstances is to start prototyping. Choose an area that you feel will be difficult and begin producing some kind of proof of concept.
- Program specification is the process of taking a requirement and reducing it done to the point where a programmer’s skill can take over.
- Some things are better done than described.
- Don’t be a slave to formal methods.
- You should work constantly to refine and improve your processes.
- Expensive tools do not produce better designs.
- As soon as you have more than one person working on a project, you need to establish some ground rules and delegate parts of the project accordingly.
- The single most important factor in making project-level activities work consistently and reliably is to automate your procedures.
- Quality is a team issue.
- Teams as a whole should not tolerate broken windows--those small imperfections that no one fixes.
- Quality can come only from the individual contributions of all team members.
- There is a simple marketing trick that helps teams communicate as one: generate a brand.
- Good developers tend to be passionate about their work.
- The closer to the user you’re allowed, the more senior you are.
- It is a mistake to think that the activities of a project--analysis, design, coding, and testing--can happen in isolation.
- Organize around functionality, not job functions.
- We favor splitting teams functionally. Divide your people into small teams, each responsible for a particular functional aspect of the final system. Let the teams organize themselves internally, building on individual strengths as they can. Each team has responsibilities to others in the project, as defined by their agreed-upon commitments. The exact set of commitments changes with each project, as does the allocation of people into teams.
- A great way to ensure both consistency and accuracy is to automate everything the team does.
- To ensure that things get automated, appoint one or more team members as tool builders to construct and deploy the tools that automate the project drudgery.
- Don’t use manual procedures.
- People just aren’t as repeatable as computers are. Nor should we expect them to be. A shell script or batch file will execute the same instructions, in the same order, time after time.
- Another favorite tool of automation is cron (or “at” on Windows NT).
- 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.
- Remember that if the project is compiled differently from earlier versions, then you must test against this version all over again.
- Misleading information is worse than no information at all.
- However it is done, web content should be generated automatically from information in the repository and published without human intervention.
- Any information generated by the nightly build should be accessible on the development web site.
- Often, people who develop software use the poorest tools to do the job.
- Let the computer do the repetitions, the mundane--it will do a better job of it than we would. We’ve got more important and more difficult things to do.
- Finding bugs is somewhat like fishing with a net. We use fine, small nets (unit tests) to catch the minnows, and big, coarse nets (integration tests) to catch the killer sharks.
- Test early. Test often. Test automatically.
- We want to start testing as soon as we have code.
- Tests that run with every build are much more effective than test plans that sit on the shelf.
- The earlier a bug is found, the cheaper it is to remedy.
- Coding ain’t done ‘til all the tests run’.
- Code is never really done.
- You can’t claim that it is usable by anyone until it passes all of the available tests.
- There are several major types of software testing that you need to perform:
- unit testing
- integration testing
- validation and verification
- resource exhaustion, errors and recovery
- performance testing
- usability testing
- A unit test is code that exercises a module.
- Integration testing shows that the major subsystems that make up the project work and play well with each other.
- A bug-free system that answers the wrong question isn’t very useful.
- In the real world, your programs don’t have limitless resources; they run out of things. A few limits your code may encounter include:
- memory
- disk space
- CPU bandwidth
- wall-clock time
- disk bandwidth
- network bandwidth
- color palette
- video resolution
- A regression test compares the output of the current test with previous (or know) values.
- Because we can’t write perfect software, it follows that we can’t write perfect test software either. We need to test the tests.
- Use saboteurs to test your testing.
- If you are really serious about testing, you might want to appoint a project saboteur. The saboteur's role is to take a separate copy of the source tree, introduce bugs on purpose, and verify that the tests will catch them.
- Test state coverage, not code coverage.
- As soon as any production code exists, it needs to be tested.
- If a bug slips through the net of existing tests, you need to add a new test to trap it next time.
- Find bugs once.
- Writing documentation can be made easier by not duplicating effort or wasting time, and by keeping documentation close at hand--in the code itself, if possible.
- Treat English as just another programming language.
- Internal documentation includes source code comments, design and test documents, and so on. External documentation is anything shipped or published to the outside world, such as user manuals.
- Build documentation in, don’t bolt it on.
- In general, comments should discuss why something is done, its purpose and its goal.
- We like to see a simple module-level header comment, comments for significant data and type declarations, and a brief per-class and per method header, describing how the function is used any anything that it does that is not obvious.
- Variable names, of course, should be well chosen and meaningful.
- Even worse than meaningless names are misleading names.
- Names are deeply meaningful to your brain, and misleading names add chaos to your code.
- One of the most important pieces of information that should appear in the source file is the author’s name.
- Documentation of any form is just a snapshot.
- A document's presentation should be independent of its content.
- Treat documentation with the same care you treat code, and the users (and maintainers who follow) will sing your praises.
- In reality, the success of a project is measured by how well it meets the expectations of its users.
- Gently exceed your user’s expectations.
- Work with your users so that their understanding of what you’ll be delivering is accurate.
- The extra bit of effort it requires to add some user-oriented feature to the system will pay for itself time and time again in goodwill.
- Sign your work.
- Craftsmen of an earlier age were proud to sign their work. You should be, too.
- Anonymity, especially on large projects, can provide a breeding ground for sloppiness, mistakes, sloth, and bad code.
- Your signature should come to be recognized as an indicator of quality.
- There are two world-class professional societies for programmers: the Association for Computing Machinery (ACM) and the IEEE Computer Society. We recommend that all programmers belong to one (or both) of these societies.
- A good programmer is always learning.
- A design pattern describes a way to solve a particular class of problems at a higher level than a programming language idiom.
- As soon as you find yourself on a C++ project, run, don’t walk, to the bookstore and get Scott Meyers Effective C++, and possibly More Effective C++.
20170220
"Pragmatic Programmer" by Andrew Hunt & David Thomas
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment