2. Broken Windows
WTF's per minute
Good code matters
Code constitutes our inventory
Bad code brings companies to their knees
We've all seen it
We've all written it - but why?
Clean it up later? Leblanc's law: Later = Never
3. Cost of Bad Code
Ever decreasing productivity
Blame lies in us - not management, or customers, or marketing
We are deeply complicit in the planning of a project
and share a great deal of responsibility, especially if failures
have to do with bad code
It's our job to defend the code - as it is a mangers to defend the
schedule
You will not make the deadline by making a mess, rather you
will be slowed down instantly and miss the deadline
4. Clean Code Is An Art
recognizing bad code does not mean you can write clean code
requires a myriad of techniques applied with 'code-sense'
code sense shows us a strategy for transforming bad code into
clean code
a sequence of transformations applied against a set of unit
tests
5. Good vs. Bad
Bad Code Good Code
β tempts the mess to grow β elegant
β gets messier over time β pleasing
β tries to do too much β efficient
β speculative β no duplication
β does not include unit tests β minimal entities
β does not run unit tests β unpolluted by surrounding details
β has duplication β reads like well written prose
β is obscure β matter-of-fact, decisive
β appears neglected β easy for others
β difficult for others to read β includes tests and runs them all
β mysterious words β literate
β functions serve multiple purposes β has been taken care of
β classes serve multiple purposes β expresses design of system
β object.child.grandchild.greatgrandchild β tiny abstractions
β has dead code β no surprises, obvious, simple,
β relies on comments compelling
6. We Are Authors
ratio of time spent reading code vs. writing is 10:1
reading should be easy, even if that makes writing hard
however, making it easy to read makes it easy to write
functions are the verbs of a system, classes are the nouns
programming is the art of language design
master programmers think of systems as stories to be told
rather than programs to be written
7. Boy Scout Rule
Keep it Clean
leave the campground cleaner than you found it
if we all check in cleaner than we find it, it won't rot
can be something small: improve one variable name, break up
one large function, eliminate one small bit of duplication, clean
up one composite 'if' statement
imagine working on a project where the code got better and
better over time, easier and easier to read
don't comment bad code - rewrite it
8. Names
Take care of your names
Change names when you find better ones
reveal all intention in every name
why it exists, what it does, how it is used
if a comment is needed, intention is not revealed
avoid disinformation, obscure anagram style names, keywords
that are not accurate (AccountList, for a container holding
accounts that is not actually a list), slight variations,
inconsistent spelling, deliberately wrong spelling
9. Names
number series names are bad (a1, a2, a3). come up with
something meaningful
noise words are redundant, e.g. ProductData, ProductInfo,
NameString, ColorVariable
reader should be able to distinguish the differences
names should be pronounceable: var genymdhms:TimeStamp
names should be searchable
length of name should correspond to size of it's scope
10. Names
encoding type or scope into name adds extra burden of
deciphering
Hungarian Notation makes it harder to change the name or
type of a variable, function or class and makes it harder to read.
the encoding system could wind up misleading the reader
member prefixing is unnecessary and winds up being ignored
Using capital i 'I' to prefix an interface is a distraction and too
much information - if you have to encode 1 or the other, encode
the implementation - but, best not to encode at all
professionals understand that clarity is king - don't try to be
cute
11. Names
Class names should be nouns or noun phrases
Methods should be verbs or verb phrases
Accessor methods should be named for their value
Methods should describe their arguments - change the name
when the arguments change
Pick 1 word for an abstract concept and stick with it
Same word for two different purposes is essentially a pun
Utilize a consistent lexicon
12. Names
OK to use Computer Science terms: algorithm names, pattern
names, math terms, etc
If possible, avoid using names from the problem domain, as
computer scientists unfamiliar with the problem domain will not
know what they mean
Names are contextual, the method lives in a class which lives in
a package - so name them appropriately to avoid encoding
Shorter is better, provided full clarity is provided - add no more
context than is necessary
Good naming requires descriptive skills - which is a teaching
issue, not a technical, business or management issue
13. Functions
should do one thing, do it well, do it only
should be small - then smaller than that
should hardly ever be 20 lines long
aim for 2-4 lines of transparency and obviousness
tell a story, lead the read from method to method in a
compelling order
blocks within if, if else, while, etc. should be 1 line - a function
call
the indent level of a function should not be greater than 1 or 2
should not be large enough to hold nested structures
14. Functions
should only perform steps 1 level below the stated name of the
function
should not be able to extract another function from it with a
name that is not merely a restatement of its implementation
should not be able to divide into sections
should not mix levels of abstraction
the step-down rule: code should read like a top down narrative
every function should be followed by next level of abstraction
where top is most abstract
15. Functions
writing functions that perform at a single level of abstraction is
challenging, but is very, very important - keeps them short and
singular of focus
each function should introduce the next
switch statements can only be tolerated if they appear only
once, are used to create polymorphic objects, and are hidden
behind an inheritance relationship where rest of system can't
see them
there should not be more than 1 reason for the function to
change and functions should not need to change when new
types are added
16. Functions
the smaller and focused a function is, the easier it is to name
don't be afraid of long names, better a long descriptive name
than a descriptive comment
don't be afraid of taking time to choose a name or of changing
names, in fact, try several names
be consistent with names, use your module names in your
functions
the ideal number of arguments is 0, next is 1, then 2. 3 should
be avoided
17. Functions
the more arguments, the more difficult a function is to test, and
the harder it is to understand
output arguments are confusing - objects passed in that get
changed in the function, but not returned - always return your
transformed object - better yet, add the function the object
common reasons for a single argument: query the object
passed in, or transform the object and return it
flag arguments are a terrible practice: complicates signature
because it does more than one thing
convert dyads to monads whenever possible
18. Functions
triads increase the complexity of a function more than double
when you have more than two or three arguments, maybe they
need to be wrapped in a class
with a monad, the function and argument should form a nice
verb/noun pairing
function names should have arguments encoded
side effects are lies: a side effect is when your function
promises to do one thing but also does other hidden things
temporal coupling are confusing, especially when hidden as a
side effect
19. Functions
should either do something or answer something - not both
function should either change state of an object, or return info
about that object
extract try/catch blocks out to functions of their own
a try/catch block should be the only thing a function does,
nothing before try, nothing after finally
exceptions are better than error codes
20. Comments
at best a necessary evil
always a failure
grimace every time and feel the failure of your ability to express
yourself
inaccurate comments are worse than no comments
rather than spend time explaining your mess - clean it up
best comment is the one you found a way not to write
21. Comments
sometimes useful
provide intent behind implementation decisions
can be helpful to explain meaning of an obscure arguments or
return value
can warn of consequences
amplify importance of something that seems trivial
TODO's are ok, but not an excuse to leave bad code in the
system - eliminate them regularly
if writing a public API - make JavaDocs, but make them good
22. Comments
replace the temptation to create noise with the determination to
clean your code
banners /////////////////// are noise, are clutter - should be
eliminated
commenting out code is odious - don't do it! there's no way for
anyone to know what to do with it - just delete it, svn will store it
for you
definitely do not add HTML to source code comments
don't offer system wide information in the context of a local
comment
23. Comments
don't use comments as a change log, or discussion board
comments should refer to code they appear near and should
make sense in context
a well chosen method name is better than a header comment
generating javadocs for classes and functions inside a system
is not generally useful - ok for public api's but not system
internals