You are on page 1of 10

Chapter 2 ­ Meaningful names

● use intention revealing names
● avoid disinformation
○ be aware of name that vary in small ways
● make meaningful distinctions
○ distinguish names in such a way that the reader knows what the difference
offers
● use pronounceable names
● use searchable names
○ use single letter name ONLY for local variables inside short methods
○ the length of a name should correspond to the size of its scope
● avoid encodings
● avoid mental mapping
○ clarity is king
● class names
○ noun or noun phrases
○ should not be a verb
● method names
○ verb or verb phrase
○ use JavaBean standards
○ when constructors are overloaded use static factory methods with names that
describe the arguments
■ make constructors private
● don’t be cute
○ choose clarity over entertainment value
○ say what you mean
○ mean what you say
● pick one word per concept
○ consistent lexicon is a great boon
● don’t pun
○ avoid using the same work for two purposes
● use solution domain names
● use problem domain names
● add meaningful context
● don’t add gratuitous context

Chapter 3 ­ Functions
● small
○ they should be smaller than small
● blocks and indenting
○ if, else, while statements should be one line long
○ they should be a function call
○ the indent level should not be greater than one or two
● do one thing
○ they should do it well
○ they should do it only
○ functions that do one thing cannot be reasonably divided into sections
● one level of abstraction per function
● use descriptive names
○ you know you are working on clean code when each routine turns out pretty
much what you expected
○ a long descriptive name is better than a short enigmatic name
● function arguments
○ ideal number is 0
○ three or more arguments should be avoided if possible
● have no side effects
● output arguments
○ if your function must change the state of something, have it change the state
of its owning object
● command query separation
○ functions should
■ do something
■ OR
■ answer something
● prefer exceptions to returning error codes
● don’t repeat yourself
Chapter 4 ­ Comments
● comments do not make up for bad code
● explain yourself in code

Chapter 5 ­ Formatting
● stick to a formatting style

Chapter 6 ­ Objects and Data Structures
● data/object anti­symmetry
○ procedural code makes it hard to add new data structures because all the
functions must change
○ OO code makes it hard to add new functions because all the classes must
change
● law of Demeter
○ a method f of a class C should only call the methods of these
■ C
■ an object created by f
■ an object passed as an argument to f
■ an object held in an instance variable of C

Chapter 7 ­ Error Handling
● use exceptions rather than return codes
● start code with try­catch­finally
● use unchecked exceptions
● don’t return null
● don’t pass null into methods

Chapter 8 ­ Boundaries
● use third party code
● learning tests verify that the third­party packages we are using work the way we
expect them to
Chapter 9 ­ Unit Tests
● three laws of test driven development
○ you may not write production code until you have written a failing test unit
○ you may not write more of a test unit than is sufficient to fail, and not
compiling is failing
○ you may not write more production code than is sufficient to pass the
currently failing tests
● having dirty tests is worse than no tests
● test code is just as important as production code
● the number asserts per test should be minimized
● FIRST
○ fast
○ independent
○ repeatable
○ self­validating
■ boolean output
○ timely

Chapter 10 ­ Classes
● classes should be small
● name of the class should describe what responsibilities it fulfills
● single responsibility principle
○ a class should have only one reason to change
● cohesion
○ classes should have a small number of instance variables
● isolating from change

Chapter 11 ­ Systems
● separate constructing a system from using it
○ software systems should separate the startup process, when the application
objects are constructed and the dependencies are “wired” together, from the
runtime logic that takes over after startup
● factories
● dependency injection
Chapter 12 ­ Emergence
● simple design
○ runs all the tests
■ writing tests leads to better design
○ contains no duplication
○ expresses the intent of the programmer
○ minimizes the number of classes and methods

