SlideShare une entreprise Scribd logo
1  sur  47
Java Best
Practices
@rtoal
2013-06-12
Why?
We professionals need to write code that is
correct, reliable, maintainable, efficient, robust,
resilient, readable, reusable, scalable, etc.
How do we learn best practices?
By understanding bad code
Okay, maybe not as bad as
CodingHorror, SerialDate,
and the thedailywtf (e.g.,this
and this and this and this and
this and this and this and
this) ...
We mean innocent-looking code arising from
misconceptions and inexperience
What will we look at?
Immutability
Collections
Guava
Exceptions
Polymorphism
Null
Exceptions
Concurrency
Formatting
Serialization
I/O
Comments
Validation
Logging
Generics
Security
What's wrong here?
public final class Task {
private final String name;
private final Date start;
public Task(final String name, final Date start) {
this.name = name;
this.start = start;
}
public String getName() {return name;}
public Date getStart() {return start;}
}
java.util.
Date is
mutable
Immutability
Immutable objects
● are thread-safe
● can be shared (cached)
● can't be trashed by someone else's code
● make great hashtable keys!
● lead to simpler code (e.g. no need to "undo"
anything when backtracking)
Favor immutable objects, using mutable
objects only when absolutely necessary
BEST PRACTICE
Defensive Copying
public final class Task {
private final String name;
private final Date start;
public Task(final String name, final Date start) {
this.name = name;
this.start = new Date(start.getTime());
}
public String getName() {return name;}
public Date getStart() {return new Date(start.getTime());}
}
Use defensive copying if your immutable
class contains mutable fields
BEST PRACTICE
COPY
COPY
Maybe you can avoid mutable fields
● Date is mutable; use Joda-Time instead
● SimpleDateFormat is mutable; use Joda-
Time instead
● Standard Java collections are mutable (even
the "unmodifiable" ones); use the
immutable Guava collections instead
Use Joda-Time and Guava
BEST PRACTICE
Speaking of Guava
Why Guava?
● It's already written (reinventing takes too
long and you make mistakes)
● It's extensively tested
● It's optimized
● It's constantly being evolved and improved
Know and use the libraries — especially
Guava
BEST PRACTICE
Guava awesomes
Map<String, Map<Integer, Budget>> m = Maps.newHashMap();
ImmutableSet<Integer> s = ImmutableSet.of(1, 3, 9, 6);
Collection<?> b = filter(a, notNull());
Multimap<String, Integer> scores = HashMultimap.create();
scores.put("Alice", 75);
scores.put("Alice", 22);
scores.put("Alice", 99);
System.out.println(Collections.max(scores.get("Alice")));
Splitter.on(',').trimResults().omitEmptyStrings().split("63,22,, 9");
More Guava wins
@Override
public int compareTo(final Dog d) {
return ComparisonChain.start().compare(
age, d.age).compare(breed, d.breed).result();
}
checkArgument(count > 0, "must be positive: %s", count);
Use preconditions (to remove if-
statements from your code)
BEST PRACTICE
Precondition
Speaking of Joda-Time
Check it out
Know the concepts!
● Instant - DateTime, DateMidnight, MutableDateTime
● Partial - LocalDateTime, LocalDate, LocalTime
● Duration (a number of millis)
● Interval (two instants)
● Period (in human-understandable terms, e.g,
days/weeks)
● Chronology
@Controller
public class DepositController {
private int accountId;
private BigDecimal depositAmount;
@POST @RequestMapping("/deposit/{id}")
public Response handleDeposit(@Param("id") String id,
String amount) {
this.accountId = validateId(id);
this.depositAmount = validateAmount(amount);
service.makeDeposit(accountId, depositAmount);
What's wrong here?
Grrrrr — Singletons!
Each request is running on a separate thread
most likely
public class DepositController {
@POST @RequestMapping("/deposit/{id}")
public Response handleDeposit(@Param("id") String id,
String amount) {
int accountId = validateId(id);
BigDecimal deposit = validateAmount(amount);
service.makeDeposit(accountId, deposit);
The fix is obvious, isn't it?
Don't put state in shared singletons like
controllers, services, and daos
BEST PRACTICE
What's wrong here?
public class FeedConfig {
public FeedConfig(String feedFileId,
String feedId, String name, String url,
String compressionType,
ConversionType conversionType,
ProviderType providerType,
boolean createsNewListing) {
. . .
}
Too Many Parameters!
● When you call a constructor (or any method,
for that matter) with a zillion arguments, what
do they all mean?
● In dynamic languages, we pass hashes
(usually)
● Can we do that in Java?
● What is wrong with you?
Fluent Builders
config = new FeedFileConfigBuilder()
.feedFileId("483")
.feedId("22")
.name("iusa-CA")
.url("ftp://example.com/iusa/ca/feed")
.compressionType("zip")
.conversionType(Conversion.CUSTOM)
.createsNewListing(false)
.build();
The builder is mutable but
the object that is built is
immutable.
Consider builders for classes with
many properties
BEST PRACTICE
What's wrong here?
start = System.currentTimeMillis();
price = computePrice();
finish = System.currentTimeMillis();
logger.debug("Computed price of $"
+ new DecimalFormat("#0.00").format(price)
+ " in " + (finish - start) + " milliseconds");
● Timing clutters the code .... it's an aspect
● Should use a currency formatter ( i18n )
● Is that the only formatter we'll need?
● And what if we are not in debug mode?
Making Logging Efficient
if (logger.isDebugEnabled()) {
logger.debug(. . .);
}
if (logger.isInfoEnabled()) {
logger.info(. . .);
}
Wrap logging calls for complex messages in
isXXXEnabled() conditions
BEST PRACTICE
FATAL — app not expected to recover
ERROR — error that app might recover from
WARN — take notice, potentially harmful
INFO — coarse-grained app progress
DEBUG — to help you debug
TRACE — super-fine-grained progress
Logging Levels
Know and use the proper logging levels
BEST PRACTICE
// tagging data case 2: tags field is not null and primaryTagId is not null, but
// primary tag is not included in the tags field, append primaryTagId
tagIds = (StringUtils.isNotBlank(tagIds)&&StringUtils.isNotBlank(primaryTagId)
? (tagIds.contains(primaryTagId)
? tagIds
: new StringBuilder(tagIds).append(",").append(primaryTagId).toString())
: tagIds);
What's wrong here?
// *************************************** //
// ***** INSTANCE METHODS ***** //
// *************************************** //
/**
* Returns the count.
* @return the count
*/
public int getCount(/* no args */) {
// NOTE: count is a field
return count; // return the count
} // end of instance method getCount
What's wrong here?
You KNOW how I feel about
comments!
public void registerItem(Item item) {
if (item != null) {
Registry registry = store.getRegistry();
if (registry != null) {
Item existing = registry.getItem(item.getId());
if (existing.getBillingPeriod().hasRetailOwner()) {
existing.register(item);
}
}
}
}
What's wrong here?
From Robert C
Martin's Clean Code
book (page 110).
OH! SOME MISSING
NULL CHECKS? I
DIDN'T SEE THEM.
THINK
HARDER
Don't return null
● Actually, there are too many null checks,
not too few
● Returning null as a normal case forces users
to clutter their code
Don't return null! For collections, return an
empty collection. For plain objects, throw
an exception or return a special case object.
BEST PRACTICE
public void writeToFile(String filename, List<String> lines) {
try {
Writer writer = new PrintWriter(new FileWriter(filename));
for (String line : lines) {
writer.append(line);
writer.append(System.getProperty("line.separator"));
}
} catch (IOException e) {
logger.error("FAILED WRITING TO: " + filename + ", RESUMING");
}
}
What's wrong here?
OH! - Not closing!! - Won't flush!!!!
Improved, but still wrong-ish
public void writeToFile(String filename, List<String> lines) {
Writer writer = null;
try {
writer = new PrintWriter(new FileWriter(filename));
for (String line : lines) {
writer.append(line);
writer.append(System.getProperty("line.separator"));
}
} catch (IOException e) {
logger.error("FAILED WRITING TO: " + filename + ", RESUMING");
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
logger.error("FAILEDTO CLOSE: " + filename + ", RESUMING");
}
}
}
} You're kidding me? Added 8 lines
just to close the file?!?!?
The code duplication is bad, too
Getting Better
public void writeToFile(String filename, List<String> lines) {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(filename));
for (String line : lines) {
writer.println(line);
}
} catch (IOException e) {
logger.error("FAILED WRITING TO: " + filename + ", RESUMING");
} finally {
if (writer != null) {
writer.close();
}
}
}
PrintWriter.close() eats the
IOException, if any, saving a
few lines....
A Little Bit Better
public void writeToFile(String filename, List<String> lines) {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(filename));
for (String line : lines) {
writer.println(line);
}
} catch (IOException e) {
logger.error("FAILED WRITING TO: " + filename + ", RESUMING");
} finally {
IOUtils.closeQuietly(writer);
}
}
IOUtils.closeQuitely from
Apache Commons is null-
safe, saving a couple more
lines....
Solutions
Guava has the Files class with utility methods
that guarantee the file will be closed no matter
what. Check it out for homework....
Or just use Java 7
try (PrintWriter output = new PrintWriter(new FileWriter(filename))) {
for (String line: lines) {
output.println(line);
}
} catch (IOException e) {
logger.error("FAILED WRITING TO: " + filename + ", RESUMING");
}
String first = servlet.getRequest().getParam("first");
...
template.update("insert into students values ("
+ " ss.nextval,'" + last + "','" + first + "')");
What's wrong here?
1. Parameter processing and database access are jammed together in
the same file, showing a complete lack of architectural sense.
2. Things look better when the SQL is moved out of the query call.
3. Is that it? Wait, there's something else, I think? Something seems
wrong here....
SQL Injection
insert into students values (ss.nextval,
'Leinhart', 'Robert'); drop table students;--')
JDBC Parameters
Parameters prevent injection attacks and help
with the efficiency gain in prepared statements
template.update("insert into students values ("
+ " ss.nextval, ?, ?)", last, first);
template.update("insert into students values ("
+ " ss.nextval, :last, :first)", map);
Always use SQL parameters
BEST PRACTICE
public class SuperImportantJob {
public static void main(String[] args) {
try {
doSomething();
doTheNextThing();
doTheLastThing();
} catch (Exception e) {
logger.fatal("Job Failed", e);
}
}
}
What's wrong here?
HINT: THE CONFIGURATION
MANAGEMENT TEAM IS NOT HAPPY WITH
YOU TODAY
(Job = standalone
application)
public static void main(String[] args) {
try {
....
} catch (Exception e) {
logger.fatal("Job Failed", e);
System.exit(1);
}
}
You are not the center of the
universe
Return non-zero status codes from failing
jobs (via System.exit or exception)
BEST PRACTICE
Your app got called by a bash
script or was launched by a
Jenkins job. And someone
else's job is gonna follow yours.
And what is wrong with this?
new Thread()
Don't create your own threads; use an
executor service as it will do most of the
thread pool management for you
BEST PRACTICE
Serialization
Some serialization questions for homework...
● What is the serialVersionUID?
● What happens if you don't explicitly specify a
value for this field?
● Why is it a best practice to always specify a
value for this field?
● What happens if you do specify a value, then
change your class, but do not change it?
● What does Josh Bloch say about all this?
A few more practices
● Write DRY code and DAMP tests
● Put calls in the proper place, e.g., don't
formulate response JSON or HTML in a dao
● Avoid magic numbers (except maybe 0, 1);
use private static final (constants)
● Superclasses should not know about their
subclasses
● Consider domain-specific exceptions over
built-in general purpose exceptions
● Avoid double negatives, e.g., if (!notFound())
● Use BigDecimal, not double, for money
But wait, there are more!
● Comment only when you must
● Get rid of obsolete, redundant, inappropriate,
rambling, crappily written comments
● DELETE COMMENTED OUT CODE
● Follow Uncle Bob's naming guidelines
● No Hungarian Notation, please
● Avoid bad names: tmp, dummy, flag
● Don't write functions that expect booleans or
nulls or things to switch on
● Avoid "out parameters", return things instead
● Prefer the single-return style
Ooooh! Yet more Java advice
● Don't make something static when there is
an obvious object it can operate on
● Override hashCode if you override equals
● Don't make a new java.util.Random every
time
● Put configurable data in their own classes or
resources
● Don't put constants in interfaces just so you
can implement the interface to avoid
qualification; use import static instead
● Make constructors private when you should
Aaah the best practice aliens have
control of my brain
● Use enums, not lame int constants
● Inner classes for observers or row mappers
often look nicer as nested static classes (and
are ever so slightly more efficient)
● Don't do string concatenation in a loop
● Use the AtomicXXX classes
● Make sure .equals() checks for null
● Never call .equals(null)
Clean your code with Java 7
● Strings in switch statement
● Binary integral literals
● Underscores in numeric literals
● Multi-catch and more precise rethrow
● Generic instance creation type inference
● Try-with-resources statement
● Simplified varargs method invocation
http://www.javacodegeeks.com/2011/11/java-7-feature-
overview.html
More Java 7 Goodness
ThreadLocalRandom
ForkJoinPool and ForkJoinTask
Phaser
NIO 2.0
Zip File System Provider
Elliptic Curve Cryptography
Disabling of weak cryptographic algorithms
Sockets Direct Protocol
Where can you find more info?
http://findbugs.sourceforge.net/b
ugDescriptions.html
http://checkstyle.sourceforge.net
/availablechecks.html
http://pmd.sourceforge.net/pmd-
5.0.4/rules/index.html
Sonar
Sonar can take output from PMD, Checkstyle, etc. and
present it to you in a useful way.
Homework (Hey why not?)
1. Skim the list of FindBugs Bug Descriptions
2. Find an item on JavaPractices.com that you
disagree with
3. Read an article on serialization
4. Run FindBugs, using the highest possible
analysis settings, on a Java Project that you
worked on
5. Refactor some existing code using Guava
and Java 7
That's it
Questions or comments?

