SlideShare a Scribd company logo
1 of 48
Writing Maintainable
       Code

           Andy Palmer
    Strong opinions, weakly held
Placeholders
   All of these talking points are placeholders for a
                      conversation.
  Many of the things that I talk about will make more
       sense when we start to look at real code.

I’ve included sample code where I think it helps explain
   the concepts, but the real code these lessons were
  learned from was proprietary, so the examples might
               seem a little over-simplistic.
Fundamentally...
The key to maintainable code is to write it so that

it can be read and understood easily
The long and winding road
One of the biggest barriers to understandable code is
             when it goes on too long.
 As humans, we can only hold a certain amount of
       context in our minds at any one time.

Methods that go on for tens of lines (or hundreds or
 thousands) are too complex for us to understand
      completely. The same is true of classes.
Reinvent the wheel?
     It’s often easy to get into a problem solving mindset,
     and that’s when we start writing code that’s probably
                        already been done

If we’re working on something not directly related to our
   business domain, check for whether there’s already a
                         library.
For example, anything to do with the web, accessing the
  disk or network, interacting with other processes.
Design Patterns
         Design patterns are very useful to talk about code.
      If we know the pattern name, we can discuss how this
                    code is doing what it’s doing

                        However
Design patterns do not tell us why we are doing something,
and so I don’t do design patterns. I make the code easier to
read and understand, and then afterwards say “Oh, I used a
                  Decorator there. Cool!”
System Metaphor
Often, when describing how a system works, we will use a metaphor.

                We rarely capture this in the code.
System Metaphor
Often, when describing how a system works, we will use a metaphor.

                We rarely capture this in the code.

                      What a shame :-(
System Metaphor
Often, when describing how a system works, we will use a metaphor.

                We rarely capture this in the code.

                      What a shame :-(

A metaphor carries lots of information in a way that is
                      easy to share.
System Metaphor (cont.)
System Metaphor (cont.)
                                  Metaphor
Useful information conveyed




                                                  Design Patterns


                                             Language Idiom

                              Number of people who understand it
System Metaphor (cont.)
                                  Metaphor                                                       Design Patterns
Useful information conveyed




                                                                    Hard




                                                                    Difficulty to Learn
                                                  Design Patterns

                                                                                         Language Idiom            Metaphor
                                             Language Idiom
                                                                    Easy
                              Number of people who understand it                           Relevance to Domain
Guard clauses
if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); }
Guard clauses
if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); }

if (someValue != null ) {
  doSomething();
  doSomethingElse();
  doSomeMoreSomething();
  return result;
}

return null;   // This null is a long way from where we decided to send it
Guard clauses
if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); }

if (someValue != null ) {
  doSomething();
  doSomethingElse();
  doSomeMoreSomething();
  return result;
}

return null;   // This null is a long way from where we decided to send it

if (someValue == null ) { return null; }   // Get out quickly

doSomething();
doSomethingElse();
doSomeMoreSomething();
return result;
Guard clauses (cont.)
  Often, we hear “Only one exit point per method”
 This makes sense in non-garbage-collected languages
   because the exit point is a good place to tidy up
                memory allocations.

   It’s not really relevant in Java, and I’d rather know
quickly if there’s some short circuit decision I can make
      if (!carStarted) { return callAA(); }   // duh!
      engageFirstGear();

      if (carStarted) {
        engageFirstGear();
        … 100s of lines …
      }
      return callAA(); // Why am I calling the AA here?
Nested ifs
Cyclomatic complexity for nested ifs follows a geometric progression.
 For a nest of 5 simple booleans, the number of possible paths is 32.
      If we have 5 guard clauses, the number of paths is only 10



          Look for “mountains” in the code
Cull Null
“I call it my billion-dollar mistake. It was the invention
            of the null reference in 1965. […]
This has led to innumerable errors, vulnerabilities, and
 system crashes, which have probably caused a billion
  dollars of pain and damage in the last forty years.”
                                    - Tony Hoare, QCon 2009
Cull Null
“I call it my billion-dollar mistake. It was the invention
            of the null reference in 1965. […]
This has led to innumerable errors, vulnerabilities, and
 system crashes, which have probably caused a billion
  dollars of pain and damage in the last forty years.”
                                    - Tony Hoare, QCon 2009

 If we never return or expect null then we:
• no longer need null checks
• can trust that what we get is valid
• can trust that error handling is dealt with
    elsewhere
Throw away Checked Exceptions
Typically checked exceptions are handled in one of two ways:
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {
  try {
    File.open(“some file”);
  } catch (IOException e) {
    e.printStackTrace();
  }
}
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {
  try {
    File.open(“some file”);   or
  } catch (IOException e) {
    e.printStackTrace();
  }
}
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {         public void someMethod() throws IOException {
  try {
    File.open(“some file”);   or   }
                                     File.open(“some file”);

  } catch (IOException e) {
    e.printStackTrace();
  }
}
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {         public void someMethod() throws IOException {
  try {
    File.open(“some file”);   or   }
                                     File.open(“some file”);

  } catch (IOException e) {
    e.printStackTrace();
  }
}


                  Both of which essentially do nothing
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {         public void someMethod() throws IOException {
  try {
    File.open(“some file”);   or   }
                                     File.open(“some file”);

  } catch (IOException e) {
    e.printStackTrace();
  }
}


              Both of which essentially do nothing
and worse... with the second option, details of the exception
  bubble up far beyond where it makes sense to the caller
Throw away Checked Exceptions
     Typically checked exceptions are handled in one of two ways:

public void someMethod() {         public void someMethod() throws IOException {
  try {
    File.open(“some file”);   or   }
                                     File.open(“some file”);

  } catch (IOException e) {
    e.printStackTrace();
  }
}


               Both of which essentially do nothing
and worse... with the second option, details of the exception
   bubble up far beyond where it makes sense to the caller
 If we want to do something, we can use and catch an unchecked
                exception without all the pollution
Fail fast
  If we know that it doesn’t make sense to continue, then
                       stop. NOW!

 Don’t return a null or some other non-useful result when
we could let the caller know that something needs attention.

 If we’re constructing an object (such as an email address)
and the email is not valid, we can throw an exception in the
constructor instead of having to check validity everywhere
                      the email is used.
 In this way, everyone who uses an EmailAddress knows
                    that it’s a valid value.
Code metrics
Code metrics can give us good places to look for risky
code.
They help us discover areas of high complexity or areas
of high dependency.
Switch statements
Switch statements
Have you ever noticed that switch statements have the
  word break all over the place, and frequently that’s
                exactly what they do?
Switch statements
    Have you ever noticed that switch statements have the
      word break all over the place, and frequently that’s
                    exactly what they do?

switch statements are often an indication that we have a
             Type that is trying to get out
Static methods
Static methods often appear in Utility classes.
Static methods
  Static methods often appear in Utility classes.

This makes sense for objects that we don’t control
       (such as any of the built-in libraries)
Static methods
  Static methods often appear in Utility classes.

This makes sense for objects that we don’t control
       (such as any of the built-in libraries)

             Well, possibly...
Static methods
     Static methods often appear in Utility classes.

  This makes sense for objects that we don’t control
         (such as any of the built-in libraries)

                Well, possibly...

But it almost never makes sense for objects that we own.

   Most static methods can be replaced with instance
    methods that are easier to test and understand
Poor Man’s Dependency Injection
    Add an overloaded version of the method or
constructor that takes the dependency, and new up the
dependency with a sensible default in the simpler case.
Poor Man’s Dependency Injection
    Add an overloaded version of the method or
constructor that takes the dependency, and new up the
dependency with a sensible default in the simpler case.

public void someMethod() {
  return someMethod(new Dependency());
}

public void someMethod(Dependency dependency) {
  return dependency.doSomething();
}
I want to store £123.45
     What data type should I use?
I want to store £123.45
                        What data type should I use?

float: The float data type is a single-precision 32-bit IEEE 754 floating point.
Use a float (instead of double) if you need to save memory in large arrays of floating
point numbers.
I want to store £123.45
                        What data type should I use?

float: The float data type is a single-precision 32-bit IEEE 754 floating point.
Use a float (instead of double) if you need to save memory in large arrays of floating
point numbers.