Chapter 13 ­ Concurrency
● myths and misconceptions
○ concurrency always improved performance
○ design does not change when writing concurrent programs
○ understanding concurrency issues is not important when working with a
container
● concurrent software
○ concurrency incurs some overhead
○ correct concurrency is complex
○ concurrency bugs aren’t usually repeatable
○ concurrency often requires a fundamental change in design strategy
● defense principles
○ single responsibility
■ concurrency­related code has its own cycle of development, change
and tuning
■ concurrency­related code has its own challenges, which are different
from and often more difficult than non­concurrency related code
■ keep your concurrency related code separate from other code
○ limit the scope of data
■ take data encapsulation to heart, severely limit the access of any data
that may be shared
○ use copies of data
○ threads should be as independent as possible
● know your library
○ thread­safe collections
● execution models
○ bound resource
○ mutual exclusion
○ starvation
■ one thread or group is prohibited from proceeding for an excesively
long time
○ deadlock
■ two or more threads waiting for each other to finish
○ livelock
■ threads trying to do work, but finding another one in the way
○ learn the basic algorithms and understand their solution
■ consumer­producer
■ dining philosophers
■ readers­writers
● beware dependencies between synchronized methods
○ avoid using more than one method on a shared object
○ client­based locking
○ server­based locking
○ adapted server
● keep synchronized sections small
● shutdown
○ think about shut down and get it working early
○ it’s gonna take longer than you expect
● testing
○ write tests that have the potential to expose problems and run them frequently
○ don’t ignore failures
○ get your non­threaded code working first
○ make your threaded code pluggable
○ make your threaded code tunable
○ run with more threads than processors
○ run on different platforms
○ try and force failures
Chapter 17 ­ Smells and Heuristics
● comments
○ inappropriate information
○ obsolete
○ redundant
○ poorly written
■ if you take time to write comments write them well
○ commented­out
■ delete it
● environment
○ build required more than one step
■ a build should be a single trivial operation
○ tests require more than one step
■ one button = test
● functions
○ too many arguments
○ output arguments
■ don’t have functions change arguments
■ use functions on objects if you have to change the object
○ flag arguments
○ dead function
● general
○ multiple languages in one source file
○ obvious behaviour is not implemented
○ incorrect behaviour at the boundaries
■ don’t rely on your intuition
○ overridden safeties
○ duplication
■ duplication = missed opportunity for abstraction
■ “once, and only once”
■ find and eliminate duplication wherever you can
○ code at the wrong level of abstraction
○ base classes depending on their derrivates
○ too much information
■ fewer methods = better
■ hide your data
■ hide your utility functions
■ don’t create classes with lots of methods or lots of instance variables
■ concentrate on keeping interfaces very tight and very small
○ dead code
■ code that isn’t executed
■ delete it from the system
○ vertical separation
■ local variables should be declared just above their first use
■ private functions should be defined just below their first usage
○ inconsistency
■ do all things in a similar way
○ clutter
■ variables never used
■ functions never called
■ comments that add no information
○ artificial coupling
○ feature envy
○ selector arguments
■ arguments that select the behaviour of the function
■ better to have many functions
○ obscured indent
○ misplaced responsibility
○ inappropriate static
■ make sure you don’t want your static function to behave
polymorphically
○ use explanatory variables
■ more are better than fewer
○ functions names should say what they do
○ understand the algorithm
○ make logical dependencies psychical
○ prefer polymorphism to if/else or switch statements
○ follow standard conventions
○ replace magic numbers with named constants
○ be precise
○ structure over convention
○ encapsulate conditionals
○ avoid negative conditionals
○ functions should do one thing
○ hidden temporal couplings
○ don’t be arbitrary
○ encapsulate boundary conditions
○ functions should descend only one level of abstraction
○ keep configurable data at high levels
○ avoid transitive navigation
● Java
○ avoid long import lists by using wildcards
○ don’t inherit constants
○ constants vs enums
● names
○ choose descriptive names
○ choose names at the appropriate level of abstraction
○ use standard nomenclature where possible
○ unambiguous names
○ use long names for long scopes
○ avoid encoding
○ names should describe side effects
● tests
○ insufficient tests
○ use a coverage tool
○ don’t skip trivial tests
○ an ignored test is a question about ambiguity
○ test boundary conditions
○ exhaustively test near bugs
○ patterns of failure are revealing
○ test coverage patterns can be revealing
○ tests should be fast

You might also like