Contenu connexe

Tendances

Tendances (20)

Code generating beans in Java
Code generating beans in JavaCode generating beans in Java
Code generating beans in Java
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
JavaScript Basics
JavaScript BasicsJavaScript Basics
JavaScript Basics
 
A Deeper look into Javascript Basics
A Deeper look into Javascript BasicsA Deeper look into Javascript Basics
A Deeper look into Javascript Basics
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
A Re-Introduction to JavaScript
A Re-Introduction to JavaScriptA Re-Introduction to JavaScript
A Re-Introduction to JavaScript
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Java tut1 Coderdojo Cahersiveen
Java tut1 Coderdojo CahersiveenJava tut1 Coderdojo Cahersiveen
Java tut1 Coderdojo Cahersiveen
 
Java tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry LevelJava tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry Level
 
Java Basics
Java BasicsJava Basics
Java Basics
 
Java Tut1
Java Tut1Java Tut1
Java Tut1
 
JavaScript - Chapter 4 - Types and Statements
 JavaScript - Chapter 4 - Types and Statements JavaScript - Chapter 4 - Types and Statements
JavaScript - Chapter 4 - Types and Statements
 
Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]
 
Java Intro
Java IntroJava Intro
Java Intro
 
Java SE 8 best practices
Java SE 8 best practicesJava SE 8 best practices
Java SE 8 best practices
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An Introduction
 