double: The double data type is a double-precision 64-bit IEEE 754 floating point.
I want to store £123.45
                          What data type should I use?

 float: The float data type is a single-precision 32-bit IEEE 754 floating point.
 Use a float (instead of double) if you need to save memory in large arrays of floating
 point numbers.


 double: The double data type is a double-precision 64-bit IEEE 754 floating point.



These data types should never be used for precise values, such as currency.
             http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
I want to store £123.45
                          What data type should I use?

 float: The float data type is a single-precision 32-bit IEEE 754 floating point.
 Use a float (instead of double) if you need to save memory in large arrays of floating
 point numbers.


 double: The double data type is a double-precision 64-bit IEEE 754 floating point.



These data types should never be used for precise values, such as currency.
             http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html



    Use the java.math.BigDecimal class instead
Avoid a void
void methods restrict our ability to extract composed methods
          e.g., ServletFilter.doFilter for Authorisation
   If we’re authorised, we want to continue to the resource
 If we’re unauthenticated, then redirect us to the login page
If we’re unauthorised, redirect us to the Access Denied page

  For the first case, we want to do a FilterChain.doFilter
                 For the others we don’t
Avoid a void (cont.)
public void doFilter(ServletRequest request,
      ServletResponse response, FilterChain chain) {
  if (filterWorkflow() == Do.Filter) {
    chain.doFilter(…);
  }
}

public Do filterWorkflow() {
   if (userIsAuthorised()) { return Do.Filter; }
   if (userIsNotLoggedIn()) { return Do.Redirect(LoginPage); }
   if (userIsNotAuthorised()) { return Do.Redirect(AccessDenied); }
}
Extending Exceptions
 One of the things that I do in my code is to make an
  obvious separation between types of exception.

  I use Apology for something that the program should
reasonably have been able to do, but failed (like fetching
                 a User from a database)

 I use Complaint for something that the program could
not possibly have achieved (like returning a single result
       when the criteria specify multiple results)
Look outside of your area
One of the best books on programming that I’ve read is
                 called “Perl Medic”.

   It covers most of what we’ve covered here and is
         completely applicable to any language
         (it’s just that the examples are in Perl)
Look outside of your area
One of the best books on programming that I’ve read is
                 called “Perl Medic”.

   It covers most of what we’ve covered here and is
         completely applicable to any language
         (it’s just that the examples are in Perl)

 Many .Netters who go to the Alt.Net events end up
migrating away from .Net once they see how easy it is
           to do things in other languages.
Continuous Learning
I read blogs most days, across a wide variety of languages and topics.
A problem that someone has solved in another domain might be
transferrable to mine.
We’ve never learned everything, there’s always something new.

Go to a coding dojo, code retreat, or a language meetup (especially if
it’s for a language other than your own)

Hold “lunch and learns” or “after school clubs” in the office
(get the company to buy pizza)

Read books (I have lots of recommendations)

Question conventional wisdom

More Related Content

Viewers also liked

Powering Systems of Engagement
Powering Systems of EngagementPowering Systems of Engagement
Powering Systems of EngagementMongoDB
 
Marketing, Technology, and the Empowered Customer
Marketing, Technology, and the Empowered CustomerMarketing, Technology, and the Empowered Customer
Marketing, Technology, and the Empowered CustomerJay Henderson
 
Business Drivers of SDN by Paul Wiefels, Chasm Group
Business Drivers of SDN by Paul Wiefels, Chasm GroupBusiness Drivers of SDN by Paul Wiefels, Chasm Group
Business Drivers of SDN by Paul Wiefels, Chasm GroupSDxCentral
 
Salesforce External Objects for Big Data
Salesforce External Objects for Big DataSalesforce External Objects for Big Data
Salesforce External Objects for Big DataSumit Sarkar
 
HILTON CRM CASE STUDY
HILTON CRM CASE STUDYHILTON CRM CASE STUDY
HILTON CRM CASE STUDYYingyuan Deng
 
User Story Mapping, Discover the whole story
User Story Mapping, Discover the whole storyUser Story Mapping, Discover the whole story
User Story Mapping, Discover the whole storyJeff Patton
 
Ten Disruptions in HR Technology for 2015: Ignore At Your Peril
Ten Disruptions in HR Technology for 2015:  Ignore At Your PerilTen Disruptions in HR Technology for 2015:  Ignore At Your Peril
Ten Disruptions in HR Technology for 2015: Ignore At Your PerilJosh Bersin
 

