SlideShare a Scribd company logo
1 of 108
Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects / Proxies / Interceptors
Java 7
Lombok / Groovy
About Me
Boilerplate – noun Code you shouldn't be writing yourself
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects / Proxies / Interceptors
Java 7
Lombok / Groovy
“Traditional Error Handling” try  { doSomething(); }  catch  (UnsupportedOperationException e) { handleError(e); }  catch  (IllegalStateException e) { handleError(e); }  catch  (IllegalArgumentException e) { handleError(e); }
“Modern Error Handling” try  { doSomething(); }  catch  (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) { handleError(e); }
“Traditional Resource Management” FileReader reader =  new  FileReader(path); try  { return  reader.read(); }  finally  { reader.close(); }
“Modern Resource Management” try  (FileReader reader =  new  FileReader(path)) { return  reader.read(); }
“Modern Resource Management” class  MyResource  implements  AutoCloseable { String getResource() { return   "some resource" ;  } @Override public   void  close()  throws  Exception { // closing } } try  (MyResource resource =  new  MyResource()) { return  resource.getResource(); }
Strings in Switch class  Calculator { Number apply( int  left, String operator,  int  right) { switch  (operator) { case   "plus" :  return  left + right; case   "minus" :  return  left - right; case   "times" :  return  left * right; case   "divided by" :  return  left / right; default :  throw   new  Exception(operator); } } } Calculator calculator =  new  Calculator(); assert  calculator.apply( 1 ,  "plus" ,  2 ).equals( 3 ); assert  calculator.apply( 5 ,  "times" ,  2 ).equals( 10 ); assert  calculator.apply( 5 ,  "minus" ,  2 ).equals( 3 );
Regex in Groovy Switch Number apply( int  left, String operator,  int  right) { switch  (operator) { case   ~/ (i)plus/ :  return  left + right case   ~/ (i)minus/ :  return  left - right case   ~/ (i)times/ :  return  left * right case   ~/ (i)divided by/ :  return  left / right default :  throw   new  Exception(operator) } } assert  apply( 1 ,  "plus" ,  2 ) ==  3 assert  apply( 5 ,  "TIMES" ,  2 ) ==  10 assert  apply( 5 ,  "MiNuS" ,  2 ) ==  3
Less Generic Cruft Map<Integer, String> map =  new  HashMap<>();
Java 7 Features + Soon to be widely used  + Terser code - No Lambdas - Not widely used
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects / Proxies / Interceptors
Java 7
Lombok / Groovy
import static  org.apache.commons.lang.StringUtils.*;
import static  org.apache.commons.lang.StringUtils.*; assert   isAlpha ( &quot;abcde&quot; ); assert   isNumeric ( &quot;12345&quot; ); assert   isAlphanumeric ( &quot;12345abc&quot; );
import static  org.apache.commons.lang.StringUtils.*; assert   isBlank ( &quot;&quot; ); assert   isBlank ( null );
import static  org.apache.commons.lang.StringUtils.*; assert   isAllLowerCase ( &quot;abcdef&quot; ); assert   isAllUpperCase ( &quot;ABCDEF&quot; );
import static  org.apache.commons.lang.StringUtils.*; assert   &quot;abc&quot;  ==  defaultString ( &quot;abc&quot; ); assert   &quot;&quot;  ==  defaultString ( &quot;&quot; ); assert   &quot;&quot;  ==  defaultString ( null );
import static  org.apache.commons.lang.StringUtils.*; assert   &quot;abc&quot; .equals( left ( &quot;abcdef&quot; ,  3 )); assert   &quot;def&quot; .equals( right ( &quot;abcdef&quot; ,  3 )); assert   null  ==  right ( null ,  3 );
import static  org.apache.commons.lang.StringUtils.*; Object[] array =  new  Object[]{ 1 ,  2 ,  3 }; assert   &quot;1, 2, 3&quot; .equals( join (array,  &quot;, &quot; )); List list = Arrays. asList ( 1 ,  2 ,  3 ); assert   &quot;1, 2, 3&quot; .equals( join (list,  &quot;, &quot; ));
import  org.apache.commons.lang.StringEscapeUtils;
import  org.apache.commons.lang.StringEscapeUtils; String xmlText =  &quot; amp;quot; Hello amp;quot;   &  amp;quot; GoodBye amp;quot; &quot; ; String escapedXml =  &quot;&quot;Hello&quot; &amp; &quot; +  &quot;&quot;GoodBye&quot;&quot; ; assert  escapedXml.equals( StringEscapeUtils. escapeXml (xmlText) ); assert  xmlText.equals( StringEscapeUtils. unescapeXml (escapedXml) );
import  org.apache.commons.lang.StringEscapeUtils; String htmlText =  &quot;<body>text</body>&quot; ; String escapedHtml =  &quot;&lt;body&gt;&quot;  + &quot;text&lt;/body&gt;&quot; ; assert  escapedHtml.equals( StringEscapeUtils. escapeHtml (htmlText) ); assert  htmlText.equals( StringEscapeUtils. unescapeHtml (escapedHtml) );
import  org.apache.commons.lang.StringEscapeUtils; String csvText =  &quot;red, beans, and rice&quot; ; String escapedCsv =  &quot; amp;quot; red, beans, and rice amp;quot; &quot; ; assert  escapedCsv.equals( StringEscapeUtils. escapeCsv (csvText) ); assert  csvText.equals( StringEscapeUtils. unescapeCsv (escapedCsv) );
import static  org.apache.commons.lang.ArrayUtils.*;
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert   contains (evens,  2 ); assert   contains (odds,  3 );
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert  Arrays. equals (   new   int []{ 2 ,  4 ,  6 ,  8 },    add (evens,  8 ) ); assert  Arrays. equals ( new   int []{ 2 ,  4 ,  6 ,  1 ,  3 ,  5 },  addAll (evens, odds) );
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert  Arrays. equals (   new   int []{ 2 ,  6 },    remove (evens,  1 ) ); assert  Arrays. equals (   new   int []{ 1 ,  3 },    remove (odds,  2 ) );
import static  org.apache.commons.lang.BooleanUtils.*;
import static  org.apache.commons.lang.BooleanUtils.*; assert   toBoolean ( &quot;true&quot; ); assert   toBoolean ( &quot;TRUE&quot; ); assert   toBoolean ( &quot;tRUe&quot; ); assert   toBoolean ( &quot;on&quot; ); assert   toBoolean ( &quot;ON&quot; ); assert   toBoolean ( &quot;yes&quot; ); assert   toBoolean ( &quot;YES&quot; );
import  org.apache.commons.lang.builder.ToStringBuilder;
import  org.apache.commons.lang.builder.ToStringBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public  String toString() { return   new  ToStringBuilder( this ) .append( &quot;name&quot; ,  name ) .append( &quot;timestamp&quot; ,  timestamp ) .toString(); } }
import  org.apache.commons.lang.builder.EqualsBuilder;
import  org.apache.commons.lang.builder.EqualsBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public   boolean  equals(Object obj) { if  (obj ==  null ) {  return   false ; } if  (obj ==  this ) {  return   true ; } if  (obj.getClass() != getClass()) {  return   false ; } Person rhs = (Person) obj; return   new  EqualsBuilder() .append( name , rhs. name ) .append( timestamp , rhs. timestamp ) .isEquals(); } }
import  org.apache.commons.lang.builder.HashCodeBuilder;
import  org.apache.commons.lang.builder.HashCodeBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public   int  hashCode() { return   new  HashCodeBuilder() .append( name ) .append( timestamp ) .toHashCode(); } }
import  org.apache.commons.lang.builder. CompareToBuilder ;
import  org.apache.commons.lang.builder. CompareToBuilder ; public   class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); public   int  compareTo(Person other) { return   new  CompareToBuilder() .append( this . name , other. name ) .toComparison(); } }
Apache Commons Lang ,[object Object]
No Generics
Many functions obsoleted by JDK 5 ,[object Object],[object Object]
Not backwards compatible with 2.6
new  HashMap<T, Set<U>>
import  com.google.common.collect.Multimap;
import  com.google.common.collect.Multimap; Multimap<String, String> multiMap =  HashMultimap. create (); multiMap.put( &quot;Canoo&quot; ,  &quot;Hamlet&quot; ); multiMap.put( &quot;Canoo&quot; ,  &quot;Dierk&quot; ); multiMap.put( &quot;Canoo&quot; ,  &quot;Andres&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Charles&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Thomas&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Nick&quot; );
import  com.google.common.collect.Multimap; assert  multiMap.containsKey( &quot;Canoo&quot; ); assert  multiMap.containsKey( &quot;EngineYard&quot; ); assert  multiMap.containsValue( &quot;Hamlet&quot; ); assert  multiMap.containsValue( &quot;Charles&quot; );
import  com.google.common.collect.Multimap; Collection<String> canooies = multiMap.get( &quot;Canoo&quot; ); Collection<String> c = Lists. newArrayList ( &quot;Dierk&quot; , &quot;Andres&quot; ,  &quot;Hamlet&quot; ); assert  canooies.containsAll(c);
import  com.google.common.collect.BiMap;
import  com.google.common.collect.BiMap; BiMap<String, String> biMap = HashBiMap. create (); biMap.put( &quot;Switzerland&quot; ,  &quot;die Schweiz&quot; ); biMap.put( &quot;Poland&quot; ,  &quot;Polska&quot; ); biMap.put( &quot;Austria&quot; ,  &quot;Österreich&quot; ); assert   &quot;Polska&quot;  == biMap.get( &quot;Poland&quot; ); assert   &quot;Switzerland&quot;  == biMap.inverse() .get( &quot;die Schweiz&quot; );
new  HashMap<T, Map<U, V>>
import  com.google.common.collect.Table;
import  com.google.common.collect.Table; Table<Integer, Integer, String> table =  HashBasedTable. create (); table.put( 1 ,  1 ,  &quot;Hamlet&quot; ); table.put( 1 ,  2 ,  &quot;Dierk&quot; ); table.put( 2 ,  1 ,  &quot;Andres&quot; ); table.put( 2 ,  2 ,  &quot;Matthius&quot; );
import  com.google.common.collect.Table; assert  table.contains( 1 ,  1 ); assert  table.containsRow( 1 ); assert  table.containsColumn( 2 ); assert  !table.contains( 3 ,  1 ); assert  !table.containsRow( 3 ); assert  !table.containsColumn( 3 ); assert   &quot;Hamlet&quot;  == table.get( 1 ,  1 ); assert  table.containsValue( &quot;Hamlet&quot; );
import  com.google.common.base.Joiner;
import  com.google.common.base.Joiner; Set<Integer> set = Sets. newHashSet ( 1 ,  2 ,  3 ); assert   &quot;1, 2, 3&quot; .equals(Joiner. on ( &quot;, &quot; ).join(set));
import  com.google.common.base.Splitter;
import  com.google.common.base.Splitter; String string =  &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quot;,&quot; ) .omitEmptyStrings() .trimResults() .split(string);
import static  com.google.common.collect.Iterables.*; import static  com.google.common.collect.Lists.*; Iterable<Integer> setAsInts =  transform (i, new  Function<String, Integer>() { @Override public  Integer apply(String input) { return  Integer. valueOf (input); } }); assert   newArrayList ( 1 ,  2 ,  3 ) .containsAll( newArrayList (setAsInts));
import static  com.google.common.base.Strings.*;
import static  com.google.common.base.Strings.*; assert   emptyToNull ( &quot;&quot; ) ==  null ; assert   &quot;&quot; .equals( nullToEmpty ( null )); assert   isNullOrEmpty ( &quot;&quot; ); assert   &quot;abcabcabc&quot; .equals( repeat ( &quot;abc&quot; ,  3 ));
import static  com.google.common.base.Preconditions.*;
import static  com.google.common.base.Preconditions.*; int  userID =  1 ; String userName =  &quot;some name&quot; ; checkArgument (userID >  0 ,  &quot;userid is negative: %s&quot; , userID); checkNotNull (userName,  &quot;user %s missing name&quot; , userID); checkState (userName.length() >  0 ,  &quot;user %s missing name&quot; , userID);
import static  com.google.common.base.Objects.*;
import static  com.google.common.base.Objects.*; class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public  String toString() { return   toStringHelper ( this ) .add( &quot;name&quot; ,  name ) .add( &quot;timestamp&quot; ,  timestamp ).toString(); } }
import static  com.google.common.base.Equivalences.*;
import static  com.google.common.base.Equivalences.*; class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); @Override public   boolean  equals(Object obj) { if  (obj ==  null ) {  return   false ; } if  (obj ==  this ) {  return   true ; } if  (obj.getClass() != getClass()) { return   false ; } Person rhs = (Person) obj; return   equals ().equivalent( name , rhs. name ) && equals ().equivalent( timestamp , rhs. timestamp ); } @Override public   int  hashCode() { return   hashCode ( name ,  timestamp ); } }
import static  com.google.common.collect.ComparisonChain.*;
import static  com.google.common.collect.ComparisonChain.*; class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); public   int  compareTo(Person other) { return   start () .compare( name , other. name ) .compare( timestamp , other. timestamp ) .result(); } }
import  com.google.common.base.Throwables;
import  com.google.common.base.Throwables; Exception ex =  new  Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex,  false );
import  com.google.common.base.Function;
import  com.google.common.base.Function; Person alice =  new  Person( &quot;Alice&quot; ); Person bob =  new  Person( &quot;Bob&quot; ); Person carol =  new  Person( &quot;Carol&quot; ); List<Person> people =  newArrayList (alice, bob, carol);
import  com.google.common.base.Function; Function<Person, String> getName =  new  Function<Person, String>() { public  String apply(Person p) { return  p.getName(); } }; assert   &quot;Alice&quot;  == getName.apply(alice); Collection<String> names = Collections2 . transform (people, getName); assert  names.containsAll( newArrayList ( &quot;Alice&quot; ,  &quot;Bob&quot; ,  &quot;Carol&quot; ) );
import  com.google.common.base.Predicate;
import  com.google.common.base.Predicate; Predicate<Person> predicate =  new  Predicate<Person>() { public   boolean  apply(Person input) { return  input.getName().contains( &quot;o&quot; ); } }; Iterable<Person> filteredList = Iterables . filter ( people, predicate); assert  Iterables. contains (filteredList, bob); assert  Iterables. contains (filteredList, carol); assert  !Iterables. contains (filteredList, alice);
Google Guava ,[object Object]
Well-Designed
Consistent?
Active
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects / Proxies / Interceptors
Java 7
Lombok / Groovy
“Traditional API” Order order =  new  Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
“Modern API” new  FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
“Modern API” class  FluentOrder { private  String  item ; private   int   quantity ; public  FluentOrder withItem(String item) { this . item  = item; return   this ; }   public  FluentOrder withQuantity( int  quantity) { this . quantity  = quantity; return   this ; }   boolean  pay(Currency currency) {   // pay order return   true ; } }
class  OrderBuilder { QuantityHolder withItem(String item) { return   new  QuantityHolder(item); } } class  QuantityHolder { private   final  String  item ; private  QuantityHolder(String item) { this . item  = item; } OrderFiller withQuantity( int  quantity) { return   new  OrderFiller( item , quantity);  } } class  OrderFiller { private   final  String  item ; private   final   int   quantity ; private  OrderFiller(String item,  int  quantity) { this . item  = item;  this . quantity  = quantity; } boolean  pay(Currency currency) { /* pay order... */   return   true ; } }
... another type-safe version new  Order( OrderBuilder. newInstance () .initItemName( &quot;latte&quot; ) .initQuantity( 10 ) .withCurrency(Currency. getInstance ( &quot;CHF&quot; )) ).pay(); // forgetting required args is a compile error new  Order( OrderBuilder.newInstance() .initItemName( &quot;latte&quot; ) .withCurrency(Currency.getInstance( &quot;CHF&quot; ) ));
public   class  OrderBuilder<NAME, QUANTITY> { // required fields private  String  itemName ; private   int   quantity ; private  Currency  currency ;  // optional field public   static  OrderBuilder<NOK, NOK> newInstance() { return   new  OrderBuilder<>(); } public  OrderBuilder(String itemName,  int  quantity, Currency currency) { this . itemName  = itemName; this . quantity  = quantity; this . currency  = currency; } public  OrderBuilder<OK, QUANTITY> initItemName(String itemName) { this . itemName  = itemName; return   new  OrderBuilder<>(name,  quantity ,  currency ); } public  OrderBuilder<NAME, OK> initQuantity( int  quantity) { this . quantity  = quantity; return   new  OrderBuilder<>( itemName , quantity,  currency ); } public  OrderBuilder<NAME, QUANTITY> withCurrency(Currency currency) { this . currency  = currency; return   this ; } ...  // getters & default ctor omitted }
... and it's just plain old Groovy new  Order( itemName:  'lattes' , quantity: 2 ).pay(Currency.getInstance( 'USD' )) new  Order().with { itemName =  'lattes' quantity = 2 pay(Currency. getInstance ( 'USD' )) }
Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
Agenda ,[object Object]
Builders / Fluent APIs

More Related Content

What's hot

The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
Mite Mitreski
 
JDK8 : parallel programming made (too ?) easy
JDK8 : parallel programming made (too ?) easyJDK8 : parallel programming made (too ?) easy
JDK8 : parallel programming made (too ?) easy
José Paumard
 
GR8Conf 2011: GPars
GR8Conf 2011: GParsGR8Conf 2011: GPars
GR8Conf 2011: GPars
GR8Conf
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
Graham Dumpleton
 

What's hot (20)

Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)
 
A Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalA Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert Fornal
 
The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
Google guava
Google guavaGoogle guava
Google guava
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
JDK8 : parallel programming made (too ?) easy
JDK8 : parallel programming made (too ?) easyJDK8 : parallel programming made (too ?) easy
JDK8 : parallel programming made (too ?) easy
 
Simplifying java with lambdas (short)
Simplifying java with lambdas (short)Simplifying java with lambdas (short)
Simplifying java with lambdas (short)
 
What's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageWhat's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritage
 
InterConnect: Server Side Swift for Java Developers
InterConnect:  Server Side Swift for Java DevelopersInterConnect:  Server Side Swift for Java Developers
InterConnect: Server Side Swift for Java Developers
 
Android dev toolbox - Shem Magnezi, WeWork
Android dev toolbox - Shem Magnezi, WeWorkAndroid dev toolbox - Shem Magnezi, WeWork
Android dev toolbox - Shem Magnezi, WeWork
 
Implementing pattern-matching in JavaScript (full version)
Implementing pattern-matching in JavaScript (full version)Implementing pattern-matching in JavaScript (full version)
Implementing pattern-matching in JavaScript (full version)
 
GR8Conf 2011: GPars
GR8Conf 2011: GParsGR8Conf 2011: GPars
GR8Conf 2011: GPars
 
Testing Java Code Effectively
Testing Java Code EffectivelyTesting Java Code Effectively
Testing Java Code Effectively
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
Client server part 12
Client server part 12Client server part 12
Client server part 12
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascript
 
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, GettLean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
 

Similar to Java Boilerplate Busters

Javascript Unit Testing
Javascript Unit TestingJavascript Unit Testing
Javascript Unit Testing
Paul Klipp
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
ShriKant Vashishtha
 
Groovy Api Tutorial
Groovy Api  TutorialGroovy Api  Tutorial
Groovy Api Tutorial
guligala
 
Programming with Java: the Basics
Programming with Java: the BasicsProgramming with Java: the Basics
Programming with Java: the Basics
Jussi Pohjolainen
 
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraum
patricklee
 

Similar to Java Boilerplate Busters (20)

Javascript Unit Testing
Javascript Unit TestingJavascript Unit Testing
Javascript Unit Testing
 
Spring Capitulo 05
Spring Capitulo 05Spring Capitulo 05
Spring Capitulo 05
 
Google collections api an introduction
Google collections api   an introductionGoogle collections api   an introduction
Google collections api an introduction
 
Jquery 1
Jquery 1Jquery 1
Jquery 1
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
My java file
My java fileMy java file
My java file
 
Groovy
GroovyGroovy
Groovy
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentation
 
Effective Java - Still Effective After All These Years
Effective Java - Still Effective After All These YearsEffective Java - Still Effective After All These Years
Effective Java - Still Effective After All These Years
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Prototype js
Prototype jsPrototype js
Prototype js
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery Presentation
 
Python - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Park
 
Groovy Api Tutorial
Groovy Api  TutorialGroovy Api  Tutorial
Groovy Api Tutorial
 
Programming with Java: the Basics
Programming with Java: the BasicsProgramming with Java: the Basics
Programming with Java: the Basics
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
JavaScript Sprachraum
JavaScript SprachraumJavaScript Sprachraum
JavaScript Sprachraum
 

More from HamletDRC (8)

Static Analysis and AST Transformations
Static Analysis and AST TransformationsStatic Analysis and AST Transformations
Static Analysis and AST Transformations
 
Static Analysis in IDEA
Static Analysis in IDEAStatic Analysis in IDEA
Static Analysis in IDEA
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
10 Years of Groovy
10 Years of Groovy10 Years of Groovy
10 Years of Groovy
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Recently uploaded (20)

Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 

Java Boilerplate Busters

  • 1. Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
  • 2.
  • 4. Function Objects / Proxies / Interceptors
  • 8. Boilerplate – noun Code you shouldn't be writing yourself
  • 9.
  • 11. Function Objects / Proxies / Interceptors
  • 14. “Traditional Error Handling” try { doSomething(); } catch (UnsupportedOperationException e) { handleError(e); } catch (IllegalStateException e) { handleError(e); } catch (IllegalArgumentException e) { handleError(e); }
  • 15. “Modern Error Handling” try { doSomething(); } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) { handleError(e); }
  • 16. “Traditional Resource Management” FileReader reader = new FileReader(path); try { return reader.read(); } finally { reader.close(); }
  • 17. “Modern Resource Management” try (FileReader reader = new FileReader(path)) { return reader.read(); }
  • 18. “Modern Resource Management” class MyResource implements AutoCloseable { String getResource() { return &quot;some resource&quot; ; } @Override public void close() throws Exception { // closing } } try (MyResource resource = new MyResource()) { return resource.getResource(); }
  • 19. Strings in Switch class Calculator { Number apply( int left, String operator, int right) { switch (operator) { case &quot;plus&quot; : return left + right; case &quot;minus&quot; : return left - right; case &quot;times&quot; : return left * right; case &quot;divided by&quot; : return left / right; default : throw new Exception(operator); } } } Calculator calculator = new Calculator(); assert calculator.apply( 1 , &quot;plus&quot; , 2 ).equals( 3 ); assert calculator.apply( 5 , &quot;times&quot; , 2 ).equals( 10 ); assert calculator.apply( 5 , &quot;minus&quot; , 2 ).equals( 3 );
  • 20. Regex in Groovy Switch Number apply( int left, String operator, int right) { switch (operator) { case ~/ (i)plus/ : return left + right case ~/ (i)minus/ : return left - right case ~/ (i)times/ : return left * right case ~/ (i)divided by/ : return left / right default : throw new Exception(operator) } } assert apply( 1 , &quot;plus&quot; , 2 ) == 3 assert apply( 5 , &quot;TIMES&quot; , 2 ) == 10 assert apply( 5 , &quot;MiNuS&quot; , 2 ) == 3
  • 21. Less Generic Cruft Map<Integer, String> map = new HashMap<>();
  • 22. Java 7 Features + Soon to be widely used + Terser code - No Lambdas - Not widely used
  • 23.
  • 25. Function Objects / Proxies / Interceptors
  • 28. import static org.apache.commons.lang.StringUtils.*;
  • 29. import static org.apache.commons.lang.StringUtils.*; assert isAlpha ( &quot;abcde&quot; ); assert isNumeric ( &quot;12345&quot; ); assert isAlphanumeric ( &quot;12345abc&quot; );
  • 30. import static org.apache.commons.lang.StringUtils.*; assert isBlank ( &quot;&quot; ); assert isBlank ( null );
  • 31. import static org.apache.commons.lang.StringUtils.*; assert isAllLowerCase ( &quot;abcdef&quot; ); assert isAllUpperCase ( &quot;ABCDEF&quot; );
  • 32. import static org.apache.commons.lang.StringUtils.*; assert &quot;abc&quot; == defaultString ( &quot;abc&quot; ); assert &quot;&quot; == defaultString ( &quot;&quot; ); assert &quot;&quot; == defaultString ( null );
  • 33. import static org.apache.commons.lang.StringUtils.*; assert &quot;abc&quot; .equals( left ( &quot;abcdef&quot; , 3 )); assert &quot;def&quot; .equals( right ( &quot;abcdef&quot; , 3 )); assert null == right ( null , 3 );
  • 34. import static org.apache.commons.lang.StringUtils.*; Object[] array = new Object[]{ 1 , 2 , 3 }; assert &quot;1, 2, 3&quot; .equals( join (array, &quot;, &quot; )); List list = Arrays. asList ( 1 , 2 , 3 ); assert &quot;1, 2, 3&quot; .equals( join (list, &quot;, &quot; ));
  • 36. import org.apache.commons.lang.StringEscapeUtils; String xmlText = &quot; amp;quot; Hello amp;quot; & amp;quot; GoodBye amp;quot; &quot; ; String escapedXml = &quot;&quot;Hello&quot; &amp; &quot; + &quot;&quot;GoodBye&quot;&quot; ; assert escapedXml.equals( StringEscapeUtils. escapeXml (xmlText) ); assert xmlText.equals( StringEscapeUtils. unescapeXml (escapedXml) );
  • 37. import org.apache.commons.lang.StringEscapeUtils; String htmlText = &quot;<body>text</body>&quot; ; String escapedHtml = &quot;&lt;body&gt;&quot; + &quot;text&lt;/body&gt;&quot; ; assert escapedHtml.equals( StringEscapeUtils. escapeHtml (htmlText) ); assert htmlText.equals( StringEscapeUtils. unescapeHtml (escapedHtml) );
  • 38. import org.apache.commons.lang.StringEscapeUtils; String csvText = &quot;red, beans, and rice&quot; ; String escapedCsv = &quot; amp;quot; red, beans, and rice amp;quot; &quot; ; assert escapedCsv.equals( StringEscapeUtils. escapeCsv (csvText) ); assert csvText.equals( StringEscapeUtils. unescapeCsv (escapedCsv) );
  • 39. import static org.apache.commons.lang.ArrayUtils.*;
  • 40. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert contains (evens, 2 ); assert contains (odds, 3 );
  • 41. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert Arrays. equals ( new int []{ 2 , 4 , 6 , 8 }, add (evens, 8 ) ); assert Arrays. equals ( new int []{ 2 , 4 , 6 , 1 , 3 , 5 }, addAll (evens, odds) );
  • 42. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert Arrays. equals ( new int []{ 2 , 6 }, remove (evens, 1 ) ); assert Arrays. equals ( new int []{ 1 , 3 }, remove (odds, 2 ) );
  • 43. import static org.apache.commons.lang.BooleanUtils.*;
  • 44. import static org.apache.commons.lang.BooleanUtils.*; assert toBoolean ( &quot;true&quot; ); assert toBoolean ( &quot;TRUE&quot; ); assert toBoolean ( &quot;tRUe&quot; ); assert toBoolean ( &quot;on&quot; ); assert toBoolean ( &quot;ON&quot; ); assert toBoolean ( &quot;yes&quot; ); assert toBoolean ( &quot;YES&quot; );
  • 46. import org.apache.commons.lang.builder.ToStringBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public String toString() { return new ToStringBuilder( this ) .append( &quot;name&quot; , name ) .append( &quot;timestamp&quot; , timestamp ) .toString(); } }
  • 48. import org.apache.commons.lang.builder.EqualsBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public boolean equals(Object obj) { if (obj == null ) { return false ; } if (obj == this ) { return true ; } if (obj.getClass() != getClass()) { return false ; } Person rhs = (Person) obj; return new EqualsBuilder() .append( name , rhs. name ) .append( timestamp , rhs. timestamp ) .isEquals(); } }
  • 50. import org.apache.commons.lang.builder.HashCodeBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public int hashCode() { return new HashCodeBuilder() .append( name ) .append( timestamp ) .toHashCode(); } }
  • 52. import org.apache.commons.lang.builder. CompareToBuilder ; public class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); public int compareTo(Person other) { return new CompareToBuilder() .append( this . name , other. name ) .toComparison(); } }
  • 53.
  • 55.
  • 57. new HashMap<T, Set<U>>
  • 59. import com.google.common.collect.Multimap; Multimap<String, String> multiMap = HashMultimap. create (); multiMap.put( &quot;Canoo&quot; , &quot;Hamlet&quot; ); multiMap.put( &quot;Canoo&quot; , &quot;Dierk&quot; ); multiMap.put( &quot;Canoo&quot; , &quot;Andres&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Charles&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Thomas&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Nick&quot; );
  • 60. import com.google.common.collect.Multimap; assert multiMap.containsKey( &quot;Canoo&quot; ); assert multiMap.containsKey( &quot;EngineYard&quot; ); assert multiMap.containsValue( &quot;Hamlet&quot; ); assert multiMap.containsValue( &quot;Charles&quot; );
  • 61. import com.google.common.collect.Multimap; Collection<String> canooies = multiMap.get( &quot;Canoo&quot; ); Collection<String> c = Lists. newArrayList ( &quot;Dierk&quot; , &quot;Andres&quot; , &quot;Hamlet&quot; ); assert canooies.containsAll(c);
  • 63. import com.google.common.collect.BiMap; BiMap<String, String> biMap = HashBiMap. create (); biMap.put( &quot;Switzerland&quot; , &quot;die Schweiz&quot; ); biMap.put( &quot;Poland&quot; , &quot;Polska&quot; ); biMap.put( &quot;Austria&quot; , &quot;Österreich&quot; ); assert &quot;Polska&quot; == biMap.get( &quot;Poland&quot; ); assert &quot;Switzerland&quot; == biMap.inverse() .get( &quot;die Schweiz&quot; );
  • 64. new HashMap<T, Map<U, V>>
  • 66. import com.google.common.collect.Table; Table<Integer, Integer, String> table = HashBasedTable. create (); table.put( 1 , 1 , &quot;Hamlet&quot; ); table.put( 1 , 2 , &quot;Dierk&quot; ); table.put( 2 , 1 , &quot;Andres&quot; ); table.put( 2 , 2 , &quot;Matthius&quot; );
  • 67. import com.google.common.collect.Table; assert table.contains( 1 , 1 ); assert table.containsRow( 1 ); assert table.containsColumn( 2 ); assert !table.contains( 3 , 1 ); assert !table.containsRow( 3 ); assert !table.containsColumn( 3 ); assert &quot;Hamlet&quot; == table.get( 1 , 1 ); assert table.containsValue( &quot;Hamlet&quot; );
  • 69. import com.google.common.base.Joiner; Set<Integer> set = Sets. newHashSet ( 1 , 2 , 3 ); assert &quot;1, 2, 3&quot; .equals(Joiner. on ( &quot;, &quot; ).join(set));
  • 71. import com.google.common.base.Splitter; String string = &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quot;,&quot; ) .omitEmptyStrings() .trimResults() .split(string);
  • 72. import static com.google.common.collect.Iterables.*; import static com.google.common.collect.Lists.*; Iterable<Integer> setAsInts = transform (i, new Function<String, Integer>() { @Override public Integer apply(String input) { return Integer. valueOf (input); } }); assert newArrayList ( 1 , 2 , 3 ) .containsAll( newArrayList (setAsInts));
  • 73. import static com.google.common.base.Strings.*;
  • 74. import static com.google.common.base.Strings.*; assert emptyToNull ( &quot;&quot; ) == null ; assert &quot;&quot; .equals( nullToEmpty ( null )); assert isNullOrEmpty ( &quot;&quot; ); assert &quot;abcabcabc&quot; .equals( repeat ( &quot;abc&quot; , 3 ));
  • 75. import static com.google.common.base.Preconditions.*;
  • 76. import static com.google.common.base.Preconditions.*; int userID = 1 ; String userName = &quot;some name&quot; ; checkArgument (userID > 0 , &quot;userid is negative: %s&quot; , userID); checkNotNull (userName, &quot;user %s missing name&quot; , userID); checkState (userName.length() > 0 , &quot;user %s missing name&quot; , userID);
  • 77. import static com.google.common.base.Objects.*;
  • 78. import static com.google.common.base.Objects.*; class Person { String name ; Date timestamp = new Date(); @Override public String toString() { return toStringHelper ( this ) .add( &quot;name&quot; , name ) .add( &quot;timestamp&quot; , timestamp ).toString(); } }
  • 79. import static com.google.common.base.Equivalences.*;
  • 80. import static com.google.common.base.Equivalences.*; class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); @Override public boolean equals(Object obj) { if (obj == null ) { return false ; } if (obj == this ) { return true ; } if (obj.getClass() != getClass()) { return false ; } Person rhs = (Person) obj; return equals ().equivalent( name , rhs. name ) && equals ().equivalent( timestamp , rhs. timestamp ); } @Override public int hashCode() { return hashCode ( name , timestamp ); } }
  • 81. import static com.google.common.collect.ComparisonChain.*;
  • 82. import static com.google.common.collect.ComparisonChain.*; class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); public int compareTo(Person other) { return start () .compare( name , other. name ) .compare( timestamp , other. timestamp ) .result(); } }
  • 84. import com.google.common.base.Throwables; Exception ex = new Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex, false );
  • 86. import com.google.common.base.Function; Person alice = new Person( &quot;Alice&quot; ); Person bob = new Person( &quot;Bob&quot; ); Person carol = new Person( &quot;Carol&quot; ); List<Person> people = newArrayList (alice, bob, carol);
  • 87. import com.google.common.base.Function; Function<Person, String> getName = new Function<Person, String>() { public String apply(Person p) { return p.getName(); } }; assert &quot;Alice&quot; == getName.apply(alice); Collection<String> names = Collections2 . transform (people, getName); assert names.containsAll( newArrayList ( &quot;Alice&quot; , &quot;Bob&quot; , &quot;Carol&quot; ) );
  • 89. import com.google.common.base.Predicate; Predicate<Person> predicate = new Predicate<Person>() { public boolean apply(Person input) { return input.getName().contains( &quot;o&quot; ); } }; Iterable<Person> filteredList = Iterables . filter ( people, predicate); assert Iterables. contains (filteredList, bob); assert Iterables. contains (filteredList, carol); assert !Iterables. contains (filteredList, alice);
  • 90.
  • 94.
  • 96. Function Objects / Proxies / Interceptors
  • 99. “Traditional API” Order order = new Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
  • 100. “Modern API” new FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
  • 101. “Modern API” class FluentOrder { private String item ; private int quantity ; public FluentOrder withItem(String item) { this . item = item; return this ; } public FluentOrder withQuantity( int quantity) { this . quantity = quantity; return this ; } boolean pay(Currency currency) { // pay order return true ; } }
  • 102. class OrderBuilder { QuantityHolder withItem(String item) { return new QuantityHolder(item); } } class QuantityHolder { private final String item ; private QuantityHolder(String item) { this . item = item; } OrderFiller withQuantity( int quantity) { return new OrderFiller( item , quantity); } } class OrderFiller { private final String item ; private final int quantity ; private OrderFiller(String item, int quantity) { this . item = item; this . quantity = quantity; } boolean pay(Currency currency) { /* pay order... */ return true ; } }
  • 103. ... another type-safe version new Order( OrderBuilder. newInstance () .initItemName( &quot;latte&quot; ) .initQuantity( 10 ) .withCurrency(Currency. getInstance ( &quot;CHF&quot; )) ).pay(); // forgetting required args is a compile error new Order( OrderBuilder.newInstance() .initItemName( &quot;latte&quot; ) .withCurrency(Currency.getInstance( &quot;CHF&quot; ) ));
  • 104. public class OrderBuilder<NAME, QUANTITY> { // required fields private String itemName ; private int quantity ; private Currency currency ; // optional field public static OrderBuilder<NOK, NOK> newInstance() { return new OrderBuilder<>(); } public OrderBuilder(String itemName, int quantity, Currency currency) { this . itemName = itemName; this . quantity = quantity; this . currency = currency; } public OrderBuilder<OK, QUANTITY> initItemName(String itemName) { this . itemName = itemName; return new OrderBuilder<>(name, quantity , currency ); } public OrderBuilder<NAME, OK> initQuantity( int quantity) { this . quantity = quantity; return new OrderBuilder<>( itemName , quantity, currency ); } public OrderBuilder<NAME, QUANTITY> withCurrency(Currency currency) { this . currency = currency; return this ; } ... // getters & default ctor omitted }
  • 105. ... and it's just plain old Groovy new Order( itemName: 'lattes' , quantity: 2 ).pay(Currency.getInstance( 'USD' )) new Order().with { itemName = 'lattes' quantity = 2 pay(Currency. getInstance ( 'USD' )) }
  • 106. Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
  • 107.
  • 109. Function Objects / Proxies / Interceptors
  • 110. Java 7
  • 112. public class ResourceProvider { private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Map<String, String> data = new ConcurrentHashMap(); public String getResource(String key) throws Exception { lock .readLock().lock(); try { return data .get(key); } finally { lock .readLock().unlock(); } } public void refresh() throws Exception { lock .writeLock().lock(); try { // reload settings... } finally { lock .writeLock().unlock(); } } } “Traditional API”
  • 113. public class ResourceController { private final ReadWriteLock lock = new ReentrantReadWriteLock(); public <T> T withReadLock(Callable<T> block) throws Exception { lock .readLock().lock(); try { return block.call(); } finally { lock .readLock().unlock(); } } public <T> T withWriteLock(Callable<T> block) throws Exception { lock .writeLock().lock(); try { return block.call(); } finally { lock .writeLock().unlock(); } } } “Modern API” con't
  • 114. public class ResourceProvider { private final ResourceController controller = new ResourceController(); private final Map<String, String> data = new ConcurrentHashMap(); public String getResource( final String key) throws Exception { return controller .withReadLock( new Callable<String>() { public String call() throws Exception { return data .get( key ); } }); } public void refresh() throws Exception { controller .withWriteLock( new Callable<Void>() { public Void call() throws Exception { // reload settings return null ; } }); } } “Modern API” -- Function Objects
  • 115. class ResourceProvider { private final controller = new ResourceController() private final data = [:] as ConcurrentHashMap String getResource(String key) { controller .withReadLock({ data .get( key ) } as Callable) } void refresh() { controller .withWriteLock( { /* reload settings */ } as Callable) } } “Modern API” -- Groovy Function Objects
  • 116. public class DefaultResourceProvider implements ResourceProvider { private final Map<String, String> data = new ConcurrentHashMap(); @WithReadLock public String getResource(String key) { return data .get(key); } @WithWriteLock public void refresh() { System. out .println( &quot;Reloading the settings...&quot; ); } } “Modern API” -- Proxy Class
  • 117. public class ResourceController implements InvocationHandler { private final Object target ; private final ReadWriteLock lock = new ReentrantReadWriteLock(); ResourceController(Object target) { this . target = target; } public Object invoke (Object proxy, Method method, Object[] args) { try { Method targetMethod = target .getClass().getMethod( method.getName(), method.getParameterTypes()); if (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try { return targetMethod.invoke( target , args); } finally { lock .readLock().unlock(); } } else if (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try { return targetMethod.invoke( target , args); } finally { lock .writeLock().unlock(); } } else { return targetMethod.invoke( target , args); } } catch (Exception ex) { throw new RuntimeException(ex); } } }
  • 118. “Modern API” -- Proxy Class con't InvocationHandler handler = new ResourceController( new DefaultResourceProvider() ); ResourceProvider p = (ResourceProvider) Proxy. newProxyInstance ( DefaultResourceProvider. class .getClassLoader(), new Class[]{ResourceProvider. class }, hand ler); p.refresh(); p.getResource( &quot;property&quot; );
  • 119. “Modern API” -- Proxy Class con't class ResourceProvider { private final Map data = new ConcurrentHashMap(); @WithReadLock String getResource(String key) { return (String) data .get(key); } @WithWriteLock void refresh() { // Reload settings... } }
  • 120. public class WithLockInterceptor { // This is shared!!! private final ReadWriteLock lock = new ReentrantReadWriteLock(); @AroundInvoke public Object enforceLock(InvocationContext context) throws Exception{ try { Method targetMethod = context.getMethod(); if (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try { return context.proceed(); } finally { lock .readLock().unlock(); } } else if (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try { //reload the resources into memory return context.proceed(); } finally { lock .writeLock().unlock(); } } return context.proceed(); } catch (Exception ex) { throw new RuntimeException(ex); } } }
  • 121. Function Objects + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks + Easier in Java 8 and Groovy - Verbose - Different
  • 122. Proxies & Interceptors + Declarative + Expressive + Easily replaces finally & catch blocks + Many implementation options - Proxy requires interface - Proxy hard to instantiate - Unproxied class may not be “valid”
  • 123.
  • 125. Function Objects / Proxies / Interceptors
  • 126. Java 7
  • 128. “Traditional Java Bean” public class Person { private String fName ; private String lName ; public String getFirstName() { return fName ; } public void setFirstName(String f) { this . fName = f; } public String getLastName() { return lName ; } public void setLastName(String l) { this . lName = l; } @Override public boolean equals(Object o) { ... } @Override public int hashCode() { ... } }
  • 129. “Modern Java Bean” -- Lombok @EqualsAndHashCode public class Person { @Setter @Getter private String firstName ; @Setter @Getter private String lastName ; }
  • 130. “Modern Java Bean” -- Lombok @Data public class Person { private String firstName ; private String lastName ; }
  • 131.
  • 132. Lombok + Generates boilerplate into Class file + Java-only, IDE support + delombok option - IDEA Plugin is poor - Hinders some Eclipse features - Not all features are loved by all
  • 133. “Modern Java Bean” -- Groovy @EqualsAndHashCode public class Person { String firstName String lastName }
  • 134.
  • 135.
  • 136. Groovy + Generates boilerplate into Class file + Great Java interop & IDE support + Gateway to many other features - Requires a new language ? Performs worse than Java ? Hinders some IDE features
  • 137.
  • 139. Function Objects / Proxies / Interceptors
  • 140. Java 7
  • 142.

Editor's Notes

  1. // Propagates throwable as-is if it is an instance of RuntimeException or Error, or else as a last resort, wraps it in a RuntimeException then propagates. Throwables.propagate(ex); // Propagates throwable exactly as-is, if and only if it is an instance of RuntimeException or Error. Throwables.propagateIfPossible(ex); // Rethrows the cause exception of a given throwable, discarding the original throwable. if the cause is null, then throws the ex Throwables.throwCause(ex, false);