- Broschiertes Buch
- Merkliste
- Auf die Merkliste
- Bewerten Bewerten
- Teilen
- Produkt teilen
- Produkterinnerung
- Produkterinnerung
As programmers, we've all seen source code that's so ugly and buggy it makes our brain ache. Over the past five years, authors Dustin Boswell and Trevor Foucher have analyzed hundreds of examples of "bad code" (much of it their own) to determine why they're bad and how they could be improved. Their conclusion? You need to write code that minimizes the time it would take someone else to understand it - even if that someone else is you. This book focuses on basic principles and practical techniques you can apply every time you write code. Using easy-to-digest code examples from different…mehr
Andere Kunden interessierten sich auch für
- Curt HibbsThe Art of Lean Software Development37,99 €
- Karl FogelProducing Open Source Software21,99 €
- Benny KokBeginning Unity Editor Scripting44,99 €
- Finding Source Code on the Web for Remix and Reuse74,99 €
- Stéphane FaroultThe Art of SQL47,99 €
- Travis SwicegoodPragmatic Version Control Using Git29,99 €
- Andy OramMaking Software47,99 €
-
-
-
As programmers, we've all seen source code that's so ugly and buggy it makes our brain ache. Over the past five years, authors Dustin Boswell and Trevor Foucher have analyzed hundreds of examples of "bad code" (much of it their own) to determine why they're bad and how they could be improved. Their conclusion? You need to write code that minimizes the time it would take someone else to understand it - even if that someone else is you.
This book focuses on basic principles and practical techniques you can apply every time you write code. Using easy-to-digest code examples from different languages, each chapter dives into a different aspect of coding, and demonstrates how you can make your code easy to understand. Simplify naming, commenting, and formatting with tips that apply to every line of code Refine your program's loops, logic, and variables to reduce complexity and confusion Attack problems at the function level, such as reorganizing blocks of code to do one task at a time Write effective test code that is thorough and concise - as well as readable
"Being aware of how the code you create affects those who look at it later is an important part of developing software. The authors did a great job in taking you through the different aspects of this challenge, explaining the details with instructive examples." - Michael Hunger, passionate Software Developer
This book focuses on basic principles and practical techniques you can apply every time you write code. Using easy-to-digest code examples from different languages, each chapter dives into a different aspect of coding, and demonstrates how you can make your code easy to understand. Simplify naming, commenting, and formatting with tips that apply to every line of code Refine your program's loops, logic, and variables to reduce complexity and confusion Attack problems at the function level, such as reorganizing blocks of code to do one task at a time Write effective test code that is thorough and concise - as well as readable
"Being aware of how the code you create affects those who look at it later is an important part of developing software. The authors did a great job in taking you through the different aspects of this challenge, explaining the details with instructive examples." - Michael Hunger, passionate Software Developer
Produktdetails
- Produktdetails
- Theory In Practice
- Verlag: O'Reilly Media
- Seitenzahl: 300
- Erscheinungstermin: 20. Dezember 2011
- Englisch
- Abmessung: 232mm x 180mm x 18mm
- Gewicht: 350g
- ISBN-13: 9780596802295
- ISBN-10: 0596802293
- Artikelnr.: 29612423
- Theory In Practice
- Verlag: O'Reilly Media
- Seitenzahl: 300
- Erscheinungstermin: 20. Dezember 2011
- Englisch
- Abmessung: 232mm x 180mm x 18mm
- Gewicht: 350g
- ISBN-13: 9780596802295
- ISBN-10: 0596802293
- Artikelnr.: 29612423
Although raised in the circus, Dustin Boswell realized early on that he was better at computers than at acrobatics. Dustin received his B.S. from CalTech, where he got hooked on Computer Science, and then went to UC San Diego for his Master's Degree. He worked at Google for five years, on a variety of projects including web crawling infrastructure. Dustin is now an internet startup junkie who spends his free time hiking the Santa Monica mountains and being a new dad. Trevor Foucher has been shipping software projects for over 10 years, including Windows 2000 and OneCare at Microsoft, and Webmaster Tools at Google. He's been an individual contributor, manager, and tech lead. His goal is to make code more readable and reliable.
Preface
What This Book Is About
How to Read This Book
Using Code Examples
Safari® Books Online
How to Contact Us
Acknowledgments
Chapter 1: Code Should Be Easy to Understand
1.1 What Makes Code "Better"?
1.2 The Fundamental Theorem of Readability
1.3 Is Smaller Always Better?
1.4 Does Time-Till-Understanding Conflict with Other Goals?
1.5 The Hard Part
Surface-Level Improvements
Chapter 2: Packing Information into Names
2.1 Choose Specific Words
2.2 Avoid Generic Names Like tmp and retval
2.3 Prefer Concrete Names over Abstract Names
2.4 Attaching Extra Information to a Name
2.5 How Long Should a Name Be?
2.6 Use Name Formatting to Convey Meaning
2.7 Summary
Chapter 3: Names That Can't Be Misconstrued
3.1 Example: Filter()
3.2 Example: Clip(text, length)
3.3 Prefer min and max for (Inclusive) Limits
3.4 Prefer first and last for Inclusive Ranges
3.5 Prefer begin and end for Inclusive/Exclusive Ranges
3.6 Naming Booleans
3.7 Matching Expectations of Users
3.8 Example: Evaluating Multiple Name Candidates
3.9 Summary
Chapter 4: Aesthetics
4.1 Why Do Aesthetics Matter?
4.2 Rearrange Line Breaks to Be Consistent and Compact
4.3 Use Methods to Clean Up Irregularity
4.4 Use Column Alignment When Helpful
4.5 Pick a Meaningful Order, and Use It Consistently
4.6 Organize Declarations into Blocks
4.7 Break Code into "Paragraphs"
4.8 Personal Style versus Consistency
4.9 Summary
Chapter 5: Knowing What to Comment
5.1 What NOT to Comment
5.2 Recording Your Thoughts
5.3 Put Yourself in the Reader's Shoes
5.4 Final Thoughts-Getting Over Writer's Block
5.5 Summary
Chapter 6: Making Comments Precise and Compact
6.1 Keep Comments Compact
6.2 Avoid Ambiguous Pronouns
6.3 Polish Sloppy Sentences
6.4 Describe Function Behavior Precisely
6.5 Use Input/Output Examples That Illustrate Corner Cases
6.6 State the Intent of Your Code
6.7 "Named Function Parameter" Comments
6.8 Use Information-Dense Words
6.9 Summary
Simplifying Loops and Logic
Chapter 7: Making Control Flow Easy to Read
7.1 The Order of Arguments in Conditionals
7.2 The Order of if/else Blocks
7.3 The ?: Conditional Expression (a.k.a. "Ternary Operator")
7.4 Avoid do/while Loops
7.5 Returning Early from a Function
7.6 The Infamous goto
7.7 Minimize Nesting
7.8 Can You Follow the Flow of Execution?
7.9 Summary
Chapter 8: Breaking Down Giant Expressions
8.1 Explaining Variables
8.2 Summary Variables
8.3 Using De Morgan's Laws
8.4 Abusing Short-Circuit Logic
8.5 Example: Wrestling with Complicated Logic
8.6 Breaking Down Giant Statements
8.7 Another Creative Way to Simplify Expressions
8.8 Summary
Chapter 9: Variables and Readability
9.1 Eliminating Variables
9.2 Shrink the Scope of Your Variables
9.3 Prefer Write-Once Variables
9.4 A Final Example
9.5 Summary
Reorganizing Your Code
Chapter 10: Extracting Unrelated Subproblems
10.1 Introductory Example: findClosestLocation()
10.2 Pure Utility Code
10.3 Other General-Purpose Code
10.4 Create a Lot of General-Purpose Code
10.5 Project-Specific Functionality
10.6 Simplifying an Existing Interface
10.7 Reshaping an Interface to Your Needs
10.8 Taking Things Too Far
10.9 Summary
Chapter 11: One Task at a Time
11.1 Tasks Can Be Small
11.2 Extracting Values from an Object
11.3 A Larger Example
11.4 Summary
Chapter 12: Turning Thoughts into Code
12.1 Describing Logic Clearly
12.2 Knowing Your Libraries Helps
12.3 Applying This Method to Larger Problems
12.4 Summary
Chapter 13: Writing Less Code
13.1 Don't Bother Implementing That Feature-You Won't Need It
13.2 Question and Break Down Your Requirements
13.3 Keeping Your Codebase Small
13.4 Be Familiar with the Libraries Around You
13.5 Example: Using Unix Tools Instead of Coding
13.6 Summary
Selected Topics
Chapter 14: Testing and Readability
14.1 Make Tests Easy to Read and Maintain
14.2 What's Wrong with This Test?
14.3 Making This Test More Readable
14.4 Making Error Messages Readable
14.5 Choosing Good Test Inputs
14.6 Naming Test Functions
14.7 What Was Wrong with That Test?
14.8 Test-Friendly Development
14.9 Going Too Far
14.10 Summary
Chapter 15: Designing and Implementing a "Minute/Hour Counter"
15.1 The Problem
15.2 Defining the Class Interface
15.3 Attempt 1: A Naive Solution
15.4 Attempt 2: Conveyor Belt Design
15.5 Attempt 3: A Time-Bucketed Design
15.6 Comparing the Three Solutions
15.7 Summary
Further Reading
Books on Writing High-Quality Code
Books on Various Programming Topics
Books of Historical Note
Colophon
What This Book Is About
How to Read This Book
Using Code Examples
Safari® Books Online
How to Contact Us
Acknowledgments
Chapter 1: Code Should Be Easy to Understand
1.1 What Makes Code "Better"?
1.2 The Fundamental Theorem of Readability
1.3 Is Smaller Always Better?
1.4 Does Time-Till-Understanding Conflict with Other Goals?
1.5 The Hard Part
Surface-Level Improvements
Chapter 2: Packing Information into Names
2.1 Choose Specific Words
2.2 Avoid Generic Names Like tmp and retval
2.3 Prefer Concrete Names over Abstract Names
2.4 Attaching Extra Information to a Name
2.5 How Long Should a Name Be?
2.6 Use Name Formatting to Convey Meaning
2.7 Summary
Chapter 3: Names That Can't Be Misconstrued
3.1 Example: Filter()
3.2 Example: Clip(text, length)
3.3 Prefer min and max for (Inclusive) Limits
3.4 Prefer first and last for Inclusive Ranges
3.5 Prefer begin and end for Inclusive/Exclusive Ranges
3.6 Naming Booleans
3.7 Matching Expectations of Users
3.8 Example: Evaluating Multiple Name Candidates
3.9 Summary
Chapter 4: Aesthetics
4.1 Why Do Aesthetics Matter?
4.2 Rearrange Line Breaks to Be Consistent and Compact
4.3 Use Methods to Clean Up Irregularity
4.4 Use Column Alignment When Helpful
4.5 Pick a Meaningful Order, and Use It Consistently
4.6 Organize Declarations into Blocks
4.7 Break Code into "Paragraphs"
4.8 Personal Style versus Consistency
4.9 Summary
Chapter 5: Knowing What to Comment
5.1 What NOT to Comment
5.2 Recording Your Thoughts
5.3 Put Yourself in the Reader's Shoes
5.4 Final Thoughts-Getting Over Writer's Block
5.5 Summary
Chapter 6: Making Comments Precise and Compact
6.1 Keep Comments Compact
6.2 Avoid Ambiguous Pronouns
6.3 Polish Sloppy Sentences
6.4 Describe Function Behavior Precisely
6.5 Use Input/Output Examples That Illustrate Corner Cases
6.6 State the Intent of Your Code
6.7 "Named Function Parameter" Comments
6.8 Use Information-Dense Words
6.9 Summary
Simplifying Loops and Logic
Chapter 7: Making Control Flow Easy to Read
7.1 The Order of Arguments in Conditionals
7.2 The Order of if/else Blocks
7.3 The ?: Conditional Expression (a.k.a. "Ternary Operator")
7.4 Avoid do/while Loops
7.5 Returning Early from a Function
7.6 The Infamous goto
7.7 Minimize Nesting
7.8 Can You Follow the Flow of Execution?
7.9 Summary
Chapter 8: Breaking Down Giant Expressions
8.1 Explaining Variables
8.2 Summary Variables
8.3 Using De Morgan's Laws
8.4 Abusing Short-Circuit Logic
8.5 Example: Wrestling with Complicated Logic
8.6 Breaking Down Giant Statements
8.7 Another Creative Way to Simplify Expressions
8.8 Summary
Chapter 9: Variables and Readability
9.1 Eliminating Variables
9.2 Shrink the Scope of Your Variables
9.3 Prefer Write-Once Variables
9.4 A Final Example
9.5 Summary
Reorganizing Your Code
Chapter 10: Extracting Unrelated Subproblems
10.1 Introductory Example: findClosestLocation()
10.2 Pure Utility Code
10.3 Other General-Purpose Code
10.4 Create a Lot of General-Purpose Code
10.5 Project-Specific Functionality
10.6 Simplifying an Existing Interface
10.7 Reshaping an Interface to Your Needs
10.8 Taking Things Too Far
10.9 Summary
Chapter 11: One Task at a Time
11.1 Tasks Can Be Small
11.2 Extracting Values from an Object
11.3 A Larger Example
11.4 Summary
Chapter 12: Turning Thoughts into Code
12.1 Describing Logic Clearly
12.2 Knowing Your Libraries Helps
12.3 Applying This Method to Larger Problems
12.4 Summary
Chapter 13: Writing Less Code
13.1 Don't Bother Implementing That Feature-You Won't Need It
13.2 Question and Break Down Your Requirements
13.3 Keeping Your Codebase Small
13.4 Be Familiar with the Libraries Around You
13.5 Example: Using Unix Tools Instead of Coding
13.6 Summary
Selected Topics
Chapter 14: Testing and Readability
14.1 Make Tests Easy to Read and Maintain
14.2 What's Wrong with This Test?
14.3 Making This Test More Readable
14.4 Making Error Messages Readable
14.5 Choosing Good Test Inputs
14.6 Naming Test Functions
14.7 What Was Wrong with That Test?
14.8 Test-Friendly Development
14.9 Going Too Far
14.10 Summary
Chapter 15: Designing and Implementing a "Minute/Hour Counter"
15.1 The Problem
15.2 Defining the Class Interface
15.3 Attempt 1: A Naive Solution
15.4 Attempt 2: Conveyor Belt Design
15.5 Attempt 3: A Time-Bucketed Design
15.6 Comparing the Three Solutions
15.7 Summary
Further Reading
Books on Writing High-Quality Code
Books on Various Programming Topics
Books of Historical Note
Colophon
Preface
What This Book Is About
How to Read This Book
Using Code Examples
Safari® Books Online
How to Contact Us
Acknowledgments
Chapter 1: Code Should Be Easy to Understand
1.1 What Makes Code "Better"?
1.2 The Fundamental Theorem of Readability
1.3 Is Smaller Always Better?
1.4 Does Time-Till-Understanding Conflict with Other Goals?
1.5 The Hard Part
Surface-Level Improvements
Chapter 2: Packing Information into Names
2.1 Choose Specific Words
2.2 Avoid Generic Names Like tmp and retval
2.3 Prefer Concrete Names over Abstract Names
2.4 Attaching Extra Information to a Name
2.5 How Long Should a Name Be?
2.6 Use Name Formatting to Convey Meaning
2.7 Summary
Chapter 3: Names That Can't Be Misconstrued
3.1 Example: Filter()
3.2 Example: Clip(text, length)
3.3 Prefer min and max for (Inclusive) Limits
3.4 Prefer first and last for Inclusive Ranges
3.5 Prefer begin and end for Inclusive/Exclusive Ranges
3.6 Naming Booleans
3.7 Matching Expectations of Users
3.8 Example: Evaluating Multiple Name Candidates
3.9 Summary
Chapter 4: Aesthetics
4.1 Why Do Aesthetics Matter?
4.2 Rearrange Line Breaks to Be Consistent and Compact
4.3 Use Methods to Clean Up Irregularity
4.4 Use Column Alignment When Helpful
4.5 Pick a Meaningful Order, and Use It Consistently
4.6 Organize Declarations into Blocks
4.7 Break Code into "Paragraphs"
4.8 Personal Style versus Consistency
4.9 Summary
Chapter 5: Knowing What to Comment
5.1 What NOT to Comment
5.2 Recording Your Thoughts
5.3 Put Yourself in the Reader's Shoes
5.4 Final Thoughts-Getting Over Writer's Block
5.5 Summary
Chapter 6: Making Comments Precise and Compact
6.1 Keep Comments Compact
6.2 Avoid Ambiguous Pronouns
6.3 Polish Sloppy Sentences
6.4 Describe Function Behavior Precisely
6.5 Use Input/Output Examples That Illustrate Corner Cases
6.6 State the Intent of Your Code
6.7 "Named Function Parameter" Comments
6.8 Use Information-Dense Words
6.9 Summary
Simplifying Loops and Logic
Chapter 7: Making Control Flow Easy to Read
7.1 The Order of Arguments in Conditionals
7.2 The Order of if/else Blocks
7.3 The ?: Conditional Expression (a.k.a. "Ternary Operator")
7.4 Avoid do/while Loops
7.5 Returning Early from a Function
7.6 The Infamous goto
7.7 Minimize Nesting
7.8 Can You Follow the Flow of Execution?
7.9 Summary
Chapter 8: Breaking Down Giant Expressions
8.1 Explaining Variables
8.2 Summary Variables
8.3 Using De Morgan's Laws
8.4 Abusing Short-Circuit Logic
8.5 Example: Wrestling with Complicated Logic
8.6 Breaking Down Giant Statements
8.7 Another Creative Way to Simplify Expressions
8.8 Summary
Chapter 9: Variables and Readability
9.1 Eliminating Variables
9.2 Shrink the Scope of Your Variables
9.3 Prefer Write-Once Variables
9.4 A Final Example
9.5 Summary
Reorganizing Your Code
Chapter 10: Extracting Unrelated Subproblems
10.1 Introductory Example: findClosestLocation()
10.2 Pure Utility Code
10.3 Other General-Purpose Code
10.4 Create a Lot of General-Purpose Code
10.5 Project-Specific Functionality
10.6 Simplifying an Existing Interface
10.7 Reshaping an Interface to Your Needs
10.8 Taking Things Too Far
10.9 Summary
Chapter 11: One Task at a Time
11.1 Tasks Can Be Small
11.2 Extracting Values from an Object
11.3 A Larger Example
11.4 Summary
Chapter 12: Turning Thoughts into Code
12.1 Describing Logic Clearly
12.2 Knowing Your Libraries Helps
12.3 Applying This Method to Larger Problems
12.4 Summary
Chapter 13: Writing Less Code
13.1 Don't Bother Implementing That Feature-You Won't Need It
13.2 Question and Break Down Your Requirements
13.3 Keeping Your Codebase Small
13.4 Be Familiar with the Libraries Around You
13.5 Example: Using Unix Tools Instead of Coding
13.6 Summary
Selected Topics
Chapter 14: Testing and Readability
14.1 Make Tests Easy to Read and Maintain
14.2 What's Wrong with This Test?
14.3 Making This Test More Readable
14.4 Making Error Messages Readable
14.5 Choosing Good Test Inputs
14.6 Naming Test Functions
14.7 What Was Wrong with That Test?
14.8 Test-Friendly Development
14.9 Going Too Far
14.10 Summary
Chapter 15: Designing and Implementing a "Minute/Hour Counter"
15.1 The Problem
15.2 Defining the Class Interface
15.3 Attempt 1: A Naive Solution
15.4 Attempt 2: Conveyor Belt Design
15.5 Attempt 3: A Time-Bucketed Design
15.6 Comparing the Three Solutions
15.7 Summary
Further Reading
Books on Writing High-Quality Code
Books on Various Programming Topics
Books of Historical Note
Colophon
What This Book Is About
How to Read This Book
Using Code Examples
Safari® Books Online
How to Contact Us
Acknowledgments
Chapter 1: Code Should Be Easy to Understand
1.1 What Makes Code "Better"?
1.2 The Fundamental Theorem of Readability
1.3 Is Smaller Always Better?
1.4 Does Time-Till-Understanding Conflict with Other Goals?
1.5 The Hard Part
Surface-Level Improvements
Chapter 2: Packing Information into Names
2.1 Choose Specific Words
2.2 Avoid Generic Names Like tmp and retval
2.3 Prefer Concrete Names over Abstract Names
2.4 Attaching Extra Information to a Name
2.5 How Long Should a Name Be?
2.6 Use Name Formatting to Convey Meaning
2.7 Summary
Chapter 3: Names That Can't Be Misconstrued
3.1 Example: Filter()
3.2 Example: Clip(text, length)
3.3 Prefer min and max for (Inclusive) Limits
3.4 Prefer first and last for Inclusive Ranges
3.5 Prefer begin and end for Inclusive/Exclusive Ranges
3.6 Naming Booleans
3.7 Matching Expectations of Users
3.8 Example: Evaluating Multiple Name Candidates
3.9 Summary
Chapter 4: Aesthetics
4.1 Why Do Aesthetics Matter?
4.2 Rearrange Line Breaks to Be Consistent and Compact
4.3 Use Methods to Clean Up Irregularity
4.4 Use Column Alignment When Helpful
4.5 Pick a Meaningful Order, and Use It Consistently
4.6 Organize Declarations into Blocks
4.7 Break Code into "Paragraphs"
4.8 Personal Style versus Consistency
4.9 Summary
Chapter 5: Knowing What to Comment
5.1 What NOT to Comment
5.2 Recording Your Thoughts
5.3 Put Yourself in the Reader's Shoes
5.4 Final Thoughts-Getting Over Writer's Block
5.5 Summary
Chapter 6: Making Comments Precise and Compact
6.1 Keep Comments Compact
6.2 Avoid Ambiguous Pronouns
6.3 Polish Sloppy Sentences
6.4 Describe Function Behavior Precisely
6.5 Use Input/Output Examples That Illustrate Corner Cases
6.6 State the Intent of Your Code
6.7 "Named Function Parameter" Comments
6.8 Use Information-Dense Words
6.9 Summary
Simplifying Loops and Logic
Chapter 7: Making Control Flow Easy to Read
7.1 The Order of Arguments in Conditionals
7.2 The Order of if/else Blocks
7.3 The ?: Conditional Expression (a.k.a. "Ternary Operator")
7.4 Avoid do/while Loops
7.5 Returning Early from a Function
7.6 The Infamous goto
7.7 Minimize Nesting
7.8 Can You Follow the Flow of Execution?
7.9 Summary
Chapter 8: Breaking Down Giant Expressions
8.1 Explaining Variables
8.2 Summary Variables
8.3 Using De Morgan's Laws
8.4 Abusing Short-Circuit Logic
8.5 Example: Wrestling with Complicated Logic
8.6 Breaking Down Giant Statements
8.7 Another Creative Way to Simplify Expressions
8.8 Summary
Chapter 9: Variables and Readability
9.1 Eliminating Variables
9.2 Shrink the Scope of Your Variables
9.3 Prefer Write-Once Variables
9.4 A Final Example
9.5 Summary
Reorganizing Your Code
Chapter 10: Extracting Unrelated Subproblems
10.1 Introductory Example: findClosestLocation()
10.2 Pure Utility Code
10.3 Other General-Purpose Code
10.4 Create a Lot of General-Purpose Code
10.5 Project-Specific Functionality
10.6 Simplifying an Existing Interface
10.7 Reshaping an Interface to Your Needs
10.8 Taking Things Too Far
10.9 Summary
Chapter 11: One Task at a Time
11.1 Tasks Can Be Small
11.2 Extracting Values from an Object
11.3 A Larger Example
11.4 Summary
Chapter 12: Turning Thoughts into Code
12.1 Describing Logic Clearly
12.2 Knowing Your Libraries Helps
12.3 Applying This Method to Larger Problems
12.4 Summary
Chapter 13: Writing Less Code
13.1 Don't Bother Implementing That Feature-You Won't Need It
13.2 Question and Break Down Your Requirements
13.3 Keeping Your Codebase Small
13.4 Be Familiar with the Libraries Around You
13.5 Example: Using Unix Tools Instead of Coding
13.6 Summary
Selected Topics
Chapter 14: Testing and Readability
14.1 Make Tests Easy to Read and Maintain
14.2 What's Wrong with This Test?
14.3 Making This Test More Readable
14.4 Making Error Messages Readable
14.5 Choosing Good Test Inputs
14.6 Naming Test Functions
14.7 What Was Wrong with That Test?
14.8 Test-Friendly Development
14.9 Going Too Far
14.10 Summary
Chapter 15: Designing and Implementing a "Minute/Hour Counter"
15.1 The Problem
15.2 Defining the Class Interface
15.3 Attempt 1: A Naive Solution
15.4 Attempt 2: Conveyor Belt Design
15.5 Attempt 3: A Time-Bucketed Design
15.6 Comparing the Three Solutions
15.7 Summary
Further Reading
Books on Writing High-Quality Code
Books on Various Programming Topics
Books of Historical Note
Colophon