puddlejumper26 / blogs

Personal Tech Blogs
4 stars 1 forks source link

Code Complete 2nd Edition (Notes) #98

Open puddlejumper26 opened 4 years ago

puddlejumper26 commented 4 years ago

Normally, this book requires a lot of practical experiences. However,

Reference

[1] https://github.com/xianshenglu/document/blob/master/Code%20Complete%202nd%20Edition.pdf

Guideline

Chapter 1 || Chapter 2-Metaphors for a Richer Understanding of Software Development || Chapter 3-Measure Twice, Cut Once: Upstream Prerequisites || Chapter 4-Key Construction Decisions || Chapter 5-Design in Construction || Chapter 6-Working Classes || Chapter 7-High-Quality Routines || Chapter 8-Defensive Programming || Chapter 9-The Pseudocode Programming Process || Chapter 10-General Issues in Using Variables || ..... || Chapter 22-Developer Testing || Chapter 23-Debugging || Chapter 24-Refactoring || ..... ||

puddlejumper26 commented 4 years ago

Chapter 1

puddlejumper26 commented 4 years ago

Chapter 2 Metaphors for a Richer Understanding of Software Development

puddlejumper26 commented 4 years ago

Chapter 3 Measure Twice, Cut Once: Upstream Prerequisites

puddlejumper26 commented 4 years ago

Chapter 4 Key Construction Decisions

puddlejumper26 commented 4 years ago

Chapter 5 Design in Construction