Viewers also liked (7)

Powering Systems of Engagement
Powering Systems of EngagementPowering Systems of Engagement
Powering Systems of Engagement
 
Marketing, Technology, and the Empowered Customer
Marketing, Technology, and the Empowered CustomerMarketing, Technology, and the Empowered Customer
Marketing, Technology, and the Empowered Customer
 
Business Drivers of SDN by Paul Wiefels, Chasm Group
Business Drivers of SDN by Paul Wiefels, Chasm GroupBusiness Drivers of SDN by Paul Wiefels, Chasm Group
Business Drivers of SDN by Paul Wiefels, Chasm Group
 
Salesforce External Objects for Big Data
Salesforce External Objects for Big DataSalesforce External Objects for Big Data
Salesforce External Objects for Big Data
 
HILTON CRM CASE STUDY
HILTON CRM CASE STUDYHILTON CRM CASE STUDY
HILTON CRM CASE STUDY
 
User Story Mapping, Discover the whole story
User Story Mapping, Discover the whole storyUser Story Mapping, Discover the whole story
User Story Mapping, Discover the whole story
 
Ten Disruptions in HR Technology for 2015: Ignore At Your Peril
Ten Disruptions in HR Technology for 2015:  Ignore At Your PerilTen Disruptions in HR Technology for 2015:  Ignore At Your Peril
Ten Disruptions in HR Technology for 2015: Ignore At Your Peril
 

Similar to Maintainable code

CLR Exception Handing And Memory Management
CLR Exception Handing And Memory ManagementCLR Exception Handing And Memory Management
CLR Exception Handing And Memory ManagementShiny Zhu
 
Android design patterns
Android design patternsAndroid design patterns
Android design patternsVitali Pekelis
 
Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz SAurabh PRajapati
 
Evolve Your Code
Evolve Your CodeEvolve Your Code
Evolve Your CodeRookieOne
 
Design patterns - The Good, the Bad, and the Anti-Pattern
Design patterns -  The Good, the Bad, and the Anti-PatternDesign patterns -  The Good, the Bad, and the Anti-Pattern
Design patterns - The Good, the Bad, and the Anti-PatternBarry O Sullivan
 
Exception handling
Exception handlingException handling
Exception handlingRavi Sharda
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesEdorian
 
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...Codemotion
 
Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Paul Houle
 
Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Paul Houle
 
Exceptions overview
Exceptions overviewExceptions overview
Exceptions overviewBharath K
 
All we like sheep: Cloning as an Engineering Tool
All we like sheep: Cloning as an Engineering ToolAll we like sheep: Cloning as an Engineering Tool
All we like sheep: Cloning as an Engineering Toolmigod
 
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Raffi Khatchadourian
 
Os Keysholistic
Os KeysholisticOs Keysholistic
Os Keysholisticoscon2007
 
Refactoring e Code Smells: Seu código está apodrecendo!
Refactoring e Code Smells:  Seu código está apodrecendo!Refactoring e Code Smells:  Seu código está apodrecendo!
Refactoring e Code Smells: Seu código está apodrecendo!Emanuel Canuto
 

Similar to Maintainable code (20)

CLR Exception Handing And Memory Management
CLR Exception Handing And Memory ManagementCLR Exception Handing And Memory Management
CLR Exception Handing And Memory Management
 
Android design patterns
Android design patternsAndroid design patterns
Android design patterns
 
Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz
 
Evolve Your Code
Evolve Your CodeEvolve Your Code
Evolve Your Code
 
Good++
Good++Good++
Good++
 
Tdd is not about testing
Tdd is not about testingTdd is not about testing
Tdd is not about testing
 
Symbolic Execution And KLEE
Symbolic Execution And KLEESymbolic Execution And KLEE
Symbolic Execution And KLEE
 
Design patterns - The Good, the Bad, and the Anti-Pattern
Design patterns -  The Good, the Bad, and the Anti-PatternDesign patterns -  The Good, the Bad, and the Anti-Pattern
Design patterns - The Good, the Bad, and the Anti-Pattern
 
All of Javascript
All of JavascriptAll of Javascript
All of Javascript
 
Exception handling
Exception handlingException handling
Exception handling
 
