SlideShare une entreprise Scribd logo
1  sur  66
Stop That! Questioning Dogmatic Programming
or Things I Wish My Coworkers Would Stop Doing

Doug Hiebert

Thank you to our Sponsors
About Me

Doug Sparling / Doug Hiebert
Software Dev - Protegra
Twitter: @doughiebert
Email: doug.hiebert@protegra.com
Dogmatism

noun
1. The tendency to lay down principles as undeniably true,
without consideration of evidence or the opinions of
others.
Programming Dogma

•
•
•
•

“A, B and C are best practices”
“X considered harmful”
“Y is evil”
“language/technology/tool Z is the best”
Programming Dogma

“Break any of these rules sooner than [code] anything
outright barbarous.”
-- George Orwell, "Politics and the English Language,"
1946
Good Programming Dogma

•
•
•
•
•

Format your code
Have a coding standard
Prefer simplicity
Refactor continuously
Use modular design
Bad Programming Dogma

•
•
•
•

Comment your code
Don’t waste cycles
Decide with conditionals
Handle all errors
Comment Your Code

/**
* @return Always returns true.
*/
public boolean isAvailable() {
return false; // FIXME: temporary testing
}
Comment Your Code

• Communicates programmer intent
- The “why” to the code’s “what”

• Explains tricky/clever code
• Explains how to use APIs/interfaces
Communicating Intent

for (Person person : people) {
if (person.getAge() >= 65) {
sendCheque(person.getAddress());
}
}
Communicating Intent

for (Person person : people) {
// send cheque to persons old enough
// to qualify for pension payout
if (person.getAge() >= 65) {
sendCheque(person.getAddress());
}
}
Communicating Intent

for (Person person : people) {
// send cheque to persons old enough
// to qualify for pension payout
if (person.getAge() >= 65 ||
person.getYearsOfService() > 30) {
sendCheque(person.getAddress());
}
}
Communicating Intent

•
•
•
•

Skipped by refactoring tools
Not essential for program function
Poorly written or misleading
Some people ignore them (like me!)
Comment-Eliminating Refactorings

• Comment as Method
• Comment as Local Variable
• Comment as Constant
Comment as Method

for (Person person : people) {
if (oldEnoughForPensionPayout(person)) {
sendCheque(person.getAddress());
}
}
...
boolean oldEnoughForPensionPayout(Person p) {
return p.getAge() >= 65;
}
Comment as Local Variable

for (Person person : people) {
boolean oldEnoughForPensionPayout =
person.getAge() >= 65;

if (oldEnoughForPensionPayout) {
sendCheque(person.getAddress());
}
}
Comment as Constant

private static final int
MIN_AGE_FOR_PENSION_PAYOUT = 65;
for (Person person : people) {
if (person.getAge() >=
MIN_AGE_FOR_PENSION_PAYOUT) {
sendCheque(person.getAddress());
}
}
Explain Tricky/Clever Code

# calculates the average
a = vals.inject(0.0) { |s, v| s + v } /
vals.size
Explain Tricky/Clever Code

sum = vals.inject(0.0) { |total, val|
total + val }
average = sum / vals.size
Explain APIs/Interfaces

• Code intended for re-use by others
• Library of classes, methods, utilities, etc.
• RDoc, Javadoc, etc.
Explain APIs/Interfaces

interface PersonRepository {
Set<Person> findPeople(String text);
...
}
Explain APIs/Interfaces

/**
* <p><b>Usage:</b></p>
*
* <pre>
* PersonRepository exampleRepo = makeRepository(bobJones, joelStevens,
shirleySmith);
*
* List<Person> persons = exampleRepo.findPeople("jo");
*
* persons.get(0); // bobJones
* persons.get(1); // joelStevens
* </pre>
*
* @author Doug
*/
interface PersonRepository {
List<Person> findPeople(String text);
...
}
Explain APIs/Interfaces

@Test
public void testFindPeopleByFirstAndLastName() {
Person bobJones = testPerson("Bob Jones");
Person joelStevens = testPerson("Joel Stevens");
Person shirleySmith = testPerson("Shirley Smith");

PersonRepository exampleRepo = makeRepository(
bobJones, joelStevens, shirleySmith);
List<Person> persons = exampleRepo.findPeople("jo");

assertEquals(bobJones, persons.get(0));
assertEquals(joelStevens, persons.get(1);
}
Documentation

• Comments are a type of documentation
• Good examples of documentation:
- User’s guide/manual
- Architecture diagrams
- Decision log
A Final Note About Comments

/**
* The person's name.
*/
private String name;
...
/**
* Returns the person's name.
*
* @return the person’s name
*/
public String getName() {
return name;
}
Don’t Waste Cycles

• Improve UI response
• Speed up long-running batch jobs
• Satisfaction of “eliminating waste”
Don’t Waste Cycles
void calcAverages1(List<Person> people) {
double averageAge = averageAge(people);
double averageHeight = averageHeight(people);
...
}
double averageAge(List<Person> people) {
long ageSum = 0;
for (Person person : people) {
ageSum += person.getAge();
}
return (double) (ageSum / people.size());
}
double averageHeight(List<Person> people) { /* as above */ }
Don’t Waste Cycles

void calcAverages2() {
long ageSum = 0;
long heightSum = 0;
for (Person person : people) {
ageSum += person.getAge();
heightSum += person.getHeight();
}
double averageAge = ageSum / people.size();
double averageHeight = heightSum / people.size();
...
}
Don’t Waste Cycles

• Microbenchmark parameters:
- 1,000,000 people
- 1500 iteration warm-up
- 10 runs (averaged)

• calcAverages1: 7237μs
• calcAverages2: 3640μs
• Roughly 100% slower (as expected)
• Only 3.6ms (imperceptible)
Don’t Waste Cycles

“Premature optimization is the root of all evil”
-- Donald Knuth
Decide with Conditionals

• if, unless, else, ?:, etc.
- Implement conditional logic
- Handle errors
- Null checking

• switch, case, etc.
- exhaustively handle different cases
Decide with Conditionals

public List<String> parseNames(String names) {

if (names == null) {
return null;
}
return Arrays.asList(names.split(","));
}
void readNames() {
String line = System.console().readLine();
List<String> names = parseNames(line);
if (names != null) {
for (String name : names) {
// ...
}
}
}
Null Object Pattern

public List<String> parseNames2(String names) {
if (names == null) {
return Collections.emptyList();
}
return Arrays.asList(names.split(","));
}
Null Object Pattern

public class CommandLookup {
public Command findCommand(String command) {
if (validCommand(command)) {
// ...
} else {
return new NullCommand();
}
}
public class NullCommand implements Command {
public void execute() {
// do nothing
}
}
}
Option Type

Option<String> aString = Option.some("string");
Option<String> noString = Option.none();
F<...> length = new F<String, Integer>() {
public Integer f(String str) {
return str.length();
}
};
aString.map(length).orSome(42); // 6
noString.map(length).orSome(0); // 0
Option<T> Type

public List<String> parseNames3(
Option<String> names) {
return Arrays.asList(
names.orSome("").split(","));
}
Decide with Conditionals

interface SensorPackage {
int getTemperature();
int getHumidity();
int getPressure();
}
Decide with Conditionals

enum SensorType {
TEMPERATURE, HUMIDITY, PRESSURE;
}
Decide with Conditionals

public int readSensor(SensorType sensorType) {
switch (sensorType) {
case TEMPERATURE:
return weatherSensor.getTemperature();
case HUMIDITY:
return weatherSensor.getHumidity();
case PRESSURE:
return weatherSensor.getPressure();
default:
throw new IllegalArgumentException("...");
}
}
Replace Conditional with
Polymorphism
enum SensorType {

abstract int getReading(SensorPackage sensors);
TEMPERATURE {
public int
return
}
}, HUMIDITY {
public int
return
}
}, PRESSURE {
...
};
}