Java8
Java8Java8
Java8
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Lazy java
Lazy javaLazy java
Lazy java
 
Javascript
JavascriptJavascript
Javascript
 

Similaire à Java Best Practices for Code Quality and Performance

Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with FindbugsCarol McDonald
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheeltcurdt
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to javaciklum_ods
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondMario Fusco
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side JavascriptJulie Iskander
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
Clean & Typechecked JS
Clean & Typechecked JSClean & Typechecked JS
Clean & Typechecked JSArthur Puthin
 
Let's refine your Scala Code
Let's refine your Scala CodeLet's refine your Scala Code
Let's refine your Scala CodeTech Triveni
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005Tugdual Grall
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeIan Robertson
 

Similaire à Java Best Practices for Code Quality and Performance (20)

Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with Findbugs
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel
 
Kotlin
KotlinKotlin
Kotlin
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
 
Java tut1
Java tut1Java tut1
Java tut1
 
Tutorial java
Tutorial javaTutorial java
Tutorial java
 
Java Tutorial
Java TutorialJava Tutorial
Java Tutorial
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Clean & Typechecked JS
Clean & Typechecked JSClean & Typechecked JS
Clean & Typechecked JS
 
Let's refine your Scala Code
Let's refine your Scala CodeLet's refine your Scala Code
Let's refine your Scala Code
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Java tutorial PPT
Java tutorial PPTJava tutorial PPT
Java tutorial PPT
 