## 5.1 Design Challenges - A good top-level design provides a structure that can safely contain multiple lower-level designs. - useful on small projects and indispensable on large projects - making mistakes is the point of design—it’s cheaper to make mistakes and correct designs than it would be to make the same mistakes, recognize them after coding, and have to correct full-blown code - hard to know when your design is “good enough.” - - Tradeoffs and Priorities - Restrictions - partly to create possibilities and partly to restrict possibilities - Nondeterministic - there are usually dozens of ways to design a computer program - Heuristic Process - trial and error - Emergent- evolve and improve through design reviews, informal discussions, experience writing the code itself, and experience revising the code. ## 5.2 Key Design Concepts ### Managing complexity - Accidental and Essential Difficulties - essential ( things must have ), accidental ( things happen to have) ### Importance of Managing Complexity - focus on one part of it at a time - minimize the amount of a program at any time - dividing into subsystems - keeps routine short - Writing programs in terms of the problem domain ### How to Attack Complexity - ineffective designs (NO) - - Minimize the amount of essential complexity - Keep accidental complexity from needlessly proliferating ### Desirable Characteristics of a Design - Minimal complexity - Ease of maintenance - Loose coupling - Extensibility - Reusability - High fan-in - having a high number of classes that use a given class. a system has been designed to make good use of utility classes at the lower levels in the system - Low-to-medium fan-out - a class uses a large number of other classes and may therefore be overly complex - Portability - easily to move to other environment - Leanness - no extra parts - Stratification - keep the levels of decomposition stratified, view the system at any single level and get a consistent view - Standard techniques ### Levels of Design ![image](https://user-images.githubusercontent.com/40550117/78956876-4bd57a00-7b16-11ea-8632-f0f6ff08894b.png) - Level 2: Division into Subsystems or Packages ( subsystems can be big: database, user interface, business rules, command interpreter,report engine, and so on. how to partition the program into major subsystems and defining how each subsystem is allowed to use each other subsystem) - - Common Subsystems ( Business rules, User interface, Database access, System dependencies) - Level 3: Division into Classes ( Classes vs. Objects, An object is any specific entity that exists in your program at run time. A class is the static thing you look at in the program listing. An object is the dynamic thing with specific values and attributes you see when you run the program. Class Person, Object Mr X ) - Level 4: Division into Routines - at least needs to be done mentally. - Level 5: Internal Routine Design - detailed functionality of the individual routines ## 5.3 Design Building Blocks: Heuristics ### Find Real-World Objects ■ Identify the objects and their attributes (methods and data). - Computer programs are usually based on real-world entities ■ Determine what can be done to each object. ■ Determine what each object is allowed to do to other objects. ■ Determine the parts of each object that will be visible to other objects—which parts will be public and which will be private. ■ Define each object’s public interface. ### Form Consistent Abstractions ### Encapsulate Implementation Details - you can look at the outside of the house but you can’t get close enough to make out the door’s details ### Inherit—When Inheritance Simplifies the Design - works synergistically with the notion of abstraction ### Hide Secrets (Information Hiding) - black boxes - Secrets and the Right to Privacy (deciding which features should be known outside the class and which should remain secret. ) - Two Categories of Secrets (1. Hiding complexity so that your brain doesn’t have to deal with it unless you’re specifically concerned with it 2. Hiding sources of change so that when change occurs, the effects are localized) - Barriers to Information Hiding ( Excessive distribution of information, Circular dependencies, Class data mistaken for global data, Perceived performance penalties) - Value of Information Hiding (ability to inspire effective design solutions) ### Identify Areas Likely to Change - ability to anticipate change, Accommodating changes, (Identify, Separate and Isolate items that are likely to change) - Business rules - Hardware dependencies - Input and output - Nonstandard language features - Difficult design and construction areas - Status variables ( 1. don't use boolean, 2. use access routines rather than checking the variable directly) - Data-size constraints - Anticipating Different Degrees of Change (identify the minimal subset of the program) ### Keep Coupling Loose - create classes and routines with small, direct, visible, and flexible relations to other classes and routines, - one module can easily be used by other modules - create modules that depend little on other modules. Make them detached - - Coupling Criteria ( Size, Visibility, Flexibility) - Kinds of Coupling ( Simple-data-parameter coupling, Simple -object coupling, Object-parameter coupling, Semantic coupling), Semantic coupling is dangerous because changing code in the used module can break code ### Look for Common Design Patterns - Common patterns include Adapter, Bridge, Decorator, Facade, Factory Method, Observor, Singleton, Strategy, and Template Method - Patterns reduce complexity by providing ready-made abstractions - Patterns reduce errors by institutionalizing details of common solutions - Patterns provide heuristic value by suggesting design alternatives - Patterns streamline communication by moving the design dialog to a higher level ![image](https://user-images.githubusercontent.com/40550117/78959427-7a0a8800-7b1d-11ea-985f-2f8c11c86df2.png) ### Other Heuristics - Aim for Strong Cohesion - Build Hierarchies - Formalize Class Contracts - Assign Responsibilities - Design for Test - Avoid Failure - Choose Binding Time Consciously - Make Central Points of Control - Consider Using Brute Force - Draw a Diagram - Keep Your Design Modular ### Summary of Design Heuristics Here’s a summary of major design heuristics: ■ Find Real-World Objects ■ Form Consistent Abstractions ■ Encapsulate Implementation Details ■ Inherit When Possible ■ Hide Secrets (Information Hiding) ■ Identify Areas Likely to Change ■ Keep Coupling Loose ■ Look for Common Design Patterns The following heuristics are sometimes useful too: ■ Aim for Strong Cohesion ■ Build Hierarchies ■ Formalize Class Contracts ■ Assign Responsibilities ■ Design for Test ■ Avoid Failure ■ Choose Binding Time Consciously ■ Make Central Points of Control ■ Consider Using Brute Force ■ Draw a Diagram ■ Keep Your Design Modular ### Guidelines for Using Heuristics - 1. Understanding the Problem - 2. Devising a Plan - 3. Carrying out the Plan - 4. Looking Back. ## 5.4 Design Practices - Iterate - Divide and Conquer - Top-Down and Bottom-Up Design Approaches ( top down tends to start simple, but sometimes low-level complexity ripples back to the top, and those ripples can make things more complex than they really needed to be. Bottom up tends to start complex, but identifying that complexity early on leads to better design of the higher-level classes—if the complexity doesn’t torpedo the whole system first) - Experimental Prototyping - Collaborative Design ( two heads are often better than one, discuss and listen) - How Much Design Is Enough? ![image](https://user-images.githubusercontent.com/40550117/78960495-d7ec9f00-7b20-11ea-8d1e-0d9f29bf9eeb.png) - Capturing Your Design Work ( Insert design documentation into the code itself, Capture design discussions and decisions on a Wiki, Write e-mail summaries, Use a digital camera, Save design flip charts, Use CRC (Class, Responsibility, Collaborator) cards , Create UML diagrams at appropriate levels of detail ## CHECKLIST: Design in Construction ### Design Practices ❑ Have you iterated, selecting the best of several attempts rather than the first attempt? ❑ Have you tried decomposing the system in several different ways to see which way will work best? ❑ Have you approached the design problem both from the top down and from the bottom up? ❑ Have you prototyped risky or unfamiliar parts of the system, creating the absolute minimum amount of throwaway code needed to answer specific questions? ❑ Has your design been reviewed, formally or informally, by others? ❑ Have you driven the design to the point that its implementation seems obvious? ❑ Have you captured your design work using an appropriate technique such as a Wiki, e-mail, flip charts, digital photography, UML, CRC cards, or comments in the code itself? ### Design Goals ❑ Does the design adequately address issues that were identified and deferred at the architectural level? ❑ Is the design stratified into layers? ❑ Are you satisfied with the way the program has been decomposed into subsystems, packages, and classes? ❑ Are you satisfied with the way the classes have been decomposed into routines? ❑ Are classes designed for minimal interaction with each other? ❑ Are classes and subsystems designed so that you can use them in other systems? ❑ Will the program be easy to maintain? ❑ Is the design lean? Are all of its parts strictly necessary? ❑ Does the design use standard techniques and avoid exotic, hard-to-understand elements? ❑ Overall, does the design help minimize both accidental and essential complexity? ## Key Points ■ Software’s Primary Technical Imperative is managing complexity. This is greatly aided by a design focus on simplicity. ■ Simplicity is achieved in two general ways: minimizing the amount of essential complexity that anyone’s brain has to deal with at any one time, and keeping accidental complexity from proliferating needlessly. ■ Design is heuristic. Dogmatic adherence to any single methodology hurts creativity and hurts your programs. ■ Good design is iterative; the more design possibilities you try, the better your final design will be. ■ Information hiding is a particularly valuable concept. Asking “What should I hide?” settles many difficult design issues. ■ Lots of useful, interesting information on design is available outside this book. The perspectives presented here are just the tip of the iceberg. --

