Code Complete, 2nd Edition
Read it now on the O’Reilly learning platform with a 10-day free trial.
O’Reilly members get unlimited access to books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.
Book description
Widely considered one of the best practical guides to programming, Steve McConnell’s original CODE COMPLETE has been helping developers write better software for more than a decade. Now this classic book has been fully updated and revised with leading-edge practices—and hundreds of new code samples—illustrating the art and science of software construction. Capturing the body of knowledge available from research, academia, and everyday commercial practice, McConnell synthesizes the most effective techniques and must-know principles into clear, pragmatic guidance. No matter what your experience level, development environment, or project size, this book will inform and stimulate your thinking—and help you build the highest quality code.
Discover the timeless techniques and strategies that help you:
- Design for minimum complexity and maximum creativity
- Reap the benefits of collaborative development
- Apply defensive programming techniques to reduce and flush out errors
- Exploit opportunities to refactor—or evolve—code, and do it safely
- Use construction practices that are right-weight for your project
- Debug problems quickly and effectively
- Resolve critical construction issues early and correctly
- Build quality into the beginning, middle, and end of your project
Show and hide more
Table of contents Product information
Table of contents
- Code Complete, Second Edition
- Contents at a Glance
- Table of Contents
- Preface
- Who Should Read This Book?
- Experienced Programmers
- Technical Leads
- Self-Taught Programmers
- Students
- The Topic of Construction Has Been Neglected
- Construction Is Important
- No Comparable Book Is Available
- Steve McConnell
- 1. Welcome to Software Construction
- 1.1. What Is Software Construction?
- 1.2. Why Is Software Construction Important?
- 1.3. How to Read This Book
- Key Points
- 2.1. The Importance of Metaphors
- 2.2. How to Use Software Metaphors
- 2.3. Common Software Metaphors
- Software Penmanship: Writing Code
- Software Farming: Growing a System
- Software Oyster Farming: System Accretion
- Software Construction: Building Software
- Applying Software Techniques: The Intellectual Toolbox
- Combining Metaphors
- Additional Resources
- 3.1. Importance of Prerequisites
- Do Prerequisites Apply to Modern Software Projects?
- Causes of Incomplete Preparation
- Utterly Compelling and Foolproof Argument for Doing Prerequisites Before Construction
- Appeal to Logic
- Appeal to Analogy
- Appeal to Data
- Boss-Readiness Test
- Iterative Approaches' Effect on Prerequisites
- Choosing Between Iterative and Sequential Approaches
- Why Have Official Requirements?
- The Myth of Stable Requirements
- Handling Requirements Changes During Construction
- Typical Architectural Components
- Program Organization
- Major Classes
- Data Design
- Business Rules
- User Interface Design
- Resource Management
- Security
- Performance
- Scalability
- Interoperability
- Internationalization/Localization
- Input/Output
- Error Processing
- Fault Tolerance
- Architectural Feasibility
- Overengineering
- Buy-vs.-Build Decisions
- Reuse Decisions
- Change Strategy
- General Architectural Quality
- Requirements
- Software Architecture
- General Software-Development Approaches
- 4.1. Choice of Programming Language
- Language Descriptions
- Ada
- Assembly Language
- C
- C++
- C#
- Cobol
- Fortran
- Java
- JavaScript
- Perl
- PHP
- Python
- SQL
- Visual Basic
- Example of Programming into a Language
- 5. Design in Construction
- 5.1. Design Challenges
- Design Is a Wicked Problem
- Design Is a Sloppy Process (Even If it Produces a Tidy Result)
- Design Is About Tradeoffs and Priorities
- Design Involves Restrictions
- Design Is Nondeterministic
- Design Is a Heuristic Process
- Design Is Emergent
- Software's Primary Technical Imperative: Managing Complexity
- Accidental and Essential Difficulties
- Importance of Managing Complexity
- How to Attack Complexity
- Level 1: Software System
- Level 2: Division into Subsystems or Packages
- Level 3: Division into Classes
- Level 4: Division into Routines
- Level 5: Internal Routine Design
- Find Real-World Objects
- Form Consistent Abstractions
- Encapsulate Implementation Details
- Inherit—When Inheritance Simplifies the Design
- Hide Secrets (Information Hiding)
- Secrets and the Right to Privacy
- An Example of Information Hiding
- Two Categories of Secrets
- Barriers to Information Hiding
- Value of Information Hiding
- Anticipating Different Degrees of Change
- Coupling Criteria
- Kinds of Coupling
- 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
- Iterate
- Divide and Conquer
- Top-Down and Bottom-Up Design Approaches
- Argument for Top Down
- Argument for Bottom Up
- No Argument, Really
- Software Design, General
- Software Design Theory
- Design Patterns
- Design in General
- Standards
- 6.1. Class Foundations: Abstract Data Types (ADTs)
- Example of the Need for an ADT
- Benefits of Using ADTs
- More Examples of ADTs
- Handling Multiple Instances of Data with ADTs in Non-Object-Oriented Environments
- ADTs and Classes
- Good Abstraction
- Good Encapsulation
- Containment ("has a" Relationships)
- Inheritance ("is a" Relationships)
- Multiple Inheritance
- Why Are There So Many Rules for Inheritance?
- Classes to Avoid
- Summary of Reasons to Create a Class
- Classes in General
- C++
- Java
- Visual Basic
- 7.1. Valid Reasons to Create a Routine
- Operations That Seem Too Simple to Put Into Routines
- Summary of Reasons to Create a Routine
- When to Use a Function and When to Use a Procedure
- Setting the Function's Return Value
- Limitations on the Use of Macro Routines
- Inline Routines
- 8.1. Protecting Your Program from Invalid Inputs
- 8.2. Assertions
- Building Your Own Assertion Mechanism
- Guidelines for Using Assertions
- Robustness vs. Correctness
- High-Level Design Implications of Error Processing
- Relationship Between Barricades and Assertions
- Don't Automatically Apply Production Constraints to the Development Version
- Introduce Debugging Aids Early
- Use Offensive Programming
- Plan to Remove Debugging Aids
- Security
- Assertions
- Exceptions
- 9.1. Summary of Steps in Building Classes and Routines
- Steps in Creating a Class
- Steps in Building a Routine
- Design the Routine
- Code the Routine
- Check the Code
- Clean Up Leftovers
- Repeat Steps as Needed
- 10. General Issues in Using Variables
- 10.1. Data Literacy
- The Data Literacy Test
- Additional Resources on Data Types
- Implicit Declarations
- Localize References to Variables
- Keep Variables "Live" for as Short a Time as Possible
- Measuring the Live Time of a Variable
- 11.1. Considerations in Choosing Good Names
- The Most Important Naming Consideration
- Problem Orientation
- Optimum Name Length
- The Effect of Scope on Variable Names
- Computed-Value Qualifiers in Variable Names
- Common Opposites in Variable Names
- Naming Loop Indexes
- Naming Status Variables
- Naming Temporary Variables
- Naming Boolean Variables
- Naming Enumerated Types
- Naming Constants
- Why Have Conventions?
- When You Should Have a Naming Convention
- Degrees of Formality
- Guidelines for a Language-Independent Convention
- Guidelines for Language-Specific Conventions
- C Conventions
- C++ Conventions
- Java Conventions
- Visual Basic Conventions
- User-Defined Type Abbreviations
- Semantic Prefixes
- Advantages of Standardized Prefixes
- General Abbreviation Guidelines
- Phonetic Abbreviations
- Comments on Abbreviations
- 12.1. Numbers in General
- 12.2. Integers
- 12.3. Floating-Point Numbers
- 12.4. Characters and Strings
- Strings in C
- If Your Language Doesn't Have Enumerated Types
- Why Are the Examples of Creating Your Own Types in Pascal and Ada?
- Guidelines for Creating Your Own Types
- 13.1. Structures
- 13.2. Pointers
- Paradigm for Understanding Pointers
- Location in Memory
- Knowledge of How to Interpret the Contents
- Common Problems with Global Data
- Reasons to Use Global Data
- Use Global Data Only as a Last Resort
- Using Access Routines Instead of Global Data
- Advantages of Access Routines
- How to Use Access Routines
- 14. Organizing Straight-Line Code
- 14.1. Statements That Must Be in a Specific Order
- 14.2. Statements Whose Order Doesn't Matter
- Making Code Read from Top to Bottom
- Grouping Related Statements
- 15.1. if Statements
- Plain if-then Statements
- Chains of if-then-else Statements
- Choosing the Most Effective Ordering of Cases
- Tips for Using case Statements
- 16.1. Selecting the Kind of Loop
- When to Use a while Loop
- Loop with Test at the Beginning
- Loop with Test at the End
- Normal Loop-With-Exit Loops
- Abnormal Loop-With-Exit Loops
- Entering the Loop
- Processing the Middle of the Loop
- Exiting the Loop
- Exiting Loops Early
- 17.1. Multiple Returns from a Routine
- 17.2. Recursion
- Example of Recursion
- Tips for Using Recursion
- The Argument Against gotos
- The Argument for gotos
- The Phony goto Debate
- Error Processing and gotos
- Comparison of the Approaches
- Returns
- gotos
- 18.1. General Considerations in Using Table-Driven Methods
- Two Issues in Using Table-Driven Methods
- Days-in-Month Example
- Insurance Rates Example
- Flexible-Message-Format Example
- Logic-Based Approach
- Object-Oriented Approach
- Table-Driven Approach
- Fudging Lookup Keys
- 19.1. Boolean Expressions
- Using true and false for Boolean Tests
- Making Complicated Expressions Simple
- Forming Boolean Expressions Positively
- Using Parentheses to Clarify Boolean Expressions
- Knowing How Boolean Expressions Are Evaluated
- Writing Numeric Expressions in Number-Line Order
- Guidelines for Comparisons to 0
- Common Problems with Boolean Expressions
- Summary of Techniques for Reducing Deep Nesting
- The Three Components of Structured Programming
- Sequence
- Selection
- Iteration
- How Important Is Complexity?
- General Guidelines for Reducing Complexity
- How to Measure Complexity
- What to Do with Your Complexity Measurement
- 20. The Software-Quality Landscape
- 20.1. Characteristics of Software Quality
- 20.2. Techniques for Improving Software Quality
- Development Process
- Setting Objectives
- Percentage of Defects Detected
- Cost of Finding Defects
- Cost of Fixing Defects
- Relevant Standards
- 21.1. Overview of Collaborative Development Practices
- Collaborative Construction Complements Other Quality-Assurance Techniques
- Collaborative Construction Provides Mentoring in Corporate Culture and Programming Expertise
- Collective Ownership Applies to All Forms of Collaborative Construction
- Collaboration Applies As Much Before Construction As After
- Keys to Success with Pair Programming
- Benefits of Pair Programming
- What Results Can You Expect from Inspections?
- Roles During an Inspection
- General Procedure for an Inspection
- Fine-Tuning the Inspection
- Walk-Throughs
- What Results Can You Expect from a Walk-Through?
- Pair Programming
- Inspections
- Relevant Standards
- 22.1. Role of Developer Testing in Software Quality
- Testing During Construction
- Test First or Test Last?
- Limitations of Developer Testing
- Incomplete Testing
- Structured Basis Testing
- Data-Flow Testing
- Combinations of Data States
- Compound Boundaries
- Which Classes Contain the Most Errors?
- Errors by Classification
- Proportion of Errors Resulting from Faulty Construction
- How Many Errors Should You Expect to Find?
- Errors in Testing Itself
- Building Scaffolding to Test Individual Classes
- Diff Tools
- Test-Data Generators
- Coverage Monitors
- Data Recorder/Logging
- Symbolic Debuggers
- System Perturbers
- Error Databases
- Planning to Test
- Retesting (Regression Testing)
- Automated Testing
- Personal Test Records
- Additional Resources
- Testing
- Test Scaffolding
- Test First Development
- Relevant Standards
- 23.1. Overview of Debugging Issues
- Role of Debugging in Software Quality
- Variations in Debugging Performance
- Defects as Opportunities
- An Ineffective Approach
- The Devil's Guide to Debugging
- Debugging by Superstition
- The Scientific Method of Debugging
- Stabilize the Error
- Locate the Source of the Error
- Brute-Force Debugging
- How "Psychological Set" Contributes to Debugging Blindness
- How "Psychological Distance" Can Help
- Source-Code Comparators
- Compiler Warning Messages
- Extended Syntax and Logic Checking
- Execution Profilers
- Test Frameworks/Scaffolding
- Debuggers
- 24.1. Kinds of Software Evolution
- Philosophy of Software Evolution
- Reasons to Refactor
- Reasons Not to Refactor
- Data-Level Refactorings
- Statement-Level Refactorings
- Routine-Level Refactorings
- Class Implementation Refactorings
- Class Interface Refactorings
- System-Level Refactorings
- Bad Times to Refactor
- 25.1. Performance Overview
- Quality Characteristics and Performance
- Performance and Code Tuning
- Program Requirements
- Program Design
- Class and Routine Design
- Operating-System Interactions
- Code Compilation
- Hardware
- Code Tuning
- The Pareto Principle
- Old Wives' Tales
- When to Tune
- Compiler Optimizations
- Common Sources of Inefficiency
- Relative Performance Costs of Common Operations
- Measurements Need to Be Precise
- Performance
- Algorithms and Data Types
- 26.1. Logic
- Stop Testing When You Know the Answer
- Order Tests by Frequency
- Compare Performance of Similar Logic Structures
- Substitute Table Lookups for Complicated Expressions
- Use Lazy Evaluation
- Unswitching
- Jamming
- Unrolling
- Minimizing the Work Inside Loops
- Sentinel Values
- Putting the Busiest Loop on the Inside
- Strength Reduction
- Use Integers Rather Than Floating-Point Numbers
- Use the Fewest Array Dimensions Possible
- Minimize Array References
- Use Supplementary Indexes
- String-Length Index
- Independent, Parallel Index Structure
- Exploit Algebraic Identities
- Use Strength Reduction
- Initialize at Compile Time
- Be Wary of System Routines
- Use the Correct Type of Constants
- Precompute Results
- Eliminate Common Subexpressions
- Rewrite Routines Inline
- 27. How Program Size Affects Construction
- 27.1. Communication and Size
- 27.2. Range of Project Sizes
- 27.3. Effect of Project Size on Errors
- 27.4. Effect of Project Size on Productivity
- 27.5. Effect of Project Size on Development Activities
- Activity Proportions and Size
- Programs, Products, Systems, and System Products
- Methodology and Size
- 28.1. Encouraging Good Coding
- Considerations in Setting Standards
- Techniques for Encouraging Good Coding
- The Role of This Book
- What Is Configuration Management?
- Requirements and Design Changes
- Software Code Changes
- Tool Versions
- Machine Configurations
- Backup Plan
- Additional Resources on Configuration Management
- Estimation Approaches
- Estimating the Amount of Construction
- Influences on Schedule
- Estimation vs. Control
- What to Do If You're Behind
- Additional Resources on Software Estimation
- Additional Resources on Software Measurement
- How Do Programmers Spend Their Time?
- Variation in Performance and Quality
- Individual Variation
- Team Variation
- Additional Resources on Managing Construction
- Relevant Standards
- 29.1. Importance of the Integration Approach
- 29.2. Integration Frequency—Phased or Incremental?
- Phased Integration
- Incremental Integration
- Benefits of Incremental Integration
- Top-Down Integration
- Bottom-Up Integration
- Sandwich Integration
- Risk-Oriented Integration
- Feature-Oriented Integration
- T-Shaped Integration
- Summary of Integration Approaches
- What Kinds of Projects Can Use the Daily Build Process?
- Continuous Integration
- Integration
- Incrementalism
- 30.1. Design Tools
- 30.2. Source-Code Tools
- Editing
- Integrated Development Environments (IDEs)
- Multiple-File String Searching and Replacing
- Diff Tools
- Merge Tools
- Source-Code Beautifiers
- Interface Documentation Tools
- Templates
- Cross-Reference Tools
- Class Hierarchy Generators
- Picky Syntax and Semantics Checkers
- Metrics Reporters
- Refactorers
- Restructurers
- Code Translators
- Code Creation
- Compilers and Linkers
- Build Tools
- Code Libraries
- Code-Generation Wizards
- Setup and Installation
- Preprocessors
- Execution Profilers
- Assembler Listings and Disassemblers
- Project-Specific Tools
- Scripts
- 31. Layout and Style
- 31.1. Layout Fundamentals
- Layout Extremes
- The Fundamental Theorem of Formatting
- Human and Computer Interpretations of a Program
- How Much Is Good Layout Worth?
- Layout as Religion
- Objectives of Good Layout
- How to Put the Layout Objectives to Use
- White Space
- Parentheses
- Pure Blocks
- Emulating Pure Blocks
- Using begin-end Pairs (Braces) to Designate Block Boundaries
- Endline Layout
- Which Style Is Best?
- Fine Points of Formatting Control-Structure Blocks
- Other Considerations
- Statement Length
- Using Spaces for Clarity
- Formatting Continuation Lines
- Using Only One Statement Per Line
- Laying Out Data Declarations
- Laying Out Class Interfaces
- Laying Out Class Implementations
- Laying Out Files and Programs
- 32.1. External Documentation
- 32.2. Programming Style as Documentation
- 32.3. To Comment or Not to Comment
- 32.4. Keys to Effective Comments
- Kinds of Comments
- Repeat of the Code
- Explanation of the Code
- Marker in the Code
- Summary of the Code
- Description of the Code's Intent
- Information That Cannot Possibly Be Expressed by the Code Itself
- Commenting Individual Lines
- Endline Comments and Their Problems
- When to Use Endline Comments
- General Guidelines for Class Documentation
- General Guidelines for File Documentation
- The Book Paradigm for Program Documentation
- Software-Development Standards
- Software Quality-Assurance Standards
- Management Standards
- Overview of Standards
- 33.1. Isn't Personal Character Off the Topic?
- 33.2. Intelligence and Humility
- 33.3. Curiosity
- 33.4. Intellectual Honesty
- 33.5. Communication and Cooperation
- 33.6. Creativity and Discipline
- 33.7. Laziness
- 33.8. Characteristics That Don't Matter As Much As You Might Think
- Persistence
- Experience
- Gonzo Programming
- 34.1. Conquer Complexity
- 34.2. Pick Your Process
- 34.3. Write Programs for People First, Computers Second
- 34.4. Program into Your Language, Not in It
- 34.5. Focus Your Attention with the Help of Conventions
- 34.6. Program in Terms of the Problem Domain
- Separating a Program into Levels of Abstraction
- Level 0: Operating-System Operations and Machine Instructions
- Level 1: Programming-Language Structures and Tools
- Level 2: Low-Level Implementation Structures
- Level 3: Low-Level Problem-Domain Terms
- Level 4: High-Level Problem-Domain Terms
- Software Oracles
- Eclecticism
- Experimentation
- 35.1. Information About Software Construction
- 35.2. Topics Beyond Construction
- Overview Material
- Software-Engineering Overviews
- Other Annotated Bibliographies
- Lowbrow Programmer Magazines
- Highbrow Programmer Journals
- Special-Interest Publications
- Professional Publications
- Popular-Market Publications
- Introductory Level
- Practitioner Level
- Professional Level
Show and hide more
Product information
- Title: Code Complete, 2nd Edition
- Author(s): Steve McConnell
- Release date: June 2004
- Publisher(s): Cisco Press
- ISBN: 9780735619678