KEMBAR78
Java Tips, Tricks and Pitfalls | PPTX
Java
Tips, Tricks and Pitfalls
KISS - Keep it Short and Simple!
KISS - Example 1 (Read properties from file)
Example of properties file:
hibernate.connection.username=myuser
hibernate.connection.password=secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
KISS - Example 1 (Implementation)
Overthinking
Elegance
Laziness
Experience
VS
KISS - Example 1 (Overthinking)
Let’s create a method with really self-describing name!
public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) {
Properties properties = null;
// logic will be here
return properties;
}
KISS - Example 1 (Elegance)
Let’s create a method with really self-describing name!
public Properties readProperties(String filename) {
Properties properties = null;
// logic will be here
return properties;
}
KISS - Example 1 (Overthinking)
Let’s read the file and fill the properties!
BufferedReader bufferedReaderForFileWhichShouldContainsLines = new BufferedReader(
new InputStreamReader(new BufferedInputStream(new FileInputStream(file)))
);
String accumulatorForLineFromFile = null; properties = new Properties();
while ((accumulatorForLineFromFile = brffwhcl.readLine()) != null)
{
properties.setProperty(accumulatorForLineFromFile.split("=")[0],
accumulatorForLineFromFile.split("=")[1]);
}
KISS - Example 1 (Experience)
Let’s read the file and fill the properties!
public Properties readProperties(String filename) {
Properties properties = new Properties();
properties.load(new FileInputStream(filename));
return properties;
}
KISS - Example 1 (Overthinking)
Let’s handle some exceptions!
public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) {
Properties properties = null;
if (file != null) {
...
} else {
throw new IllegalArgumentException("file which should contains all needed information "
+
"to init Properties object is null, that means that Java can't work with it, "
+
"please check your code and make sure that you are passing valid arguments",
new NullPointerException()
);
}
return properties;
}
KISS - Example 1 (Overthinking)
And several more...
public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) {
Properties properties = null;
if (file != null) {
if (file.exists()) {
if (file.canRead()) {
try {
BufferedReader
bufferedReaderForFileWhichShouldContainsLines = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(
new FileInputStream(file)
)
)
);
try {
String accumulatorForLineFromFile = null;
properties = new Properties();
while ((accumulatorForLineFromFile
=
bufferedReaderForFileWhichShouldContainsLines.readLine()) != null) {
properties.setProperty(
accumulatorForLineFromFile.split("=")[0],
accumulatorForLineFromFile.split("=")[1]
);
}
} catch (IOException ioException) {
throw new IllegalArgumentException("file which should contains all needed information "
+
"to init Properties object is not null, but it isn't suitable for reading, " +
"that means that Java can't work with it, " +
"please check your code and make sure that you are passing valid arguments",
new IOException(ioException)
);
} finally {
try {
bufferedReaderForFileWhichShouldContainsLines.close();
} catch (IOException ioException) {
System.err.printf("Can't close bufferedReaderForFileWhichShouldContainsLines: %s",
ioException.getMessage()
);
}
}
} catch (FileNotFoundException fileNotFoundException) {
throw new IllegalArgumentException("file which should contains all needed information " +
"to init Properties object is not null, but it not found, " +
"that means that Java can't work with it, " +
"please check your code and make sure that you are passing valid arguments",
new FileNotFoundException(fileNotFoundException.getMessage())
);
}
} else {
throw new IllegalArgumentException("file which should contains all needed information " +
"to init Properties object is not null, but it now unreadable, " +
"that means that Java can't work with it, " +
"please check your code and make sure that you are passing valid arguments",
new IllegalAccessException()
);
}
} else {
throw new IllegalArgumentException("file which should contains all needed information " +
"to init Properties object is not null, but it isn't exists, " +
"that means that Java can't work with it, " +
"please check your code and make sure that you are passing valid arguments",
new IllegalAccessException()
);
}
} else {
throw new IllegalArgumentException("file which should contains all needed information " +
"to init Properties object is null, that means that Java can't work with it, " +
"please check your code and make sure that you are passing valid arguments",
new NullPointerException()
);
}
return properties;
}
KISS - Example 1 (Laziness)
Let’s handle some exceptions!
public Properties readProperties(String filename) throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream(filename));
return properties;
}
Naming best & bad practices
Programming routine:
Naming best & bad practices
Programming routine:
Naming best practices
● Keep all names close to context and self-describing
○ But avoid “secret knowledge”
○ Share the context via javadoc or comments
Naming best practices
● Keep all names close to context and self-describing
○ But avoid “secret knowledge”
○ Share the context via javadoc or comments
● Variable type should be obvious
○ That doesn’t mean that name should contain Type
Naming best practices
● Keep all names close to context and self-describing
○ But avoid “secret knowledge”
○ Share the context via javadoc or comments
● Variable type should be obvious
○ That doesn’t mean that name should contain Type
● Boolean variables/methods names should be suitable
for the sentence: “if <variable_name> then ...?”
Naming best practices
● Keep all names close to context and self-describing
○ But avoid “secret knowledge”
○ Share the context via javadoc or comments
● Variable type should be obvious
○ That doesn’t mean that name should contain Type
● Boolean variables/methods names should be suitable
for the sentence: “if <variable_name> then ...?”
● Methods names should answer the question “what to do?”
Naming best practices
● Keep all names close to context and self-describing
○ But avoid “secret knowledge”
○ Share the context via javadoc or comments
● Variable type should be obvious
○ That doesn’t mean that name should contain Type
● Boolean variables/methods names should be suitable
for the sentence: “if <variable_name> then ...?”
● Methods names should answer the question “what to do?”
● Type names might contain parent names
Naming bad practices
Naming bad practices
● Using words that means nothing: obj, data, value, tmp...
a. There is always place for exceptions
Naming bad practices
● Using words that means nothing: obj, data, value, tmp...
a. There is always place for exceptions
● Fake/Wrong variable type
a. This might cost a burned chair...
Naming bad practices
● Using words that means nothing: obj, data, value, tmp...
a. There is always place for exceptions
● Fake/Wrong variable type
a. This might cost a burned chair...
● Single-character names: w, t, f ... o, m, g
a. Especially without any context - 100% burned chair
Naming bad practices
● Using words that means nothing: obj, data, value, tmp...
a. There is always place for exceptions
● Fake/Wrong variable type
a. This might cost a burned chair...
● Single-character names: w, t, f ... o, m, g
a. Especially without any context - 100% burned chair
● Fake/Incomplete names of the methods
Naming bad practices
● Using words that means nothing: obj, data, value, tmp...
a. There is always place for exceptions
● Fake/Wrong variable type
a. This might cost a burned chair...
● Single-character names: w, t, f ... o, m, g
a. Especially without any context - 100% burned chair
● Fake/Incomplete names of the methods
● Public argument names based on secret knowledge
a. Especially without any context - 200% burned chair
Dirty and Pure methods
Hello, my name is side-effect...
public int[] sortArray(int[] array) {
Arrays.sort(array);
return array;
}
Dirty and Pure methods
And sometimes I’m not obvious at all…
public <T> T[] sortArray(T[] array) {
if (array == null || array.length < 2) return array;
Comparator<T> comparator = null;
T[] tmpArray = checkAndReturnArray(array);
T notNullElement = null;
for (int i = 0; i < tmpArray.length && notNullElement == null; notNullElement = tmpArray[i++]) ;
if (notNullElement == null) return array;
if (notNullElement instanceof Comparator) { comparator = (Comparator<T>) notNullElement; }
else if (notNullElement instanceof Comparable) {
comparator = (o1, o2) -> {
if (o1 == null) return 1; if (o2 == null) return -1; return ((Comparable<T>) o1).compareTo(o2);
};
}
if (comparator == null) return array;
Arrays.sort(tmpArray, comparator);
return tmpArray;
}
Dirty and Pure methods
Here's Johnny!
/**
* Checks array and returns copy if Mars is in the zenith of Saturn
*/
public <T> T[] checkAndReturnArray(T[] array) {
return (array != null)
? ((System.currentTimeMillis() > (42 * 64 * 30 * 365))
? ((System.getenv("magic") == null)
? array : null) : array) : null;
}
Dirty and Pure methods
Here's Johnny!
/**
* Checks array and returns copy if Mars is in the zenith of Saturn
*/
public <T> T[] checkAndReturnArray(T[] array) {
return (array != null)
? ((System.currentTimeMillis() > (42 * 64 * 30 * 365))
? ((System.getenv("magic") == null)
? array : null) : array) : null;
}
Immutability and final keyword
If you can’t change the methods,
you can change the arguments...
Immutability and final keyword
What is immutability?
class Immutable {
private final String immutableField;
public Immutable(String immutableField) {
this.immutableField = immutableField;
}
public String getImmutableField() {
return immutableField;
}
}
Examples:
String, Integer, File, URL...
Immutability and final keyword
What is immutability?
class Immutable {
private final String immutableField;
public Immutable(String immutableField) {
this.immutableField = immutableField;
}
public String getImmutableField() {
return immutableField;
}
}
Examples:
String, Integer, File, URL...
What is mutability?
class Mutable {
private List<String> mutableField;
public List<String> getMutableField() {
return mutableField;
}
public void setMutableField(List<String> mutableField) {
this.mutableField = mutableField;
}
}
Examples:
ArrayList, Arrays, StringBuilder...
Immutability and final keyword
Why immutability is good?
● Preventing side-effects
● Thread-safe
● Easy to debug
● Easy to implement
● Easy to extend
● Easy to scale
Immutability and final keyword
Why immutability is good?
● Preventing side-effects
● Thread-safe
● Easy to debug
● Easy to implement
● Easy to extend
● Easy to scale
Why immutability is bad?
● Real world isn’t immutable
● Constraints you
● Not always convenient
● Increases memory usage
● Performance degradation
● There is always will be an
exception...
Immutability and final keyword
Keyword final can be used with:
● Variables
○ final Object someField;
Immutability and final keyword
Keyword final can be used with:
● Variables
○ final Object someField;
● Methods
○ final public void someMethod() { ... }
○ public void someMethod(final Object argument) { ... }
Immutability and final keyword
Keyword final can be used with:
● Variables
○ final Object someField;
● Methods
○ final public void someMethod() { ... }
○ public void someMethod(final Object argument) { ... }
● Classes
○ public final class Example3;
try-catch-finally pitfalls
Simple puzzle?
public static int puzzle() {
try {
return 5;
} catch (Exception ex) {
return 10;
} finally {
return 15;
}
}
try-catch-finally pitfalls
Simple puzzle?
public static int puzzle() {
try {
return 5;
} catch (Exception ex) {
return 10;
} finally {
return 15;
}
}
try-catch-finally pitfalls
try pitfalls
● It’s a new scope…
● Each line might raise exception
● catch or finally is required
● Try with resources?
○ Custom AutoCloseable implementation
○ Implicit side-effect
try-catch-finally pitfalls
catch pitfalls
● It’s a new scope…
● Type erasing
● Performance degradation
● Exception-oriented logic
try-catch-finally pitfalls
finally pitfalls
● It’s a new scope…
● WILL BE EXECUTED ALWAYS!!!
○ Except for that moment, in which you will really need this...
● Might cause performance degradation
● Newer return value in finally
○ But sometimes...
Early exception handling
Exception handling
public int someMethod(String arg1, String arg2) {
final int defaultValue = 42;
int value = 0;
try {
int int1 = Integer.parseInt(arg1);
int int2 = Integer.parseInt(arg2);
value = int1 / int2;
} catch (Exception ex) {
System.err.println(ex);
return defaultValue;
}
return value;
}
Early exception handling
Exception handling
public int someMethod(String arg1, String arg2) {
final int defaultValue = 42;
int value = 0;
try {
int int1 = Integer.parseInt(arg1);
int int2 = Integer.parseInt(arg2);
value = int1 / int2;
} catch (Exception ex) {
System.err.println(ex);
return defaultValue;
}
return value;
}
Early exception handling
public int someMethod(String arg1, String arg2) {
final int defaultValue = 42;
if (notNumber(arg1) || notNumber(arg2)) {
return defaultValue;
}
int int1 = Integer.parseInt(arg1);
int int2 = Integer.parseInt(arg2);
if (int2 == 0) {
return defaultValue;
}
int value = int1 / int2;
return value;
}
Early exception handling
● Objects.requireNonNull(argument); (throw early)
Early exception handling
● Objects.requireNonNull(argument); (throw early)
● Use IllegalArgumentException() (throw early)
Early exception handling
● Objects.requireNonNull(argument); (throw early)
● Use IllegalArgumentException() (throw early)
● Use UnsupportedOperationException() (throw early)
Early exception handling
● Objects.requireNonNull(argument); (throw early)
● Use IllegalArgumentException() (throw early)
● Use UnsupportedOperationException() (throw early)
● Delegate exception handling, use throws (catch late)
Early exception handling
● Objects.requireNonNull(argument); (throw early)
● Use IllegalArgumentException() (throw early)
● Use UnsupportedOperationException() (throw early)
● Delegate exception handling, use throws (catch late)
● Write javadoc
● Write logs
Why null is bad?
● More than 2500 NPE defects in our Jira
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
● Zero information
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
● Zero information
● null instanceof Type --> false
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
● Zero information
● null instanceof Type --> false
● int value = (Integer) null; --> NPE
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
● Zero information
● null instanceof Type --> false
● int value = (Integer) null; --> NPE
● Many methods uses .toString() --> NPE
○ String.valueOf(obj) - solves this issue
Why null is bad?
● More than 2500 NPE defects in our Jira
● null is low-level concept
● Zero information
● null instanceof Type --> false
● int value = (Integer) null; --> NPE
● Many methods uses .toString() --> NPE
○ String.valueOf(obj) - solves this issue
● Null-oriented programming is legacy
○ Use Optional<T> instead
Lean refactoring
● Don’t broke tests (Red-Green-Refactor)
Lean refactoring
● Don’t broke tests (Red-Green-Refactor)
● Don’t change signatures
Lean refactoring
● Don’t broke tests (Red-Green-Refactor)
● Don’t change signatures
● Don’t change parameters order
○ Especially for constructors
Lean refactoring
● Don’t broke tests (Red-Green-Refactor)
● Don’t change signatures
● Don’t change parameters order
○ Especially for constructors
● Don’t change contract
Lean refactoring
● Don’t broke tests (Red-Green-Refactor)
● Don’t change signatures
● Don’t change parameters order
○ Especially for constructors
● Don’t change contract
● Use @Deprecated
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
● Use static as Singleton
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
● Use static as Singleton
● Use reflection
○ Especially for internal JDK classes
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
● Use static as Singleton
● Use reflection
○ Especially for internal JDK classes
● Use interface just because of signature
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
● Use static as Singleton
● Use reflection
○ Especially for internal JDK classes
● Use interface just because of signature
● Use inheritance as aggregation/delegation
Abusing Java
Just because you can, it doesn’t mean you should...
● Use enum as Singleton
● Use static as Singleton
● Use reflection
○ Especially for internal JDK classes
● Use interface just because of signature
● Use inheritance as aggregation/delegation
● ...
● If it works, it doesn’t mean it’s good.
SOLID in the nutshell
● S - Single responsibility
SOLID in the nutshell
● S - Single responsibility
● O - Opened for extension, but closed for changes
SOLID in the nutshell
● S - Single responsibility
● O - Opened for extension, but closed for changes
● L - Liskov substitution, children should keep parents
contracts.
SOLID in the nutshell
● S - Single responsibility
● O - Opened for extension, but closed for changes
● L - Liskov substitution, children should keep parents
contracts.
● I - Interface segregation is better than God-interface.
SOLID in the nutshell
● S - Single responsibility
● O - Opened for extension, but closed for changes
● L - Liskov substitution, children should keep parents
contracts.
● I - Interface segregation is better than God-interface.
● D - Dependency inversion, build dependencies over
abstractions, not over implementations.
Q&A Session (the end)
Attention!
Thanks for your attention!