Guideline

puddlejumper26 commented 4 years ago

Chapter 6 Working Classes

6.1 Class Foundations: Abstract Data Types (ADTs)

Example of the Need for an ADT

currentFont.sizeInPixels = PointsToPixels( 12 )
currentFont.SetSizeInPoints( sizeInPoints )
currentFont.SetSizeInPixels( sizeInPixels )
currentFont.SetBoldOn()
currentFont.SetBoldOff()
currentFont.SetItalicOn()
currentFont.SetItalicOff()
currentFont.SetTypeFace( faceName )

Benefits of Using ADTs

Guidelines of ADT

Handling Multiple Instances of Data with ADTs in Non-ObjectOriented Environments

ADTs and Classes

6.2 Good Class Interfaces

Good Abstraction

Good Encapsulation

6.3 Design and Implementation Issues

Containment (“has a” Relationships)

Inheritance (“is a” Relationships)

When to use inheritance and when to use containment:

■ If multiple classes share common data but not behavior, create a common object that those classes can contain. ■ If multiple classes share common behavior but not data, derive them from a common base class that defines the common routines. ■ If multiple classes share common data and behavior, inherit from a common base class that defines the common data and routines. ■ Inherit when you want the base class to control your interface; contain when you want to control your interface

Member Functions and Data

