This book addresses the topic of software design: how to decompose complex software systems into modules (such as classes and methods) that can be implemented relatively independently. The book first introduces the fundamental problem in software design, which is managing complexity. It then discusses philosophical issues about how to approach the software design process, and it presents a collection of design principles to apply during software design. The book also introduces a set of red flags that identify design problems. You can apply the ideas in this book to minimize the complexity of large software systems, so that you can write software more quickly and cheaply.
A Philosophy of Software Designby john OusterhoutCopyright o 2018 John K OusterhoutAll rights reserved. No part of this book may be reproduced, in any form or by any means, withoutpermission in writing from the author.Published by yaknyam Press, Palo alto, CACoverdesignbyPeteNguyenandShirinoReizy(www.hellonextstep.com)Printing History:April 2018First Edition(v1.0)November 2018: First Edition(v1.01)ISBN978-1-7321022-0-0Digital book(s)(epub and mobi) produced by Booknook bizContentsPreface1 Introduction1. 1 How to use this book2 The Nature of Complexity2. 1 Complexity defined2.2 Symptoms of complexity2.3 Causes of complexity2.4 Complexity is incremental2.5 Conclusion3 Working Code Isnt Enoug3.1 Tactical programming3.2 Strategic programming3.3 How much to invest?3.4 Startups and investment3.5 Conclusion4 Modules Should Be Deep4. 1 Modular design4.2 What's in an interface?4.3 Abstractions4.4 Deep modules4.5 Shallow modules4.6 Classitis4.7 Examples: Java and Unix 1/O4.8 Conclusion5 Information Hiding(and Leakage)Information hiding5.2 Information leakage5.3 Temporal decomposition5.4 Example Http server5.5 Example: too many classes5.6 Example Http parameter handling5.7 Example defaults in Http responses5.8 Information hiding within a class5.9 Taking it too far5.10 Conclusion6 General-Purpose Modules are Deeper6. 1 Make classes somewhat general-purpose6.2 Example: storing text for an editor6.3 A more general-purpose API6.4 Generality leads to better information hiding6.5 Questions to ask yourself6.6 Conclusion7 Different Layer. Different Abstraction7.1 Pass-through methods7.2 When is interface duplication OK?7.3 Decorators7.4 Interface versus implementation7.5 PaSs-through variables7. 6 Conclusion8 Pull Complexity Downwards8.Example: editor text class8.2 Example: configuration parameters34Taking it too far8Conclusion9 Better Together Or Better Apart?9.1 Bring together if information is shared9.2 Bring together if it will simplify the interface9.3 Bring together to eliminate duplication9.4 Separate general-purpose and special-purpose code9.5 Example: insertion cursor and selection9.6 Example: separate class for logging9.7 Example: editor undo mechanism9.8 Splitting and joining methods9.9 Conclusion10 Define errors out of existence10. 1 Why exceptions add complexity10.2 Too many exceptions10.3 Define errors out of existence10.4 Example: file deletion in Windows10.5 Example: Java substring method10.6 Mask exceptions10.7 Exception aggregation10.8 Just crash?10.9 Design special cases out of existence10.10 Taking it too far10.11 Conclusion11 Design it Twice12 Why Write Comments? The Four Excuses12. 1 Good code is self-documenting12. i don 't have time to write comments12.3 Comments get out of date and become misleading12.4 All the comments i have seen are worthless12.5 Benefits of well-written comments13 Comments Should Describe Things that Arent Obvious from the Code13.1 Pick conventions13.2 Don t repeat the code13. 3 Lower-level comments add precision13.4 Higher-level comments enhance intuition13.5 Interface documentation13.6 Implementation comments: what and why, not how13.7 Cross-module design decisions13. 8 Conclusion13.9 Answers to questions from Section 13.514 Choosing names14.1 Example: bad names cause bugs14.2 Create an image14.3 Names should be precise4. Use names consistently14.5 A different opinion Go style guide14.6 Conclusion15 Write The Comments first15. 1 Delayed comments are bad comments15.2 Write the comments first15.3 Comments are a design tool15.4 Early comments are fun comments15.5 Are early comments expensive?15.6 Conclusion16 Modifying Existing Code16.1 Stay strategic16.2 Maintaining comments: keep the comments near the code16.3 Comments belong in the code, not the commit log16.4 Maintaining comments: avoid duplication16.5 Maintaining comments: check the diffs16.6 Higher-level comments are easier to maintain17 Consistency17.1 Examples of consistency17.2 Ensuring consistency17.3 Taking it too far17.4 Conclusion1 8 Code should be obvious18.1 Things that make code more obvious18.2 Things that make code less obvious18.3 Conclusion19 Software Trends19.1 Object-oriented programming and inheritance19.2 Agile development19.3 Unit tests19.4 Test-driven development19.5 Design patterns19.6 Getters and setters19. 7 Conclusion20 Designing for performance20. 1 How to think about performance20.2 Measure before modifying20.3 Design around the critical path20.4 An example: RAMCloud buffers20.5 Conclusion21 ConclusionIndexSummary of Design PrinciplesSummary of red FlagsPrefacePeople have been writing programs for electronic computers for more than 80years, but there has been surprisingly little conversation about how to designthose programs or what good programs should look like. There has beenconsiderable discussion about software development processes such as agiledevelopment and about development tools such as debuggers, version controlsystems, and test coverage tools. There has also been extensive analysis ofprogramming techniques such as object-oriented programming and functionalprogramming, and of design patterns and algorithms. All of these discussionshave been valuable, but the core problem of software design is still largelyuntouched. David Parnas classic paper "On the Criteria to be used inDecomposing Systems into Modules" appeared in 1971, but the state of the art insoftware design has not progressed much beyond that paper in the ensuing 45yearsThe most fundamental problem in computer science is problemdecomposition: how to take a complex problem and divide it up into pieces thatcan be solved independently. problem decomposition is the central design taskthat programmers face every day, and yet, other than the work described here, Ihave not been able to identify a single class in any university where problemdecomposition is a central topic. We teach for loops and object-orientedprogramming, but not software designIn addition, there is a huge variation in quality and productivity amongprogrammers, but we have made little attempt to understand what makes the bestprogrammers so much better or to teach those skills in our classes. I have talkedwith several people i consider to be great programmers, but most of them haddifficulty articulating specific techniques that give them their advantage. Manypeople assume that software design skill is an innate talent that cannot be taughtHowever, there is quite a bit of scientific evidence that outstanding performancein many fields is related more to high-quality practice than innate ability(see, forexample, Talent is Overrated by geoff colvin)For many years these issues have perplexed and frustrated me. I havewondered whether software design can be taught, and I have hypothesized thatdesign skill is what separates great programmers from average ones. I finallydecided that the only way to answer these questions was to attempt to teach acourse on software design. The result is cs 190 at Stanford University. In thisclass i put forth a set of principles of software design. Students then workhrough a series of projects to assimilate and practice the principles. The class istaught in a fashion similar to a traditional english writing class In an englishclass, students use an iterative process where they write a draft, get feedback, andthen rewrite to make improvements. In CS 190, students develop a substantialpiece of software from scratch. We then go through extensive code reviews toidentify design problems, and students revise their projects to fix the problemsThis allows students to see how their code can be improved by applying designprinciplesI have now taught the software design class three times and this book isbased on the design principles that emerged from the class. The principles arefairly high level and border on the philosophical (Define errors out ofexistence"), so it is hard for students to understand the ideas in the abstractStudents learn best by writing code, making mistakes, and then seeing how theirmistakes and the subsequent fixes relate to the principlesAt this point you may well be wondering: what makes me think i know allthe answers about software design to be honest i dont There were no classeson software design when i learned to program and i never had a mentor to teachme design principles. At the time I learned to program, code reviews werevirtually nonexistent. My ideas about software design come from personalexperience writing and reading code. Over my career I have written about250,000 lines of code in a variety of languages. Ive worked on teams thatcreated three operating systems from scratch, multiple file and storage systemsinfrastructure tools such as debuggers, build systems, and Gui toolkits,ascripting language, and interactive editors for text, drawings, presentations, andintegrated circuits. Along the way I've experienced firsthand the problems oflarge systems and experimented with various design techniques. In addition, Iveread a considerable amount of code written by other people, which has exposedme to a variety of approaches, both good and badOut of all of this experience, I've tried to extract common threads, both aboutmistakes to avoid and techniques to use. This book is a reflection of myexperiences: every problem described here is one that I have experienced
1