Stop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principlesStop wasting-time-by-applying-clean-code-principles
Stop wasting-time-by-applying-clean-code-principles
 
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
 
All of javascript
All of javascriptAll of javascript
All of javascript
 
Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#
 
Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#Extension methods, nulls, namespaces and precedence in c#
Extension methods, nulls, namespaces and precedence in c#
 
Exceptions overview
Exceptions overviewExceptions overview
Exceptions overview
 
All we like sheep: Cloning as an Engineering Tool
All we like sheep: Cloning as an Engineering ToolAll we like sheep: Cloning as an Engineering Tool
All we like sheep: Cloning as an Engineering Tool
 
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
 
Os Keysholistic
Os KeysholisticOs Keysholistic
Os Keysholistic
 
Refactoring e Code Smells: Seu código está apodrecendo!
Refactoring e Code Smells:  Seu código está apodrecendo!Refactoring e Code Smells:  Seu código está apodrecendo!
Refactoring e Code Smells: Seu código está apodrecendo!
 

More from RiverGlide

User Stories Re-explained - Antony Marcano
User Stories Re-explained - Antony MarcanoUser Stories Re-explained - Antony Marcano
User Stories Re-explained - Antony MarcanoRiverGlide
 
Transitioning from component teams to End-to-End Teams
Transitioning from component teams to End-to-End TeamsTransitioning from component teams to End-to-End Teams
Transitioning from component teams to End-to-End TeamsRiverGlide
 
Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern RiverGlide
 
A journey beyond the page object pattern
A journey beyond the page object patternA journey beyond the page object pattern
A journey beyond the page object patternRiverGlide
 
BDD - beyond: Given, When and Then
BDD - beyond: Given, When and ThenBDD - beyond: Given, When and Then
BDD - beyond: Given, When and ThenRiverGlide
 

More from RiverGlide (6)

User Stories Re-explained - Antony Marcano
User Stories Re-explained - Antony MarcanoUser Stories Re-explained - Antony Marcano
User Stories Re-explained - Antony Marcano
 
Transitioning from component teams to End-to-End Teams
Transitioning from component teams to End-to-End TeamsTransitioning from component teams to End-to-End Teams
Transitioning from component teams to End-to-End Teams
 
Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern
 
Robot handles
Robot handlesRobot handles
Robot handles
 
A journey beyond the page object pattern
A journey beyond the page object patternA journey beyond the page object pattern
A journey beyond the page object pattern
 
BDD - beyond: Given, When and Then
BDD - beyond: Given, When and ThenBDD - beyond: Given, When and Then
BDD - beyond: Given, When and Then
 