Java Tips, Tricks and Pitfalls

  • 1.
  • 2.
    KISS - Keepit Short and Simple!
  • 3.
    KISS - Example1 (Read properties from file) Example of properties file: hibernate.connection.username=myuser hibernate.connection.password=secret hibernate.c3p0.min_size=5 hibernate.c3p0.max_size=20 hibernate.c3p0.timeout=1800 hibernate.c3p0.max_statements=50
  • 4.
    KISS - Example1 (Implementation) Overthinking Elegance Laziness Experience VS
  • 5.
    KISS - Example1 (Overthinking) Let’s create a method with really self-describing name! public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) { Properties properties = null; // logic will be here return properties; }
  • 6.
    KISS - Example1 (Elegance) Let’s create a method with really self-describing name! public Properties readProperties(String filename) { Properties properties = null; // logic will be here return properties; }
  • 7.
    KISS - Example1 (Overthinking) Let’s read the file and fill the properties! BufferedReader bufferedReaderForFileWhichShouldContainsLines = new BufferedReader( new InputStreamReader(new BufferedInputStream(new FileInputStream(file))) ); String accumulatorForLineFromFile = null; properties = new Properties(); while ((accumulatorForLineFromFile = brffwhcl.readLine()) != null) { properties.setProperty(accumulatorForLineFromFile.split("=")[0], accumulatorForLineFromFile.split("=")[1]); }
  • 8.
    KISS - Example1 (Experience) Let’s read the file and fill the properties! public Properties readProperties(String filename) { Properties properties = new Properties(); properties.load(new FileInputStream(filename)); return properties; }
  • 9.
    KISS - Example1 (Overthinking) Let’s handle some exceptions! public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) { Properties properties = null; if (file != null) { ... } else { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is null, that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new NullPointerException() ); } return properties; }
  • 10.
    KISS - Example1 (Overthinking) And several more... public Properties readAllLinesFromFileAndReturnPropertiesObject(File file) { Properties properties = null; if (file != null) { if (file.exists()) { if (file.canRead()) { try { BufferedReader bufferedReaderForFileWhichShouldContainsLines = new BufferedReader( new InputStreamReader( new BufferedInputStream( new FileInputStream(file) ) ) ); try { String accumulatorForLineFromFile = null; properties = new Properties(); while ((accumulatorForLineFromFile = bufferedReaderForFileWhichShouldContainsLines.readLine()) != null) { properties.setProperty( accumulatorForLineFromFile.split("=")[0], accumulatorForLineFromFile.split("=")[1] ); } } catch (IOException ioException) { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is not null, but it isn't suitable for reading, " + "that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new IOException(ioException) ); } finally { try { bufferedReaderForFileWhichShouldContainsLines.close(); } catch (IOException ioException) { System.err.printf("Can't close bufferedReaderForFileWhichShouldContainsLines: %s", ioException.getMessage() ); } } } catch (FileNotFoundException fileNotFoundException) { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is not null, but it not found, " + "that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new FileNotFoundException(fileNotFoundException.getMessage()) ); } } else { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is not null, but it now unreadable, " + "that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new IllegalAccessException() ); } } else { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is not null, but it isn't exists, " + "that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new IllegalAccessException() ); } } else { throw new IllegalArgumentException("file which should contains all needed information " + "to init Properties object is null, that means that Java can't work with it, " + "please check your code and make sure that you are passing valid arguments", new NullPointerException() ); } return properties; }
  • 11.
    KISS - Example1 (Laziness) Let’s handle some exceptions! public Properties readProperties(String filename) throws IOException { Properties properties = new Properties(); properties.load(new FileInputStream(filename)); return properties; }
  • 12.
    Naming best &bad practices Programming routine:
  • 13.
    Naming best &bad practices Programming routine:
  • 14.
    Naming best practices ●Keep all names close to context and self-describing ○ But avoid “secret knowledge” ○ Share the context via javadoc or comments
  • 15.
    Naming best practices ●Keep all names close to context and self-describing ○ But avoid “secret knowledge” ○ Share the context via javadoc or comments ● Variable type should be obvious ○ That doesn’t mean that name should contain Type
  • 16.
    Naming best practices ●Keep all names close to context and self-describing ○ But avoid “secret knowledge” ○ Share the context via javadoc or comments ● Variable type should be obvious ○ That doesn’t mean that name should contain Type ● Boolean variables/methods names should be suitable for the sentence: “if <variable_name> then ...?”
  • 17.
    Naming best practices ●Keep all names close to context and self-describing ○ But avoid “secret knowledge” ○ Share the context via javadoc or comments ● Variable type should be obvious ○ That doesn’t mean that name should contain Type ● Boolean variables/methods names should be suitable for the sentence: “if <variable_name> then ...?” ● Methods names should answer the question “what to do?”
  • 18.
    Naming best practices ●Keep all names close to context and self-describing ○ But avoid “secret knowledge” ○ Share the context via javadoc or comments ● Variable type should be obvious ○ That doesn’t mean that name should contain Type ● Boolean variables/methods names should be suitable for the sentence: “if <variable_name> then ...?” ● Methods names should answer the question “what to do?” ● Type names might contain parent names
  • 19.
  • 20.
    Naming bad practices ●Using words that means nothing: obj, data, value, tmp... a. There is always place for exceptions
  • 21.
    Naming bad practices ●Using words that means nothing: obj, data, value, tmp... a. There is always place for exceptions ● Fake/Wrong variable type a. This might cost a burned chair...
  • 22.
    Naming bad practices ●Using words that means nothing: obj, data, value, tmp... a. There is always place for exceptions ● Fake/Wrong variable type a. This might cost a burned chair... ● Single-character names: w, t, f ... o, m, g a. Especially without any context - 100% burned chair
  • 23.
    Naming bad practices ●Using words that means nothing: obj, data, value, tmp... a. There is always place for exceptions ● Fake/Wrong variable type a. This might cost a burned chair... ● Single-character names: w, t, f ... o, m, g a. Especially without any context - 100% burned chair ● Fake/Incomplete names of the methods
  • 24.
    Naming bad practices ●Using words that means nothing: obj, data, value, tmp... a. There is always place for exceptions ● Fake/Wrong variable type a. This might cost a burned chair... ● Single-character names: w, t, f ... o, m, g a. Especially without any context - 100% burned chair ● Fake/Incomplete names of the methods ● Public argument names based on secret knowledge a. Especially without any context - 200% burned chair
  • 25.
    Dirty and Puremethods Hello, my name is side-effect... public int[] sortArray(int[] array) { Arrays.sort(array); return array; }
  • 26.
    Dirty and Puremethods And sometimes I’m not obvious at all… public <T> T[] sortArray(T[] array) { if (array == null || array.length < 2) return array; Comparator<T> comparator = null; T[] tmpArray = checkAndReturnArray(array); T notNullElement = null; for (int i = 0; i < tmpArray.length && notNullElement == null; notNullElement = tmpArray[i++]) ; if (notNullElement == null) return array; if (notNullElement instanceof Comparator) { comparator = (Comparator<T>) notNullElement; } else if (notNullElement instanceof Comparable) { comparator = (o1, o2) -> { if (o1 == null) return 1; if (o2 == null) return -1; return ((Comparable<T>) o1).compareTo(o2); }; } if (comparator == null) return array; Arrays.sort(tmpArray, comparator); return tmpArray; }
  • 27.
    Dirty and Puremethods Here's Johnny! /** * Checks array and returns copy if Mars is in the zenith of Saturn */ public <T> T[] checkAndReturnArray(T[] array) { return (array != null) ? ((System.currentTimeMillis() > (42 * 64 * 30 * 365)) ? ((System.getenv("magic") == null) ? array : null) : array) : null; }
  • 28.
    Dirty and Puremethods Here's Johnny! /** * Checks array and returns copy if Mars is in the zenith of Saturn */ public <T> T[] checkAndReturnArray(T[] array) { return (array != null) ? ((System.currentTimeMillis() > (42 * 64 * 30 * 365)) ? ((System.getenv("magic") == null) ? array : null) : array) : null; }
  • 29.
    Immutability and finalkeyword If you can’t change the methods, you can change the arguments...
  • 30.
    Immutability and finalkeyword What is immutability? class Immutable { private final String immutableField; public Immutable(String immutableField) { this.immutableField = immutableField; } public String getImmutableField() { return immutableField; } } Examples: String, Integer, File, URL...
  • 31.
    Immutability and finalkeyword What is immutability? class Immutable { private final String immutableField; public Immutable(String immutableField) { this.immutableField = immutableField; } public String getImmutableField() { return immutableField; } } Examples: String, Integer, File, URL... What is mutability? class Mutable { private List<String> mutableField; public List<String> getMutableField() { return mutableField; } public void setMutableField(List<String> mutableField) { this.mutableField = mutableField; } } Examples: ArrayList, Arrays, StringBuilder...
  • 32.
    Immutability and finalkeyword Why immutability is good? ● Preventing side-effects ● Thread-safe ● Easy to debug ● Easy to implement ● Easy to extend ● Easy to scale
  • 33.
    Immutability and finalkeyword Why immutability is good? ● Preventing side-effects ● Thread-safe ● Easy to debug ● Easy to implement ● Easy to extend ● Easy to scale Why immutability is bad? ● Real world isn’t immutable ● Constraints you ● Not always convenient ● Increases memory usage ● Performance degradation ● There is always will be an exception...
  • 34.
    Immutability and finalkeyword Keyword final can be used with: ● Variables ○ final Object someField;
  • 35.
    Immutability and finalkeyword Keyword final can be used with: ● Variables ○ final Object someField; ● Methods ○ final public void someMethod() { ... } ○ public void someMethod(final Object argument) { ... }
  • 36.
    Immutability and finalkeyword Keyword final can be used with: ● Variables ○ final Object someField; ● Methods ○ final public void someMethod() { ... } ○ public void someMethod(final Object argument) { ... } ● Classes ○ public final class Example3;
  • 37.
    try-catch-finally pitfalls Simple puzzle? publicstatic int puzzle() { try { return 5; } catch (Exception ex) { return 10; } finally { return 15; } }
  • 38.
    try-catch-finally pitfalls Simple puzzle? publicstatic int puzzle() { try { return 5; } catch (Exception ex) { return 10; } finally { return 15; } }
  • 39.
    try-catch-finally pitfalls try pitfalls ●It’s a new scope… ● Each line might raise exception ● catch or finally is required ● Try with resources? ○ Custom AutoCloseable implementation ○ Implicit side-effect
  • 40.
    try-catch-finally pitfalls catch pitfalls ●It’s a new scope… ● Type erasing ● Performance degradation ● Exception-oriented logic
  • 41.
    try-catch-finally pitfalls finally pitfalls ●It’s a new scope… ● WILL BE EXECUTED ALWAYS!!! ○ Except for that moment, in which you will really need this... ● Might cause performance degradation ● Newer return value in finally ○ But sometimes...
  • 42.
    Early exception handling Exceptionhandling public int someMethod(String arg1, String arg2) { final int defaultValue = 42; int value = 0; try { int int1 = Integer.parseInt(arg1); int int2 = Integer.parseInt(arg2); value = int1 / int2; } catch (Exception ex) { System.err.println(ex); return defaultValue; } return value; }
  • 43.
    Early exception handling Exceptionhandling public int someMethod(String arg1, String arg2) { final int defaultValue = 42; int value = 0; try { int int1 = Integer.parseInt(arg1); int int2 = Integer.parseInt(arg2); value = int1 / int2; } catch (Exception ex) { System.err.println(ex); return defaultValue; } return value; } Early exception handling public int someMethod(String arg1, String arg2) { final int defaultValue = 42; if (notNumber(arg1) || notNumber(arg2)) { return defaultValue; } int int1 = Integer.parseInt(arg1); int int2 = Integer.parseInt(arg2); if (int2 == 0) { return defaultValue; } int value = int1 / int2; return value; }
  • 44.
    Early exception handling ●Objects.requireNonNull(argument); (throw early)
  • 45.
    Early exception handling ●Objects.requireNonNull(argument); (throw early) ● Use IllegalArgumentException() (throw early)
  • 46.
    Early exception handling ●Objects.requireNonNull(argument); (throw early) ● Use IllegalArgumentException() (throw early) ● Use UnsupportedOperationException() (throw early)
  • 47.
    Early exception handling ●Objects.requireNonNull(argument); (throw early) ● Use IllegalArgumentException() (throw early) ● Use UnsupportedOperationException() (throw early) ● Delegate exception handling, use throws (catch late)
  • 48.
    Early exception handling ●Objects.requireNonNull(argument); (throw early) ● Use IllegalArgumentException() (throw early) ● Use UnsupportedOperationException() (throw early) ● Delegate exception handling, use throws (catch late) ● Write javadoc ● Write logs
  • 49.
    Why null isbad? ● More than 2500 NPE defects in our Jira
  • 50.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept
  • 51.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept ● Zero information
  • 52.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept ● Zero information ● null instanceof Type --> false
  • 53.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept ● Zero information ● null instanceof Type --> false ● int value = (Integer) null; --> NPE
  • 54.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept ● Zero information ● null instanceof Type --> false ● int value = (Integer) null; --> NPE ● Many methods uses .toString() --> NPE ○ String.valueOf(obj) - solves this issue
  • 55.
    Why null isbad? ● More than 2500 NPE defects in our Jira ● null is low-level concept ● Zero information ● null instanceof Type --> false ● int value = (Integer) null; --> NPE ● Many methods uses .toString() --> NPE ○ String.valueOf(obj) - solves this issue ● Null-oriented programming is legacy ○ Use Optional<T> instead
  • 56.
    Lean refactoring ● Don’tbroke tests (Red-Green-Refactor)
  • 57.
    Lean refactoring ● Don’tbroke tests (Red-Green-Refactor) ● Don’t change signatures
  • 58.
    Lean refactoring ● Don’tbroke tests (Red-Green-Refactor) ● Don’t change signatures ● Don’t change parameters order ○ Especially for constructors
  • 59.
    Lean refactoring ● Don’tbroke tests (Red-Green-Refactor) ● Don’t change signatures ● Don’t change parameters order ○ Especially for constructors ● Don’t change contract
  • 60.
    Lean refactoring ● Don’tbroke tests (Red-Green-Refactor) ● Don’t change signatures ● Don’t change parameters order ○ Especially for constructors ● Don’t change contract ● Use @Deprecated
  • 61.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton
  • 62.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton ● Use static as Singleton
  • 63.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton ● Use static as Singleton ● Use reflection ○ Especially for internal JDK classes
  • 64.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton ● Use static as Singleton ● Use reflection ○ Especially for internal JDK classes ● Use interface just because of signature
  • 65.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton ● Use static as Singleton ● Use reflection ○ Especially for internal JDK classes ● Use interface just because of signature ● Use inheritance as aggregation/delegation
  • 66.
    Abusing Java Just becauseyou can, it doesn’t mean you should... ● Use enum as Singleton ● Use static as Singleton ● Use reflection ○ Especially for internal JDK classes ● Use interface just because of signature ● Use inheritance as aggregation/delegation ● ... ● If it works, it doesn’t mean it’s good.
  • 67.
    SOLID in thenutshell ● S - Single responsibility
  • 68.
    SOLID in thenutshell ● S - Single responsibility ● O - Opened for extension, but closed for changes
  • 69.
    SOLID in thenutshell ● S - Single responsibility ● O - Opened for extension, but closed for changes ● L - Liskov substitution, children should keep parents contracts.
  • 70.
    SOLID in thenutshell ● S - Single responsibility ● O - Opened for extension, but closed for changes ● L - Liskov substitution, children should keep parents contracts. ● I - Interface segregation is better than God-interface.
  • 71.
    SOLID in thenutshell ● S - Single responsibility ● O - Opened for extension, but closed for changes ● L - Liskov substitution, children should keep parents contracts. ● I - Interface segregation is better than God-interface. ● D - Dependency inversion, build dependencies over abstractions, not over implementations.
  • 72.
    Q&A Session (theend) Attention! Thanks for your attention!