getReading(SensorPackage sensors) {
sensors.getTemperature();

getReading(SensorPackage sensors) {
sensors.getHumidity();
Replace Conditional with
Polymorphism
abstract class SensorWrapper {
abstract int getReading();
static class TemperatureSensorWrapper extends SensorWrapper {
private SensorPackage sensorPackage;
public TemperatureSensorWrapper(SensorPackage sensorPackage) { /*...*/ }
int getReading() { return sensorPackage.getTemperature(); }
}
static SensorWrapper create(
SensorType sensorType, SensorPackage sensorPackage) {
switch (sensorType) {
case TEMPERATURE: return new TemperatureSensorWrapper(sensorPackage);
case ...
default: throw new IllegalArgumentException("...");
}
}
}
Decide with Conditionals

if (province == Province.MB
&& productType == ProductType.WIDGET) {
tax = 0.05; // no PST on widgets in MB
} else if (province == Province.MB) {
tax = 0.13;
} else if (province == Province.AB) {
tax = 0.05;
} else if (...) {
// and so on
} else if (...) {
Replace Conditional with Map

static {
taxByProvince.put(Province.MB, 0.13);
taxByProvince.put(Province.AB, 0.05);
// ... etc.
}

if (province == Province.MB
&& productType == ProductType.WIDGET) {
tax = 0.05; // no PST on widgets in MB
} else {
tax = taxByProvince.get(province);
}
Anti-If Campaign
Anti-If Campaign

•
•
•
•

Cyclomatic complexity
if-else chains invite trouble
Polymorphism more appropriate
Testing is tedious
Handle All Errors

private Map<String, File> imagesMap = ...
...
Image image = null;
File imageFile = imagesMap.get("expectedImage");
try {
if (imageFile != null) {
image = ImageIO.read(imageFile);
}
} catch (IOException e) {
// image could not be read
}

if (image != null) {
// do something with image
}
Handle All Errors

High
Level
main(...)
{
try {
...
} catch {
...
}
}

...
...

...

Low
Level
throw e;

...
...

...

...
Wrap Exception

static class ImageUtil {
static BufferedImage read(File imageFile) {
try {
return ImageIO.read(imageFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Wrap Checked Exception

private Map<String, File> imagesMap = ...
...
File imageFile =
imagesMap.get("expectedImage");
Image image = null;
if (imageFile != null) {
image = ImageUtil.read(imageFile);
}
// do something with image
Push Error Handling Down

public class ImageKeyNotFoundException extends
RuntimeException { ... }
public File getImageFile(String imageKey) {
if (imagesMap.get(imageKey) == null) {
throw new ImageKeyNotFoundException(
"image key not found: " + imageKey);
}
return imagesMap.get(imageKey);
}
Push Error Handling Down

File imageFile = getImageFile("expectedImage");
Image image = ImageUtil.read(imageFile);
// do something with image
In Conclusion
In Conclusion

“The only „best practice‟ you should be using all
the time is „Use Your Brain‟”
-- Steven Robbins, StackExchange
More Information / Next Steps

• Clean Code (free!)
• Pragmatic Programmer (classic!)
• Code Complete 2nd Edition (thick?)
Thank You!
@doughiebert
doug.hiebert@protegra.com

Thank you to our Sponsors

Contenu connexe

Tendances

Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youAndrey Karpov
 
Guaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in RustGuaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in Rustnikomatsakis
 
Introduction to Functional Programming with Scheme
Introduction to Functional Programming with SchemeIntroduction to Functional Programming with Scheme
Introduction to Functional Programming with SchemeDoc Norton
 
Killing Bugs with Pry
Killing Bugs with PryKilling Bugs with Pry
Killing Bugs with PryJason Carter
 
Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Claudio Capobianco
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09Guy Korland
 
Clojure ♥ cassandra
Clojure ♥ cassandra Clojure ♥ cassandra
Clojure ♥ cassandra Max Penet
 
London-GGUG 2015 - Metaprogramming Options with Groovy
London-GGUG 2015 - Metaprogramming Options with GroovyLondon-GGUG 2015 - Metaprogramming Options with Groovy
London-GGUG 2015 - Metaprogramming Options with GroovyIván López Martín
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsAzul Systems, Inc.
 
Non-blocking synchronization — what is it and why we (don't?) need it
Non-blocking synchronization — what is it and why we (don't?) need itNon-blocking synchronization — what is it and why we (don't?) need it
Non-blocking synchronization — what is it and why we (don't?) need itAlexey Fyodorov
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an OverviewRoberto Casadei
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Dimitrios Platis
 
Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrencypriyank09
 
4 - OOP - Taste of Smalltalk (Tamagoshi)
4 - OOP - Taste of Smalltalk (Tamagoshi)4 - OOP - Taste of Smalltalk (Tamagoshi)
4 - OOP - Taste of Smalltalk (Tamagoshi)The World of Smalltalk
 
Rust: Reach Further (from QCon Sao Paolo 2018)
Rust: Reach Further (from QCon Sao Paolo 2018)Rust: Reach Further (from QCon Sao Paolo 2018)
Rust: Reach Further (from QCon Sao Paolo 2018)nikomatsakis
 

Tendances (20)

Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
 
Guaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in RustGuaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in Rust
 
Drools Ecosystem
Drools EcosystemDrools Ecosystem
Drools Ecosystem
 
Introduction to Functional Programming with Scheme
Introduction to Functional Programming with SchemeIntroduction to Functional Programming with Scheme
Introduction to Functional Programming with Scheme
 
Killing Bugs with Pry
Killing Bugs with PryKilling Bugs with Pry
Killing Bugs with Pry
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09
 
Clojure ♥ cassandra
Clojure ♥ cassandra Clojure ♥ cassandra
Clojure ♥ cassandra
 
JavaTalks: OOD principles
JavaTalks: OOD principlesJavaTalks: OOD principles
JavaTalks: OOD principles
 
London-GGUG 2015 - Metaprogramming Options with Groovy
London-GGUG 2015 - Metaprogramming Options with GroovyLondon-GGUG 2015 - Metaprogramming Options with Groovy
London-GGUG 2015 - Metaprogramming Options with Groovy
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
Non-blocking synchronization — what is it and why we (don't?) need it
Non-blocking synchronization — what is it and why we (don't?) need itNon-blocking synchronization — what is it and why we (don't?) need it
Non-blocking synchronization — what is it and why we (don't?) need it
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an Overview
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
 
Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrency
 
4 - OOP - Taste of Smalltalk (Tamagoshi)
4 - OOP - Taste of Smalltalk (Tamagoshi)4 - OOP - Taste of Smalltalk (Tamagoshi)
4 - OOP - Taste of Smalltalk (Tamagoshi)
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
 
Rust: Reach Further (from QCon Sao Paolo 2018)
Rust: Reach Further (from QCon Sao Paolo 2018)Rust: Reach Further (from QCon Sao Paolo 2018)
Rust: Reach Further (from QCon Sao Paolo 2018)
 
8 - OOP - Smalltalk Syntax
8 - OOP - Smalltalk Syntax8 - OOP - Smalltalk Syntax
8 - OOP - Smalltalk Syntax
 

En vedette

Advanced Web Graphics with Canvas
Advanced Web Graphics with CanvasAdvanced Web Graphics with Canvas
Advanced Web Graphics with CanvasJason Harwig
 
JavaScript Language Paradigms
JavaScript Language ParadigmsJavaScript Language Paradigms
JavaScript Language ParadigmsJason Harwig
 
Functional Javascript, CVjs
Functional Javascript, CVjsFunctional Javascript, CVjs
Functional Javascript, CVjskaw2
 
Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Will Kurt
 
A Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC LibrariesA Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC LibrariesBrian Moschel
 
Functional javascript
Functional javascriptFunctional javascript
Functional javascriptMagnus Lassi
 
How to not suck at JavaScript
How to not suck at JavaScriptHow to not suck at JavaScript
How to not suck at JavaScripttmont
 
Maria Elena Gutierrez Reyes Gerencia de proyectos
 Maria Elena Gutierrez Reyes  Gerencia de proyectos Maria Elena Gutierrez Reyes  Gerencia de proyectos
Maria Elena Gutierrez Reyes Gerencia de proyectosmisticalsand
 
Estrategias que no funcionan
Estrategias que no funcionanEstrategias que no funcionan
Estrategias que no funcionanJose M Leon H
 
Gary resume draft 022315-6
Gary resume draft 022315-6Gary resume draft 022315-6
Gary resume draft 022315-6Gary Waxman
 
How I got over my fear of teleportation
How I got over my fear of teleportationHow I got over my fear of teleportation
How I got over my fear of teleportationWill Kurt
 
брейн ринг
брейн рингбрейн ринг
брейн рингsemyurihor
 

En vedette (14)

Advanced Web Graphics with Canvas
Advanced Web Graphics with CanvasAdvanced Web Graphics with Canvas
Advanced Web Graphics with Canvas
 
JavaScript Language Paradigms
JavaScript Language ParadigmsJavaScript Language Paradigms
JavaScript Language Paradigms
 
Functional Javascript, CVjs
Functional Javascript, CVjsFunctional Javascript, CVjs
Functional Javascript, CVjs
 
Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)
 
A Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC LibrariesA Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC Libraries
 
Functional javascript
Functional javascriptFunctional javascript
Functional javascript
 
How to not suck at JavaScript
How to not suck at JavaScriptHow to not suck at JavaScript
How to not suck at JavaScript
 
Maria Elena Gutierrez Reyes Gerencia de proyectos
 Maria Elena Gutierrez Reyes  Gerencia de proyectos Maria Elena Gutierrez Reyes  Gerencia de proyectos
Maria Elena Gutierrez Reyes Gerencia de proyectos
 
Estrategias que no funcionan
Estrategias que no funcionanEstrategias que no funcionan
Estrategias que no funcionan
 
Inteligenciaartificial
InteligenciaartificialInteligenciaartificial
Inteligenciaartificial
 
RUNYOURBIZONOFFICE365 (1)
RUNYOURBIZONOFFICE365 (1)RUNYOURBIZONOFFICE365 (1)
RUNYOURBIZONOFFICE365 (1)
 
Gary resume draft 022315-6
Gary resume draft 022315-6Gary resume draft 022315-6
Gary resume draft 022315-6
 
How I got over my fear of teleportation
How I got over my fear of teleportationHow I got over my fear of teleportation
How I got over my fear of teleportation
 
брейн ринг
брейн рингбрейн ринг
брейн ринг
 

Similaire à Stop that!

Algorithms - Future Decoded 2016
Algorithms - Future Decoded 2016Algorithms - Future Decoded 2016
Algorithms - Future Decoded 2016Frank Krueger
 
Java best practices
Java best practicesJava best practices
Java best practicesRay Toal
 
Drools Introduction
Drools IntroductionDrools Introduction
Drools IntroductionJBug Italy
 
SOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSergey Karpushin
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for CassandraEdward Capriolo
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"DataStax Academy
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptxTamas Rev
 
Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with FindbugsCarol McDonald
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! aleks-f
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable CodeBaidu, Inc.
 
Clean & Typechecked JS
Clean & Typechecked JSClean & Typechecked JS
Clean & Typechecked JSArthur Puthin
 
Refactoring at Large
Refactoring at LargeRefactoring at Large
Refactoring at LargeDanilo Sato
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The LandingHaci Murat Yaman
 

Similaire à Stop that! (20)

Clean Code 2
Clean Code 2Clean Code 2
Clean Code 2
 
Algorithms - Future Decoded 2016
Algorithms - Future Decoded 2016Algorithms - Future Decoded 2016
Algorithms - Future Decoded 2016
 
Java best practices
Java best practicesJava best practices
Java best practices
 
Drools Introduction
Drools IntroductionDrools Introduction
Drools Introduction
 
SOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principles
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptx
 
Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with Findbugs
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! 
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
SOLID Java Code
SOLID Java CodeSOLID Java Code
SOLID Java Code
 
Day 1
Day 1Day 1
Day 1
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable Code
 
Clean & Typechecked JS
Clean & Typechecked JSClean & Typechecked JS
Clean & Typechecked JS
 
Refactoring at Large
Refactoring at LargeRefactoring at Large
Refactoring at Large
 
Javascript 101
Javascript 101Javascript 101
Javascript 101
 
CSC PPT 13.pptx
CSC PPT 13.pptxCSC PPT 13.pptx
CSC PPT 13.pptx
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 

Dernier

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 

Dernier (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 

Stop that!

  • 1. Stop That! Questioning Dogmatic Programming or Things I Wish My Coworkers Would Stop Doing Doug Hiebert Thank you to our Sponsors
  • 2. About Me Doug Sparling / Doug Hiebert Software Dev - Protegra Twitter: @doughiebert Email: doug.hiebert@protegra.com
  • 3. Dogmatism noun 1. The tendency to lay down principles as undeniably true, without consideration of evidence or the opinions of others.
  • 4. Programming Dogma • • • • “A, B and C are best practices” “X considered harmful” “Y is evil” “language/technology/tool Z is the best”
  • 5. Programming Dogma “Break any of these rules sooner than [code] anything outright barbarous.” -- George Orwell, "Politics and the English Language," 1946
  • 6. Good Programming Dogma • • • • • Format your code Have a coding standard Prefer simplicity Refactor continuously Use modular design
  • 7. Bad Programming Dogma • • • • Comment your code Don’t waste cycles Decide with conditionals Handle all errors
  • 8. Comment Your Code /** * @return Always returns true. */ public boolean isAvailable() { return false; // FIXME: temporary testing }
  • 9. Comment Your Code • Communicates programmer intent - The “why” to the code’s “what” • Explains tricky/clever code • Explains how to use APIs/interfaces
  • 10. Communicating Intent for (Person person : people) { if (person.getAge() >= 65) { sendCheque(person.getAddress()); } }
  • 11. Communicating Intent for (Person person : people) { // send cheque to persons old enough // to qualify for pension payout if (person.getAge() >= 65) { sendCheque(person.getAddress()); } }
  • 12.
  • 13. Communicating Intent for (Person person : people) { // send cheque to persons old enough // to qualify for pension payout if (person.getAge() >= 65 || person.getYearsOfService() > 30) { sendCheque(person.getAddress()); } }
  • 14. Communicating Intent • • • • Skipped by refactoring tools Not essential for program function Poorly written or misleading Some people ignore them (like me!)
  • 15. Comment-Eliminating Refactorings • Comment as Method • Comment as Local Variable • Comment as Constant
  • 16. Comment as Method for (Person person : people) { if (oldEnoughForPensionPayout(person)) { sendCheque(person.getAddress()); } } ... boolean oldEnoughForPensionPayout(Person p) { return p.getAge() >= 65; }
  • 17. Comment as Local Variable for (Person person : people) { boolean oldEnoughForPensionPayout = person.getAge() >= 65; if (oldEnoughForPensionPayout) { sendCheque(person.getAddress()); } }
  • 18. Comment as Constant private static final int MIN_AGE_FOR_PENSION_PAYOUT = 65; for (Person person : people) { if (person.getAge() >= MIN_AGE_FOR_PENSION_PAYOUT) { sendCheque(person.getAddress()); } }
  • 19. Explain Tricky/Clever Code # calculates the average a = vals.inject(0.0) { |s, v| s + v } / vals.size
  • 20.
  • 21. Explain Tricky/Clever Code sum = vals.inject(0.0) { |total, val| total + val } average = sum / vals.size
  • 22. Explain APIs/Interfaces • Code intended for re-use by others • Library of classes, methods, utilities, etc. • RDoc, Javadoc, etc.
  • 23. Explain APIs/Interfaces interface PersonRepository { Set<Person> findPeople(String text); ... }
  • 24. Explain APIs/Interfaces /** * <p><b>Usage:</b></p> * * <pre> * PersonRepository exampleRepo = makeRepository(bobJones, joelStevens, shirleySmith); * * List<Person> persons = exampleRepo.findPeople("jo"); * * persons.get(0); // bobJones * persons.get(1); // joelStevens * </pre> * * @author Doug */ interface PersonRepository { List<Person> findPeople(String text); ... }
  • 25.
  • 26. Explain APIs/Interfaces @Test public void testFindPeopleByFirstAndLastName() { Person bobJones = testPerson("Bob Jones"); Person joelStevens = testPerson("Joel Stevens"); Person shirleySmith = testPerson("Shirley Smith"); PersonRepository exampleRepo = makeRepository( bobJones, joelStevens, shirleySmith); List<Person> persons = exampleRepo.findPeople("jo"); assertEquals(bobJones, persons.get(0)); assertEquals(joelStevens, persons.get(1); }
  • 27. Documentation • Comments are a type of documentation • Good examples of documentation: - User’s guide/manual - Architecture diagrams - Decision log
  • 28. A Final Note About Comments /** * The person's name. */ private String name; ... /** * Returns the person's name. * * @return the person’s name */ public String getName() { return name; }
  • 29.
  • 30.
  • 31. Don’t Waste Cycles • Improve UI response • Speed up long-running batch jobs • Satisfaction of “eliminating waste”
  • 32. Don’t Waste Cycles void calcAverages1(List<Person> people) { double averageAge = averageAge(people); double averageHeight = averageHeight(people); ... } double averageAge(List<Person> people) { long ageSum = 0; for (Person person : people) { ageSum += person.getAge(); } return (double) (ageSum / people.size()); } double averageHeight(List<Person> people) { /* as above */ }
  • 33. Don’t Waste Cycles void calcAverages2() { long ageSum = 0; long heightSum = 0; for (Person person : people) { ageSum += person.getAge(); heightSum += person.getHeight(); } double averageAge = ageSum / people.size(); double averageHeight = heightSum / people.size(); ... }
  • 34.
  • 35. Don’t Waste Cycles • Microbenchmark parameters: - 1,000,000 people - 1500 iteration warm-up - 10 runs (averaged) • calcAverages1: 7237μs • calcAverages2: 3640μs • Roughly 100% slower (as expected) • Only 3.6ms (imperceptible)
  • 36. Don’t Waste Cycles “Premature optimization is the root of all evil” -- Donald Knuth
  • 37.
  • 38. Decide with Conditionals • if, unless, else, ?:, etc. - Implement conditional logic - Handle errors - Null checking • switch, case, etc. - exhaustively handle different cases
  • 39. Decide with Conditionals public List<String> parseNames(String names) { if (names == null) { return null; } return Arrays.asList(names.split(",")); } void readNames() { String line = System.console().readLine(); List<String> names = parseNames(line); if (names != null) { for (String name : names) { // ... } } }
  • 40.
  • 41. Null Object Pattern public List<String> parseNames2(String names) { if (names == null) { return Collections.emptyList(); } return Arrays.asList(names.split(",")); }
  • 42. Null Object Pattern public class CommandLookup { public Command findCommand(String command) { if (validCommand(command)) { // ... } else { return new NullCommand(); } } public class NullCommand implements Command { public void execute() { // do nothing } } }
  • 43. Option Type Option<String> aString = Option.some("string"); Option<String> noString = Option.none(); F<...> length = new F<String, Integer>() { public Integer f(String str) { return str.length(); } }; aString.map(length).orSome(42); // 6 noString.map(length).orSome(0); // 0
  • 44. Option<T> Type public List<String> parseNames3( Option<String> names) { return Arrays.asList( names.orSome("").split(",")); }
  • 45. Decide with Conditionals interface SensorPackage { int getTemperature(); int getHumidity(); int getPressure(); }
  • 46. Decide with Conditionals enum SensorType { TEMPERATURE, HUMIDITY, PRESSURE; }
  • 47. Decide with Conditionals public int readSensor(SensorType sensorType) { switch (sensorType) { case TEMPERATURE: return weatherSensor.getTemperature(); case HUMIDITY: return weatherSensor.getHumidity(); case PRESSURE: return weatherSensor.getPressure(); default: throw new IllegalArgumentException("..."); } }
  • 48.
  • 49. Replace Conditional with Polymorphism enum SensorType { abstract int getReading(SensorPackage sensors); TEMPERATURE { public int return } }, HUMIDITY { public int return } }, PRESSURE { ... }; } getReading(SensorPackage sensors) { sensors.getTemperature(); getReading(SensorPackage sensors) { sensors.getHumidity();
  • 50. Replace Conditional with Polymorphism abstract class SensorWrapper { abstract int getReading(); static class TemperatureSensorWrapper extends SensorWrapper { private SensorPackage sensorPackage; public TemperatureSensorWrapper(SensorPackage sensorPackage) { /*...*/ } int getReading() { return sensorPackage.getTemperature(); } } static SensorWrapper create( SensorType sensorType, SensorPackage sensorPackage) { switch (sensorType) { case TEMPERATURE: return new TemperatureSensorWrapper(sensorPackage); case ... default: throw new IllegalArgumentException("..."); } } }
  • 51. Decide with Conditionals if (province == Province.MB && productType == ProductType.WIDGET) { tax = 0.05; // no PST on widgets in MB } else if (province == Province.MB) { tax = 0.13; } else if (province == Province.AB) { tax = 0.05; } else if (...) { // and so on } else if (...) {
  • 52. Replace Conditional with Map static { taxByProvince.put(Province.MB, 0.13); taxByProvince.put(Province.AB, 0.05); // ... etc. } if (province == Province.MB && productType == ProductType.WIDGET) { tax = 0.05; // no PST on widgets in MB } else { tax = taxByProvince.get(province); }
  • 54. Anti-If Campaign • • • • Cyclomatic complexity if-else chains invite trouble Polymorphism more appropriate Testing is tedious
  • 55.
  • 56. Handle All Errors private Map<String, File> imagesMap = ... ... Image image = null; File imageFile = imagesMap.get("expectedImage"); try { if (imageFile != null) { image = ImageIO.read(imageFile); } } catch (IOException e) { // image could not be read } if (image != null) { // do something with image }
  • 57.
  • 58. Handle All Errors High Level main(...) { try { ... } catch { ... } } ... ... ... Low Level throw e; ... ... ... ...
  • 59. Wrap Exception static class ImageUtil { static BufferedImage read(File imageFile) { try { return ImageIO.read(imageFile); } catch (IOException e) { throw new RuntimeException(e); } } }
  • 60. Wrap Checked Exception private Map<String, File> imagesMap = ... ... File imageFile = imagesMap.get("expectedImage"); Image image = null; if (imageFile != null) { image = ImageUtil.read(imageFile); } // do something with image
  • 61. Push Error Handling Down public class ImageKeyNotFoundException extends RuntimeException { ... } public File getImageFile(String imageKey) { if (imagesMap.get(imageKey) == null) { throw new ImageKeyNotFoundException( "image key not found: " + imageKey); } return imagesMap.get(imageKey); }
  • 62. Push Error Handling Down File imageFile = getImageFile("expectedImage"); Image image = ImageUtil.read(imageFile); // do something with image
  • 64. In Conclusion “The only „best practice‟ you should be using all the time is „Use Your Brain‟” -- Steven Robbins, StackExchange
  • 65. More Information / Next Steps • Clean Code (free!) • Pragmatic Programmer (classic!) • Code Complete 2nd Edition (thick?)

Notes de l'éditeur

  1. Welcome to my talk: Questioning Dogmatic Programming, or, “things I wish my coworkers would stop doing”. This is a a semi-serious talk about lots of programming practices that are taken for granted, but that I think should be avoided at all costs.
  2. What form does dogmatism take in the programming community?&lt;read list&gt;Considering programming is a logical, rational activity people sure have a lot of rigid beliefs. You’ll never find justification provided in similar strength to these claims.
  3. Here’s a butchered quote that has guided my personal philosophy regarding so-called rules, idioms, best practices, whatever you want to call them.&lt;quote&gt;So what rules should we be following and what rules should we be breaking?
  4. Not saying all dogma is bad: there are lots of good examples.Formatting code: no reason not to, tools do it automatically, improves readabilityThings like using camelcase for methods, don’t allow multiple returns, whatever. Improves readability among the team and we don’t waste time thinking about trivial things.All things being equal: less code is better than more code, and simpler designs are better than complex design.Everybody should be refactoring their code as they go.Modular fashion, parts of the system are essentially black boxes that talk to each other. Can&apos;t think of a reason not to do this.
  5. Here are some more statements that are broadly accepted as true but are actually almost always wrong.&lt;read the list to prime people&gt;In this talk we’ll go over some situations where dogmatic adherence to these principles will get you into lots of trouble. Or at least get the future maintainers of your code into trouble.
  6. Okay, let’s start with comments. Every programming language has this neat feature: you can put whatever you want after or in between certain characters. Then, using the syntax highlighting, readers are trained to ignore blue and green text. It’s really handy.
  7. Seriously, though: first get introduced to dogmatic thinking in education: always comment your code. Lose marks for uncommented code, or profs give you standard headers describing inputs, outputs etc. and you have to fill them in.Intent: what the programmer was trying to accomplishTricky: if code is non-obvious, does something unusual, or is otherwise unclear, comments can elaborateAPI/interface: for code intended for re-use such as APIs or interfaces, comments provide examples of use, what parameters to pass, what the structure of results are, etc.One argument says: code is literal; can only explain what is going on: not why it needs to be done.
  8. Very clear what this code is doing, but why is it doing it? What business rule can explain it?
  9. Might be tempted to throw in a comment to explain why we need to send the cheque…
  10. Stop doing this! Already have something that communicates what the programmer is trying to do… the code!Repetitious (violates DRY) to simply re-state what the code is doing, even if you add extra information or summarize.
  11. Oops, the code is working correctly but the comment is no longer accurate. At best, people will ignore the comment, or at worst somebody reading it may be misled. Might try to track down a bug and assume that the problem lies with the person’s age. &lt;explanation of wrongness ahead&gt;
  12. What else can go wrong?Skipped: refactoring tools won’t update comments, and some people use them blindly without checking updated code (e.g. rename method at 100 call sites… are you going to check them all?)Not-essential: Poorly written: we’re hired as programmers, not writers. Lots of comments are just badly written, full of typos. Don’t give you much confidence.Ignored: some people like myself have been burned so many times by bad comments that they are just trained to ignore them entirely. &lt;anecdote about not seeing Dave’s comment block in rails partial)&gt;. So they end up as a waste of your time to write and waste of space.
  13. So how to we eliminate these sorts of comments? Each of these refactorings takes a comment and embeds it into the program as a symbol, which you are forced to read as part of the program. They are refactorable, can be as descriptive, and leave the code cleaner than comments.
  14. In this refactoring, we give method a name to include additional meaning, or why it&apos;s being done.This embeds the “why” directly in the code and improves the readability of the original code.Maintainers are practically forced to read the method name, and it occurs in multiple places, so the code isless likely to be modified such that the method name is invalid. I’ve seen it happen, but not nearly as often.
  15. more compact than the &quot;comment as method&quot; refactoring, but equally descriptive. Good for one-offs.
  16. Constant helps us to understand the conditional check - it&apos;s a minimum so we use greater than or equal.With all of these refactorings, there’s no reason to use short names. We have fancy autocompletion from text editors like vi all the way to IDEs like Eclipse.
  17. Using a language (Ruby) that people aren’t likely to be familiar with to illustrate the point.If you write clever or tricky code, sometimes you get this feeling, like an itch, telling you “oh, I should add a comment”.
  18. Stop! This is a product of dogma.Instead, interpret that itch or feeling as a sign that you need to refactor, simplify, rename, whatever it takes to make the code’s purpose and function obvious.Comments are admissions of failure to express your intent in code.When you add an explanatory comment, it&apos;s because you weren&apos;t clear enough using the programming language, so you fall back to the comfort of a natural language.
  19. &lt;explain code&gt;Maintains the original cleverness, but the reader can tell at a glance what the purpose is, and has a better chance of being able to understand how the two steps work. It’s a trivial example, but you can blow it up to larger sizes and the idea is the same. You should always attempt to simplify/refactor/rename/etc. before falling back to comments.
  20. The last reason you might want to add comments to your code: it’s intended for re-use. Generally a collection of classes, methods, utils. If you want to get fancy, can publish documentation using a tool like rdoc or javadoc.Might be compelled to add comments to achieve a higher level of qualitythan regular code. Feels more complete, done due diligence. You just have this feeling that high quality code should have lots of comments. No, you can’t explain it. That’s kind of a bad sign…
  21. &lt;explain code&gt;Obviously this isn’t very descriptive on its own. You can’t push much meaning into constants, method names or locals here… you decide: give in, have to add a comment.What form might that comment take? Here’s a hint: after learning about what a library generally does, what is the next step you take? …. &lt;code example upcoming&gt;
  22. Look for code examples! So write some code examples for your API. Good examples should demonstrate what valid parameters are and what the return values look like.So here’s one approach: a code example embedded into a comment. Here, the example has been marked up with HTML so it displays nicely as Javadoc. Usage of the interface is nicely illustrated for the reader, at the source.Looks like we’ve got this one solved, right?
  23. No, not solved at all. This is even worse than the comments we looked at before… Because the interface definition is in a different file, it’s likely somebody will miss the comment entirely when changing the impl.Another issue, you’re mixing three languages together: HTML, English and Java, which is a maintenance headache. I think we’ve all been in the situation where we’re manually formatting a code snippet in a comment by spacing every line just so…Finally, the compiler isn’t checking your comment so make sure it compiles, and even if it does, there’s no guarantee it will work. Code examples in comments might become obsolete and omit key steps.So how do we keep our example code and resolve these issues? Well, we have to get the compiler to check it. It also has to be in the source repository so other developers can find it. And lastly, it also has to be periodically executed to make sure it works.To some of you, that probably sounds like a real headache. Hopefully the rest of you are thinking: that sounds a lot like a test.
  24. You’re right, I am talking about tests! So let’s document the usage of our API with a test. We have everything that useful documentation should have:1) input: a string2) output: a list of people3) what the method does: appears to be matching on the people’s first and last namesWe know it’s valid code as it is checked by the compiler. As an example, if the test passes, it very likely to be a valid use case. There are also likely to be multiple examples testing different cases, as good tests typically exercise all parts of the code.If all API documentation came in the form of runnable tests, I would be pretty happy.----- Meeting Notes (2013-10-17 23:54) -----make them &quot;live&quot; -&gt; make sure they compilewant to execute them -&gt; make sure they actually worktest -&gt; thing that you&apos;re already writing anyway, so no extra work. fix code exampleknow code example works -&gt; running tests all teh timetests make better API documentation than inline comments----- Meeting Notes (2013-10-18 13:12) -----fix last bracket
  25. I’d like to clarify: not saying “don’t write documentation”, I’m just talking about inline comments.Documentation in general is much broader, and includes lots of good stuff &lt;examples above&gt;. Write code when communicating with programmers, and save English and diagrams for non-programmers.
  26. As a final note about comments, I&apos;d like to bring out this fabulous snippet of code, which I&apos;ve seen countless variations of over the yearsI&apos;d like to think stuff like this is written by people silently rebelling against poor coding standards, or planted there by people like me who secretly hate comments, because I&apos;d be depressed to find out that somebody did this and actually thought they were being helpful.
  27. So please, stop writing comments! Unless you are being paid by the line. Then right on &lt;thumbs up&gt;
  28. Next, let’s talk about optimization: making code go faster at the expense of other concerns.
  29. There are good reasons to optimize. But, most of the time our efforts are wasted, because we&apos;ve convinced ourselves that we know where the important bottlenecks are, but in reality we don&apos;t.
  30. Going to go through one example,drawn from a recent code review.&lt;explain code&gt;Somebody might look at this and think: hey, you’re iterating over the list twice! These two loops could be combined and that would make this go a lot faster.----- Meeting Notes (2013-10-17 23:54) -----&quot;some recent code review feedback&quot;
  31. The only obvious way to me to combine the loops is to inline the two methods and mix up the sums and calculations.
  32. Slow down!Now the calculate method has two new problems:1) It’s doing more than one thing.2) The method is much longer and harder to decompose.2) It’s operating at multiple levels of abstraction: not only does it have to know about all the averages we want to calculate, it has to know how to calculate them!Okay, so we’ve mangled the code, but at least it&apos;s faster right?
  33. An extra loop over a million objects is 3.6 milliseconds, nothing to get worked up about, and certainly not worth sacrificing the readability and maintainability of the code. 3.5 ms -&gt; UI, imperceptiblebatch job -&gt; irrelevantIntegration with other systems, e.g. database -&gt; those calls will greatly outweigh thisThe point isn’t that looping over a collection multiple times is okay. The point is that there’s nothing wrong with wasting some cycles and putting readability first. Programmer time is more expensive than computer time. Also, small code optimizations like this are almost never worthwhile.Another way to reiterate this similar to what I said about comments: write code for people first, computers second.
  34. I feel like this quote is in the collective consciousness, but people choose to ignore it anyway.Maybe folks don’t realize how broad the advice is intended to be, so I’ll expand on it a bit:1) What is ‘premature’? - before the feature has been determined to be too slow. What’s too slow? Need to answer this question. Set performance goals for max response time. Maybe you never come near them and so no optimization required. - before the code has been profiled - before you have determined whether the code will be kept or not (i.e. don’t waste time polishing temporary or volatile code)2) What is ‘optimization’? -thinking of bit twiddling? Other low level stuff? No, it’s designing or modifying code with performance as the foremost consideration. Using these definitions, you pretty much never need to optimize.
  35. Let’s talk about program flow, specifically conditional statements.
  36. What’s wrong with these things? We’re almostnever told to avoid them. Everybody uses them. What’s the problem? We need to use them, right?
  37. One of those things that people do without thinking about it. Have to check for nulls, because somebody might pass them into our method, or because another method might return one. Stuff like this ispretty common
  38. You might be thinking: wait, what’s wrong with that code? We have to check for nulls, and they make a really convenient value to indicate “no result”.The problem:1) Null checks violate DRY: every time you check the same return value for null, you’re essentially saying over and over again that some value X could be null. And you’re likely to miss one.2) Null checks are sometimes unnecessary. Such checks at best add clutter, and at worst mislead readers or cause them to question their understanding of code.
  39. Here’s a neat idea: the null object pattern. replace nulls with objects containing “empty” behaviour.In this case, an empty list makes a natural null object. &lt;explain code&gt;Now callers can just iterate over the list without checking for null.
  40. Another application of the Null Object Pattern with a custom type that has empty behaviour defined. &lt;explain code&gt; It might be be natural to simply null here, but if what you really want to do is nothing, use a null object to represent a missing command. Then callers don&apos;t need to worry about null checks. You can also log calls to execute or print a stack trace similar to what you would get if a NPE was thrown.
  41. Another option for eliminating null checks: the option type.Lets you wrap nullable values like objects, strings, etc. Provides multiple benefits:1) Encodes the fact that the value might be null using the type system, which forces you to deal with that possibility by going through Option rather than remembering to sprinkle null checks everywhere.2) Provides mechanism for transforming or using the value wrapped in a new Option (via map, passing in a transformation function).3) Can elegantly return the value or if missing, a default (via orSome) without a conditional.4) Can query it to see if the value is null, so at worst you’re just in the same boat as you were before&lt;explain code&gt;
  42. &lt;explain how it works&gt;TODOadd parseNames4 using map??
  43. As an example of another case where you might want to use conditional statements, suppose you want to create a method for sampling weather data from a 3rd party library.You think all of these different methods are kinda clunky, so you want to replace them with a single, generic call.
  44. might be thinking: what the heck is wrong with that?Having just one switch statement isn’t awful, but when you add enums, checks with switch or if tend to pop up everywhere. This is just repeating the knowledge of what the complete list is in multiple places. This means adding new sensor types becomes difficult as all of these will need to be located and updated. Adding new behaviour based on type (e.g. print with units) isn’t much better : copy &amp; paste switch and modify
  45. &lt;title&gt;: Fancy way of saying: push the differing behaviour into method of a class hierarchy.A fairly well-known refactoring:This works out quite nicely in Java with a rarely used feature and just a bit of boilerplate, but all of the switch statements’ behaviour can be consolidated into a single location, and no conditionals are required at all.&lt;explain how it works as a replacement&gt;TODO: add revised readsensor (one-liner)
  46. In situations where we can’t imbue our enumerated types with methods, we can still achieve the same effect by creating a wrapper hierarchy around the sensor package that has polymorphic behaviour. &lt;explain code&gt; This solution adds more boilerplate still, but we get most of the benefits:1) elimination of all but one switch2) consolidation of the different behaviours into one place3) compiler errors if new behaviours are requiredMight not look great right now, but when you need to add new types or behaviours, it&apos;ll pay off
  47. I’m sure we’ve all written code like this at some point, and it&apos;s kind of embarassing. Very clumsy, just go through every condition to get an answer. This sort of code makes it hard to test, hard to maintain, hard to reason about; especially if later checks depend on earlier ones being false.There’s no magic bullet to refactor stuff like this. Could use a map from province to tax to replace some of it. Either way you should try to avoid writing if statements that invite this kind of behaviour.
  48. A good start would be “replace conditional with map”. This refactoring replaces the conditions with a map key, and the assignment with a value from a map. Most of the if statement is eliminated.You could take this further by moving some logic into the enums if appropriate, or splitting up the tax into pst and gst, or extending the map to work on pairs of province and product.
  49. If you think I’m being extreme, there’s an entire campaign organized around the elimination of conditional statements altogether.
  50. Some further arguments against conditionals:1) Adding conditional statements can exponentially increase the number of paths through code. (e.g. 8 independent if statements results in 256 unique paths!) One measure of code paths is called cyclomatic complexity. This is a well-known issue and there are tools you can use to enforce per-method limits on cyclomatic complexity, and you should set the limit as low as is bearable.2) If-else chains invite people to simply add additional cases to meet needs.3) If you are switching on enum values or various subtypes of something, it’s a missed opportunity to use polymorphism, and we’ve already seen how that works4) Writing tests against code with lots of conditionals is tedious if you want 100% coverage, and the tests often end up full of duplication.So try some of the previous techniques and refactorings before adding if statements to your programs. I’ll talk more about this in the next section…
  51. Next I’d like to talk about error handling.
  52. Here’s some beginneradvice: make sure your programs can handle all of the errors thrown at it. This code might be a bit exaggerated, but it’s common.
  53. Stop doing this! This code is a sprawling, confusing mess at least compared to what it could be. Null checks everywhere and all possible exceptions are caught. Code like this is very common, and people seem to write it without thinking. Yet you might even be proud because you &quot;caught all the errors&quot;, good job. Unfortunately, there are some problems with coding this way:Most of the code is fluff, not related to the work we are trying to do. We justify this by saying it is necessary, but I&apos;ll show you why not in a bit.2) If not finding the image was actually an error case, best case the code doesn’t do anything, and worst case, the error causes an exception later on, but now the original cause has been obfuscated by our misguided attempt to handle all errors.3) Our methods tend up being responsible for multiple things: their primary task, and handling errors. This mixing of responsibilitiesmakes it hard to figure out what code is doing.4) Sometimes duplicate action may be taken. Countless times I’ve seen exceptions double-logged, which can be confusing.
  54. Error checking should exist at two levels in the system:First, errors and exceptions should be initially detected at the lowest possible level, only if necessary, and then thrown and unwind through the entire app. Most of the app shouldn’t even care about errors at all. If third party code throws an exception, just let it go. Don’t bother catching it. Most of the time we can’t or shouldn’t attempt to recover.Second, at the top-most level where we can centralize error handling&quot;, all exceptions should be caught and logged. Top-level depends on type of app, e.g.1) webapp, this might be in the initial request handler, often frameworks provide a hook for dealing with exceptions2) command-line apps, this will likely be in or close to the main method3) GUI app, this will be in the event dispatcher. The common theme is: decide what to do with exceptions at a single point, and avoid duplication and clutter.So how do we implement this architecture?
  55. Checked exceptions are dumb. Why? The language is forcing you to either handle errors immediately even if it doesn’t make any sense, or to clutter up your method declarations with lists of checked exceptions that may be thrown.If your language has checked exceptions, start by writing wrappers against APIs that throw them to pass the results through and wrap the exception in an unchecked variety.For example, let’s wrap the ImageIO.read and make the exception unchecked. You could even create some new exception types if you want to (e.g. UncheckedIOException)
  56. Here, we’ve made use of our wrapper to simplify our original image reading code. The behaviour did change, as now we’re passing the exception off to be handled elsewhere. We don’t care anymore. The decision about how to handle the error is no longer at this level.We’ve still got that pesky map lookup to deal with, so let’s fix that next.
  57. We add a new exception type to represent missing image keys, then create a method to try and read the key from the map, and fail with an exception.This gets back to what I was saying earlier about null checks: don’t even let this method return null and it will simplify all of the calling code. When you can’t recover, exceptions are superior to returning error values.
  58. Our original code has been reduced to just the important stuff and all of the details of error handling have been pushed down to lower levels of abstraction. The exceptions can now be caught and handled at a higher level.
  59. So what’s the point?Maybe you’ll leave this talk thinking “wow I’m never going to use conditionals or nulls ever again!” Well, no, that’s actually the opposite of what I want. I may have used some strong language, but you shouldn’t always do what I say, for the exact same reasons you shouldn’t always follow existing dogma. Instead, if you just pause and think before writing a switch statement or adding a long-winded comment to some code, that’s great.Maybe you disagree with me, and that’s good too! If you disagree, at the very least you understood what I was saying, spent an hour thinking about your craft and came to your own conclusions. Hopefully the techniques and refactorings I’ve demonstrated will help you to improve your code, but if not, hopefully I’ve got you started down the path of finding ones that will.
  60. Or maybe the best I can hope for is that you heed the advice given by this user of StackExchange: &lt;quote&gt;Best practices, dogma, design patterns or what have you are not a substitute for careful thought. Instead of getting hung up on particular techniques or idioms, just be do whatever makes sense, and then be consistent.
  61. The goal with most of this talk is to encourage you to write code that is readable by people first. This isn’t easy, so here are some handy books.- clean code – PDF available free online, paper copy available.- pragmatic programmer – ebook or paper, a classic full of great principles and practices- code complete – exhaustive, covers everything. E.g. entire chapter devoted to variable names. Would be hard pressed to read it front to back but it&apos;s a good addition to the bookshelf.
  62. Thank you!