Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[SnowOne 2023] Григорий Кошелев: Каждый Java-разработчик делал это...

[SnowOne 2023] Григорий Кошелев: Каждый Java-разработчик делал это...

В докладе поговорим про самые популярные ошибки начинающих Java-разработчиков и не только: что делает код неоправданно сложным, зачем нужны стайл-гайды, и как научиться им следовать, почему недостаточно знать принципы (ООП, SOLID и др.), почему быстрый код не всегда хороший, а читаемость имеет значение.

jugnsk

March 17, 2023
Tweet

More Decks by jugnsk

Other Decks in Programming

Transcript

  1. КАЖДЫЙ
    JAVA-РАЗРАБОТЧИК
    ДЕЛАЛ ЭТО...
    Григорий Кошелев
    Контур
    SnowOne 2023

    View Slide

  2. О докладчике
    2
    c 2017
    преподавание курсов
    по ООП и Java
    с 2011
    промышленная
    разработка на Java
    Проведение
    стажировок на Java
    с 2013
    функциональный
    руководитель Java
    с 2021
    с 2014

    View Slide

  3. О чём доклад
    Доклад про
    - практики написания кода
    - распространённые ошибки
    начинающих Java-разработчиков
    3

    View Slide

  4. О чём доклад
    Доклад про
    - практики написания кода
    - распространённые ошибки
    начинающих Java-разработчиков
    Контекст (перформанс)
    - Java 17, Liberica OpenJDK
    - x64, Apple M1
    4

    View Slide

  5. VS
    5

    View Slide

  6. VS
    Недостаток знаний
    - «Да, в проекте уже
    так было...»
    6

    View Slide

  7. VS
    Недостаток знаний
    - «Да, в проекте уже
    так было...»
    7
    Избыток знаний
    - «А вот, Шипилёв
    говорил, что...»

    View Slide

  8. VS
    Недостаток знаний
    - «Да, в проекте уже
    так было...»
    8
    Избыток знаний
    - «А вот, Шипилёв
    говорил, что...»
    - «Нет времени разбираться,
    надо код писать»

    View Slide

  9. 0. == VS equals
    9

    View Slide

  10. 0. == VS equals
    Сколько строк нужно,
    чтобы определить
    C#-разработчика?
    10

    View Slide

  11. 0. == VS equals
    Сколько строк нужно,
    чтобы определить
    C#-разработчика?
    "Hello, world!" == myString
    11

    View Slide

  12. 1. Комментарии VS
    Самодокументированный код
    12

    View Slide

  13. 1. Комментарии VS
    Самодокументированный код
    «Прекратите усердствовать
    с комментариями в коде»
    Brian Norlander
    https://habr.com/ru/company/piter/blog/458990/ 13

    View Slide

  14. 1. Комментарии VS
    Самодокументированный код
    «Прекратите усердствовать
    с комментариями в коде»
    Brian Norlander
    «Самодокументируемый код
    - это (как правило) чушь»
    Christopher Laine
    https://habr.com/ru/company/piter/blog/460725/ 14

    View Slide

  15. 1. Комментарии VS
    Самодокументированный код
    15
    public static double quadraticMean(double... values) {
    int n = values.length;// Value count
    if (n == 0) {// If values is empty, then throw an exception
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double s = 0;// Init sum with 0
    for (double v : values) {// Iterate over the values
    s += v * v;// Add squared value to the sum
    }
    s = Math.sqrt(s / n);// Divide the sum by count and calculate the square root
    return s; // Return the average
    }

    View Slide

  16. 1. Комментарии VS
    Самодокументированный код
    16
    public static double quadraticMean(double... values) {
    int n = values.length;// Value count
    if (n == 0) {// If values is empty, then throw an exception
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double s = 0;// Init sum with 0
    for (double v : values) {// Iterate over the values
    s += v * v;// Add squared value to the sum
    }
    s = Math.sqrt(s / n);// Divide the sum by count and calculate the square root
    return s; // Return the average
    }

    View Slide

  17. 1. Комментарии VS
    Самодокументированный код
    17
    public static double quadraticMean(double... values) {
    int n = values.length;// Value count
    if (n == 0) {// If values is empty, then throw an exception
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double s = 0;// Init sum with 0
    for (double v : values) {// Iterate over the values
    s += v * v;// Add squared value to the sum
    }
    s = Math.sqrt(s / n);// Divide the sum by count and calculate the square root
    return s; // Return the average
    }

    View Slide

  18. 1. Комментарии VS
    Самодокументированный код
    18
    public static double quadraticMean(double... values) {
    int n = values.length;// Value count
    if (n == 0) {// If values is empty, then throw an exception
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double s = 0;// Init sum with 0
    for (double v : values) {// Iterate over the values
    s += v * v;// Add squared value to the sum
    }
    s = Math.sqrt(s / n);// Divide the sum by count and calculate the square root
    return s; // Return the average
    }

    View Slide

  19. 1. Комментарии VS
    Самодокументированный код
    19
    public static double quadraticMean(double... values) {
    int n = values.length;// Value count
    if (n == 0) {// If values is empty, then throw an exception
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double s = 0;// Init sum with 0
    for (double v : values) {// Iterate over the values
    s += v * v;// Add squared value to the sum
    }
    s = Math.sqrt(s / n);// Divide the sum by count and calculate the square root
    return s; // Return the average
    }

    View Slide

  20. 1. Комментарии VS
    Самодокументированный код
    20
    public static double rootMeanSquare(double... values) {
    int valueCount = values.length;
    if (valueCount == 0) {
    throw new IllegalArgumentException("Need at least 1 value to calculate quadratic mean");
    }
    double sumOfValueSquares = 0;
    for (double value : values) {
    sumOfValueSquares += value * value;
    }
    double rootMeanSquare = Math.sqrt(sumOfValueSquares / valueCount);
    return rootMeanSquare;
    }

    View Slide

  21. 1. Комментарии VS
    Самодокументированный код
    21

    View Slide

  22. 1. Комментарии VS
    Самодокументированный код
    22
    /**
    * Calculate root mean square (or quadratic mean).
    *
    * Need at least 1 value to calculate quadratic mean.
    *
    * @param values non-empty array of values
    * @return quadratic mean
    * @throws IllegalArgumentException if no values provided
    * @see root mean square (wiki)
    */
    public static double quadraticMean(double... values) {

    View Slide

  23. 1. Комментарии VS
    Самодокументированный код
    23
    /**
    * Calculate root mean square (or quadratic mean).
    *
    * Need at least 1 value to calculate quadratic mean.
    *
    * @param values non-empty array of values
    * @return quadratic mean
    * @throws IllegalArgumentException if no values provided
    * @see root mean square (wiki)
    */
    public static double quadraticMean(double... values) {

    View Slide

  24. 1. Комментарии VS
    Самодокументированный код
    24
    /**
    * Calculate root mean square (or quadratic mean).
    *
    * Need at least 1 value to calculate quadratic mean.
    *
    * @param values non-empty array of values
    * @return quadratic mean
    * @throws IllegalArgumentException if no values provided
    * @see root mean square (wiki)
    */
    public static double quadraticMean(double... values) {

    View Slide

  25. 1. Комментарии VS
    Самодокументированный код
    25
    /**
    * Calculate root mean square (or quadratic mean).
    *
    * Need at least 1 value to calculate quadratic mean.
    *
    * @param values non-empty array of values
    * @return quadratic mean
    * @throws IllegalArgumentException if no values provided
    * @see root mean square (wiki)
    */
    public static double quadraticMean(double... values) {

    View Slide

  26. 1. Комментарии VS
    Самодокументированный код
    26
    /**
    * Calculate root mean square (or quadratic mean).
    *
    * Need at least 1 value to calculate quadratic mean.
    *
    * @param values non-empty array of values
    * @return quadratic mean
    * @throws IllegalArgumentException if no values provided
    * @see root mean square (wiki)
    */
    public static double quadraticMean(double... values) {

    View Slide

  27. 1. Комментарии VS
    Самодокументированный код
    27

    View Slide

  28. 1. Комментарии VS
    Самодокументированный код
    Google Java Style Guide
    https://google.github.io/styleguide/javaguide.html#s7.3-javadoc-where-required 28

    View Slide

  29. 1. Комментарии VS
    Самодокументированный код
    Google Java Style Guide
    https://google.github.io/styleguide/javaguide.html#s7.3-javadoc-where-required 29

    View Slide

  30. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    https://checkstyle.org 30

    View Slide

  31. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    https://checkstyle.org/checks.html 31

    View Slide

  32. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    https://checkstyle.org/config_javadoc.html 32

    View Slide

  33. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    - Поддержка Sun Code Conventions
    https://checkstyle.org/sun_style.html 33

    View Slide

  34. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    - Поддержка Sun Code Conventions
    - Поддержка Google Java Style Guide
    https://checkstyle.org/google_style.html 34

    View Slide

  35. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    - Поддержка Sun Code Conventions
    - Поддержка Google Java Style Guide
    - Интегрируется в сборку Maven
    https://maven.apache.org/plugins/maven-checkstyle-plugin/ 35

    View Slide

  36. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    - Поддержка Sun Code Conventions
    - Поддержка Google Java Style Guide
    - Интегрируется в сборку Maven
    и Gradle
    https://docs.gradle.org/current/userguide/checkstyle_plugin.html 36

    View Slide

  37. 1. Комментарии VS
    Самодокументированный код
    CheckStyle - https://checkstyle.org
    - Десятки «code style» проверок
    (в том числе проверки для Java Doc)
    - Поддержка Sun Code Conventions
    - Поддержка Google Java Style Guide
    - Интегрируется в сборку Maven
    и Gradle
    - MUST HAVE в проекте!
    https://checkstyle.org 37

    View Slide

  38. 2.
    38
    Связь
    Связь
    VS

    View Slide

  39. 2. Loose Coupling VS
    High Cohesion
    39

    View Slide

  40. 2. Loose Coupling VS
    High Cohesion
    40

    View Slide

  41. 2. Loose Coupling VS
    High Cohesion
    Как разбить код между классами?
    41

    View Slide

  42. 2. Loose Coupling VS
    High Cohesion
    Как разбить код между классами?
    - Классы побольше
    42

    View Slide

  43. 2. Loose Coupling VS
    High Cohesion
    Как разбить код между классами?
    - Классы побольше
    - Классы поменьше
    43

    View Slide

  44. 2. Loose Coupling VS
    High Cohesion
    Как разбить код между классами?
    - Классы побольше (быстро написать)
    - Классы поменьше
    44

    View Slide

  45. 2. Loose Coupling VS
    High Cohesion
    Как разбить код между классами?
    - Классы побольше (быстро написать)
    - Классы поменьше (SRP!)
    45

    View Slide

  46. 2. Loose Coupling VS
    High Cohesion
    46

    View Slide

  47. 2. Loose Coupling VS
    High Cohesion
    47
    Сложность
    кода
    Размер
    классов

    View Slide

  48. 2. Loose Coupling VS
    High Cohesion
    48
    Сложность
    кода
    Размер
    классов
    * Основано на личном опыте

    View Slide

  49. 2. Loose Coupling VS
    High Cohesion
    49
    Сложность
    кода
    Размер
    классов
    1 метод
    на класс

    View Slide

  50. 2. Loose Coupling VS
    High Cohesion
    50
    Сложность
    кода
    Размер
    классов
    несколько
    методов
    на класс

    View Slide

  51. 2. Loose Coupling VS
    High Cohesion
    51
    Сложность
    кода
    Размер
    классов
    весь код
    в одном
    классе

    View Slide

  52. 2. Loose Coupling VS
    High Cohesion
    52
    Сложность
    кода
    Размер
    классов
    несколько
    God-классов

    View Slide

  53. 2. Loose Coupling VS
    High Cohesion
    53
    Сложность
    кода
    Размер
    классов
    совершенный
    код

    View Slide

  54. 2. Loose Coupling VS
    High Cohesion
    54
    Сложность
    кода
    Размер
    классов
    снижаем
    зависимость
    между классами

    View Slide

  55. 2. Loose Coupling VS
    High Cohesion
    55
    Сложность
    кода
    Размер
    классов
    повышаем
    связность кода
    внутри классов

    View Slide

  56. 2. Loose Coupling VS
    High Cohesion
    java.lang.System
    56

    View Slide

  57. 2. Loose Coupling VS
    High Cohesion
    java.lang.System.arraycopy
    57

    View Slide

  58. 2. Loose Coupling VS
    High Cohesion
    java.lang.System.arraycopy
    - 20+ использований в java.util.Arrays
    58

    View Slide

  59. 2. Loose Coupling VS
    High Cohesion
    java.lang.System.arraycopy
    - 20+ использований в java.util.Arrays
    - 0 использований в System
    59

    View Slide

  60. 2. Loose Coupling VS
    High Cohesion
    java.lang.System.arraycopy
    - 20+ использований в java.util.Arrays
    - 0 использований в System
    НО
    - arraycopy с Java 1.0
    - Arrays с 1.2
    60

    View Slide

  61. 2. Loose Coupling VS
    High Cohesion
    java.lang.System.arraycopy
    - 20+ использований в java.util.Arrays
    - 0 использований в System
    НО
    - arraycopy с Java 1.0
    - Arrays с 1.2
    61

    View Slide

  62. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean
    62

    View Slide

  63. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean.getBoolean
    63

    View Slide

  64. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean.getBoolean
    64
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  65. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean.getBoolean
    65
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  66. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean.getBoolean
    66
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  67. 2. Loose Coupling VS
    High Cohesion
    java.lang.Boolean.getBoolean
    67
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  68. 2. Loose Coupling VS
    High Cohesion
    java.lang.Integer.getInteger
    68
    public static Integer getInteger(String nm) {
    return getInteger(nm, null);
    }

    View Slide

  69. 2. Loose Coupling VS
    High Cohesion
    java.lang.Integer.getInteger
    69
    public static Integer getInteger(String nm, Integer val) {
    String v = null;
    try {
    v = System.getProperty(nm);
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    if (v != null) {
    try {
    return Integer.decode(v);
    } catch (NumberFormatException e) {
    }
    }
    return val;
    }

    View Slide

  70. 2. Loose Coupling VS
    High Cohesion
    java.lang.Integer.getInteger
    70
    public static Integer getInteger(String nm, Integer val) {
    String v = null;
    try {
    v = System.getProperty(nm);
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    if (v != null) {
    try {
    return Integer.decode(v);
    } catch (NumberFormatException e) {
    }
    }
    return val;
    }

    View Slide

  71. 2. Loose Coupling VS
    High Cohesion
    java.lang.Integer.getInteger
    71
    public static Integer getInteger(String nm, Integer val) {
    String v = null;
    try {
    v = System.getProperty(nm);
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    if (v != null) {
    try {
    return Integer.decode(v);
    } catch (NumberFormatException e) {
    }
    }
    return val;
    }
    There isn't the code
    you're looking for

    View Slide

  72. 2. Loose Coupling VS
    High Cohesion
    java.lang.Long.getLong
    72

    View Slide

  73. 2. Loose Coupling VS
    High Cohesion
    java.lang.Long.getLong
    73
    That's enough!

    View Slide

  74. 2. Loose Coupling VS
    High Cohesion
    Выводы
    74

    View Slide

  75. 2. Loose Coupling VS
    High Cohesion
    Выводы
    - DRY
    - KISS
    75

    View Slide

  76. 2. Loose Coupling VS
    High Cohesion
    Выводы
    - DRY: Don't Repeat Yourself
    - KISS: Keep It Simple, Smart
    76

    View Slide

  77. 2. Loose Coupling VS
    High Cohesion
    Выводы
    - DRY: Don't Repeat Yourself
    - KISS: Keep It Simple, Smart
    - Чем меньше требуется навигации по коду,
    тем лучше: между пакетами и классами,
    переключение экрана с кодом класса
    77

    View Slide

  78. 3. Наследование VS
    Делегирование
    78

    View Slide

  79. 3. Наследование VS
    Делегирование
    https://www.youtube.com/watch?v=jl_4g2QxqMg 79
    «В любой непонятной ситуации
    - делегируй»
    Александр Кучук

    View Slide

  80. 3. Наследование VS
    Делегирование
    Классический пример
    80
    Animal
    Dog Cat

    View Slide

  81. 3. Наследование VS
    Делегирование
    Классический пример
    81
    public class Dog extends Animal {
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Animal {
    public String meow() { return "Мяу!"; }
    }
    Animal
    Dog Cat

    View Slide

  82. 3. Наследование VS
    Делегирование
    Классический пример
    82
    public class Dog extends Animal {
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Animal {
    public String meow() { return "Мяу!"; }
    }
    Animal
    Dog Cat
    bark()
    m
    eow
    ()

    View Slide

  83. 3. Наследование VS
    Делегирование
    Классический пример
    83
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    public class Dog extends Caniformia {
    @Override
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Feliformia {
    @Override
    public String meow() { return "Мяу!"; }
    }
    bark()
    m
    eow
    ()

    View Slide

  84. 3. Наследование VS
    Делегирование
    Классический пример
    84
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    public class Dog extends Caniformia {
    @Override
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Feliformia {
    @Override
    public String meow() { return "Мяу!"; }
    }
    bark()
    m
    eow
    ()

    View Slide

  85. 3. Наследование VS
    Делегирование
    Классический пример
    85
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    public class Dog extends Caniformia {
    @Override
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Feliformia {
    @Override
    public String meow() { return "Мяу!"; }
    }
    bark()
    m
    eow
    ()

    View Slide

  86. 3. Наследование VS
    Делегирование
    Классический пример
    86
    public class Dog extends Caniformia {
    @Override
    public String bark() { return "Гав!"; }
    }
    public class Cat extends Feliformia {
    @Override
    public String meow() { return "Мяу!"; }
    }
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    bark()
    m
    eow
    ()

    View Slide

  87. 3. Наследование VS
    Делегирование
    87
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal

    View Slide

  88. 3. Наследование VS
    Делегирование
    88
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena

    View Slide

  89. 3. Наследование VS
    Делегирование
    89
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  90. 3. Наследование VS
    Делегирование
    90
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  91. 3. Наследование VS
    Делегирование
    91
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  92. 3. Наследование VS
    Делегирование
    92
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  93. 3. Наследование VS
    Делегирование
    93
    public static class Hyena extends Feliformia {
    public String bark() {
    return "Ай!";
    }
    //WTF???
    @Override
    public String meow() {
    return bark();
    }
    }
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    m
    eow
    ()
    m
    eow
    ()

    View Slide

  94. 3. Наследование VS
    Делегирование
    94
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    Hyena?
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  95. 3. Наследование VS
    Делегирование
    95
    Animal
    Dog Cat
    Caniformia Feliformia
    Mammal
    Hyena bark()
    Ваще!
    Hyena?
    bark()
    m
    eow
    ()
    bark()
    m
    eow
    ()

    View Slide

  96. 3. Наследование VS
    Делегирование
    96
    public interface Talkable {
    String talk();
    }
    public abstract class Animal implements Talkable {
    }
    interface Barkable extends Talkable {
    @Override
    default String talk() { return bark(); }
    String bark();
    }

    View Slide

  97. 3. Наследование VS
    Делегирование
    97
    public static class Dog extends Caniformia implements Barkable {
    public String bark() { return "Гав!"; }
    }
    public static class Cat extends Feliformia implements Meowable {
    public String meow() { return "Мяу!"; }
    }
    public static class Hyena extends Feliformia implements Barkable {
    public String bark() { return "Ай!"; }
    }

    View Slide

  98. 3. Наследование VS
    Делегирование
    https://kotlinlang.org/docs/delegation.html 98
    interface Talkable {
    fun talk(): String
    }
    abstract class Animal : Talkable
    interface Barkable : Talkable {
    override fun talk(): String = bark()
    fun bark(): String
    }
    class Barking(val s: String) : Barkable {
    override fun bark(): String = s
    }

    View Slide

  99. 3. Наследование VS
    Делегирование
    https://kotlinlang.org/docs/delegation.html 99
    interface Talkable {
    fun talk(): String
    }
    abstract class Animal : Talkable
    interface Barkable : Talkable {
    override fun talk(): String = bark()
    fun bark(): String
    }
    class Barking(val s: String) : Barkable {
    override fun bark(): String = s
    }

    View Slide

  100. 3. Наследование VS
    Делегирование
    https://kotlinlang.org/docs/delegation.html 100
    class Dog : Caniformia(), Barkable by Barking("Гав!")
    class Cat : Feliformia(), Meowable by Meowing("Мяу!")
    class Hyena : Feliformia(), Barkable by Barking("Ай!")
    interface Talkable {
    fun talk(): String
    }
    abstract class Animal : Talkable
    interface Barkable : Talkable {
    override fun talk(): String = bark()
    fun bark(): String
    }
    class Barking(val s: String) : Barkable {
    override fun bark(): String = s
    }

    View Slide

  101. 3. Наследование VS
    Делегирование
    https://kotlinlang.org/docs/delegation.html 101
    class Dog : Caniformia(), Barkable by Barking("Гав!")
    class Cat : Feliformia(), Meowable by Meowing("Мяу!")
    class Hyena : Feliformia(), Barkable by Barking("Ай!")
    interface Talkable {
    fun talk(): String
    }
    abstract class Animal : Talkable
    interface Barkable : Talkable {
    override fun talk(): String = bark()
    fun bark(): String
    }
    class Barking(val s: String) : Barkable {
    override fun bark(): String = s
    }

    View Slide

  102. 3. Наследование VS
    Делегирование
    https://www.youtube.com/watch?v=jl_4g2QxqMg 102
    «В любой непонятной ситуации
    - делегируй»
    Александр Кучук

    View Slide

  103. 3. Наследование VS
    Делегирование
    103
    Выводы

    View Slide

  104. 3. Наследование VS
    Делегирование
    104
    Выводы
    - Использовать наследование,
    когда это очевидно

    View Slide

  105. 3. Наследование VS
    Делегирование
    105
    Выводы
    - Использовать наследование,
    когда это очевидно
    - Всегда помнить,
    что наследуется поведение

    View Slide

  106. 3. Наследование VS
    Делегирование
    106
    Выводы
    - Использовать наследование,
    когда это очевидно
    - Всегда помнить,
    что наследуется поведение
    - Если кто-то крякает как утка, ходит как утка
    и плавает как утка,
    то это ещё ничего не значит

    View Slide

  107. 4. Абстракции:
    создавать VS не создавать
    107

    View Slide

  108. 4. Абстракции:
    создавать VS не создавать
    «Не следует множить сущности
    без необходимости»
    «Бритва Оккама», William of Ockham
    108

    View Slide

  109. 4. Абстракции:
    создавать VS не создавать
    «Не следует множить сущности
    без необходимости»
    «Бритва Оккама», William of Ockham
    «Loose Coupling & High Cohesion»
    Larry Constantine
    109

    View Slide

  110. 4. Абстракции:
    создавать VS не создавать
    110
    public static double computeWithRawScalars(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    double x = y1 * z2 - z1 * y2;
    double y = z1 * x2 - x1 * z2;
    double z = x1 * y2 - y1 * x2;
    return x * x + y * y + z * z;
    }
    public static double computeWithVectors(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    Vector v1 = new Vector(x1, y1, z1);
    Vector v2 = new Vector(x2, y2, z2);
    return v1.crossProduct(v2).squared();
    }

    View Slide

  111. 4. Абстракции:
    создавать VS не создавать
    111
    public static double computeWithRawScalars(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    double x = y1 * z2 - z1 * y2;
    double y = z1 * x2 - x1 * z2;
    double z = x1 * y2 - y1 * x2;
    return x * x + y * y + z * z;
    }
    public static double computeWithVectors(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    Vector v1 = new Vector(x1, y1, z1);
    Vector v2 = new Vector(x2, y2, z2);
    return v1.crossProduct(v2).squared();
    }
    Junior

    View Slide

  112. 4. Абстракции:
    создавать VS не создавать
    112
    public static double computeWithRawScalars(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    double x = y1 * z2 - z1 * y2;
    double y = z1 * x2 - x1 * z2;
    double z = x1 * y2 - y1 * x2;
    return x * x + y * y + z * z;
    }
    public static double computeWithVectors(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    Vector v1 = new Vector(x1, y1, z1);
    Vector v2 = new Vector(x2, y2, z2);
    return v1.crossProduct(v2).squared();
    }
    Junior
    M
    iddle

    View Slide

  113. 4. Абстракции:
    создавать VS не создавать
    113
    public static double computeWithRawScalars(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    double x = y1 * z2 - z1 * y2;
    double y = z1 * x2 - x1 * z2;
    double z = x1 * y2 - y1 * x2;
    return x * x + y * y + z * z;
    }
    public static double computeWithVectors(
    double x1, double y1, double z1,
    double x2, double y2, double z2) {
    Vector v1 = new Vector(x1, y1, z1);
    Vector v2 = new Vector(x2, y2, z2);
    return v1.crossProduct(v2).squared();
    }
    Junior
    Senior
    M
    iddle

    View Slide

  114. 4. Абстракции:
    создавать VS не создавать
    https://habr.com/ru/company/skbkontur/blog/351540/ 114
    Benchmark Mode Cnt Score Error Units
    computeWithRawScalars avgt 50 4,783 ± 0,031 ns/op
    computeWithVectors avgt 50 4,785 ± 0,040 ns/op

    View Slide

  115. 4. Абстракции:
    создавать VS не создавать
    https://habr.com/ru/company/skbkontur/blog/351540/ 115
    Benchmark Mode Cnt Score Error Units
    computeWithRawScalars avgt 50 4,783 ± 0,031 ns/op
    computeWithVectors avgt 50 4,785 ± 0,040 ns/op
    «Разбор перформансных задач
    с JBreak (часть 3)»
    JBreak 2018

    View Slide

  116. 4. Абстракции:
    создавать VS не создавать
    https://habr.com/ru/company/skbkontur/blog/351540/ 116
    Benchmark Mode Cnt Score Error Units
    computeWithRawScalars avgt 50 4,783 ± 0,031 ns/op
    computeWithVectors avgt 50 4,785 ± 0,040 ns/op
    «Разбор перформансных задач
    с JBreak (часть 3)»
    JBreak 2018

    View Slide

  117. 4. Абстракции:
    создавать VS не создавать
    Выводы
    117

    View Slide

  118. 4. Абстракции:
    создавать VS не создавать
    Выводы
    - При создании новой абстракции не нужно
    думать о мифической производительности
    118

    View Slide

  119. 4. Абстракции:
    создавать VS не создавать
    Выводы
    - При создании новой абстракции не нужно
    думать о мифической производительности
    - На первом месте должна быть
    читаемость кода!
    119

    View Slide

  120. 4. Абстракции:
    создавать VS не создавать
    Выводы
    - При создании новой абстракции не нужно
    думать о мифической производительности
    - На первом месте должна быть
    читаемость кода!
    - См. Loose Coupling & High Cohesion
    120

    View Slide

  121. 5. Integer VS int
    121

    View Slide

  122. 5. Integer VS int
    122
    java.lang.Integer
    public final class Integer extends Number
    implements Comparable, Constable, ConstantDesc {
    private final int value;
    /* Methods, static fields and static methods */
    }

    View Slide

  123. 5. Integer VS int
    Auto-boxing и unboxing
    123
    Integer integer = 42;// Auto-boxing
    int i = integer;// Auto-unboxing

    View Slide

  124. 5. Integer VS int
    Auto-boxing и unboxing
    А как быть с null?
    124
    Integer integer = 42;// Auto-boxing
    int i = integer;// Auto-unboxing
    Integer integer = null;
    int i = integer;

    View Slide

  125. 5. Integer VS int
    Auto-boxing и unboxing
    А как быть с null?
    125
    Integer integer = 42;// Auto-boxing
    int i = integer;// Auto-unboxing
    Integer integer = null;
    int i = integer;
    Exception in thread "main" java.lang.NullPointerException:
    Cannot invoke "java.lang.Integer.intValue()" because "integer" is null

    View Slide

  126. 5. Integer VS int
    126
    private class IntegerContainer {
    private int value;
    }
    IntegerContainer container = new IntegerContainer();
    if (container.value == 0) {
    System.out.println("Value is 0");
    }

    View Slide

  127. 5. Integer VS int
    127
    private class IntegerContainer {
    private int value;
    }
    IntegerContainer container = new IntegerContainer();
    if (container.value == 0) {
    System.out.println("Value is 0");
    }

    View Slide

  128. 5. Integer VS int
    128
    private class IntegerContainer {
    private Integer value;
    }
    IntegerContainer container = new IntegerContainer();
    if (container.value == 0) {
    System.out.println("Value is 0");
    }

    View Slide

  129. 5. Integer VS int
    129
    private class IntegerContainer {
    private Integer value;
    }
    IntegerContainer container = new IntegerContainer();
    if (container.value == 0) {
    System.out.println("Value is 0");
    }
    Exception in thread "main”
    java.lang.NullPointerException:
    Cannot invoke "java.lang.Integer.intValue()"
    because "container.value" is null

    View Slide

  130. 5. Integer VS int
    sizeOf
    130

    View Slide

  131. 5. Integer VS int
    sizeOf
    https://shipilev.net/jvm/objects-inside-out/ 131
    x32 HotSpot x64 -XX:+UseCompressedOops x64 -XX:-UseCompressedOops
    int 4 bytes 4 bytes 4 bytes
    Object 8 bytes 16 bytes 16 bytes
    Integer 16 bytes 16 bytes 24 bytes

    View Slide

  132. 5. Integer VS int
    sizeOf
    https://shipilev.net/jvm/objects-inside-out/ 132
    x32 HotSpot x64 -XX:+UseCompressedOops x64 -XX:-UseCompressedOops
    int 4 bytes 4 bytes 4 bytes
    Object 8 bytes 16 bytes 16 bytes
    Integer 16 bytes 16 bytes 24 bytes
    int[] 4 bytes 4 bytes 4 bytes
    Integer[] 20 bytes 20 bytes 32 bytes

    View Slide

  133. 5. Integer VS int
    sizeOf
    https://shipilev.net/jvm/objects-inside-out/ 133
    x32 HotSpot x64 -XX:+UseCompressedOops x64 -XX:-UseCompressedOops
    int 4 bytes 4 bytes 4 bytes
    Object 8 bytes 16 bytes 16 bytes
    Integer 16 bytes 16 bytes 24 bytes
    int[] 4 bytes 4 bytes 4 bytes
    Integer[] 20 bytes 20 bytes 32 bytes
    * В пересчёте на одно значение
    без учёта затрат на сам объект массива

    View Slide

  134. 5. Integer VS int
    Если всё так плохо, то зачем нужен Integer?
    134

    View Slide

  135. 5. Integer VS int
    Если всё так плохо, то зачем нужен Integer?
    - Collection: List, Set, Queue, ...
    - Map
    135

    View Slide

  136. 5. Integer VS int
    Google Guava
    https://github.com/google/guava 136

    View Slide

  137. 5. Integer VS int
    Google Guava
    - Ints.asList - IntArrayAsList
    https://github.com/google/guava/blob/master/guava/src/com/google/common/primitives/Ints.java 137
    int[] backingArray = /* ... */
    List guavaArrayList = Ints.asList(backingArray);

    View Slide

  138. 5. Integer VS int
    Arrays.asList vs Ints.asList
    138

    View Slide

  139. 5. Integer VS int
    Arrays.asList vs Ints.asList
    - IntArrayAsList занимает меньше памяти
    в 5 или 8 раз
    139

    View Slide

  140. 5. Integer VS int
    Arrays.asList vs Ints.asList
    - IntArrayAsList занимает меньше памяти
    в 5 или 8 раз
    - IntArrayAsList медленее на итерирование
    до 5 раз, если используется boxing
    - IntArrayAsList быстрее на итерирование
    на 25%, если не используется boxing
    140

    View Slide

  141. 5. Integer VS int
    Будущее - Project Valhalla
    https://openjdk.org/projects/valhalla/ 141

    View Slide

  142. 5. Integer VS int
    Будущее - Project Valhalla
    - https://openjdk.org/projects/valhalla/
    https://openjdk.org/projects/valhalla/ 142

    View Slide

  143. 6. ArrayList VS LinkedList
    143

    View Slide

  144. 6. ArrayList VS LinkedList
    - Кто использует LinkedList?
    144

    View Slide

  145. 6. ArrayList VS LinkedList
    - Кто использует LinkedList?
    - А ArrayList?
    145

    View Slide

  146. 6. ArrayList VS LinkedList
    - Кто использует LinkedList?
    - А ArrayList?
    - Может быть, что-то другое?
    146

    View Slide

  147. 6. ArrayList VS LinkedList
    147

    View Slide

  148. 6. ArrayList VS LinkedList
    Примеры использования связных списков
    148

    View Slide

  149. 6. ArrayList VS LinkedList
    Примеры использования связных списков
    - HashMap.Node (Josh Bloch)
    149

    View Slide

  150. 6. ArrayList VS LinkedList
    Примеры использования связных списков
    - HashMap.Node (Josh Bloch)
    - LinkedHashMap.Entry (Josh Bloch)
    150

    View Slide

  151. 6. ArrayList VS LinkedList
    Примеры использования связных списков
    - HashMap.Node (Josh Bloch)
    - LinkedHashMap.Entry (Josh Bloch)
    - ConcurrentDoublyLinkedList (Doug Lea)
    http://www.java2s.com/Code/Java/Collections-Data-Structure/ConcurrentDoublyLinkedList.htm 151

    View Slide

  152. 6. ArrayList VS LinkedList
    Плохой сценарий для ArrayList -
    152

    View Slide

  153. 6. ArrayList VS LinkedList
    Плохой сценарий для ArrayList -
    добавление и удаление из начала
    153

    View Slide

  154. 6. ArrayList VS LinkedList
    Плохой сценарий для ArrayList -
    добавление и удаление из начала
    ArrayDeque - ваш выбор!
    154

    View Slide

  155. 6. ArrayList VS LinkedList
    Выводы
    155

    View Slide

  156. 6. ArrayList VS LinkedList
    Выводы
    - Каждой задаче своя структура данных
    156

    View Slide

  157. 6. ArrayList VS LinkedList
    Выводы
    - Каждой задаче своя структура данных
    - Вместо java.util.LinkedList
    есть структуры получше
    157

    View Slide

  158. 7. Result VS Exception
    158

    View Slide

  159. 7. Result VS Exception
    159
    public class Result {
    private final D data;
    private final E error;
    private Result(D data, E error) {
    this.data = data;
    this.error = error;
    }
    public D data() {
    return data;
    }
    public E error() {
    return error;
    }

    View Slide

  160. 7. Result VS Exception
    160
    public class Result {
    private final D data;
    private final E error;
    private Result(D data, E error) {
    this.data = data;
    this.error = error;
    }
    public D data() {
    return data;
    }
    public E error() {
    return error;
    }
    public static Result of(@NotNull D data) {
    return new Result<>(data, null);
    }
    public static Result ofError(@NotNull E error) {
    return new Result<>(null, error);
    }
    }

    View Slide

  161. 7. Result VS Exception
    161
    public record Result(D data, E error) {
    public static Result ofError(@NotNull E error) {
    return new Result<>(null, error);
    }
    public static Result of(@NotNull D data) {
    return new Result<>(data, null);
    }
    }

    View Slide

  162. 7. Result VS Exception
    Exception-as-a-Result
    162

    View Slide

  163. 7. Result VS Exception
    Exception-as-a-Result
    PlayFramework?
    https://www.playframework.com 163

    View Slide

  164. 7. Result VS Exception
    https://www.playframework.com/documentation/1.2.1/api/play/mvc/results/Result.html 164

    View Slide

  165. 7. Result VS Exception
    https://www.playframework.com/documentation/1.2.1/api/play/mvc/results/Result.html 165

    View Slide

  166. 7. Result VS Exception
    https://www.playframework.com/documentation/1.2.1/api/play/mvc/results/Result.html 166

    View Slide

  167. 7. Result VS Exception
    167

    View Slide

  168. 7. Result VS Exception
    168

    View Slide

  169. 7. Result VS Exception
    169

    View Slide

  170. 7. Result VS Exception
    170

    View Slide

  171. 7. Result VS Exception
    171

    View Slide

  172. 7. Result VS Exception
    172

    View Slide

  173. 7. Result VS Exception
    173
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  174. Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op
    7. Result VS Exception
    174

    View Slide

  175. 7. Result VS Exception
    175
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  176. Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op
    7. Result VS Exception
    176

    View Slide

  177. Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op
    7. Result VS Exception
    177

    View Slide

  178. Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op
    7. Result VS Exception
    178

    View Slide

  179. 7. Result VS Exception
    179
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  180. Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op
    7. Result VS Exception
    180

    View Slide

  181. 7. Result VS Exception
    181
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  182. 7. Result VS Exception
    182
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  183. 7. Result VS Exception
    183
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  184. 7. Result VS Exception
    184
    Benchmark (failRatio) Score Error Units
    baseline 2.725 ± 0.051 ns/op
    result 2.799 ± 0.018 ns/op
    exceptionDriven 1/1 645.310 ± 2.572 ns/op
    exceptionDriven 1/2 647.682 ± 4.328 ns/op
    exceptionDriven 1/5 644.445 ± 4.775 ns/op
    exceptionDriven 1/10 645.337 ± 3.772 ns/op
    exceptionDriven 1/100 641.115 ± 6.571 ns/op
    exceptionDriven 1/1000 642.891 ± 4.471 ns/op
    exceptional 1/1 642.602 ± 5.368 ns/op
    exceptional 1/2 323.427 ± 2.723 ns/op
    exceptional 1/5 130.551 ± 0.856 ns/op
    exceptional 1/10 66.263 ± 0.629 ns/op
    exceptional 1/100 9.216 ± 0.234 ns/op
    exceptional 1/1000 3.512 ± 0.494 ns/op

    View Slide

  185. 7. Result VS Exception
    Выводы
    185

    View Slide

  186. 7. Result VS Exception
    Выводы
    - При обработке исключительных (редких)
    ситуаций разница между Result и Exception
    не существенная
    186

    View Slide

  187. 7. Result VS Exception
    Выводы
    - При обработке исключительных (редких)
    ситуаций разница между Result и Exception
    не существенная
    - Result в большинстве случаев
    оптимизируется JIT-компилятором
    187

    View Slide

  188. 7. Result VS Exception
    Выводы
    - При обработке исключительных (редких)
    ситуаций разница между Result и Exception
    не существенная
    - Result в большинстве случаев
    оптимизируется JIT-компилятором
    - Exception медленные,
    а Exception для happy-path - дурной тон
    188

    View Slide

  189. 7.1. NullPointerException
    189

    View Slide

  190. 7.1. NullPointerException
    190
    java.lang.Boolean.getBoolean
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  191. 7.1. NullPointerException
    191
    java.lang.Boolean.getBoolean
    public static boolean getBoolean(String name) {
    boolean result = false;
    try {
    result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
    }

    View Slide

  192. 7.1. NullPointerException
    192
    java.lang.System.getProperty
    public static String getProperty(String key) {
    checkKey(key);
    @SuppressWarnings("removal")
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
    sm.checkPropertyAccess(key);
    }
    return props.getProperty(key);
    }

    View Slide

  193. 7.1. NullPointerException
    193
    java.lang.System.checkKey
    private static void checkKey(String key) {
    if (key == null) {
    throw new NullPointerException("key can't be null");
    }
    if (key.isEmpty()) {
    throw new IllegalArgumentException("key can't be empty");
    }
    }

    View Slide

  194. 7.1. NullPointerException
    194
    Выводы

    View Slide

  195. 7.1. NullPointerException
    195
    Выводы
    - Fail-fast

    View Slide

  196. 7.1. NullPointerException
    196
    Выводы
    - Fail-fast
    - NPE - это ошибка в коде,
    который кинул Exception

    View Slide

  197. 7.1. NullPointerException
    197
    Выводы
    - Fail-fast
    - NPE - это ошибка в коде,
    который кинул Exception
    - IAE - это ошибка в коде,
    который вызвал код,
    который кинул Exception

    View Slide

  198. 7.2. Exception VS
    RuntimeException
    198

    View Slide

  199. 7.2. Exception VS
    RuntimeException
    «Какой вы веры:
    checked или unchecked?»
    Александр Кучук
    https://www.youtube.com/watch?v=jl_4g2QxqMg 199

    View Slide

  200. 7.2. Exception VS
    RuntimeException
    «Какой вы веры:
    checked или unchecked?»
    Александр Кучук
    «Я делаю исключения от RuntimeException
    и молюсь, чтобы их словил кто-нибудь»
    Александр Кучук
    https://www.youtube.com/watch?v=jl_4g2QxqMg 200

    View Slide

  201. 7.2. Exception VS
    RuntimeException
    201

    View Slide

  202. 7.2. Exception VS
    RuntimeException
    Бизнес-исключения наследуются
    от Exception
    202

    View Slide

  203. 7.2. Exception VS
    RuntimeException
    Бизнес-исключения наследуются
    от Exception
    203
    Controller
    DB Redis
    Repository Cache
    Service

    View Slide

  204. 7.2. Exception VS
    RuntimeException
    Бизнес-исключения наследуются
    от Exception
    204
    RepositoryException
    Controller
    DB Redis
    Repository Cache
    Service

    View Slide

  205. 7.2. Exception VS
    RuntimeException
    Бизнес-исключения наследуются
    от Exception
    205
    RepositoryException
    Controller
    DB Redis
    Repository Cache
    Service

    View Slide

  206. 7.2. Exception VS
    RuntimeException
    Бизнес-исключения наследуются
    от Exception
    206
    RepositoryException
    Controller
    DB Redis
    Repository Cache
    Service

    View Slide

  207. 7.2. Exception VS
    RuntimeException
    java.io.UnsupportedEncodingException
    extends IOException
    207

    View Slide

  208. 7.2. Exception VS
    RuntimeException
    java.io.UnsupportedEncodingException
    extends IOException
    java.io.UncheckedIOException
    extends RuntimeException
    208

    View Slide

  209. 7.2. Exception VS
    RuntimeException
    java.util.stream.Stream
    209

    View Slide

  210. 7.2. Exception VS
    RuntimeException
    java.util.stream.Stream
    - filter(Predicate)
    - map(Function)
    - ...
    210

    View Slide

  211. 7.2. Exception VS
    RuntimeException
    java.util.stream.Stream
    - filter(Predicate)
    - map(Function)
    - ...
    211
    Optional, Result
    и другие монады

    View Slide

  212. 8. Null VS Optional
    212

    View Slide

  213. 8. Null VS Optional
    «Null - это очень быстро»
    Неизвестный автор
    213

    View Slide

  214. 8. Null VS Optional
    «Null - это очень быстро»
    Неизвестный автор
    «Null Reference -
    это моя ошибка на миллиард долларов»
    Tony Hoare,
    автор ALGOL
    и Null Reference
    https://en.wikipedia.org/wiki/Tony_Hoare#Research_and_career 214

    View Slide

  215. 8. Null VS Optional
    215
    private Object findNullable() {
    Object obj = /* ... */
    return obj;
    }
    Object result = findNull();
    if (result != null) {
    /* ... */
    } else {
    /* ... */
    }

    View Slide

  216. 8. Null VS Optional
    216
    private Object findNullable() {
    Object obj = /* ... */
    return obj;
    }
    Object result = findNull();
    if (result != null) {
    /* ... */
    } else {
    /* ... */
    }
    private Optional findOptional() {
    Object obj = /* ... */
    return Optional.ofNullable(obj);
    }
    Optional result = findOptional();
    if (result.isPresent()) {
    /* ... */
    } else {
    /* ... */
    }

    View Slide

  217. 8. Null VS Optional
    Вариант с Optional
    217

    View Slide

  218. 8. Null VS Optional
    Вариант с Optional медленнее
    218

    View Slide

  219. 8. Null VS Optional
    Вариант с Optional медленнее
    на
    219

    View Slide

  220. 8. Null VS Optional
    Вариант с Optional медленнее
    на 1-1.5
    220

    View Slide

  221. 8. Null VS Optional
    Вариант с Optional медленнее
    на 1-1.5 наносекунды
    221

    View Slide

  222. 8. Null VS Optional
    Вариант с Optional медленнее
    на 1-1.5 наносекунды
    Вывод: практической выгоды
    от использования Null нет!
    222

    View Slide

  223. 8.1. ??? VS Empty
    223

    View Slide

  224. 8.1. ??? VS Empty
    224
    Collections
    - emptyList
    - emptySet
    - emptyMap

    View Slide

  225. 8.1. ??? VS Empty
    225
    private List findAllOrEmpty() {
    if (count == 0) {
    return Collections.emptyList();
    }
    /* make result list */
    return list;
    }
    List objects = findAllOrEmpty();
    for (var object : objects) {
    /* consume objects */
    }
    Collections
    - emptyList
    - emptySet
    - emptyMap

    View Slide

  226. 8.2. @NotNull VS @Nullable
    226

    View Slide

  227. 8.2. @NotNull VS @Nullable
    JetBrains Annotations
    https://github.com/JetBrains/java-annotations 227

    View Slide

  228. 8.2. @NotNull VS @Nullable
    JetBrains Annotations
    https://github.com/JetBrains/java-annotations 228
    public static class Container {
    private final T value;
    public Container(@NotNull T value) {
    this.value = value;
    }
    @NotNull
    public T value() { return value; }
    }

    View Slide

  229. 8.2. @NotNull VS @Nullable
    JetBrains Annotations
    https://github.com/JetBrains/java-annotations 229

    View Slide

  230. 8.2. @NotNull VS @Nullable
    JetBrains Annotations
    https://github.com/JetBrains/java-annotations 230

    View Slide

  231. 8.2. @NotNull VS @Nullable
    JetBrains Annotations
    https://github.com/JetBrains/java-annotations 231

    View Slide

  232. 8.2. @NotNull VS @Nullable
    SpotBugs
    https://github.com/spotbugs/spotbugs 232

    View Slide

  233. 8.2. @NotNull VS @Nullable
    SpotBugs
    - Maven
    - Gradle
    https://github.com/spotbugs/spotbugs 233

    View Slide

  234. 8.2. @NotNull VS @Nullable
    SpotBugs
    - Maven
    - Gradle
    - Intellij IDEA
    - Eclipse
    https://github.com/spotbugs/spotbugs 234

    View Slide

  235. 8.2. @NotNull VS @Nullable
    SpotBugs
    - Maven
    - Gradle
    - Intellij IDEA
    - Eclipse
    SpotBugs Annotations
    https://github.com/spotbugs/spotbugs/tree/master/spotbugs-annotations 235

    View Slide

  236. 8.3. Nullability check
    236

    View Slide

  237. 8.3. Nullability check
    237
    java.util.Objects
    - requireNonNull
    - nonNull
    - ...

    View Slide

  238. 8.3. Nullability check
    238
    /**
    * Returns {@code true} if the provided reference is non-{@code null} otherwise returns {@code false}.
    *
    * @apiNote This method exists to be used as a
    * {@link java.util.function.Predicate}, {@code filter(Objects::nonNull)}
    *
    * @param obj a reference to be checked against {@code null}
    * @return {@code true} if the provided reference is non-{@code null} otherwise {@code false}
    *
    * @see java.util.function.Predicate
    * @since 1.8
    */
    public static boolean nonNull(Object obj) {
    return obj != null;
    }

    View Slide

  239. 8.3. Nullability check
    239
    if (object != null) {
    /* process */
    }
    if (Objects.nonNull(object)) {
    /* process */
    }

    View Slide

  240. 8.3. Nullability check
    240
    if (object != null) {
    /* process */
    }
    if (Objects.nonNull(object)) {
    /* process */
    }

    View Slide

  241. 8.3. Nullability check
    241
    if (object != null) {
    /* process */
    }
    if (Objects.nonNull(object)) {
    /* process */
    }

    View Slide

  242. 8.3. Nullability check
    242
    /**
    * Returns {@code true} if the provided reference is non-{@code null} otherwise returns {@code false}.
    *
    * @apiNote This method exists to be used as a
    * {@link java.util.function.Predicate}, {@code filter(Objects::nonNull)}
    *
    * @param obj a reference to be checked against {@code null}
    * @return {@code true} if the provided reference is non-{@code null} otherwise {@code false}
    *
    * @see java.util.function.Predicate
    * @since 1.8
    */
    public static boolean nonNull(Object obj) {
    return obj != null;
    }

    View Slide

  243. 8.3. Nullability check
    243
    /**
    * Returns {@code true} if the provided reference is non-{@code null} otherwise returns {@code false}.
    *
    * @apiNote This method exists to be used as a
    * {@link java.util.function.Predicate}, {@code filter(Objects::nonNull)}
    *
    * @param obj a reference to be checked against {@code null}
    * @return {@code true} if the provided reference is non-{@code null} otherwise {@code false}
    *
    * @see java.util.function.Predicate
    * @since 1.8
    */
    public static boolean nonNull(Object obj) {
    return obj != null;
    }

    View Slide

  244. 8.3. Nullability check
    244

    View Slide

  245. Kotlin:
    8.3. Nullability check
    245

    View Slide

  246. Kotlin:
    Снимок экрана 2022-09-27 в 16.56.05
    8.3. Nullability check
    246

    View Slide

  247. 9. Mutable VS Immutable
    247

    View Slide

  248. 9. Mutable VS Immutable
    «Использование Immutable-структур
    требует много памяти и много CPU»
    Неизвестный автор
    248

    View Slide

  249. 9. Mutable VS Immutable
    «Использование Immutable-структур
    требует много памяти и много CPU»
    Неизвестный автор
    «Mutable-структуры -
    корень всех Concurrent-ошибок»
    Неизвестный автор
    249

    View Slide

  250. 9. Mutable VS Immutable
    java.util.HashMap
    java.util.concurrent.ConcurrentHashMap
    250

    View Slide

  251. 9. Mutable VS Immutable
    java.util.HashMap
    java.util.concurrent.ConcurrentHashMap
    K
    - hashCode
    - equals
    251

    View Slide

  252. 9. Mutable VS Immutable
    java.util.Collections
    252

    View Slide

  253. 9. Mutable VS Immutable
    java.util.Collections
    - unmodifiableCollections
    - unmodifiableList
    - unmodifiableSet
    - unmodifiableMap
    - ...
    253

    View Slide

  254. 9. Mutable VS Immutable
    Record
    254

    View Slide

  255. 9. Mutable VS Immutable
    Record
    255
    public record ImmutableDataClass(String foo, String bar) {
    }
    ImmutableDataClass obj = new ImmutableDataClass("foo", "bar");
    System.out.println(obj.foo() + " and " + obj.bar());

    View Slide

  256. 9. Mutable VS Immutable
    Immutable
    256

    View Slide

  257. 9. Mutable VS Immutable
    Immutable
    - Read-only структура
    - Долго живёт, но редко меняется
    - DTO (Data Transfer Object)
    - Передаётся между слоями приложения в
    качестве результата
    - Требуется потокобезопасность,
    а расходы на создание незначительны
    257

    View Slide

  258. 10. AutoCloseable vs finalize()
    258

    View Slide

  259. 10. AutoCloseable vs finalize()
    259
    public class CloseableResource implements AutoCloseable {
    public void use() { /* use resource */ }
    @Override
    public void close() { /* close resource */ }
    }

    View Slide

  260. 10. AutoCloseable vs finalize()
    260
    public class CloseableResource implements AutoCloseable {
    public void use() { /* use resource */ }
    @Override
    public void close() { /* close resource */ }
    }
    try (var resource = new CloseableResource()) {
    resource.use();
    }

    View Slide

  261. 10. AutoCloseable vs finalize()
    261
    public class FinalizableResource {
    public void use() { /* use resource */ }
    @Override
    protected void finalize() { /* close resource */ }
    }

    View Slide

  262. 10. AutoCloseable vs finalize()
    262
    public class FinalizableResource {
    public void use() { /* use resource */ }
    @Override
    protected void finalize() { /* close resource */ }
    }
    var resource = new FinalizableResource();
    resource.use();

    View Slide

  263. 10. AutoCloseable vs finalize()
    263
    public class FinalizableResource implements Closeable {
    public void use() { /* use resource */ }
    @Override
    protected void finalize() { close(); }
    @Override
    public void close() { /* close resource */ }
    }

    View Slide

  264. 10. AutoCloseable vs finalize()
    264
    public class FinalizableResource implements Closeable {
    public void use() { /* use resource */ }
    @Override
    protected void finalize() { close(); }
    @Override
    public void close() { /* close resource */ }
    }
    Deprecated c Java 9

    View Slide

  265. 10. AutoCloseable vs finalize()
    - Не гарантируется момент выполнения
    finalize(), реализация JVM-специфична
    - Дорогое создание и удаление объектов с
    переопределённым finalize()
    - Финализация выполняется в одном
    выделенном потоке (HotSpot)
    - Невозможно перехватить исключение,
    брошенное из finalize
    https://www.infoq.com/articles/Finalize-Exiting-Java/ 265

    View Slide

  266. 10. AutoCloseable vs finalize()
    266
    public class CleanableResource implements AutoCloseable {
    private static final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;
    public CleanableResource() {
    Runnable clean = () -> { /* Cleaning operation without referencing to 'this'. */ };
    cleanable = cleaner.register(this, clean);
    }
    public void use() { /* use resource */ }
    @Override
    public void close() { cleanable.clean(); }
    }

    View Slide

  267. 10. AutoCloseable vs finalize()
    267
    public class CleanableResource implements AutoCloseable {
    private static final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;
    public CleanableResource() {
    Runnable clean = () -> { /* Cleaning operation without referencing to 'this'. */ };
    cleanable = cleaner.register(this, clean);
    }
    public void use() { /* use resource */ }
    @Override
    public void close() { cleanable.clean(); }
    }
    Лямбду можно,
    но случайно можно сослаться на this,
    и clean автоматически не отработает

    View Slide

  268. 10. AutoCloseable vs finalize()
    268
    public static void main(String[] args) throws InterruptedException {
    CleanableResource resource = new CleanableResource();
    resource.use();
    resource = null;// Resource is phantom reachable from now
    System.gc();// There is no guarantee but normally GC should start
    Thread.sleep(5_000);
    // Resource cleaned successfully if GC succeeded before time out
    }

    View Slide

  269. 10. AutoCloseable vs finalize()
    - Не гарантируется вызов clean до выхода
    приложения, реализация зависит от JVM
    - У каждого Cleaner свой поток очистки
    - Игнорируются исключения,
    брошенные при очистке
    https://www.infoq.com/articles/Finalize-Exiting-Java/ 269

    View Slide

  270. Выводы
    270

    View Slide

  271. Выводы
    «Только Ситхи всё возводят в абсолют»
    Оби-Ван Кеноби
    271

    View Slide

  272. Выводы
    DRY - Don't Repeat Yourself
    KISS - Keep It Simple, Smart
    272

    View Slide

  273. - https://t.me/chnl_GregoryKoshelev
    - https://t.me/chat_GregoryKoshelev
    Код
    - https://github.com/gnkoshelev/snowone2023
    273

    View Slide