Constructors

6.4 Reasons to Create a Class

Classes to Avoid

6.5 Language-Specific Issues

6.6 Beyond Classes: Packages

■ Naming conventions that differentiate which classes are public and which are for the package’s private use ■ Naming conventions, code-organization conventions (project structure), or both that identify which package each class belongs to ■ Rules that define which packages are allowed to use which other packages, including whether the usage can be inheritance, containment, or both

CHECKLIST: Class Quality

Abstract Data Types

❑ Have you thought of the classes in your program as abstract data types and evaluated their interfaces from that point of view?

Abstraction

❑ Does the class have a central purpose? ❑ Is the class well named, and does its name describe its central purpose? ❑ Does the class’s interface present a consistent abstraction? ❑ Does the class’s interface make obvious how you should use the class? ❑ Is the class’s interface abstract enough that you don’t have to think about how its services are implemented? Can you treat the class as a black box? ❑ Are the class’s services complete enough that other classes don’t have to meddle with its internal data? ❑ Has unrelated information been moved out of the class? ❑ Have you thought about subdividing the class into component classes, and have you subdivided it as much as you can? ❑ Are you preserving the integrity of the class’s interface as you modify the class?

Encapsulation

❑ Does the class minimize accessibility to its members? ❑ Does the class avoid exposing member data? ❑ Does the class hide its implementation details from other classes as much as the programming language permits? ❑ Does the class avoid making assumptions about its users, including its derived classes? ❑ Is the class independent of other classes? Is it loosely coupled?

Inheritance

❑ Is inheritance used only to model “is a” relationships—that is, do derived classes adhere to the Liskov Substitution Principle? ❑ Does the class documentation describe the inheritance strategy? ❑ Do derived classes avoid “overriding” non-overridable routines? ❑ Are common interfaces, data, and behavior as high as possible in the inheritance tree? ❑ Are inheritance trees fairly shallow? ❑ Are all data members in the base class private rather than protected?

Other Implementation Issues

❑ Does the class contain about seven data members or fewer? ❑ Does the class minimize direct and indirect routine calls to other classes? ❑ Does the class collaborate with other classes only to the extent absolutely necessary? ❑ Is all member data initialized in the constructor? ❑ Is the class designed to be used as deep copies rather than shallow copies unless there’s a measured reason to create shallow copies?

Language-Specific Issues

❑ Have you investigated the language-specific issues for classes in your specific programming language?

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 7 High Quality Routines

--

7.1 Valid Reasons to Create a Routine

Operations That Seem Too Simple to Put Into Routines

■ Isolate complexity ■ Hide implementation details ■ Limit effects of changes ■ Hide global data ■ Make central points of control ■ Facilitate reusable code ■ Accomplish a specific refactoring

7.2 Design at the Routine Level

--

7.3 Good Routine Names

7.4 How Long Can a Routine Be?

7.5 How to Use Routine Parameters

7.6 Special Considerations in the Use of Functions

When to Use a Function and When to Use a Procedure

Setting the Function’s Return Value

7.7 Macro Routines and Inline Routines

Limitations on the Use of Macro Routines

■ const for declaring constant values ■ inline for defining functions that will be compiled as inline code ■ template for defining standard operations like min, max, and so on in a type-safe way ■ enum for defining enumerated types ■ typedef for defining simple type substitutions

Inline Routines

CHECKLIST: High-Quality Routines

Big-Picture Issues

❑ Is the reason for creating the routine sufficient? ❑ Have all parts of the routine that would benefit from being put into routines of their own been put into routines of their own? ❑ Is the routine’s name a strong, clear verb-plus-object name for a procedure or a description of the return value for a function? ❑ Does the routine’s name describe everything the routine does? ❑ Have you established naming conventions for common operations? ❑ Does the routine have strong, functional cohesion—doing one and only one thing and doing it well? ❑ Do the routines have loose coupling—are the routine’s connections to other routines small, intimate, visible, and flexible? ❑ Is the length of the routine determined naturally by its function and logic, rather than by an artificial coding standard?