Java tutorial PPT
Java tutorial  PPTJava tutorial  PPT
Java tutorial PPT
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
 

Plus de Ray Toal

Git workshop
Git workshopGit workshop
Git workshopRay Toal
 
Learning and Modern Programming Languages
Learning and Modern Programming LanguagesLearning and Modern Programming Languages
Learning and Modern Programming LanguagesRay Toal
 
unittest in 5 minutes
unittest in 5 minutesunittest in 5 minutes
unittest in 5 minutesRay Toal
 
Convention-Based Syntactic Descriptions
Convention-Based Syntactic DescriptionsConvention-Based Syntactic Descriptions
Convention-Based Syntactic DescriptionsRay Toal
 
An Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax TreesAn Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax TreesRay Toal
 
Economics of Open Source Software
Economics of Open Source SoftwareEconomics of Open Source Software
Economics of Open Source SoftwareRay Toal
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesRay Toal
 

Plus de Ray Toal (7)

Git workshop
Git workshopGit workshop
Git workshop
 
Learning and Modern Programming Languages
Learning and Modern Programming LanguagesLearning and Modern Programming Languages
Learning and Modern Programming Languages
 
unittest in 5 minutes
unittest in 5 minutesunittest in 5 minutes
unittest in 5 minutes
 
Convention-Based Syntactic Descriptions
Convention-Based Syntactic DescriptionsConvention-Based Syntactic Descriptions
Convention-Based Syntactic Descriptions
 
An Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax TreesAn Annotation Framework for Statically-Typed Syntax Trees
An Annotation Framework for Statically-Typed Syntax Trees
 
Economics of Open Source Software
Economics of Open Source SoftwareEconomics of Open Source Software
Economics of Open Source Software
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based Games
 

Dernier

Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 

Dernier (20)

Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Odoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting ServiceOdoo Development Company in India | Devintelle Consulting Service
Odoo Development Company in India | Devintelle Consulting Service
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 

Java Best Practices for Code Quality and Performance

  • 2. Why? We professionals need to write code that is correct, reliable, maintainable, efficient, robust, resilient, readable, reusable, scalable, etc.
  • 3. How do we learn best practices? By understanding bad code Okay, maybe not as bad as CodingHorror, SerialDate, and the thedailywtf (e.g.,this and this and this and this and this and this and this and this) ... We mean innocent-looking code arising from misconceptions and inexperience
  • 4. What will we look at? Immutability Collections Guava Exceptions Polymorphism Null Exceptions Concurrency Formatting Serialization I/O Comments Validation Logging Generics Security
  • 5. What's wrong here? public final class Task { private final String name; private final Date start; public Task(final String name, final Date start) { this.name = name; this.start = start; } public String getName() {return name;} public Date getStart() {return start;} } java.util. Date is mutable
  • 6. Immutability Immutable objects ● are thread-safe ● can be shared (cached) ● can't be trashed by someone else's code ● make great hashtable keys! ● lead to simpler code (e.g. no need to "undo" anything when backtracking) Favor immutable objects, using mutable objects only when absolutely necessary BEST PRACTICE
  • 7. Defensive Copying public final class Task { private final String name; private final Date start; public Task(final String name, final Date start) { this.name = name; this.start = new Date(start.getTime()); } public String getName() {return name;} public Date getStart() {return new Date(start.getTime());} } Use defensive copying if your immutable class contains mutable fields BEST PRACTICE COPY COPY
  • 8. Maybe you can avoid mutable fields ● Date is mutable; use Joda-Time instead ● SimpleDateFormat is mutable; use Joda- Time instead ● Standard Java collections are mutable (even the "unmodifiable" ones); use the immutable Guava collections instead Use Joda-Time and Guava BEST PRACTICE
  • 9. Speaking of Guava Why Guava? ● It's already written (reinventing takes too long and you make mistakes) ● It's extensively tested ● It's optimized ● It's constantly being evolved and improved Know and use the libraries — especially Guava BEST PRACTICE
  • 10. Guava awesomes Map<String, Map<Integer, Budget>> m = Maps.newHashMap(); ImmutableSet<Integer> s = ImmutableSet.of(1, 3, 9, 6); Collection<?> b = filter(a, notNull()); Multimap<String, Integer> scores = HashMultimap.create(); scores.put("Alice", 75); scores.put("Alice", 22); scores.put("Alice", 99); System.out.println(Collections.max(scores.get("Alice"))); Splitter.on(',').trimResults().omitEmptyStrings().split("63,22,, 9");
  • 11. More Guava wins @Override public int compareTo(final Dog d) { return ComparisonChain.start().compare( age, d.age).compare(breed, d.breed).result(); } checkArgument(count > 0, "must be positive: %s", count); Use preconditions (to remove if- statements from your code) BEST PRACTICE Precondition
  • 12. Speaking of Joda-Time Check it out Know the concepts! ● Instant - DateTime, DateMidnight, MutableDateTime ● Partial - LocalDateTime, LocalDate, LocalTime ● Duration (a number of millis) ● Interval (two instants) ● Period (in human-understandable terms, e.g, days/weeks) ● Chronology
  • 13. @Controller public class DepositController { private int accountId; private BigDecimal depositAmount; @POST @RequestMapping("/deposit/{id}") public Response handleDeposit(@Param("id") String id, String amount) { this.accountId = validateId(id); this.depositAmount = validateAmount(amount); service.makeDeposit(accountId, depositAmount); What's wrong here?
  • 14. Grrrrr — Singletons! Each request is running on a separate thread most likely
  • 15. public class DepositController { @POST @RequestMapping("/deposit/{id}") public Response handleDeposit(@Param("id") String id, String amount) { int accountId = validateId(id); BigDecimal deposit = validateAmount(amount); service.makeDeposit(accountId, deposit); The fix is obvious, isn't it? Don't put state in shared singletons like controllers, services, and daos BEST PRACTICE
  • 16. What's wrong here? public class FeedConfig { public FeedConfig(String feedFileId, String feedId, String name, String url, String compressionType, ConversionType conversionType, ProviderType providerType, boolean createsNewListing) { . . . }
  • 17. Too Many Parameters! ● When you call a constructor (or any method, for that matter) with a zillion arguments, what do they all mean? ● In dynamic languages, we pass hashes (usually) ● Can we do that in Java? ● What is wrong with you?
  • 18. Fluent Builders config = new FeedFileConfigBuilder() .feedFileId("483") .feedId("22") .name("iusa-CA") .url("ftp://example.com/iusa/ca/feed") .compressionType("zip") .conversionType(Conversion.CUSTOM) .createsNewListing(false) .build(); The builder is mutable but the object that is built is immutable. Consider builders for classes with many properties BEST PRACTICE
  • 19. What's wrong here? start = System.currentTimeMillis(); price = computePrice(); finish = System.currentTimeMillis(); logger.debug("Computed price of $" + new DecimalFormat("#0.00").format(price) + " in " + (finish - start) + " milliseconds"); ● Timing clutters the code .... it's an aspect ● Should use a currency formatter ( i18n ) ● Is that the only formatter we'll need? ● And what if we are not in debug mode?
  • 20. Making Logging Efficient if (logger.isDebugEnabled()) { logger.debug(. . .); } if (logger.isInfoEnabled()) { logger.info(. . .); } Wrap logging calls for complex messages in isXXXEnabled() conditions BEST PRACTICE
  • 21. FATAL — app not expected to recover ERROR — error that app might recover from WARN — take notice, potentially harmful INFO — coarse-grained app progress DEBUG — to help you debug TRACE — super-fine-grained progress Logging Levels Know and use the proper logging levels BEST PRACTICE
  • 22. // tagging data case 2: tags field is not null and primaryTagId is not null, but // primary tag is not included in the tags field, append primaryTagId tagIds = (StringUtils.isNotBlank(tagIds)&&StringUtils.isNotBlank(primaryTagId) ? (tagIds.contains(primaryTagId) ? tagIds : new StringBuilder(tagIds).append(",").append(primaryTagId).toString()) : tagIds); What's wrong here?
  • 23. // *************************************** // // ***** INSTANCE METHODS ***** // // *************************************** // /** * Returns the count. * @return the count */ public int getCount(/* no args */) { // NOTE: count is a field return count; // return the count } // end of instance method getCount What's wrong here? You KNOW how I feel about comments!
  • 24. public void registerItem(Item item) { if (item != null) { Registry registry = store.getRegistry(); if (registry != null) { Item existing = registry.getItem(item.getId()); if (existing.getBillingPeriod().hasRetailOwner()) { existing.register(item); } } } } What's wrong here? From Robert C Martin's Clean Code book (page 110). OH! SOME MISSING NULL CHECKS? I DIDN'T SEE THEM. THINK HARDER
  • 25. Don't return null ● Actually, there are too many null checks, not too few ● Returning null as a normal case forces users to clutter their code Don't return null! For collections, return an empty collection. For plain objects, throw an exception or return a special case object. BEST PRACTICE
  • 26. public void writeToFile(String filename, List<String> lines) { try { Writer writer = new PrintWriter(new FileWriter(filename)); for (String line : lines) { writer.append(line); writer.append(System.getProperty("line.separator")); } } catch (IOException e) { logger.error("FAILED WRITING TO: " + filename + ", RESUMING"); } } What's wrong here? OH! - Not closing!! - Won't flush!!!!
  • 27. Improved, but still wrong-ish public void writeToFile(String filename, List<String> lines) { Writer writer = null; try { writer = new PrintWriter(new FileWriter(filename)); for (String line : lines) { writer.append(line); writer.append(System.getProperty("line.separator")); } } catch (IOException e) { logger.error("FAILED WRITING TO: " + filename + ", RESUMING"); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { logger.error("FAILEDTO CLOSE: " + filename + ", RESUMING"); } } } } You're kidding me? Added 8 lines just to close the file?!?!? The code duplication is bad, too
  • 28. Getting Better public void writeToFile(String filename, List<String> lines) { PrintWriter writer = null; try { writer = new PrintWriter(new FileWriter(filename)); for (String line : lines) { writer.println(line); } } catch (IOException e) { logger.error("FAILED WRITING TO: " + filename + ", RESUMING"); } finally { if (writer != null) { writer.close(); } } } PrintWriter.close() eats the IOException, if any, saving a few lines....
  • 29. A Little Bit Better public void writeToFile(String filename, List<String> lines) { PrintWriter writer = null; try { writer = new PrintWriter(new FileWriter(filename)); for (String line : lines) { writer.println(line); } } catch (IOException e) { logger.error("FAILED WRITING TO: " + filename + ", RESUMING"); } finally { IOUtils.closeQuietly(writer); } } IOUtils.closeQuitely from Apache Commons is null- safe, saving a couple more lines....
  • 30. Solutions Guava has the Files class with utility methods that guarantee the file will be closed no matter what. Check it out for homework.... Or just use Java 7 try (PrintWriter output = new PrintWriter(new FileWriter(filename))) { for (String line: lines) { output.println(line); } } catch (IOException e) { logger.error("FAILED WRITING TO: " + filename + ", RESUMING"); }
  • 31. String first = servlet.getRequest().getParam("first"); ... template.update("insert into students values (" + " ss.nextval,'" + last + "','" + first + "')"); What's wrong here? 1. Parameter processing and database access are jammed together in the same file, showing a complete lack of architectural sense. 2. Things look better when the SQL is moved out of the query call. 3. Is that it? Wait, there's something else, I think? Something seems wrong here....
  • 32. SQL Injection insert into students values (ss.nextval, 'Leinhart', 'Robert'); drop table students;--')
  • 33. JDBC Parameters Parameters prevent injection attacks and help with the efficiency gain in prepared statements template.update("insert into students values (" + " ss.nextval, ?, ?)", last, first); template.update("insert into students values (" + " ss.nextval, :last, :first)", map); Always use SQL parameters BEST PRACTICE
  • 34. public class SuperImportantJob { public static void main(String[] args) { try { doSomething(); doTheNextThing(); doTheLastThing(); } catch (Exception e) { logger.fatal("Job Failed", e); } } } What's wrong here? HINT: THE CONFIGURATION MANAGEMENT TEAM IS NOT HAPPY WITH YOU TODAY (Job = standalone application)
  • 35. public static void main(String[] args) { try { .... } catch (Exception e) { logger.fatal("Job Failed", e); System.exit(1); } } You are not the center of the universe Return non-zero status codes from failing jobs (via System.exit or exception) BEST PRACTICE Your app got called by a bash script or was launched by a Jenkins job. And someone else's job is gonna follow yours.
  • 36. And what is wrong with this? new Thread() Don't create your own threads; use an executor service as it will do most of the thread pool management for you BEST PRACTICE
  • 37. Serialization Some serialization questions for homework... ● What is the serialVersionUID? ● What happens if you don't explicitly specify a value for this field? ● Why is it a best practice to always specify a value for this field? ● What happens if you do specify a value, then change your class, but do not change it? ● What does Josh Bloch say about all this?
  • 38. A few more practices ● Write DRY code and DAMP tests ● Put calls in the proper place, e.g., don't formulate response JSON or HTML in a dao ● Avoid magic numbers (except maybe 0, 1); use private static final (constants) ● Superclasses should not know about their subclasses ● Consider domain-specific exceptions over built-in general purpose exceptions ● Avoid double negatives, e.g., if (!notFound()) ● Use BigDecimal, not double, for money
  • 39. But wait, there are more! ● Comment only when you must ● Get rid of obsolete, redundant, inappropriate, rambling, crappily written comments ● DELETE COMMENTED OUT CODE ● Follow Uncle Bob's naming guidelines ● No Hungarian Notation, please ● Avoid bad names: tmp, dummy, flag ● Don't write functions that expect booleans or nulls or things to switch on ● Avoid "out parameters", return things instead ● Prefer the single-return style
  • 40. Ooooh! Yet more Java advice ● Don't make something static when there is an obvious object it can operate on ● Override hashCode if you override equals ● Don't make a new java.util.Random every time ● Put configurable data in their own classes or resources ● Don't put constants in interfaces just so you can implement the interface to avoid qualification; use import static instead ● Make constructors private when you should
  • 41. Aaah the best practice aliens have control of my brain ● Use enums, not lame int constants ● Inner classes for observers or row mappers often look nicer as nested static classes (and are ever so slightly more efficient) ● Don't do string concatenation in a loop ● Use the AtomicXXX classes ● Make sure .equals() checks for null ● Never call .equals(null)
  • 42. Clean your code with Java 7 ● Strings in switch statement ● Binary integral literals ● Underscores in numeric literals ● Multi-catch and more precise rethrow ● Generic instance creation type inference ● Try-with-resources statement ● Simplified varargs method invocation http://www.javacodegeeks.com/2011/11/java-7-feature- overview.html
  • 43. More Java 7 Goodness ThreadLocalRandom ForkJoinPool and ForkJoinTask Phaser NIO 2.0 Zip File System Provider Elliptic Curve Cryptography Disabling of weak cryptographic algorithms Sockets Direct Protocol
  • 44. Where can you find more info? http://findbugs.sourceforge.net/b ugDescriptions.html http://checkstyle.sourceforge.net /availablechecks.html http://pmd.sourceforge.net/pmd- 5.0.4/rules/index.html
  • 45. Sonar Sonar can take output from PMD, Checkstyle, etc. and present it to you in a useful way.
  • 46. Homework (Hey why not?) 1. Skim the list of FindBugs Bug Descriptions 2. Find an item on JavaPractices.com that you disagree with 3. Read an article on serialization 4. Run FindBugs, using the highest possible analysis settings, on a Java Project that you worked on 5. Refactor some existing code using Guava and Java 7