Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
Agenda <ul><li>Google Guava /  Commons Lang
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy </li></ul>
About Me
Boilerplate – noun Code you shouldn't be writing yourself
Agenda <ul><li>Google Guava /  Commons Lang
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy </li></ul>
import static  org.apache.commons.lang.StringUtils.*;
import static  org.apache.commons.lang.StringUtils.*; assert   isAlpha ( &quot;abcde&quot; ); assert   isNumeric ( &quot;1...
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   isAllUpperC...
import static  org.apache.commons.lang.StringUtils.*; assert   &quot;abc&quot;  ==  defaultString ( &quot;abc&quot; ); ass...
import static  org.apache.commons.lang.StringUtils.*; assert   &quot;abc&quot; .equals( left ( &quot;abcdef&quot; ,  3 ));...
import static  org.apache.commons.lang.StringUtils.*; Object[] array =  new  Object[]{ 1 ,  2 ,  3 }; assert   &quot;1, 2,...
import  org.apache.commons.lang.StringEscapeUtils;
import  org.apache.commons.lang.StringEscapeUtils; String xmlText =  &quot; &quot; Hello &quot;   &  &quot; GoodBye &quot;...
import  org.apache.commons.lang.StringEscapeUtils; String htmlText =  &quot;<body>text</body>&quot; ; String escapedHtml =...
import  org.apache.commons.lang.StringEscapeUtils; String csvText =  &quot;red, beans, and rice&quot; ; String 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...
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int...
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int...
import static  org.apache.commons.lang.BooleanUtils.*;
import static  org.apache.commons.lang.BooleanUtils.*; assert   toBoolean ( &quot;true&quot; ); assert   toBoolean ( &quot...
import  org.apache.commons.lang.builder.ToStringBuilder;
import  org.apache.commons.lang.builder.ToStringBuilder; public   class  Person { String  name ; Date  timestamp  =  new  ...
import  org.apache.commons.lang.builder.EqualsBuilder;
import  org.apache.commons.lang.builder.EqualsBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Da...
import  org.apache.commons.lang.builder.HashCodeBuilder;
import  org.apache.commons.lang.builder.HashCodeBuilder; public   class  Person { String  name ; Date  timestamp  =  new  ...
import  org.apache.commons.lang.builder. CompareToBuilder ;
import  org.apache.commons.lang.builder. CompareToBuilder ; public   class  Person  implements  Comparable<Person> { Strin...
Apache Commons Lang <ul>+ Tons of other Helper Objects <ul><li>Version 2.6 Stable </li><ul><li>JDK 1.3 Compatible
No Generics
Many functions obsoleted by JDK 5 </li></ul><li>Version 3.0  </li><ul><li>JDK 1.5 Compatible
Not backwards compatible with 2.6 </li></ul></ul></ul>
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( &q...
import  com.google.common.collect.Multimap; assert  multiMap.containsKey( &quot;Canoo&quot; ); assert  multiMap.containsKe...
import  com.google.common.collect.Multimap; Collection<String> canooies = multiMap.get( &quot;Canoo&quot; ); Collection<St...
import  com.google.common.collect.BiMap;
import  com.google.common.collect.BiMap; BiMap<String, String> biMap = HashBiMap. create (); biMap.put( &quot;Switzerland&...
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 ...
import  com.google.common.collect.Table; assert  table.contains( 1 ,  1 ); assert  table.containsRow( 1 ); assert  table.c...
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; ....
import  com.google.common.base.Splitter;
import  com.google.common.base.Splitter; String string =  &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quo...
import static  com.google.common.collect.Iterables.*; import static  com.google.common.collect.Lists.*; Iterable<Integer> ...
import static  com.google.common.base.Strings.*;
import static  com.google.common.base.Strings.*; assert   emptyToNull ( &quot;&quot; ) ==  null ; assert   &quot;&quot; .e...
import static  com.google.common.base.Preconditions.*;
import static  com.google.common.base.Preconditions.*; int  userID =  1 ; String userName =  &quot;some name&quot; ; check...
import static  com.google.common.base.Objects.*;
import static  com.google.common.base.Objects.*; class  Person { String  name ; Date  timestamp  =  new  Date(); @Override...
import static  com.google.common.base.Equivalences.*;
import static  com.google.common.base.Equivalences.*; class  Person  implements  Comparable<Person> { String  name ; Date ...
import static  com.google.common.collect.ComparisonChain.*;
import static  com.google.common.collect.ComparisonChain.*; class  Person  implements  Comparable<Person> { String  name ;...
import  com.google.common.base.Throwables;
import  com.google.common.base.Throwables; Exception ex =  new  Exception(); Throwables. propagateIfPossible (ex); Throwab...
import  com.google.common.base.Function;
import  com.google.common.base.Function; Person alice =  new  Person( &quot;Alice&quot; ); Person bob =  new  Person( &quo...
import  com.google.common.base.Function; Function<Person, String> getName =  new  Function<Person, String>() { public  Str...
import  com.google.common.base.Predicate;
import  com.google.common.base.Predicate; Predicate<Person> predicate =  new  Predicate<Person>() { public   boolean  appl...
Google Guava <ul>+ Tons of other Helper Objects <ul><li>Modern (Fluent APIs & Generics)
Well-Designed
Consistent?
Active </li></ul></ul>
Agenda <ul><li>Google Guava / Commons Lang
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy </li></ul>
“Traditional API” Order order =  new  Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(...
“Modern API” new  FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&...
“Modern API” class  FluentOrder { private  String  item ; private   int   quantity ; public  FluentOrder withItem(String i...
class  OrderBuilder { QuantityHolder withItem(String item) { return   new  QuantityHolder(item); } } class  QuantityHolder...
... another type-safe version new  Order( OrderBuilder. newInstance () .initItemName( &quot;latte&quot; ) .initQuantity( 1...
public   class  OrderBuilder<NAME, QUANTITY> { // required fields private  String  itemName ; private   int   quantity ; p...
... and it's just plain old Groovy new  Order( itemName:  'lattes' , quantity: 2 ).pay(Currency.getInstance( 'USD' )) new ...
Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatt...
Agenda <ul><li>Google Guava / Commons Lang
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy </li></ul>
public   class  ResourceProvider {   private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); private   fin...
public   class  ResourceController { private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); public  <T> T...
public   class  ResourceProvider { private   final  ResourceController  controller  =  new  ResourceController(); private ...
class  ResourceProvider { private   final   controller  =  new  ResourceController() private   final   data  = [:]  as  Co...
public   class  DefaultResourceProvider  implements  ResourceProvider { private   final  Map<String, String>  data  =  new...
public   class  ResourceController  implements  InvocationHandler { private   final  Object  target ; private   final  Rea...
“Modern API” -- Proxy Class con't InvocationHandler handler =  new  ResourceController( new  DefaultResourceProvider() ); ...
“Modern API” -- Proxy Class con't class  ResourceProvider { private   final  Map  data  =  new  ConcurrentHashMap(); @With...
public   class  WithLockInterceptor  {   // This is shared!!! private   final  ReadWriteLock  lock  =  new  ReentrantReadW...
Function Objects  + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks  + Easier in Java 8 a...
Proxies & Interceptors + Declarative  + Expressive + Easily replaces finally & catch blocks  + Many implementation options...
Upcoming SlideShare
Loading in …5
×

Java Boilerplate Busters

2,438 views
2,327 views

Published on

Java has a reputation for boilerplate code: ubiquitous getters and setters, a verbose anonymous class syntax, and redundant declarations to name a few. It doesn't have to be this way! There are many ways to bust the boilerplate and this session provides a solid understanding of the most modern techniques. Come learn about inversion of control idioms, Proxy objects, code generation tools, and the latest libraries that both create and manage boilerplate code so you don't have to. A leaner, meaner codebase is yours for the taking.

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,438
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
86
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide
  • // 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);
  • Java Boilerplate Busters

    1. 1. Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
    2. 2. Agenda <ul><li>Google Guava / Commons Lang
    3. 3. Builders / Fluent APIs
    4. 4. Function Objects / Proxies / Interceptors
    5. 5. Java 7
    6. 6. Lombok / Groovy </li></ul>
    7. 7. About Me
    8. 8. Boilerplate – noun Code you shouldn't be writing yourself
    9. 9. Agenda <ul><li>Google Guava / Commons Lang
    10. 10. Builders / Fluent APIs
    11. 11. Function Objects / Proxies / Interceptors
    12. 12. Java 7
    13. 13. Lombok / Groovy </li></ul>
    14. 14. import static org.apache.commons.lang.StringUtils.*;
    15. 15. import static org.apache.commons.lang.StringUtils.*; assert isAlpha ( &quot;abcde&quot; ); assert isNumeric ( &quot;12345&quot; ); assert isAlphanumeric ( &quot;12345abc&quot; );
    16. 16. import static org.apache.commons.lang.StringUtils.*; assert isBlank ( &quot;&quot; ); assert isBlank ( null );
    17. 17. import static org.apache.commons.lang.StringUtils.*; assert isAllLowerCase ( &quot;abcdef&quot; ); assert isAllUpperCase ( &quot;ABCDEF&quot; );
    18. 18. 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 );
    19. 19. 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 );
    20. 20. 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; ));
    21. 21. import org.apache.commons.lang.StringEscapeUtils;
    22. 22. import org.apache.commons.lang.StringEscapeUtils; String xmlText = &quot; &quot; Hello &quot; & &quot; GoodBye &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) );
    23. 23. 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) );
    24. 24. import org.apache.commons.lang.StringEscapeUtils; String csvText = &quot;red, beans, and rice&quot; ; String escapedCsv = &quot; &quot; red, beans, and rice &quot; &quot; ; assert escapedCsv.equals( StringEscapeUtils. escapeCsv (csvText) ); assert csvText.equals( StringEscapeUtils. unescapeCsv (escapedCsv) );
    25. 25. import static org.apache.commons.lang.ArrayUtils.*;
    26. 26. 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 );
    27. 27. 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) );
    28. 28. 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 ) );
    29. 29. import static org.apache.commons.lang.BooleanUtils.*;
    30. 30. 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; );
    31. 31. import org.apache.commons.lang.builder.ToStringBuilder;
    32. 32. 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(); } }
    33. 33. import org.apache.commons.lang.builder.EqualsBuilder;
    34. 34. 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(); } }
    35. 35. import org.apache.commons.lang.builder.HashCodeBuilder;
    36. 36. 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(); } }
    37. 37. import org.apache.commons.lang.builder. CompareToBuilder ;
    38. 38. 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(); } }
    39. 39. Apache Commons Lang <ul>+ Tons of other Helper Objects <ul><li>Version 2.6 Stable </li><ul><li>JDK 1.3 Compatible
    40. 40. No Generics
    41. 41. Many functions obsoleted by JDK 5 </li></ul><li>Version 3.0 </li><ul><li>JDK 1.5 Compatible
    42. 42. Not backwards compatible with 2.6 </li></ul></ul></ul>
    43. 43. new HashMap<T, Set<U>>
    44. 44. import com.google.common.collect.Multimap;
    45. 45. 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; );
    46. 46. 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; );
    47. 47. 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);
    48. 48. import com.google.common.collect.BiMap;
    49. 49. 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; );
    50. 50. new HashMap<T, Map<U, V>>
    51. 51. import com.google.common.collect.Table;
    52. 52. 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; );
    53. 53. 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; );
    54. 54. import com.google.common.base.Joiner;
    55. 55. 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));
    56. 56. import com.google.common.base.Splitter;
    57. 57. import com.google.common.base.Splitter; String string = &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quot;,&quot; ) .omitEmptyStrings() .trimResults() .split(string);
    58. 58. 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));
    59. 59. import static com.google.common.base.Strings.*;
    60. 60. 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 ));
    61. 61. import static com.google.common.base.Preconditions.*;
    62. 62. 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);
    63. 63. import static com.google.common.base.Objects.*;
    64. 64. 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(); } }
    65. 65. import static com.google.common.base.Equivalences.*;
    66. 66. 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 ); } }
    67. 67. import static com.google.common.collect.ComparisonChain.*;
    68. 68. 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(); } }
    69. 69. import com.google.common.base.Throwables;
    70. 70. import com.google.common.base.Throwables; Exception ex = new Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex, false );
    71. 71. import com.google.common.base.Function;
    72. 72. 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);
    73. 73. 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; ) );
    74. 74. import com.google.common.base.Predicate;
    75. 75. 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);
    76. 76. Google Guava <ul>+ Tons of other Helper Objects <ul><li>Modern (Fluent APIs & Generics)
    77. 77. Well-Designed
    78. 78. Consistent?
    79. 79. Active </li></ul></ul>
    80. 80. Agenda <ul><li>Google Guava / Commons Lang
    81. 81. Builders / Fluent APIs
    82. 82. Function Objects / Proxies / Interceptors
    83. 83. Java 7
    84. 84. Lombok / Groovy </li></ul>
    85. 85. “Traditional API” Order order = new Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
    86. 86. “Modern API” new FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
    87. 87. “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 ; } }
    88. 88. 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 ; } }
    89. 89. ... 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; ) ));
    90. 90. 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 }
    91. 91. ... 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' )) }
    92. 92. Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
    93. 93. Agenda <ul><li>Google Guava / Commons Lang
    94. 94. Builders / Fluent APIs
    95. 95. Function Objects / Proxies / Interceptors
    96. 96. Java 7
    97. 97. Lombok / Groovy </li></ul>
    98. 98. 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”
    99. 99. 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
    100. 100. 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
    101. 101. 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
    102. 102. 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
    103. 103. 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); } } }
    104. 104. “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; );
    105. 105. “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... } }
    106. 106. 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); } } }
    107. 107. Function Objects + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks + Easier in Java 8 and Groovy - Verbose - Different
    108. 108. 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”
    109. 109. Agenda <ul><li>Google Guava / Commons Lang
    110. 110. Builders / Fluent APIs
    111. 111. Function Objects / Proxies / Interceptors
    112. 112. Java 7
    113. 113. Lombok / Groovy </li></ul>
    114. 114. “Traditional Error Handling” try { doSomething(); } catch (UnsupportedOperationException e) { handleError(e); } catch (IllegalStateException e) { handleError(e); } catch (IllegalArgumentException e) { handleError(e); }
    115. 115. “Modern Error Handling” try { doSomething(); } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) { handleError(e); }
    116. 116. “Traditional Resource Management” FileReader reader = new FileReader(path); try { return reader.read(); } finally { reader.close(); }
    117. 117. “Modern Resource Management” try (FileReader reader = new FileReader(path)) { return reader.read(); }
    118. 118. “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(); }
    119. 119. 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 );
    120. 120. Regex in Groovy Switch Number apply( int left, String operator, int right) { switch (operator) { c ase ~/ (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
    121. 121. Less Generic Cruft Map<Integer, String> map = new HashMap<>();
    122. 122. Java 7 Features + Soon to be widely used + Terser code - No Lambdas - Not widely used
    123. 123. Agenda <ul><li>Google Guava / Commons Lang
    124. 124. Builders / Fluent APIs
    125. 125. Function Objects / Proxies / Interceptors
    126. 126. Java 7
    127. 127. Lombok / Groovy </li></ul>
    128. 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. 129. “Modern Java Bean” -- Lombok @EqualsAndHashCode public class Person { @Setter @Getter private String firstName ; @Setter @Getter private String lastName ; }
    130. 130. “Modern Java Bean” -- Lombok @Data public class Person { private String firstName ; private String lastName ; }
    131. 131. Lombok <ul>@Getter / @Setter @ToString @EqualsAndHashCode @NoArgsConstructor @RequiredArgsConstructor @AllArgsConstructor </ul><ul>@Data @Cleanup @Synchronized @SneakyThrows @Log val </ul>
    132. 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. 133. “Modern Java Bean” -- Groovy @EqualsAndHashCode public class Person { String firstName String lastName }
    134. 134. Groovy <ul>@ToString @EqualsAndHashCode @Canonical @Lazy @InheritConstructors @TupleConstructor @AutoClone @AutoExternalize </ul><ul>@Delegate @Singleton @Immutable @Bindable @IndexedProperties @ListenerList @Vetoable </ul>
    135. 135. Groovy <ul>@Synchronized @WithReadLock @WithWriteLock @Log @Log4j @Slf4j @Commons </ul><ul>... and many more as libraries </ul>
    136. 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. 137. Agenda <ul><li>Google Guava / Commons Lang
    138. 138. Builders / Fluent APIs
    139. 139. Function Objects / Proxies / Interceptors
    140. 140. Java 7
    141. 141. Lombok / Groovy </li></ul>
    142. 142. Thanks <ul>Twitter: @HamletDRC Blog: http://hamletdarcy.blogspot.com Work Blog: http://www.canoo.com/blog JetBrains.tv Screencasts: http://tv.jetbrains.net/tags/hamlet YouTube Screencasts: http://www.youtube.com/user/HamletDRC Share-a-Canooie – http://people.canoo.com/share/ Hackergarten – http://www.hackergarten.net/ </ul>

    ×