Successfully reported this slideshow.

Java Boilerplate Busters

717 views

Published on

This is my Java Boilerplate Busters talk that I gave for an awesome client down in Ticino.

Published in: Technology
  • Be the first to comment

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. “Traditional Error Handling” try { doSomething(); } catch (UnsupportedOperationException e) { handleError(e); } catch (IllegalStateException e) { handleError(e); } catch (IllegalArgumentException e) { handleError(e); }
  15. 15. “Modern Error Handling” try { doSomething(); } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) { handleError(e); }
  16. 16. “Traditional Resource Management” FileReader reader = new FileReader(path); try { return reader.read(); } finally { reader.close(); }
  17. 17. “Modern Resource Management” try (FileReader reader = new FileReader(path)) { return reader.read(); }
  18. 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. 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. 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. 21. Less Generic Cruft Map<Integer, String> map = new HashMap<>();
  22. 22. Java 7 Features + Soon to be widely used + Terser code - No Lambdas - Not widely used
  23. 23. Agenda <ul><li>Google Guava / Commons Lang
  24. 24. Builders / Fluent APIs
  25. 25. Function Objects / Proxies / Interceptors
  26. 26. Java 7
  27. 27. Lombok / Groovy </li></ul>
  28. 28. import static org.apache.commons.lang.StringUtils.*;
  29. 29. import static org.apache.commons.lang.StringUtils.*; assert isAlpha ( &quot;abcde&quot; ); assert isNumeric ( &quot;12345&quot; ); assert isAlphanumeric ( &quot;12345abc&quot; );
  30. 30. import static org.apache.commons.lang.StringUtils.*; assert isBlank ( &quot;&quot; ); assert isBlank ( null );
  31. 31. import static org.apache.commons.lang.StringUtils.*; assert isAllLowerCase ( &quot;abcdef&quot; ); assert isAllUpperCase ( &quot;ABCDEF&quot; );
  32. 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. 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. 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; ));
  35. 35. import org.apache.commons.lang.StringEscapeUtils;
  36. 36. 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) );
  37. 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. 38. 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) );
  39. 39. import static org.apache.commons.lang.ArrayUtils.*;
  40. 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. 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. 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. 43. import static org.apache.commons.lang.BooleanUtils.*;
  44. 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; );
  45. 45. import org.apache.commons.lang.builder.ToStringBuilder;
  46. 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(); } }
  47. 47. import org.apache.commons.lang.builder.EqualsBuilder;
  48. 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(); } }
  49. 49. import org.apache.commons.lang.builder.HashCodeBuilder;
  50. 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(); } }
  51. 51. import org.apache.commons.lang.builder. CompareToBuilder ;
  52. 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. 53. Apache Commons Lang <ul>+ Tons of other Helper Objects <ul><li>Version 2.6 Stable </li><ul><li>JDK 1.3 Compatible
  54. 54. No Generics
  55. 55. Many functions obsoleted by JDK 5 </li></ul><li>Version 3.0 </li><ul><li>JDK 1.5 Compatible
  56. 56. Not backwards compatible with 2.6 </li></ul></ul></ul>
  57. 57. new HashMap<T, Set<U>>
  58. 58. import com.google.common.collect.Multimap;
  59. 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. 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. 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);
  62. 62. import com.google.common.collect.BiMap;
  63. 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. 64. new HashMap<T, Map<U, V>>
  65. 65. import com.google.common.collect.Table;
  66. 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. 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; );
  68. 68. import com.google.common.base.Joiner;
  69. 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));
  70. 70. import com.google.common.base.Splitter;
  71. 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. 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. 73. import static com.google.common.base.Strings.*;
  74. 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. 75. import static com.google.common.base.Preconditions.*;
  76. 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. 77. import static com.google.common.base.Objects.*;
  78. 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. 79. import static com.google.common.base.Equivalences.*;
  80. 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. 81. import static com.google.common.collect.ComparisonChain.*;
  82. 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(); } }
  83. 83. import com.google.common.base.Throwables;
  84. 84. import com.google.common.base.Throwables; Exception ex = new Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex, false );
  85. 85. import com.google.common.base.Function;
  86. 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. 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; ) );
  88. 88. import com.google.common.base.Predicate;
  89. 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. 90. Google Guava <ul>+ Tons of other Helper Objects <ul><li>Modern (Fluent APIs & Generics)
  91. 91. Well-Designed
  92. 92. Consistent?
  93. 93. Active </li></ul></ul>
  94. 94. Agenda <ul><li>Google Guava / Commons Lang
  95. 95. Builders / Fluent APIs
  96. 96. Function Objects / Proxies / Interceptors
  97. 97. Java 7
  98. 98. Lombok / Groovy </li></ul>
  99. 99. “Traditional API” Order order = new Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
  100. 100. “Modern API” new FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
  101. 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. 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. 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. 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. 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. 106. Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
  107. 107. Agenda <ul><li>Google Guava / Commons Lang
  108. 108. Builders / Fluent APIs
  109. 109. Function Objects / Proxies / Interceptors
  110. 110. Java 7
  111. 111. Lombok / Groovy </li></ul>
  112. 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. 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. 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. 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. 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. 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. 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. 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. 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. 121. Function Objects + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks + Easier in Java 8 and Groovy - Verbose - Different
  122. 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. 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>

×