Maintainable code

  • 1. Writing Maintainable Code Andy Palmer Strong opinions, weakly held
  • 2. Placeholders All of these talking points are placeholders for a conversation. Many of the things that I talk about will make more sense when we start to look at real code. I’ve included sample code where I think it helps explain the concepts, but the real code these lessons were learned from was proprietary, so the examples might seem a little over-simplistic.
  • 3. Fundamentally... The key to maintainable code is to write it so that it can be read and understood easily
  • 4. The long and winding road One of the biggest barriers to understandable code is when it goes on too long. As humans, we can only hold a certain amount of context in our minds at any one time. Methods that go on for tens of lines (or hundreds or thousands) are too complex for us to understand completely. The same is true of classes.
  • 5. Reinvent the wheel? It’s often easy to get into a problem solving mindset, and that’s when we start writing code that’s probably already been done If we’re working on something not directly related to our business domain, check for whether there’s already a library. For example, anything to do with the web, accessing the disk or network, interacting with other processes.
  • 6. Design Patterns Design patterns are very useful to talk about code. If we know the pattern name, we can discuss how this code is doing what it’s doing However Design patterns do not tell us why we are doing something, and so I don’t do design patterns. I make the code easier to read and understand, and then afterwards say “Oh, I used a Decorator there. Cool!”
  • 7. System Metaphor Often, when describing how a system works, we will use a metaphor. We rarely capture this in the code.
  • 8. System Metaphor Often, when describing how a system works, we will use a metaphor. We rarely capture this in the code. What a shame :-(
  • 9. System Metaphor Often, when describing how a system works, we will use a metaphor. We rarely capture this in the code. What a shame :-( A metaphor carries lots of information in a way that is easy to share.
  • 11. System Metaphor (cont.) Metaphor Useful information conveyed Design Patterns Language Idiom Number of people who understand it
  • 12. System Metaphor (cont.) Metaphor Design Patterns Useful information conveyed Hard Difficulty to Learn Design Patterns Language Idiom Metaphor Language Idiom Easy Number of people who understand it Relevance to Domain
  • 13. Guard clauses if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); }
  • 14. Guard clauses if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); } if (someValue != null ) { doSomething(); doSomethingElse(); doSomeMoreSomething(); return result; } return null; // This null is a long way from where we decided to send it
  • 15. Guard clauses if (weDontKnowWhichWireToCut()) { return new GetOutOfHereShesGonnaBlow(); } if (someValue != null ) { doSomething(); doSomethingElse(); doSomeMoreSomething(); return result; } return null; // This null is a long way from where we decided to send it if (someValue == null ) { return null; } // Get out quickly doSomething(); doSomethingElse(); doSomeMoreSomething(); return result;
  • 16. Guard clauses (cont.) Often, we hear “Only one exit point per method” This makes sense in non-garbage-collected languages because the exit point is a good place to tidy up memory allocations. It’s not really relevant in Java, and I’d rather know quickly if there’s some short circuit decision I can make if (!carStarted) { return callAA(); } // duh! engageFirstGear(); if (carStarted) { engageFirstGear(); … 100s of lines … } return callAA(); // Why am I calling the AA here?
  • 17. Nested ifs Cyclomatic complexity for nested ifs follows a geometric progression. For a nest of 5 simple booleans, the number of possible paths is 32. If we have 5 guard clauses, the number of paths is only 10 Look for “mountains” in the code
  • 18. Cull Null “I call it my billion-dollar mistake. It was the invention of the null reference in 1965. […] This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.” - Tony Hoare, QCon 2009
  • 19. Cull Null “I call it my billion-dollar mistake. It was the invention of the null reference in 1965. […] This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.” - Tony Hoare, QCon 2009 If we never return or expect null then we: • no longer need null checks • can trust that what we get is valid • can trust that error handling is dealt with elsewhere
  • 20. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways:
  • 21. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { try { File.open(“some file”); } catch (IOException e) { e.printStackTrace(); } }
  • 22. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { try { File.open(“some file”); or } catch (IOException e) { e.printStackTrace(); } }
  • 23. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { public void someMethod() throws IOException { try { File.open(“some file”); or } File.open(“some file”); } catch (IOException e) { e.printStackTrace(); } }
  • 24. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { public void someMethod() throws IOException { try { File.open(“some file”); or } File.open(“some file”); } catch (IOException e) { e.printStackTrace(); } } Both of which essentially do nothing
  • 25. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { public void someMethod() throws IOException { try { File.open(“some file”); or } File.open(“some file”); } catch (IOException e) { e.printStackTrace(); } } Both of which essentially do nothing and worse... with the second option, details of the exception bubble up far beyond where it makes sense to the caller
  • 26. Throw away Checked Exceptions Typically checked exceptions are handled in one of two ways: public void someMethod() { public void someMethod() throws IOException { try { File.open(“some file”); or } File.open(“some file”); } catch (IOException e) { e.printStackTrace(); } } Both of which essentially do nothing and worse... with the second option, details of the exception bubble up far beyond where it makes sense to the caller If we want to do something, we can use and catch an unchecked exception without all the pollution
  • 27. Fail fast If we know that it doesn’t make sense to continue, then stop. NOW! Don’t return a null or some other non-useful result when we could let the caller know that something needs attention. If we’re constructing an object (such as an email address) and the email is not valid, we can throw an exception in the constructor instead of having to check validity everywhere the email is used. In this way, everyone who uses an EmailAddress knows that it’s a valid value.
  • 28. Code metrics Code metrics can give us good places to look for risky code. They help us discover areas of high complexity or areas of high dependency.
  • 30. Switch statements Have you ever noticed that switch statements have the word break all over the place, and frequently that’s exactly what they do?
  • 31. Switch statements Have you ever noticed that switch statements have the word break all over the place, and frequently that’s exactly what they do? switch statements are often an indication that we have a Type that is trying to get out
  • 32. Static methods Static methods often appear in Utility classes.
  • 33. Static methods Static methods often appear in Utility classes. This makes sense for objects that we don’t control (such as any of the built-in libraries)
  • 34. Static methods Static methods often appear in Utility classes. This makes sense for objects that we don’t control (such as any of the built-in libraries) Well, possibly...
  • 35. Static methods Static methods often appear in Utility classes. This makes sense for objects that we don’t control (such as any of the built-in libraries) Well, possibly... But it almost never makes sense for objects that we own. Most static methods can be replaced with instance methods that are easier to test and understand
  • 36. Poor Man’s Dependency Injection Add an overloaded version of the method or constructor that takes the dependency, and new up the dependency with a sensible default in the simpler case.
  • 37. Poor Man’s Dependency Injection Add an overloaded version of the method or constructor that takes the dependency, and new up the dependency with a sensible default in the simpler case. public void someMethod() { return someMethod(new Dependency()); } public void someMethod(Dependency dependency) { return dependency.doSomething(); }
  • 38. I want to store £123.45 What data type should I use?
  • 39. I want to store £123.45 What data type should I use? float: The float data type is a single-precision 32-bit IEEE 754 floating point. Use a float (instead of double) if you need to save memory in large arrays of floating point numbers.
  • 40. I want to store £123.45 What data type should I use? float: The float data type is a single-precision 32-bit IEEE 754 floating point. Use a float (instead of double) if you need to save memory in large arrays of floating point numbers. double: The double data type is a double-precision 64-bit IEEE 754 floating point.
  • 41. I want to store £123.45 What data type should I use? float: The float data type is a single-precision 32-bit IEEE 754 floating point. Use a float (instead of double) if you need to save memory in large arrays of floating point numbers. double: The double data type is a double-precision 64-bit IEEE 754 floating point. These data types should never be used for precise values, such as currency. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
  • 42. I want to store £123.45 What data type should I use? float: The float data type is a single-precision 32-bit IEEE 754 floating point. Use a float (instead of double) if you need to save memory in large arrays of floating point numbers. double: The double data type is a double-precision 64-bit IEEE 754 floating point. These data types should never be used for precise values, such as currency. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html Use the java.math.BigDecimal class instead
  • 43. Avoid a void void methods restrict our ability to extract composed methods e.g., ServletFilter.doFilter for Authorisation If we’re authorised, we want to continue to the resource If we’re unauthenticated, then redirect us to the login page If we’re unauthorised, redirect us to the Access Denied page For the first case, we want to do a FilterChain.doFilter For the others we don’t
  • 44. Avoid a void (cont.) public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { if (filterWorkflow() == Do.Filter) { chain.doFilter(…); } } public Do filterWorkflow() { if (userIsAuthorised()) { return Do.Filter; } if (userIsNotLoggedIn()) { return Do.Redirect(LoginPage); } if (userIsNotAuthorised()) { return Do.Redirect(AccessDenied); } }
  • 45. Extending Exceptions One of the things that I do in my code is to make an obvious separation between types of exception. I use Apology for something that the program should reasonably have been able to do, but failed (like fetching a User from a database) I use Complaint for something that the program could not possibly have achieved (like returning a single result when the criteria specify multiple results)
  • 46. Look outside of your area One of the best books on programming that I’ve read is called “Perl Medic”. It covers most of what we’ve covered here and is completely applicable to any language (it’s just that the examples are in Perl)
  • 47. Look outside of your area One of the best books on programming that I’ve read is called “Perl Medic”. It covers most of what we’ve covered here and is completely applicable to any language (it’s just that the examples are in Perl) Many .Netters who go to the Alt.Net events end up migrating away from .Net once they see how easy it is to do things in other languages.
  • 48. Continuous Learning I read blogs most days, across a wide variety of languages and topics. A problem that someone has solved in another domain might be transferrable to mine. We’ve never learned everything, there’s always something new. Go to a coding dojo, code retreat, or a language meetup (especially if it’s for a language other than your own) Hold “lunch and learns” or “after school clubs” in the office (get the company to buy pizza) Read books (I have lots of recommendations) Question conventional wisdom

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n