Medical physicists often write computer programs to support scientific, educational, and clinical endeavors. Errors in scientific and educational software can waste time and effort by producing meaningless results, but errors in clinical software can contribute to patient injuries. Although the ultimate goal of error-free software is impossible to achieve except in very small programs, there are many good design, implementation, and testing practices that can be used by small development groups to significantly reduce errors, improve quality, and reduce maintenance. The software development process should include four basic steps: specifications, design, implementation, and testing. A specifications document defining what the software is intended to do is valuable for clearly delimiting the scope of the project and providing a benchmark for evaluating the final product. Keep the software design simple and straightforward. Document assumptions, and check them. Emphasize maintainability, portability, and reliability rather than speed. Use layers to isolate the application from hardware and the operating system. Plan for upgrades. Expect the software to be used in unplanned ways. Whenever possible, be generous with RAM and disk storage; hardware is cheaper than development and maintenance. During implementation, use well-known algorithms whenever possible. Use prototypes to try out ideas. Use generic modules, version numbering, unique file names, defensive programming, and operating system and language/compiler defaults. Avoid binary data files and clever tricks. Remember that real numbers are not exact in a computer. Get it right before making it faster. Document the software extensively. Test continuously during development; the later a problem is found, the more it costs to fix. Use a written procedure to test the final product exactly as a typical user would run it. Allow no changes after clinical release. Expect to spend at least an additional 50% of the initial development effort on testing, fixing errors, and getting the software into routine operation.