Clean Code
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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

Clean Code

  • 1.
  • 2.
    Broken Windows WTF's perminute 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 BadCode 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 IsAn 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 BadCode 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 ratioof 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 Keepit 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 ofyour 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 namesare 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 orscope 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 shouldbe 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 useComputer 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 onething, 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 performsteps 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 thatperform 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 andfocused 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 thecomplexity 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 dosomething 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 anecessary 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 intentbehind 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 temptationto 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 commentsas 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