Parameter-Passing Issues

❑ Does the routine’s parameter list, taken as a whole, present a consistent interface abstraction? ❑ Are the routine’s parameters in a sensible order, including matching the order of parameters in similar routines? ❑ Are interface assumptions documented? ❑ Does the routine have seven or fewer parameters? ❑ Is each input parameter used? ❑ Is each output parameter used? ❑ Does the routine avoid using input parameters as working variables? ❑ If the routine is a function, does it return a valid value under all possible circumstances?

Key Points

■ The most important reason for creating a routine is to improve the intellectual manageability of a program, and you can create a routine for many other good reasons. Saving space is a minor reason; improved readability, reliability, and modifiability are better reasons. ■ Sometimes the operation that most benefits from being put into a routine of its own is a simple one. ■ You can classify routines into various kinds of cohesion, but you can make most routines functionally cohesive, which is best. ■ The name of a routine is an indication of its quality. If the name is bad and it’s accurate, the routine might be poorly designed. If the name is bad and it’s inaccurate, it’s not telling you what the program does. Either way, a bad name means that the program needs to be changed. ■ Functions should be used only when the primary purpose of the function is to return the specific value described by the function’s name. ■ Careful programmers use macro routines with care and only as a last resort.

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 8 Defensive Programming

8.1 Protecting Your Program from Invalid Inputs

8.2 Assertions

Building Your Own Assertion Mechanism

Guidelines for Using Assertions

8.3 Error-Handling Techniques

Robustness vs. Correctness

High-Level Design Implications of Error Processing

8.4 Exceptions

8.5 Barricade Your Program to Contain the Damage Caused by Errors

image

8.6 Debugging Aids

Don’t Automatically Apply Production Constraints to the Development Version

Introduce Debugging Aids Early

Use Offensive Programming

Plan to Remove Debugging Aids

8.7 Determining How Much Defensive Programming to Leave in Production Code

8.8 Being Defensive About Defensive Programming

8.9 CHECKLIST: Defensive Programming

General

❑ Does the routine protect itself from bad input data? ❑ Have you used assertions to document assumptions, including preconditions and postconditions? ❑ Have assertions been used only to document conditions that should never occur? ❑ Does the architecture or high-level design specify a specific set of errorhandling techniques? ❑ Does the architecture or high-level design specify whether error handling should favor robustness or correctness? ❑ Have barricades been created to contain the damaging effect of errors and reduce the amount of code that has to be concerned about error processing? ❑ Have debugging aids been used in the code? ❑ Have debugging aids been installed in such a way that they can be activated or deactivated without a great deal of fuss? ❑ Is the amount of defensive programming code appropriate—neither too much nor too little? ❑ Have you used offensive-programming techniques to make errors difficult to overlook during development?

Exceptions

❑ Has your project defined a standardized approach to exception handling? ❑ Have you considered alternatives to using an exception? ❑ Is the error handled locally rather than throwing a nonlocal exception, if possible? ❑ Does the code avoid throwing exceptions in constructors and destructors? ❑ Are all exceptions at the appropriate levels of abstraction for the routines that throw them? ❑ Does each exception include all relevant exception background information? ❑ Is the code free of empty catch blocks? (Or if an empty catch block truly is appropriate, is it documented?)

Security Issues

❑ Does the code that checks for bad input data check for attempted buffer overflows, SQL injection, HTML injection, integer overflows, and other malicious inputs? ❑ Are all error-return codes checked? ❑ Are all exceptions caught? ❑ Do error messages avoid providing information that would help an attacker break into the systems?

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 9 The Pseudocode Programing Process

9.1 Summary of Steps in Building Classes and Routines

image

Steps in Creating a Class

Steps in Building a Routine

image

9.2 Pseudocode for Pros

9.3 Constructing Routines by Using the PPP

