Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Good Practices

There are several instances where Groovy and Kotlin take different approaches to implement Effective Java. As a participant, you walk away appreciating the simplicity with which these JVM languages empower the developers. The talk also provides food for thought - how languages can influence its users to adopt good practices.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

  • Be the first to like this

Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Good Practices

  1. 1. Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good Practices Naresha K @naresha_k https://blog.nareshak.com/
  2. 2. About me Developer, Architect & Tech Excellence Coach Founder & Organiser Bangalore Groovy User Group
  3. 3. 3 Java Language JVM Platform/ Real Machine Platform/ Real Machine Platform/ Real Machine
  4. 4. 4 Java Language Platform/ Real Machine Platform/ Real Machine Platform/ Real Machine Groovy JVM
  5. 5. 5 Java Language Platform/ Real Machine Platform/ Real Machine Platform/ Real Machine Groovy Kotlin JVM
  6. 6. 6 Most people talk about Java the language, and this may sound odd coming from me, but I could hardly care less. At the core of the Java ecosystem is the JVM. - James Gosling, Creator of the Java Programming Language(2011, TheServerSide)
  7. 7. 7
  8. 8. 8 http://groovy-lang.org/
  9. 9. 9 initial idea was to make a little dynamic language which compiles directly to Java classes and provides all the nice (alleged) productivity benefits - James Strachan http://radio-weblogs.com/0112098/2003/08/29.html
  10. 10. 10 https://kotlinlang.org/
  11. 11. 11 https://kotlinlang.org/
  12. 12. Know your guides Context/ the Problem What does “Effective Java” say? The traps Idiomatic Solution Lessons Learned Tool Wisdom 12
  13. 13. 13
  14. 14. 14 class Product { String sku String description BigDecimal price }
  15. 15. 15 Product book1 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) Product book2 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) println book1 == book2 false
  16. 16. 16 Product book1 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) Product book2 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) def stock = [:] stock[book1] = 100 println stock[book2] null
  17. 17. 17
  18. 18. 18 #10: Obey the general contract when overriding equals #11: Always override hashCode when you override equals
  19. 19. 19
  20. 20. 20 class Product { String sku String description BigDecimal price } class Product { String sku String description BigDecimal price LocalDate dateOfManufacture } class Product { String sku String description BigDecimal price LocalDate dateOfManufacture LocalDate dateOfExpiry }
  21. 21. 21 @EqualsAndHashCode class Product { String sku String description BigDecimal price }
  22. 22. 22 Product book1 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) Product book2 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) println book1 == book2 true
  23. 23. 23 Product book1 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) Product book2 = new Product( sku: 'P101', description: 'Effective Java’, price: 40.0) def stock = [:] stock[book1] = 100 println stock[book2] 100
  24. 24. 24 @EqualsAndHashCode(includes = 'id') class Product { Long id String sku String description BigDecimal price }
  25. 25. 25 @EqualsAndHashCode(includes = 'id') class Product { Long id String sku String description BigDecimal price }
  26. 26. 26 @EqualsAndHashCode(includes = ‘sku') class Product { Long id String sku String description BigDecimal price }
  27. 27. 27 class Product(val sku: String, val description: String, val price: BigDecimal) fun main() { val book1 = Product("P101", "Effective Java", BigDecimal("35.08")) val book2 = Product("P101", "Effective Java", BigDecimal("35.08")) println(book1 == book2) val stock = mapOf(book1 to 100) println(stock[book2]) } false null
  28. 28. 28 data class Product(val sku: String, val description: String, val price: BigDecimal) fun main() { val book1 = Product("P101", "Effective Java", BigDecimal("35.08")) val book2 = Product("P101", "Effective Java", BigDecimal("35.08")) println(book1 == book2) val stock = mapOf(book1 to 100) println(stock[book2]) } true 100
  29. 29. 29 data class Product(val sku: String, val description: String, val price: BigDecimal, var id: Long?) fun main() { val book1 = Product("P101", "Effective Java", BigDecimal("35.08"), null) val book2 = Product("P101", "Effective Java", BigDecimal("35.08"), 1L) println(book1 == book2) val stock = mapOf(book1 to 100) println(stock[book2]) } false null
  30. 30. 30 data class Product(val sku: String, val description: String, val price: BigDecimal) { var id: Long? = null } fun main() { val book1 = Product("P101", "Effective Java", BigDecimal("35.08")) val book2 = Product("P101", "Effective Java", BigDecimal("35.08")) book2.id = 1L println(book1 == book2) val stock = mapOf(book1 to 100) println(stock[book2]) } true 100
  31. 31. 31 AST Transformation Single point of representation of any knowledge Language / Compiler
  32. 32. 32
  33. 33. 33 List<String> languages = List.of("Java", "Groovy", "Kotlin"); for (int i = 0; i < languages.size(); i++) { System.out.println(languages.get(i)); } for (String language : languages) { System.out.println(language); }
  34. 34. 34 #58: Prefer for-each loops to traditional for loops
  35. 35. 35 numbers.forEach { println(it) } println(numbers.map { it * 2 }) println(numbers.fold(0) { acc, number -> acc + number }) 10 20 30 40 [20, 40, 60, 80] 100
  36. 36. 36 numbers.each { number -> println number } println numbers.collect { number -> number * 2 } println numbers.inject(0, { result, number -> result + number } ) 10 20 30 40 [20, 40, 60, 80] 100
  37. 37. 37 Closures/ Higher Order Functions Favor Internal iterators to external iterators Minimise the moving parts
  38. 38. 38 Million Dollar Effort
  39. 39. 39 Million Dollar Effort null check
  40. 40. 40 List<Speaker> getSpeakers(String conference) { return null; } List<Speaker> speakers = getSpeakers(“I Code Java Africa"); if (speakers != null) { //... }
  41. 41. 41 #54: Return empty arrays or collections, not nulls
  42. 42. 42 println getSpeakers('I Code Java Africa') .collect { it.firstName } println getSpeakers('I Code Java Africa') .findAll { it.firstName.length() > 5 }
  43. 43. 43 println getSpeakers('I Code Java Africa') .collect { it.firstName } // [] println getSpeakers('I Code Java Africa') .findAll { it.firstName.length() > 5 } // []
  44. 44. 44
  45. 45. 45 fun getSpeakers(conference: String): List<Speaker> { return null }
  46. 46. 46 fun getSpeakers(conference: String): List<Speaker> { return null } Null can not be a value of a non-null type List<Speaker>
  47. 47. 47 fun getSpeakers(conference: String): List<Speaker> { return null } Null can not be a value of a non-null type List<Speaker> fun getSpeakers(conference: String): List<Speaker>? { return null }
  48. 48. 48 NullObject Pattern No boilerplate code - $$$ Life is too short for null checks! Type system
  49. 49. 49 https://www.flickr.com/photos/38080114@N07/8594601982/
  50. 50. 50 #17: Minimize Mutability
  51. 51. Rules to make a class immutable 1. Don’t provide any mutators 2. Ensure that the class can’t be extended 3. Make all fields final 4. Make all fields private 5. Ensure exclusive access to any mutable components
  52. 52. 52 class ImmutableClass{ private final def field1 private final def field2 //... private final def field10 public ImmutableClass(f1, f2,… f10){ //initialization } }
  53. 53. 53 import groovy.transform.Immutable @Immutable class Rectangle { int length int breadth } def r = new Rectangle(length: 10, breadth: 5) println r // Rectangle(10, 5)
  54. 54. 54 public final class Rectangle extends java.lang.Object implements groovy.lang.GroovyObject { private final int length private final int breadth public Rectangle(int length, int breadth) { // } public Rectangle(java.util.Map args) { } public Rectangle() { this([:]) } } new Rectangle(length: 10, breadth: 5)
  55. 55. 55 data class Rectangle(val length: Int, val breadth: Int) public final class Rectangle { private final int length; private final int breadth; public final int getLength() { return this.length; } public final int getBreadth() { return this.breadth; } public Rectangle(int length, int breadth) { this.length = length; this.breadth = breadth; } // more code }
  56. 56. 56 data class Rectangle(val length: Int, val breadth: Int) fun main() { val rectangle = Rectangle(20, 10) val r2 = Rectangle(length = 20, breadth = 10) } public static final void main() { Rectangle rectangle = new Rectangle(20, 10); Rectangle r2 = new Rectangle(20, 10); }
  57. 57. 57 AST Transformation Readability Matters Syntactic Sugar
  58. 58. 58
  59. 59. 59 #18: Favour composition over inheritance
  60. 60. 60 def ph = ['919812312345', '4512341234', ‘19252199916'] as PhoneNumbers println ph.find { it == '19252199916'} println ph.findAll { it.endsWith('4') }
  61. 61. 61 def ph = ['919812312345', '4512341234', '19252199916'] as PhoneNumbers println ph.find { it == '19252199916'} println ph.findAll { it.endsWith('4') } println ph.indianNumbers()
  62. 62. 62 class PhoneNumbers extends ArrayList { }
  63. 63. 63 class PhoneNumbers { private @Delegate List phoneNumbers PhoneNumbers(numbers) { phoneNumbers = numbers } def indianNumbers() { phoneNumbers.findAll { it.startsWith('91') } } }
  64. 64. 64 class PhoneNumbers(val list: List<String>) : List<String> by list { fun indianNumbers(): List<String> { return list.filter { it.startsWith("91") } } }
  65. 65. 65 trait CanSing { def sing() { println "Singing" } } trait CanDance { def dance() { println "Dancing" } } class Person implements CanSing, CanDance {} Person reema = new Person() reema.sing() reema.dance() https://www.slideshare.net/nareshak/designing-with-groovy-traits-gr8conf-india
  66. 66. 66 AST Transformation Simplify
  67. 67. 67
  68. 68. 68 #3: Enforce the singleton property with a private constructor or an enum type
  69. 69. 69 class Manager { private static final Manager manager = new Manager() private Manager() { super() } static Manager getInstance() { manager } } def m1 = Manager.getInstance() def m2 = Manager.getInstance() println m1 == m2 true
  70. 70. 70 class Manager { private static final Manager manager = new Manager() private Manager() { super() } static Manager getInstance() { manager } } def m1 = Manager.getInstance() def m2 = Manager.getInstance() println m1 == m2 true def m3 = new Manager() println m3 Manager@b968a76
  71. 71. 71 @Singleton class Manager {} def m1 = Manager.getInstance() def m2 = Manager.getInstance() println m1 == m2 def m3 = new Manager() println m3 true Caught: java.lang.RuntimeException: Can't instantiate singleton Manager. Use Manager.instance
  72. 72. 72 object Manager { init { println("Initialising Manager") } } public final class Manager { public static final Manager INSTANCE; private Manager() { } static { Manager var0 = new Manager(); INSTANCE = var0; String var1 = "Initialising Manager"; boolean var2 = false; System.out.println(var1); } }
  73. 73. 73 private static Manager manager static Manager getInstance() { if(!manager){ manager = new Manager() } manager }
  74. 74. 74 private static Manager manager static synchronized Manager getInstance() { if(!manager){ manager = new Manager() } manager }
  75. 75. 75 private static volatile Manager manager static synchronized Manager getInstance() { if(!manager){ manager = new Manager() } manager }
  76. 76. 76 @Singleton(lazy=true) class Manager {} public static Manager getInstance() { if (instance != null) { return instance } else { synchronized (Manager) { if (instance != null) { return instance } else { return instance = new Manager() } } } }
  77. 77. 77 AST Transformation YAGNI Premature optimisation is the root of all evil Object Declaration
  78. 78. 78 Take Aways
  79. 79. 79 Some of the ‘Effective Java’ already built into the languages
  80. 80. 80 Favour compiler generated code to IDE generated code
  81. 81. 81 Don’t fall into the trap of copying the Java implementation
  82. 82. 82 Programming languages can reduce friction to implement good practices
  83. 83. 83 There could be multiple right solutions. Choose what fits your context
  84. 84. 84 The way we code is influenced not just by the language we code in, but also by the languages we know.
  85. 85. 85 Happy Coding. Thank You

    Be the first to comment

There are several instances where Groovy and Kotlin take different approaches to implement Effective Java. As a participant, you walk away appreciating the simplicity with which these JVM languages empower the developers. The talk also provides food for thought - how languages can influence its users to adopt good practices.

Views

Total views

156

On Slideshare

0

From embeds

0

Number of embeds

4

Actions

Downloads

1

Shares

0

Comments

0

Likes

0

×