Arjan van Leeuwen
The Evolution of
Good Code
ACCU 2014
@avl7771
Take one of each
! !
"The past is a foreign
country: they do things
differently there."
— L.P. Hartley
GoodSolidReadable
MaintainableElegant
Bug-free
reliableTestable
Debuggable CLEAN
The bookshelf
“A man may as well expect to
grow stronger by always eating
as wiser by always reading.”!
— Jeremy Collier
Writing Solid Code
❖ Steve Maguire!
❖ Microsoft Programming!
❖ 1993!
❖ “Microsoft’s Techniques for
Developing Bug-Free C
Programs”
The Pragmatic Programmer
❖ Andrew Hunt & David
Thomas!
❖ Addison Wesley!
❖ 2000!
❖ “examines the core process -
taking a requirement and
producing working, maintainable
code that delights its users”
Code Complete
❖ Steve McConnell!
❖ Microsoft Programming!
❖ 2004 (1st Edition 1993)!
❖ “A Practical Handbook of
Software Construction” - “Helps
you build the highest quality
code”
Clean Code
❖ Robert C. Martin (“Uncle Bob”)!
❖ Prentice Hall!
❖ 2009!
❖ “A handbook for Agile Software
Craftsmanship” — “How to write
good code and how to transform
bad code into good code”
97 Things Every Programmer Should Know
❖ Various Artists, edited by
Kevlin Henney!
❖ O’Reilly!
❖ 2010!
❖ “Collective Wisdom from the
Experts” — “you’ll expand your
skills by … learning appropriate
best practices”
Growing Object-Oriented Software, Guided by Tests
❖ Steve Freeman & Nat Pryce!
❖ Addison Wesley!
❖ 2010!
❖ “Two TDD pioneers show how to
let tests guide your development
and ‘grow’ software that is
coherent, reliable, and
maintainable”
The Art of Readable Code
❖ Dustin Boswell & Trevor
Foucher!
❖ O’Reilly!
❖ 2011!
❖ “Simple and Practical Techniques
for Writing Better Code”
Guess the book!
“If we encounter a man of rare
intellect, we should ask him what
books he reads.”!
— Ralph Waldo Emerson
2011
2009
! ! 1993
Use Hungarian notation for variables
❖ “Although names like pch look
funny and are hard to
pronounce, they are filled with
information.”!
❖ “Conveying information is far
more important in naming your
variables than being able to
stand up and read your code
aloud during a program
review.”
/* pointer to character	
pointer */	
char **ppch;
! ! 1993
Use Hungarian notation for variables
❖ “Although names like pch look
funny and are hard to
pronounce, they are filled with
information.”!
❖ “Conveying information is far
more important in naming your
variables than being able to
stand up and read your code
aloud during a program
review.”
/* pointer to character	
pointer */	
char **ppch;
Don’t use Hungarian notation for variables
❖ “In modern languages we have
much richer type systems, and
the compilers remember and
enforce the types.”!
❖ “Nowadays HN and other
forms of type encoding are
simply impediments. They
make it harder to read the
code.”
/* pointer to character	
pointer */	
char **ppch;
2011
2009
! ! 1993
Don’t use Hungarian notation for variables
❖ “In modern languages we have
much richer type systems, and
the compilers remember and
enforce the types.”!
❖ “Nowadays HN and other
forms of type encoding are
simply impediments. They
make it harder to read the
code.”
/* pointer to character	
pointer */	
char **ppch;
2009
2004
Don’t use Yoda Conditions
❖ “Putting constants and
expressions on the left-hand
side of comparisons works
only when one of the operands
is a constant or an expression.”!
❖ “If instead you use a compiler
switch, the compiler would
alert you to every possible
assignment bug.”
2011
! ! 1993
if (10 == x)	
// if 10, x is!
Don’t use Yoda Conditions
❖ “Putting constants and
expressions on the left-hand
side of comparisons works
only when one of the operands
is a constant or an expression.”!
❖ “If instead you use a compiler
switch, the compiler would
alert you to every possible
assignment bug.”
if (10 == x)	
// if 10, x is!
! ! 1993
2010
Enforce singletons
❖ “If you want to define a class
that allows only one object to
be instantiated, enforce this by
hiding all the constructors of
the class and providing a static
routine to access the class’s
single instance.”
public class MaxId {	
	 private MaxId() {}	
	 public static MaxId	
	 	 GetInstance() { /*..*/ }	
}
2004
! ! 1993
Enforce singletons
❖ “If you want to define a class
that allows only one object to
be instantiated, enforce this by
hiding all the constructors of
the class and providing a static
routine to access the class’s
single instance.”
public class MaxId {	
	 private MaxId() {}	
	 public static MaxId	
	 	 GetInstance() { /*..*/ }	
}
2004
2011
Prefer Write-Once Variables
❖ “The more places a variable is
manipulated, the harder it is to
reason about its current value”!
❖ “Variables that are a
‘permanent fixture’ are easier
to think about”!
❖ “Immutables tend to more
often be trouble-free”
2004
! ! 2000
2011
Prefer Write-Once Variables
❖ “The more places a variable is
manipulated, the harder it is to
reason about its current value”!
❖ “Variables that are a
‘permanent fixture’ are easier
to think about”!
❖ “Immutables tend to more
often be trouble-free”
2011
Design for Unit Tests
❖ “Most important, is it possible
to automatically and
thoroughly validate the design
using a unit test? If not, you
should consider using an
alternative design that can be
tested.”
2004
! ! 1993
Design for Unit Tests
❖ “Most important, is it possible
to automatically and
thoroughly validate the design
using a unit test? If not, you
should consider using an
alternative design that can be
tested.”
! ! 1993
Names and aesthetics Small changes that help you
understand code
Use Hungarian Notation for Variables
❖ Prefix indicates type or intended use!
❖ Widely used after use in Microsoft Windows C libraries!
❖ “Systems Hungarian” vs. “Apps Hungarian”
char ch; /* a plain old character */
bool f; /* flags that are always TRUE or FALSE */
char *pch; /* a character pointer */
char **ppch; /* pointer to a character pointer */
char *szName; /* a zero-terminated string */
Why?
❖ Makes wrong code ‘look wrong’ [Maguire93], [McConnell04]!
❖ Easy to decipher pointer expressions [McConnell04]!
❖ Semantic prefixes add information that compiler doesn’t
know about [McConnell04]!
❖ Standardized prefixes encourage consistent naming
[McConnell04]
Why not?
❖ Encoding adds burden of deciphering [Martin09]!
❖ Not necessary for types anymore [Martin09]!
❖ Functions and classes are shorter now [Martin09]!
❖ Inappropriate in object-oriented systems [Hunt00]!
❖ Code is read more than it’s written [Hunt00]
Use Hungarian Notation for Variables
1993 2000 2004 2009 2011
Specify interface or implementation in class name
❖ Denote in the class name when a class is an interface or
when it implements an interface!
❖ Typically using prefix ‘I’ for Interface and/or postfix
‘Impl’ for Implementation
class IBloober {
virtual void blob() = 0;
};
!
class BlooberImpl : public IBloober {
virtual void blob();
};
Why?
❖ See whether you are using an interface just from the
name
Why not?
❖ Users shouldn’t (have to) know they’re dealing with an
interface, better to encode the Impl [Martin09]!
❖ Names ending in Impl duplicate information [Freeman10]!
❖ Can indicate poorly named interface or design [Freeman10]
Specify interface or implementation in class name
1993 2004 2009 2010
? ?
Align similar statements
❖ Can be used wherever similar statements are done on
multiple lines!
❖ Purely aesthetic enhancement
customerPurchases = customerPurchases + CustomerSales(customerID);
customerBill = customerBill + customerPurchases;
totalCustomerBill = customerBill + PreviousBalance(customerID) +
LateCharge(customerID);
customerRating = Rating(customerID, totalCustomerBill);
Why?
❖ Alignment scheme shows statements belong together
[McConnell93]!
❖ Neater listing and quicker scanning [McConnell93]!
❖ Column edges provide “visual handrails” [Boswell11]!
❖ Doesn’t take much work [Boswell11]
Why not?
❖ A headache to maintain as names change and lines are
moved amongst different indentations [McConnell04]!
❖ Emphasizes wrong things [Martin09]!
❖ Keep lists short [Martin09]!
❖ Eliminated by automatic reformatting tools [Martin09]
Align similar statements
1993 2004 2009 2011
Keep functions short
❖ Functions should be as small as possible
std::string renderPageWithSetupsAndTeardowns(
PageData pageData, bool isSuite) {
if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}
Why?
❖ Easier to read and understand [Martin09]!
❖ Documentary value (descriptive name) [Martin09]!
❖ Easier to improve function when the code is by itself
[Boswell11]
Why not?
❖ Routines of longer length are no more error prone than
shorter routines, shorter may have more errors [McConnell93],
[McConnell04]!
❖ Routines of longer length are cheaper to develop
[McConnell93], [McConnell04]!
❖ Tiny functions can hurt readability [Boswell11]
Keep functions short
1993 2004 2009 2011
Simplifying Logic Or: how to write less
Don’t Repeat Yourself (DRY)
❖ Every piece of code must have a single, unambiguous,
authoritative representation within a system [Hunt00]
Why?
❖ Change in one will make two implementations diverge
[Hunt00]!
❖ Similar code in two routines implies an error in
decomposition [McConnell93]!
❖ Duplication is a missed opportunity for abstraction
[Martin09]!
❖ Duplication can indicate bad design [Hunt00]!
❖ Copy/Paste programming is bad, remember Y2K [Hunt00]
Don’t Repeat Yourself (DRY)
1993 2000 2009 2011
Early Return
❖ Use guard clauses to return early for exceptional or
error conditions!
❖ Return early from e.g. linear search when a result is
found
public boolean Contains(String str, String substr) {
if (str == null || substr == null) return false;
if (substr.equals("")) return true;
...
}
Why?
❖ Implementing without guard clauses unnatural [Boswell11]!
❖ Avoids deep nesting [McConnell04], [Boswell11]!
❖ Single exit point less important with shorter functions
[Martin09]!
❖ Single exit point less important with modern languages
[Boswell11]
Why not?
❖ Breaks Structured Programming single-entry, single exit
‘law’ [Martin09]!
❖ Harder to understand a routine when unaware of all
return points [McConnell93]
Early Return
1993 2000 2004 2009 2011
Prefer Exceptions to Returning Error Codes
❖ Use exceptions to clarify the control flow
try {
socket.read(name);
process(name);
socket.read(address);
processAddress(address);
socket.read(telNo)
// etc, etc...
} catch (IOException e) {
Logger.log("Error reading individual: " +
e.getMessage());
}
Why?
❖ Clarifies normal flow of control [Hunt00]!
❖ Avoids violation of command query separation [Martin09]!
❖ Don’t force user to handle error immediately [Martin09]!
❖ Signal errors in a way that cannot be ignored [McConnell04]
Why not?
❖ High-level program flow obscured by bubbling up
[Boswell11]!
❖ Alternative error handling often more appropriate
[McConnell04]!
❖ Exceptions should only be used in exceptional
situations (that should never happen) [Hunt00]
Prefer Exceptions to Returning Error Codes
2000 2004 2009 2011
Tell, Don’t Ask
❖ Objects make their decisions based only on the
information they hold internally or that which came
with the triggering message [Freeman10]
((EditSaveCustomizer) master.getModelisable()
.getDockablePanel()
.getCustomizer()
.getSaveItem().setEnabled(Boolean.FALSE.booleanValue());
!
// becomes...
master.allowSavingOfCustomisations();
Why?
❖ Produces more flexible code, easier to swap objects
[Freeman10]!
❖ Hides internal structure [Freeman10], [Martin09]!
❖ Avoids train wrecks [Freeman10], [Martin09]!
❖ Minimizes coupling [Hunt00]
Tell, Don’t Ask
2000 2004 2009 2010
Reliability, Debugging
and Testing
Use Functional Programming Principles
❖ Use knowledge of functional programming in
imperative languages!
❖ Work with immutable data and pure functions where
possible
Why?
❖ Avoid side effects [Garson10]!
❖ Simpler to debug (source of change easy to find) [Garson10]!
❖ Avoid thread race conditions [Carmack12]!
❖ The more places a variable is manipulated, the harder it
is to reason about its value [Boswell11]
Use Functional Programming Principles
1993 2004 2010 2011 2012
? ?
Use Functional Programming Principles
1993 2004 2010 2011 2012
? ?
Program in Terms of the Problem Domain
❖ Model types and behavior in terms of the programming
problem rather than the computer science solution
if (portfolioIdsByTraderId.get(trader.getId())
.containsKey(portfolio.getId())) { ... }
!
// becomes ...
if (trader.canView(portfolio)) { ... }
Why?
❖ Increases code readability and understanding [North10]!
❖ Can evolve code when domain model evolves [North10]!
❖ Work at a higher level of abstraction to allow focusing
on solving domain problems [Hunt00]!
❖ Hides low-level details [McConnell93]!
❖ Separating solution and problem domain is part of the
job of a good programmer [Martin09]
Why not?
❖ The people who read your code are programmers: they
know CS terms [Martin09]
Program in Terms of the Problem Domain
1993 2000 2004 2009 2010
Prefer Message-Passing in Parallel Systems
❖ Use message passing instead of shared mutable
variables!
❖ Use copies of data where necessary!
❖ If the language doesn’t provide it, use libraries or
frameworks that do
Why?
❖ Shared mutable memory is at the root of problems
related to concurrency: race conditions, deadlock,
livelock [Winder10]!
❖ Proven way of handling concurrency [Winder10]!
❖ Avoiding synchronization makes up for overhead [Martin09]
Prefer Message-Passing in Parallel Systems
1993 2004 2009 2010
? ?
Step Through your Code in a Debugger
❖ Actively step through all new or modified code to watch
it execute!
❖ As you step through code, focus on data flow!
❖ Step through every code path
Why?
❖ Allows you to get a ‘feeling’ for the code and gain
confidence [Maguire93]!
❖ You could create tests, but debugging is much faster
[Maguire93]
Why not?
❖ Problems can be found more quickly and more
accurately by thinking [McConnell04]!
❖ A bug should be reproducible with a single command
[Hunt00]
Step Through your Code in a Debugger
1993 2004 2009 2011
??
Test-Friendly Development
❖ Design your code so that it’s easy to test!
❖ Avoid use of global state!
❖ Avoid coupling
Why?
❖ Easier to test [Everyone]!
❖ Test-friendly code leads naturally to well-organized
code [Boswell11]!
❖ Decoupling leads to easier refactoring [Boswell11]!
❖ Classes with less state are simpler and easier to
understand [Boswell11]!
❖ Designing to test promotes reusability [Hunt00]
Why not?
❖ Could sacrifice readability for the sake of enabling tests
[Boswell11]!
❖ Testing by itself does not improve software quality
[McConnell93], [McConnell04]
Test-Friendly Development
1993 2000 2004 2009 2011
Test-Driven Development
❖ Write test cases before writing code!
❖ Follow Red-Green-Refactor cycle!
❖ Do not write code without having test cases
Why?
❖ Forces you to think about requirements and design of
the code, finds problems earlier [McConnell04]!
❖ Tests will cover virtually all production code [Martin09]!
❖ Creates short feedback cycle in development [Freeman10]!
❖ Integrates refactoring in development [Freeman10]!
❖ Takes same amount of time as creating tests afterwards
[McConnell04]
Why not?
❖ Can create false sense of security (should not be only
form of testing) [McConnell04]!
❖ Just keeping testing in mind can help improve the code
[Boswell11]!
❖ Testing can get in the way of product development
[Boswell11]
Test-Driven Development
1993 2004 2009 2010 2011
?
Boy Scout Rule
❖ “Always leave the campground cleaner than you found
it”!
❖ When you check in a module, make a small
improvement, regardless of who the original author was
Why?
❖ The end of deterioration of software systems [Martin10]!
❖ Systems gradually get better [Martin10]!
❖ Promotes collective ownership [Martin10]!
❖ Don’t be afraid of the code [Lewis10]
Why not?
❖ What kind of motto is “If it ain’t broke, fix it anyway”?
[Maguire93]!
❖ Programmers don’t treat improved code as if it were
new code [Maguire93]!
❖ Your colleagues are not bozos, they might have had
their reasons [Maguire93]!
❖ Change in itself is not a virtue [McConnell04]
Boy Scout Rule
1993 2004 2009 2010
Conclusion
“The word is about,!
there's something evolving,!
whatever may come,!
the world keeps revolving!
!
They say the next big thing is here,!
that the revolution's near,!
but to me it seems quite clear!
that it's all just a little bit of history
repeating”!
!
—Alex Gifford by way of Shirley Bassey
Arjan van Leeuwen / @avl7771
Conclusion
❖ (Better) unit testing and test-driven development have
an impact on other practices!
❖ Concurrency finally having an impact, comeback of
functional language principles!
❖ Many practices that might seem recent were in fact
known for a long time
References
❖ [Boswell11] Dustin Boswell, Trevor Forcher, “The Art of Readable Code”. O’Reilly, 2011.!
❖ [Carmack12] John Carmack, “Functional Programming in C++”. http://www.altdevblogaday.com/2012/04/26/functional-
programming-in-c/, 2012.!
❖ [Freeman10] Steve Freeman, Nat Pryce, “Growing Object-Oriented Software”. Addison-Wesley, 2010.!
❖ [Garson10] Edward Garson, “Apply Functional Programming Principles”, from “97 Things Every Programmer Should Know”.
O’Reilly, 2010.!
❖ [Hunt00] Andrew Hunt, David Thomas, “The Pragmatic Programmer”. Addison-Wesley, 2000.!
❖ [Maguire93] Stephen A. Maguire, “Writing Solid Code”. Microsoft Press, 1993!
❖ [Martin09] Robert C. Martin, “Clean Code”. Prentice Hall, 2009.!
❖ [McConnell93] Steve McConnell, “Code Complete”. Microsoft Press, 1993!
❖ [McConnell04] Steve McConnell, “Code Complete 2”. Microsoft Press, 2004.!
❖ [North10] Dan North, “Code in the Language of the Domain”, from “97 Things Every Programmer Should Know”. O’Reilly, 2010.!
❖ [Winder10] Russel Winder, “Message Passing Leads to Better Scalability in Parallel Systems”, from “97 Things Every Programmer
Should Know”. O’Reilly, 2010.

The Evolution of Good Code

  • 1.
    Arjan van Leeuwen TheEvolution of Good Code ACCU 2014 @avl7771
  • 2.
    Take one ofeach ! !
  • 3.
    "The past isa foreign country: they do things differently there." — L.P. Hartley
  • 4.
  • 5.
    The bookshelf “A manmay as well expect to grow stronger by always eating as wiser by always reading.”! — Jeremy Collier
  • 6.
    Writing Solid Code ❖Steve Maguire! ❖ Microsoft Programming! ❖ 1993! ❖ “Microsoft’s Techniques for Developing Bug-Free C Programs”
  • 7.
    The Pragmatic Programmer ❖Andrew Hunt & David Thomas! ❖ Addison Wesley! ❖ 2000! ❖ “examines the core process - taking a requirement and producing working, maintainable code that delights its users”
  • 8.
    Code Complete ❖ SteveMcConnell! ❖ Microsoft Programming! ❖ 2004 (1st Edition 1993)! ❖ “A Practical Handbook of Software Construction” - “Helps you build the highest quality code”
  • 9.
    Clean Code ❖ RobertC. Martin (“Uncle Bob”)! ❖ Prentice Hall! ❖ 2009! ❖ “A handbook for Agile Software Craftsmanship” — “How to write good code and how to transform bad code into good code”
  • 10.
    97 Things EveryProgrammer Should Know ❖ Various Artists, edited by Kevlin Henney! ❖ O’Reilly! ❖ 2010! ❖ “Collective Wisdom from the Experts” — “you’ll expand your skills by … learning appropriate best practices”
  • 11.
    Growing Object-Oriented Software,Guided by Tests ❖ Steve Freeman & Nat Pryce! ❖ Addison Wesley! ❖ 2010! ❖ “Two TDD pioneers show how to let tests guide your development and ‘grow’ software that is coherent, reliable, and maintainable”
  • 12.
    The Art ofReadable Code ❖ Dustin Boswell & Trevor Foucher! ❖ O’Reilly! ❖ 2011! ❖ “Simple and Practical Techniques for Writing Better Code”
  • 13.
    Guess the book! “Ifwe encounter a man of rare intellect, we should ask him what books he reads.”! — Ralph Waldo Emerson
  • 14.
    2011 2009 ! ! 1993 UseHungarian notation for variables ❖ “Although names like pch look funny and are hard to pronounce, they are filled with information.”! ❖ “Conveying information is far more important in naming your variables than being able to stand up and read your code aloud during a program review.” /* pointer to character pointer */ char **ppch;
  • 15.
    ! ! 1993 UseHungarian notation for variables ❖ “Although names like pch look funny and are hard to pronounce, they are filled with information.”! ❖ “Conveying information is far more important in naming your variables than being able to stand up and read your code aloud during a program review.” /* pointer to character pointer */ char **ppch;
  • 16.
    Don’t use Hungariannotation for variables ❖ “In modern languages we have much richer type systems, and the compilers remember and enforce the types.”! ❖ “Nowadays HN and other forms of type encoding are simply impediments. They make it harder to read the code.” /* pointer to character pointer */ char **ppch; 2011 2009 ! ! 1993
  • 17.
    Don’t use Hungariannotation for variables ❖ “In modern languages we have much richer type systems, and the compilers remember and enforce the types.”! ❖ “Nowadays HN and other forms of type encoding are simply impediments. They make it harder to read the code.” /* pointer to character pointer */ char **ppch; 2009
  • 18.
    2004 Don’t use YodaConditions ❖ “Putting constants and expressions on the left-hand side of comparisons works only when one of the operands is a constant or an expression.”! ❖ “If instead you use a compiler switch, the compiler would alert you to every possible assignment bug.” 2011 ! ! 1993 if (10 == x) // if 10, x is!
  • 19.
    Don’t use YodaConditions ❖ “Putting constants and expressions on the left-hand side of comparisons works only when one of the operands is a constant or an expression.”! ❖ “If instead you use a compiler switch, the compiler would alert you to every possible assignment bug.” if (10 == x) // if 10, x is! ! ! 1993
  • 20.
    2010 Enforce singletons ❖ “Ifyou want to define a class that allows only one object to be instantiated, enforce this by hiding all the constructors of the class and providing a static routine to access the class’s single instance.” public class MaxId { private MaxId() {} public static MaxId GetInstance() { /*..*/ } } 2004 ! ! 1993
  • 21.
    Enforce singletons ❖ “Ifyou want to define a class that allows only one object to be instantiated, enforce this by hiding all the constructors of the class and providing a static routine to access the class’s single instance.” public class MaxId { private MaxId() {} public static MaxId GetInstance() { /*..*/ } } 2004
  • 22.
    2011 Prefer Write-Once Variables ❖“The more places a variable is manipulated, the harder it is to reason about its current value”! ❖ “Variables that are a ‘permanent fixture’ are easier to think about”! ❖ “Immutables tend to more often be trouble-free” 2004 ! ! 2000
  • 23.
    2011 Prefer Write-Once Variables ❖“The more places a variable is manipulated, the harder it is to reason about its current value”! ❖ “Variables that are a ‘permanent fixture’ are easier to think about”! ❖ “Immutables tend to more often be trouble-free”
  • 24.
    2011 Design for UnitTests ❖ “Most important, is it possible to automatically and thoroughly validate the design using a unit test? If not, you should consider using an alternative design that can be tested.” 2004 ! ! 1993
  • 25.
    Design for UnitTests ❖ “Most important, is it possible to automatically and thoroughly validate the design using a unit test? If not, you should consider using an alternative design that can be tested.” ! ! 1993
  • 26.
    Names and aestheticsSmall changes that help you understand code
  • 27.
    Use Hungarian Notationfor Variables ❖ Prefix indicates type or intended use! ❖ Widely used after use in Microsoft Windows C libraries! ❖ “Systems Hungarian” vs. “Apps Hungarian” char ch; /* a plain old character */ bool f; /* flags that are always TRUE or FALSE */ char *pch; /* a character pointer */ char **ppch; /* pointer to a character pointer */ char *szName; /* a zero-terminated string */
  • 28.
    Why? ❖ Makes wrongcode ‘look wrong’ [Maguire93], [McConnell04]! ❖ Easy to decipher pointer expressions [McConnell04]! ❖ Semantic prefixes add information that compiler doesn’t know about [McConnell04]! ❖ Standardized prefixes encourage consistent naming [McConnell04]
  • 29.
    Why not? ❖ Encodingadds burden of deciphering [Martin09]! ❖ Not necessary for types anymore [Martin09]! ❖ Functions and classes are shorter now [Martin09]! ❖ Inappropriate in object-oriented systems [Hunt00]! ❖ Code is read more than it’s written [Hunt00]
  • 30.
    Use Hungarian Notationfor Variables 1993 2000 2004 2009 2011
  • 31.
    Specify interface orimplementation in class name ❖ Denote in the class name when a class is an interface or when it implements an interface! ❖ Typically using prefix ‘I’ for Interface and/or postfix ‘Impl’ for Implementation class IBloober { virtual void blob() = 0; }; ! class BlooberImpl : public IBloober { virtual void blob(); };
  • 32.
    Why? ❖ See whetheryou are using an interface just from the name
  • 33.
    Why not? ❖ Usersshouldn’t (have to) know they’re dealing with an interface, better to encode the Impl [Martin09]! ❖ Names ending in Impl duplicate information [Freeman10]! ❖ Can indicate poorly named interface or design [Freeman10]
  • 34.
    Specify interface orimplementation in class name 1993 2004 2009 2010 ? ?
  • 35.
    Align similar statements ❖Can be used wherever similar statements are done on multiple lines! ❖ Purely aesthetic enhancement customerPurchases = customerPurchases + CustomerSales(customerID); customerBill = customerBill + customerPurchases; totalCustomerBill = customerBill + PreviousBalance(customerID) + LateCharge(customerID); customerRating = Rating(customerID, totalCustomerBill);
  • 36.
    Why? ❖ Alignment schemeshows statements belong together [McConnell93]! ❖ Neater listing and quicker scanning [McConnell93]! ❖ Column edges provide “visual handrails” [Boswell11]! ❖ Doesn’t take much work [Boswell11]
  • 37.
    Why not? ❖ Aheadache to maintain as names change and lines are moved amongst different indentations [McConnell04]! ❖ Emphasizes wrong things [Martin09]! ❖ Keep lists short [Martin09]! ❖ Eliminated by automatic reformatting tools [Martin09]
  • 38.
  • 39.
    Keep functions short ❖Functions should be as small as possible std::string renderPageWithSetupsAndTeardowns( PageData pageData, bool isSuite) { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); }
  • 40.
    Why? ❖ Easier toread and understand [Martin09]! ❖ Documentary value (descriptive name) [Martin09]! ❖ Easier to improve function when the code is by itself [Boswell11]
  • 41.
    Why not? ❖ Routinesof longer length are no more error prone than shorter routines, shorter may have more errors [McConnell93], [McConnell04]! ❖ Routines of longer length are cheaper to develop [McConnell93], [McConnell04]! ❖ Tiny functions can hurt readability [Boswell11]
  • 42.
  • 43.
    Simplifying Logic Or:how to write less
  • 44.
    Don’t Repeat Yourself(DRY) ❖ Every piece of code must have a single, unambiguous, authoritative representation within a system [Hunt00]
  • 45.
    Why? ❖ Change inone will make two implementations diverge [Hunt00]! ❖ Similar code in two routines implies an error in decomposition [McConnell93]! ❖ Duplication is a missed opportunity for abstraction [Martin09]! ❖ Duplication can indicate bad design [Hunt00]! ❖ Copy/Paste programming is bad, remember Y2K [Hunt00]
  • 46.
    Don’t Repeat Yourself(DRY) 1993 2000 2009 2011
  • 47.
    Early Return ❖ Useguard clauses to return early for exceptional or error conditions! ❖ Return early from e.g. linear search when a result is found public boolean Contains(String str, String substr) { if (str == null || substr == null) return false; if (substr.equals("")) return true; ... }
  • 48.
    Why? ❖ Implementing withoutguard clauses unnatural [Boswell11]! ❖ Avoids deep nesting [McConnell04], [Boswell11]! ❖ Single exit point less important with shorter functions [Martin09]! ❖ Single exit point less important with modern languages [Boswell11]
  • 49.
    Why not? ❖ BreaksStructured Programming single-entry, single exit ‘law’ [Martin09]! ❖ Harder to understand a routine when unaware of all return points [McConnell93]
  • 50.
    Early Return 1993 20002004 2009 2011
  • 51.
    Prefer Exceptions toReturning Error Codes ❖ Use exceptions to clarify the control flow try { socket.read(name); process(name); socket.read(address); processAddress(address); socket.read(telNo) // etc, etc... } catch (IOException e) { Logger.log("Error reading individual: " + e.getMessage()); }
  • 52.
    Why? ❖ Clarifies normalflow of control [Hunt00]! ❖ Avoids violation of command query separation [Martin09]! ❖ Don’t force user to handle error immediately [Martin09]! ❖ Signal errors in a way that cannot be ignored [McConnell04]
  • 53.
    Why not? ❖ High-levelprogram flow obscured by bubbling up [Boswell11]! ❖ Alternative error handling often more appropriate [McConnell04]! ❖ Exceptions should only be used in exceptional situations (that should never happen) [Hunt00]
  • 54.
    Prefer Exceptions toReturning Error Codes 2000 2004 2009 2011
  • 55.
    Tell, Don’t Ask ❖Objects make their decisions based only on the information they hold internally or that which came with the triggering message [Freeman10] ((EditSaveCustomizer) master.getModelisable() .getDockablePanel() .getCustomizer() .getSaveItem().setEnabled(Boolean.FALSE.booleanValue()); ! // becomes... master.allowSavingOfCustomisations();
  • 56.
    Why? ❖ Produces moreflexible code, easier to swap objects [Freeman10]! ❖ Hides internal structure [Freeman10], [Martin09]! ❖ Avoids train wrecks [Freeman10], [Martin09]! ❖ Minimizes coupling [Hunt00]
  • 57.
    Tell, Don’t Ask 20002004 2009 2010
  • 58.
  • 59.
    Use Functional ProgrammingPrinciples ❖ Use knowledge of functional programming in imperative languages! ❖ Work with immutable data and pure functions where possible
  • 60.
    Why? ❖ Avoid sideeffects [Garson10]! ❖ Simpler to debug (source of change easy to find) [Garson10]! ❖ Avoid thread race conditions [Carmack12]! ❖ The more places a variable is manipulated, the harder it is to reason about its value [Boswell11]
  • 61.
    Use Functional ProgrammingPrinciples 1993 2004 2010 2011 2012 ? ?
  • 62.
    Use Functional ProgrammingPrinciples 1993 2004 2010 2011 2012 ? ?
  • 63.
    Program in Termsof the Problem Domain ❖ Model types and behavior in terms of the programming problem rather than the computer science solution if (portfolioIdsByTraderId.get(trader.getId()) .containsKey(portfolio.getId())) { ... } ! // becomes ... if (trader.canView(portfolio)) { ... }
  • 64.
    Why? ❖ Increases codereadability and understanding [North10]! ❖ Can evolve code when domain model evolves [North10]! ❖ Work at a higher level of abstraction to allow focusing on solving domain problems [Hunt00]! ❖ Hides low-level details [McConnell93]! ❖ Separating solution and problem domain is part of the job of a good programmer [Martin09]
  • 65.
    Why not? ❖ Thepeople who read your code are programmers: they know CS terms [Martin09]
  • 66.
    Program in Termsof the Problem Domain 1993 2000 2004 2009 2010
  • 67.
    Prefer Message-Passing inParallel Systems ❖ Use message passing instead of shared mutable variables! ❖ Use copies of data where necessary! ❖ If the language doesn’t provide it, use libraries or frameworks that do
  • 68.
    Why? ❖ Shared mutablememory is at the root of problems related to concurrency: race conditions, deadlock, livelock [Winder10]! ❖ Proven way of handling concurrency [Winder10]! ❖ Avoiding synchronization makes up for overhead [Martin09]
  • 69.
    Prefer Message-Passing inParallel Systems 1993 2004 2009 2010 ? ?
  • 70.
    Step Through yourCode in a Debugger ❖ Actively step through all new or modified code to watch it execute! ❖ As you step through code, focus on data flow! ❖ Step through every code path
  • 71.
    Why? ❖ Allows youto get a ‘feeling’ for the code and gain confidence [Maguire93]! ❖ You could create tests, but debugging is much faster [Maguire93]
  • 72.
    Why not? ❖ Problemscan be found more quickly and more accurately by thinking [McConnell04]! ❖ A bug should be reproducible with a single command [Hunt00]
  • 73.
    Step Through yourCode in a Debugger 1993 2004 2009 2011 ??
  • 74.
    Test-Friendly Development ❖ Designyour code so that it’s easy to test! ❖ Avoid use of global state! ❖ Avoid coupling
  • 75.
    Why? ❖ Easier totest [Everyone]! ❖ Test-friendly code leads naturally to well-organized code [Boswell11]! ❖ Decoupling leads to easier refactoring [Boswell11]! ❖ Classes with less state are simpler and easier to understand [Boswell11]! ❖ Designing to test promotes reusability [Hunt00]
  • 76.
    Why not? ❖ Couldsacrifice readability for the sake of enabling tests [Boswell11]! ❖ Testing by itself does not improve software quality [McConnell93], [McConnell04]
  • 77.
  • 78.
    Test-Driven Development ❖ Writetest cases before writing code! ❖ Follow Red-Green-Refactor cycle! ❖ Do not write code without having test cases
  • 79.
    Why? ❖ Forces youto think about requirements and design of the code, finds problems earlier [McConnell04]! ❖ Tests will cover virtually all production code [Martin09]! ❖ Creates short feedback cycle in development [Freeman10]! ❖ Integrates refactoring in development [Freeman10]! ❖ Takes same amount of time as creating tests afterwards [McConnell04]
  • 80.
    Why not? ❖ Cancreate false sense of security (should not be only form of testing) [McConnell04]! ❖ Just keeping testing in mind can help improve the code [Boswell11]! ❖ Testing can get in the way of product development [Boswell11]
  • 81.
  • 82.
    Boy Scout Rule ❖“Always leave the campground cleaner than you found it”! ❖ When you check in a module, make a small improvement, regardless of who the original author was
  • 83.
    Why? ❖ The endof deterioration of software systems [Martin10]! ❖ Systems gradually get better [Martin10]! ❖ Promotes collective ownership [Martin10]! ❖ Don’t be afraid of the code [Lewis10]
  • 84.
    Why not? ❖ Whatkind of motto is “If it ain’t broke, fix it anyway”? [Maguire93]! ❖ Programmers don’t treat improved code as if it were new code [Maguire93]! ❖ Your colleagues are not bozos, they might have had their reasons [Maguire93]! ❖ Change in itself is not a virtue [McConnell04]
  • 85.
    Boy Scout Rule 19932004 2009 2010
  • 86.
    Conclusion “The word isabout,! there's something evolving,! whatever may come,! the world keeps revolving! ! They say the next big thing is here,! that the revolution's near,! but to me it seems quite clear! that it's all just a little bit of history repeating”! ! —Alex Gifford by way of Shirley Bassey Arjan van Leeuwen / @avl7771
  • 87.
    Conclusion ❖ (Better) unittesting and test-driven development have an impact on other practices! ❖ Concurrency finally having an impact, comeback of functional language principles! ❖ Many practices that might seem recent were in fact known for a long time
  • 88.
    References ❖ [Boswell11] DustinBoswell, Trevor Forcher, “The Art of Readable Code”. O’Reilly, 2011.! ❖ [Carmack12] John Carmack, “Functional Programming in C++”. http://www.altdevblogaday.com/2012/04/26/functional- programming-in-c/, 2012.! ❖ [Freeman10] Steve Freeman, Nat Pryce, “Growing Object-Oriented Software”. Addison-Wesley, 2010.! ❖ [Garson10] Edward Garson, “Apply Functional Programming Principles”, from “97 Things Every Programmer Should Know”. O’Reilly, 2010.! ❖ [Hunt00] Andrew Hunt, David Thomas, “The Pragmatic Programmer”. Addison-Wesley, 2000.! ❖ [Maguire93] Stephen A. Maguire, “Writing Solid Code”. Microsoft Press, 1993! ❖ [Martin09] Robert C. Martin, “Clean Code”. Prentice Hall, 2009.! ❖ [McConnell93] Steve McConnell, “Code Complete”. Microsoft Press, 1993! ❖ [McConnell04] Steve McConnell, “Code Complete 2”. Microsoft Press, 2004.! ❖ [North10] Dan North, “Code in the Language of the Domain”, from “97 Things Every Programmer Should Know”. O’Reilly, 2010.! ❖ [Winder10] Russel Winder, “Message Passing Leads to Better Scalability in Parallel Systems”, from “97 Things Every Programmer Should Know”. O’Reilly, 2010.