Design the Routine

Code the Routine

image

Check the Code

Clean Up Leftovers

■ Check the routine’s interface. ■ Check for general design quality. ■ Check the routine’s variables. ■ Check the routine’s statements and logic. ■ Check the routine’s layout. ■ Check the routine’s documentation. ■ Remove redundant comments.

9.4 Alternatives to the PPP

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 10 General Issues in Using Variables

10.1 Data Literacy

10.2 Making Variable Declarations Easy

Implicit Declarations

10.3 Guidelines for Initializing Variables

10.4 Scope

Localize References to Variables

Keep Variables “Live” for as Short a Time as Possible

Measuring the Live Time of a Variable

image image image image

General Guidelines for Minimizing Scope

10.5 Persistence

10.6 Binding Time

10.7 Relationship Between Data Types and Control Structures

10.8 Using Each Variable for Exactly One Purpose

Guideline

puddlejumper26 commented 4 years ago

Chapter 11 The Power of Variable Names

puddlejumper26 commented 4 years ago

Chapter 12 Fundamental Data Types

puddlejumper26 commented 4 years ago

Chapter 13 Unusual Data Types

puddlejumper26 commented 4 years ago

Chapter 14 Organizing Straight-Line Code

puddlejumper26 commented 4 years ago

Chapter 15 Using Conditionals

puddlejumper26 commented 4 years ago

Chapter 16 Controlling Loops

puddlejumper26 commented 4 years ago

Chapter 17 Unusual Control Structures

puddlejumper26 commented 4 years ago

Chapter 18 Table-Driven Methods

puddlejumper26 commented 4 years ago

Chapter 19 General Control Issues

puddlejumper26 commented 4 years ago

Chapter 20 The Software-Quality Landscape

puddlejumper26 commented 4 years ago

Chapter 21 Collaborative Construction

puddlejumper26 commented 4 years ago

Chapter 22 Developer Testing

Unit testing is the execution of a complete class, routine, or small program that has been written by a single programmer or team of programmers, which is tested in isolation from the more complete system.

Component testing is the execution of a class, package, small program, or other program element that involves the work of multiple programmers or programming teams, which is tested in isolation from the more complete system.

Integration testing is the combined execution of two or more classes, packages, components, or subsystems that have been created by multiple programmers or programming teams.

Regression testing is the repetition of previously executed test cases for the purpose of finding defects in software that previously passed the same set of tests.

System testing is the execution of the software in its final configuration, including integration with other software and hardware systems. It tests for security, performance, resource loss, timing problems, and other issues that can’t be tested at lower levels of integration.

22.1 Role of Developer Testing in Software Quality

Testing is hard

■ Testing’s goal runs counter to the goals of other development activities. ■ Testing can never completely prove the absence of errors. ■ Testing by itself does not improve software quality. ■ Testing requires you to assume that you’ll find errors in your code.

How much time would be enough

image

Testing During Construction

22.2 Recommended Approach to Developer Testing

■ Test for each relevant requirement to make sure that the requirements have been implemented. ■ Test for each relevant design concern to make sure that the design has been implemented. ■ Use “basis testing” to add detailed test cases to those that test the requirements and the design. ■ Use a checklist of the kinds of errors you’ve made on the project to date or have made on previous projects.

Test First or Test Last?

Limitations of Developer Testing

22.3 Bag of Testing Tricks

Incomplete Testing

Structured Basis Testing

Data-Flow Testing

Equivalence Partitioning

Error Guessing

Boundary Analysis

Classes of Bad Data

■ Too little data (or no data) ■ Too much data ■ The wrong kind of data (invalid data) ■ The wrong size of data ■ Uninitialized data

Classes of Good Data

■ Nominal cases—middle-of-the-road, expected values ■ Minimum normal configuration ■ Maximum normal configuration ■ Compatibility with old data

22.4 Typical Errors

Which Classes Contain the Most Errors?

Errors by Classification

Proportion of Errors Resulting from Faulty Construction

Errors in Testing Itself

22.5 Test-Support Tools

Building Scaffolding to Test Individual Classes

Coverage Monitors

Data Recorder/Logging

Symbolic Debuggers

System Perturbers

Error Databases

22.6 Improving Your Testing

Planning to Test

Retesting (Regression Testing)

Automated Testing

22.7 Keeping Test Records

■ Administrative description of the defect (the date reported, the person who reported it, a title or description, the build number, the date fixed) ■ Full description of the problem ■ Steps to take to repeat the problem ■ Suggested workaround for the problem ■ Related defects ■ Severity of the problem—for example, fatal, bothersome, or cosmetic ■ Origin of the defect: requirements, design, coding, or testing ■ Subclassification of a coding defect: off-by-one, bad assignment, bad array index, bad routine call, and so on ■ Classes and routines changed by the fix ■ Number of lines of code affected by the defect ■ Hours to find the defect ■ Hours to fix the defect Number of defects in each class, sorted from worst class to best, possibly normalized by class size ■ Number of defects in each routine, sorted from worst routine to best, possibly normalized by routine size ■ Average number of testing hours per defect found ■ Average number of defects found per test case ■ Average number of programming hours per defect fixed ■ Percentage of code covered by test cases ■ Number of outstanding defects in each severity classification

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 23 Debugging

23.1 Overview of Debugging Issues

Defects as Opportunities

An Ineffective Approach

23.2 Finding a Defect

The Scientific Method of Debugging

  1. Gather data through repeatable experiments.
  2. Form a hypothesis that accounts for the relevant data.
  3. Design an experiment to prove or disprove the hypothesis.
  4. Prove or disprove the hypothesis.
  5. Repeat as needed.
  1. Stabilize the error. (narrowing the test case to the simplest one that still produces the error. The goal of simplifying the test case is to make it so simple that changing any aspect of it changes the behavior of the error)
  2. Locate the source of the error (the “fault”). --a. Gather the data that produces the defect. --b. Analyze the data that has been gathered, and form a hypothesis about the defect. --c. Determine how to prove or disprove the hypothesis, either by testing the program or by examining the code. d. Prove or disprove the hypothesis by using the procedure identified in 2(c).
  3. Fix the defect.
  4. Test the fix.
  5. Look for similar errors.

Tips for Finding Defects

Brute-Force Debugging

Syntax Errors

23.3 Fixing a Defect

23.4 Psychological Considerations in Debugging

23.5 Debugging Tools—Obvious and Not-So-Obvious

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 24 Refactoring

24.1 Kinds of Software Evolution

Philosophy of Software Evolution

24.2 Introduction to Refactoring

Reasons to Refactor

24.3 Specific Refactorings

Data-Level Refactorings

Statement-Level Refactorings

Routine-Level Refactorings

Class Implementation Refactorings

Class Interface Refactorings

System-Level Refactorings

24.4 Refactoring Safely

Bad Times to Refactor

24.5 Refactoring Strategies

--

Guideline

puddlejumper26 commented 4 years ago

Chapter 25 Code-Tuning Strategies

puddlejumper26 commented 4 years ago

Chapter 26 Code-Tuning Techniques

puddlejumper26 commented 4 years ago

Chapter 27 How Program Size Affects Construction

puddlejumper26 commented 4 years ago

Chapter 28 Managing Construction

puddlejumper26 commented 4 years ago

Chapter 29 Integration

puddlejumper26 commented 4 years ago

Chapter 30 Programming Tools

puddlejumper26 commented 4 years ago

Chapter 31 Layout and Style

puddlejumper26 commented 4 years ago

Chapter 32 Self-Documenting Code

puddlejumper26 commented 4 years ago

Chapter 33 Personal Character

puddlejumper26 commented 4 years ago

Chapter 34 Themes in Software Craftsmanship

puddlejumper26 commented 4 years ago

Chapter 35 Where to Find More Information