Какой код выполнится быстрее и насколько?
Anonymous Poll
12%
Код с плюсиками, быстрее в 20 раз
9%
Код с плюсиками, быстрее на 15%
17%
Вариант с StringBuilder быстрее в 20 раз
28%
Вариант с StringBuilder быстрее на 15%
34%
Примерно одинаково
Сложение строк, часть 1: java 8
В JDK есть четыре способа слепить строчки между собой:
🔸 Оператор +
🔸 Класс StringBuilder
🔸 Класс StringBuffer (потокобезопасный StringBuilder)
🔸 Метод concat
В чём проблема с объединением строк?
Класс String - неизменяемый, поэтому при каждом сложении строк создаётся новый объект.
Если это просто
Но в типичном java приложении очень много строчек и их взаимодействий. Больше строк - больше промежуточных объектов. Если не принять специальных мер, то
Строки иногда занимают половину памяти, поэтому оптимизация очень важна.
StringBuilder - специальный класс, который снижает накладные расходы при соединении строк. Выглядит это так:
Единственный минус StringBuilder - плохая читаемость. Половину кода занимает append.
Через + работать приятнее, поэтому у компилятора есть набор оптимизаций при использовании плюсика. Что делает компилятор:
🔸 Соединяет явно обозначенные строки:
🔸 Сразу соединяет final строки:
🔸 Если строки НЕ final, то код выше компилируется в создание объекта StringBuilder, 3 вызова метода append и метод toString
Тут мы подходим к популярному мифу. Помните, вначале я говорила, что
Так вот, это неправда. StringBuilder используется под капотом плюсика со времён java 5. А это 2004 год, 17 лет уже прошло.
У такого подхода есть серьёзный недостаток. StringBuilder создаётся даже при сложении двух строк:
Чтобы склеить две строки без лишних StringBuilder, используйте метод concat:
🔹 final строчки - через плюсик
🔹 Две строки - через concat
🔹 Несколько строк, но один раз - через плюсик, внутри работает StringBuilder
🔹 Сложные соединения, например, в цикле - явно объявить StringBuilder и использовать его
Ответ на вопрос перед постом
В первом варианте строка-результат соберётся на этапе компиляции, а во втором - во время работы программы. Поэтому первый вариант выполнится быстрее в 20-30 раз.
В JDK есть четыре способа слепить строчки между собой:
🔸 Оператор +
🔸 Класс StringBuilder
🔸 Класс StringBuffer (потокобезопасный StringBuilder)
🔸 Метод concat
В чём проблема с объединением строк?
Класс String - неизменяемый, поэтому при каждом сложении строк создаётся новый объект.
Если это просто
"a"+"b", то проблемы нет. Но в типичном java приложении очень много строчек и их взаимодействий. Больше строк - больше промежуточных объектов. Если не принять специальных мер, то
"a"+"b"+"c"+"d" приведёт к созданию ab, abc и abcd.Строки иногда занимают половину памяти, поэтому оптимизация очень важна.
StringBuilder - специальный класс, который снижает накладные расходы при соединении строк. Выглядит это так:
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
String res = sb.toString();
Что происходит: StringBuilder выделяет байтовый массив и с каждым append добавляет туда строчки. При вызове toString из этого массива создаётся неизменяемая строка. Так количество лишних объектов существенно сокращается.Единственный минус StringBuilder - плохая читаемость. Половину кода занимает append.
Через + работать приятнее, поэтому у компилятора есть набор оптимизаций при использовании плюсика. Что делает компилятор:
🔸 Соединяет явно обозначенные строки:
String s = "a" + "b" + "c";
Сразу компилируется в abc.🔸 Сразу соединяет final строки:
final String s1 = "a";
final String s2 = "b";
final String s3 = "с";
String s4 = s1 + s2 + s3;
Это тоже компилируется в abc, без промежуточных объектов.🔸 Если строки НЕ final, то код выше компилируется в создание объекта StringBuilder, 3 вызова метода append и метод toString
Тут мы подходим к популярному мифу. Помните, вначале я говорила, что
"a"+"b"+"c" приводит к созданию объектов ab и abc. Многие понимают это буквально, что это оператор + приводит к созданию лишних объектов. Поэтому лучше плюсик не использовать, а использовать StringBuilder.Так вот, это неправда. StringBuilder используется под капотом плюсика со времён java 5. А это 2004 год, 17 лет уже прошло.
У такого подхода есть серьёзный недостаток. StringBuilder создаётся даже при сложении двух строк:
String s1 = "b";
String s2 = "с";
String s3 = s1 + s2;
В данном случае это не рационально.Чтобы склеить две строки без лишних StringBuilder, используйте метод concat:
String s3 = s1.concat(s2);
Итого, как соединить две строки:🔹 final строчки - через плюсик
🔹 Две строки - через concat
🔹 Несколько строк, но один раз - через плюсик, внутри работает StringBuilder
🔹 Сложные соединения, например, в цикле - явно объявить StringBuilder и использовать его
Ответ на вопрос перед постом
В первом варианте строка-результат соберётся на этапе компиляции, а во втором - во время работы программы. Поэтому первый вариант выполнится быстрее в 20-30 раз.
👍6
Сложение строк, часть 2: java 9
Возьмём код из прошлого поста
(Подробно про invokedynamic я писала в этом посте, сейчас не будем углубляться)
В классе StringConcatFactory лежит та же логика со стринг билдером. Но очень параметризуемая: через JVM параметры доступны немного разные реализации и стратегии вычисления исходного размера StringBuilder.
Это слишком глубокие дебри, поэтому не буду расписывать подробно. Почитать про все опции и посмотреть бенчмарки можно тут.
У любой задачи есть цель, поэтому давайте разберёмся, зачем это всё затевалось. Первый вариант, приходящий на ум - увеличение производительности.
Но по бенчмаркам видно, что перенос логики из байткода в java код не увеличил скорость работы.
Второй вариант - большая гибкость. Да, параметров стало больше, но не думаю, что это будет востребовано в большинстве проектов.
Основная цель изменений - это "причёсывание" кода. Что получилось после рефакторинга:
✅ Логичность. Я воспринимаю + как сокращённую форму метода add для строк и ожидаю реализацию этого метода внутри JDK.
✅ Чёткое разделение обязанностей. Работа компилятора - преобразовать конструкции языка в инструкции для JVM. Например, превратить + в вызов метода.
Оптимизации на этом уровне могут быть, но не на уровне "бизнес-логики". Соединить две строчки на этапе компиляции - это одно. Прописать создание объектов и тд - совсем другое.
✅ Легче сделать сложную логику обработки. В классе StringConcatFactory 900 строк с кучей параметров и проверок. Представляете, если такое будет в байткоде? Написал в коде плюсик, а при компиляции получил чудовище.
✅ Легче менять реализацию. Для изменения конкатенации в будущем достаточно поменять код в JDK, и не нужно трогать компилятор. Это снижает количество работы и возможных ошибок.
Если совсем просто, то перенос логики соединения строк из байткода в JDK - это как перенос логики из хранимых процедур в основной код🙂
Возьмём код из прошлого поста
String s = s1 + s2 + s3;Для него компилятор java 8 соберёт байткод:
// Method StringBuilder."(init)":()Компилятор java 9 сделает по-другому:
// Method StringBuilder.append:(String)
// Method StringBuilder.append:(String)
// Method StringBuilder.append:(String)
// Method StringBuilder.toString:()
invokedynamic #13По ссылкам мы придём в метод StringConcatFactory#makeConcatWithConstants
(Подробно про invokedynamic я писала в этом посте, сейчас не будем углубляться)
В классе StringConcatFactory лежит та же логика со стринг билдером. Но очень параметризуемая: через JVM параметры доступны немного разные реализации и стратегии вычисления исходного размера StringBuilder.
Это слишком глубокие дебри, поэтому не буду расписывать подробно. Почитать про все опции и посмотреть бенчмарки можно тут.
У любой задачи есть цель, поэтому давайте разберёмся, зачем это всё затевалось. Первый вариант, приходящий на ум - увеличение производительности.
Но по бенчмаркам видно, что перенос логики из байткода в java код не увеличил скорость работы.
Второй вариант - большая гибкость. Да, параметров стало больше, но не думаю, что это будет востребовано в большинстве проектов.
Основная цель изменений - это "причёсывание" кода. Что получилось после рефакторинга:
✅ Логичность. Я воспринимаю + как сокращённую форму метода add для строк и ожидаю реализацию этого метода внутри JDK.
✅ Чёткое разделение обязанностей. Работа компилятора - преобразовать конструкции языка в инструкции для JVM. Например, превратить + в вызов метода.
Оптимизации на этом уровне могут быть, но не на уровне "бизнес-логики". Соединить две строчки на этапе компиляции - это одно. Прописать создание объектов и тд - совсем другое.
✅ Легче сделать сложную логику обработки. В классе StringConcatFactory 900 строк с кучей параметров и проверок. Представляете, если такое будет в байткоде? Написал в коде плюсик, а при компиляции получил чудовище.
✅ Легче менять реализацию. Для изменения конкатенации в будущем достаточно поменять код в JDK, и не нужно трогать компилятор. Это снижает количество работы и возможных ошибок.
Если совсем просто, то перенос логики соединения строк из байткода в JDK - это как перенос логики из хранимых процедур в основной код🙂
👍2
Чем отличаются кодировки?
Продолжаем тему прошлой недели и снова поговорим о классе String. В java 9 вышло интересное обновление - компактные строки. Чтобы лучше понять, в чём была проблема и как она решена, разберём в этом посте отличия между кодировками. А в четверг обсудим уже сами компактные строки.
Итак, символы хранятся в памяти в виде чисел. Кодировки отвечают за формат хранения и правила перевода символов в числа и обратно. Кодировки условно делятся на две группы:
🔹 ASCII-based
🔹 Unicode-based
1️⃣ ASCII
В большинстве ASCII кодировок символ занимает 1 байт и содержит число от 0 до 256. Первые 128 значений транслируются одинаково во всех кодировках:
▫️0-31: управляющие последовательности - перенос строки, конец файла и т.д.
▫️32-127: латинский алфавит, цифры, знаки препинания
Значения 128-255 отображаются на специфичные символы языков. Разные кодировки - разные наборы символов:
🔸Кириллица: ISO-8859-5, Windows-1251
🔸Греческий алфавит: ISO-8859-7, Windows-1253
🔸Исландские символы: OEM 861
200 может стать Ш, Θ, È или чем-то ещё. Фраза Я люблю Java в другой кодировке отобразится как Ď ŰîŃŰî Java.
✅ Компактный формат: 1 символ — 1 байт
❌ Всего 256 значений — нет места для эмодзи
❌ Неоднозначность трактовки
❌ Нельзя использовать украинский и норвежский язык в одном тексте
2️⃣ Unicode
В основе преобразований лежит гигантская таблица с большинством символов, которые используются в мире. Первые 127 символов полностью совпадают с ASCII.
Но ASCII-кодировки не умеют читать символы больше 255. Если подсунуть им юникод, то непонятные значения превратятся в❓ и текст Я люблю Java отобразится как ? ????? Java.
Как хранится юникод.
Ранние версии используют отображение 1 к 1. Все символы хранятся одинаково и занимают одинаковое количество памяти.
Одна из первых кодировок UCS-2 хранила один символ в двух байтах. После ASCII с их диапазоном 0-256 казалось, что диапазона 0-65536 хватит навсегда.
Со временем в таблицу добавилось больше символов и встал вопрос об эффективном хранении данных. Сегодня, чтобы однозначно представить символ юникода нужно 32 бита — так символы хранятся в UTF-32:
✅ Прямое отображение
✅ Простота обработки
✅ Очень много символов
❌ Неэффективный расход памяти — если использовать только латиницу с кодами типа 0..045 и 0...077, три четверти памяти будет занято нулями.
Чтобы решить проблему выше, появились кодировки с переменной длиной: UTF-8 и UTF-16.
Они используют не отображение 1 к 1, а схему с флажками и вычислениями.
В UTF-8 символ занимает 1, 2, 3 или 4 байта. В UTF-16 популярные символы занимают 2 байта, а непопулярные - 4.
✅ Экономный расход памяти для латинских символов
❌ Обработка и поиск происходят чуть медленнее, тк надо делать преобразования
❌ Отметка длины находится в первых 2 битах и уменьшает диапазон значений
Если в структуре 2 или больше байтов, то одни процессоры быстрее считывают их в прямом порядке, а другие — в обратном. Поэтому у UTF-16 и UTF-32 могут быть приставки LE или BE: Little/Big endian.
Что в java. В ранних версиях для char использовалась UCS-2, один символ занимал 2 байта. Затем java перешла на UTF-16 с переменной длиной.
Ну а что с этим не так, и как обстоят дела в java 9 - поговорим в следующем посте.
Продолжаем тему прошлой недели и снова поговорим о классе String. В java 9 вышло интересное обновление - компактные строки. Чтобы лучше понять, в чём была проблема и как она решена, разберём в этом посте отличия между кодировками. А в четверг обсудим уже сами компактные строки.
Итак, символы хранятся в памяти в виде чисел. Кодировки отвечают за формат хранения и правила перевода символов в числа и обратно. Кодировки условно делятся на две группы:
🔹 ASCII-based
🔹 Unicode-based
1️⃣ ASCII
В большинстве ASCII кодировок символ занимает 1 байт и содержит число от 0 до 256. Первые 128 значений транслируются одинаково во всех кодировках:
▫️0-31: управляющие последовательности - перенос строки, конец файла и т.д.
▫️32-127: латинский алфавит, цифры, знаки препинания
Значения 128-255 отображаются на специфичные символы языков. Разные кодировки - разные наборы символов:
🔸Кириллица: ISO-8859-5, Windows-1251
🔸Греческий алфавит: ISO-8859-7, Windows-1253
🔸Исландские символы: OEM 861
200 может стать Ш, Θ, È или чем-то ещё. Фраза Я люблю Java в другой кодировке отобразится как Ď ŰîŃŰî Java.
✅ Компактный формат: 1 символ — 1 байт
❌ Всего 256 значений — нет места для эмодзи
❌ Неоднозначность трактовки
❌ Нельзя использовать украинский и норвежский язык в одном тексте
2️⃣ Unicode
В основе преобразований лежит гигантская таблица с большинством символов, которые используются в мире. Первые 127 символов полностью совпадают с ASCII.
Но ASCII-кодировки не умеют читать символы больше 255. Если подсунуть им юникод, то непонятные значения превратятся в❓ и текст Я люблю Java отобразится как ? ????? Java.
Как хранится юникод.
Ранние версии используют отображение 1 к 1. Все символы хранятся одинаково и занимают одинаковое количество памяти.
Одна из первых кодировок UCS-2 хранила один символ в двух байтах. После ASCII с их диапазоном 0-256 казалось, что диапазона 0-65536 хватит навсегда.
Со временем в таблицу добавилось больше символов и встал вопрос об эффективном хранении данных. Сегодня, чтобы однозначно представить символ юникода нужно 32 бита — так символы хранятся в UTF-32:
✅ Прямое отображение
✅ Простота обработки
✅ Очень много символов
❌ Неэффективный расход памяти — если использовать только латиницу с кодами типа 0..045 и 0...077, три четверти памяти будет занято нулями.
Чтобы решить проблему выше, появились кодировки с переменной длиной: UTF-8 и UTF-16.
Они используют не отображение 1 к 1, а схему с флажками и вычислениями.
В UTF-8 символ занимает 1, 2, 3 или 4 байта. В UTF-16 популярные символы занимают 2 байта, а непопулярные - 4.
✅ Экономный расход памяти для латинских символов
❌ Обработка и поиск происходят чуть медленнее, тк надо делать преобразования
❌ Отметка длины находится в первых 2 битах и уменьшает диапазон значений
Если в структуре 2 или больше байтов, то одни процессоры быстрее считывают их в прямом порядке, а другие — в обратном. Поэтому у UTF-16 и UTF-32 могут быть приставки LE или BE: Little/Big endian.
Что в java. В ранних версиях для char использовалась UCS-2, один символ занимал 2 байта. Затем java перешла на UTF-16 с переменной длиной.
Ну а что с этим не так, и как обстоят дела в java 9 - поговорим в следующем посте.
👍4
Compact String в java 9
По данным OpenJDK более 25% объектов в памяти занимают строки. По той же статистике 95% строк содержат только латинские символы и цифры, числовое значение которых умещается в 1 байт, а до 15% памяти заняты бесполезными нулями.
В java 8 символы хранятся в типе char и кодировке UTF-16. Занимают 8 или 16 бит. Экземпляр String содержит массив символов char[].
В java 9 вышло обновление Compact Strings. Символы теперь лежат в byte[] и хранятся в одной из двух кодировок. Кодировка записана в новом поле coder.
Это может быть:
1️⃣ ASCII кодировка Latin-1. Используется, если все символы строки умещаются в 1 байт. Т.е в тексте только латиница и цифры.
2️⃣ UTF-16 - если хотя бы один символ требует 16 бит.
Строки в разных кодировках по-разному лежат в памяти, и работать с ними нужно по-разному. Каждый метод в классе String начинается с проверки кодировки и разделяется на две ветки — для Latin-1 и UTF-16. Их код вынесен в отдельные классы StringLatin1 и StringUTF16.
❓Почему не UTF-8? Он же занимает ещё меньше места.
— UTF-8 действительно занимает меньше памяти, но работает он медленнее. Если символы в массиве одной длины, то адрес символа в памяти быстро ищется по индексу. Если элементы с переменной длиной - адрес вычисляется на основе предыдущих элементов, а это долго. Все методы класса String работали бы дольше.
❓Память сэкономили, кода стало в 3 раза больше. Стало ли быстрее?
— Любая дополнительная проверка снижает скорость работы, особенно при работе с маленькими строками. Поэтому на уровне JVM много оптимизаций по проверкам кодировки и сравнению строк, изменён механизм конкатенации и других операций. Именно за счёт внутренних оптимизаций компактные строки работают в среднем на 20% быстрее и создают на 30% меньше промежуточных объектов.
Самое главное - эти изменения никак не отразились на интерфейсе String. I/O классы, StringBuilder, StringBuffer тоже адаптированы без внешних изменений.
Нужно просто перейти на java 9 и приложение будет занимать на 5-15% меньше памяти.
По данным OpenJDK более 25% объектов в памяти занимают строки. По той же статистике 95% строк содержат только латинские символы и цифры, числовое значение которых умещается в 1 байт, а до 15% памяти заняты бесполезными нулями.
В java 8 символы хранятся в типе char и кодировке UTF-16. Занимают 8 или 16 бит. Экземпляр String содержит массив символов char[].
В java 9 вышло обновление Compact Strings. Символы теперь лежат в byte[] и хранятся в одной из двух кодировок. Кодировка записана в новом поле coder.
Это может быть:
1️⃣ ASCII кодировка Latin-1. Используется, если все символы строки умещаются в 1 байт. Т.е в тексте только латиница и цифры.
2️⃣ UTF-16 - если хотя бы один символ требует 16 бит.
Строки в разных кодировках по-разному лежат в памяти, и работать с ними нужно по-разному. Каждый метод в классе String начинается с проверки кодировки и разделяется на две ветки — для Latin-1 и UTF-16. Их код вынесен в отдельные классы StringLatin1 и StringUTF16.
❓Почему не UTF-8? Он же занимает ещё меньше места.
— UTF-8 действительно занимает меньше памяти, но работает он медленнее. Если символы в массиве одной длины, то адрес символа в памяти быстро ищется по индексу. Если элементы с переменной длиной - адрес вычисляется на основе предыдущих элементов, а это долго. Все методы класса String работали бы дольше.
❓Память сэкономили, кода стало в 3 раза больше. Стало ли быстрее?
— Любая дополнительная проверка снижает скорость работы, особенно при работе с маленькими строками. Поэтому на уровне JVM много оптимизаций по проверкам кодировки и сравнению строк, изменён механизм конкатенации и других операций. Именно за счёт внутренних оптимизаций компактные строки работают в среднем на 20% быстрее и создают на 30% меньше промежуточных объектов.
Самое главное - эти изменения никак не отразились на интерфейсе String. I/O классы, StringBuilder, StringBuffer тоже адаптированы без внешних изменений.
Нужно просто перейти на java 9 и приложение будет занимать на 5-15% меньше памяти.
👍2
Мини-новость: стартовал 3 поток курса по многопоточке. Кто записался, но пропустил - проверьте почту! Если не нашли письмо, напишите мне.
Кто хотел, но не успел - запишитесь в список, и вы первыми получите новость о старте нового потока. Когда он будет - не знаю:)
Что по постам.
На этой неделе поговорим о том, как перейти в айти из других сфер. Я получаю много таких вопросов, будут теперь отвечать ссылкой на посты.
Кто хотел, но не успел - запишитесь в список, и вы первыми получите новость о старте нового потока. Когда он будет - не знаю:)
Что по постам.
На этой неделе поговорим о том, как перейти в айти из других сфер. Я получаю много таких вопросов, будут теперь отвечать ссылкой на посты.
Вопрос для тех, кто проходил java курсы от скиллбокс, гикбрейнс, нетологии и тд. К какому результату вы пришли?
Anonymous Poll
8%
Устроился на работу сразу после курсов
6%
Пришлось доучиваться, но в итоге стал джуниором
2%
Хожу по собеседованиям, подтягиваю знания
3%
Курс прошёл, в айти не пошёл
4%
Не закончил по какой-то причине
78%
Посмотреть ответы
Как войти в айти, часть 1
Сразу начну с горячей темы - эффективны ли java курсы за 100-200к?
Вообще учиться на курсах очень комфортно:
🔸 Чёткая программа и расписание
🔸 Группа единомышленников
🔸 Обратная связь преподавателя
Но минусы текущих предложений настолько сильные, что затмевают плюсы:
❌ Завышенные обещания
Реклама обещает, что после курса за 100к легко найти работу за 100к. По факту рекрутеры часто отбрасывают резюме, если в нём только прохождение курсов. Потому что знаний у таких кандидатов обычно недостаточно.
❌ Группы 30-40 человек, слабая обратная связь
❌ Программа везде одна и та же, часто устаревшая
Если вы отметили пункт "Устроился на работу сразу после курсов", то напишите мне! Вдруг я неправа, и хорошие варианты тоже встречаются.
Что же делать?
Для начала рассмотрите другие пути.
Любая профессия при переходе в IT оплачивается больше. Зарплата IT рекрутёра может быть в 2 раза больше, чем у коллеги из другой сферы.
В IT полно других профессий: аналитик, тестировщик, automation тестировщик или UX/UI дизайнер. У многих входной порог ниже, и можно больше общаться с людьми.
Если вас привлекает именно программирование, то в следующем посте я дам список бесплатных и недорогих материалов.
Но просмотреть список недостаточно, их нужно изучить:) Построить план и встроить учёбу в привычное расписание.
Что может помочь:
🔹 Напарник. Учитесь вместе, обсуждайте проблемы, мотивируйте друг друга. Дело пойдёт быстрее 100%
🔹 Ментор. Самый эффективный путь. Ментор - это человек, который уже дошёл до вашей точки Б и готов помочь вам пройти этот путь. Как найти ментора и договориться с ним - отдельный вопрос. Когда-нибудь напишу об этом пост.
❓Сколько времени займёт подготовка?
— Зависит от многих факторов, но ориентируйтесь на регулярные занятия 30-60 минут в день в течение года.
❓Я юрист/пекарь/бухгалтер, мне 30/40/50 лет, могу ли я стать программистом?
— Сможете, если у вас есть:
▫️ Интерес к самому программированию, а не только к деньгам в IT
▫️ Английский язык на уровне чтения технической документации
❓ А меня возьмут? Я юрист/пекарь/бухгалтер, мне 30/40/50
— Если вы хорошо знаете основы java, приятны в общении и сообразительны, то вам будут рады. Последние два пункта не менее важны, чем первый!
Сразу начну с горячей темы - эффективны ли java курсы за 100-200к?
Вообще учиться на курсах очень комфортно:
🔸 Чёткая программа и расписание
🔸 Группа единомышленников
🔸 Обратная связь преподавателя
Но минусы текущих предложений настолько сильные, что затмевают плюсы:
❌ Завышенные обещания
Реклама обещает, что после курса за 100к легко найти работу за 100к. По факту рекрутеры часто отбрасывают резюме, если в нём только прохождение курсов. Потому что знаний у таких кандидатов обычно недостаточно.
❌ Группы 30-40 человек, слабая обратная связь
❌ Программа везде одна и та же, часто устаревшая
Если вы отметили пункт "Устроился на работу сразу после курсов", то напишите мне! Вдруг я неправа, и хорошие варианты тоже встречаются.
Что же делать?
Для начала рассмотрите другие пути.
Любая профессия при переходе в IT оплачивается больше. Зарплата IT рекрутёра может быть в 2 раза больше, чем у коллеги из другой сферы.
В IT полно других профессий: аналитик, тестировщик, automation тестировщик или UX/UI дизайнер. У многих входной порог ниже, и можно больше общаться с людьми.
Если вас привлекает именно программирование, то в следующем посте я дам список бесплатных и недорогих материалов.
Но просмотреть список недостаточно, их нужно изучить:) Построить план и встроить учёбу в привычное расписание.
Что может помочь:
🔹 Напарник. Учитесь вместе, обсуждайте проблемы, мотивируйте друг друга. Дело пойдёт быстрее 100%
🔹 Ментор. Самый эффективный путь. Ментор - это человек, который уже дошёл до вашей точки Б и готов помочь вам пройти этот путь. Как найти ментора и договориться с ним - отдельный вопрос. Когда-нибудь напишу об этом пост.
❓Сколько времени займёт подготовка?
— Зависит от многих факторов, но ориентируйтесь на регулярные занятия 30-60 минут в день в течение года.
❓Я юрист/пекарь/бухгалтер, мне 30/40/50 лет, могу ли я стать программистом?
— Сможете, если у вас есть:
▫️ Интерес к самому программированию, а не только к деньгам в IT
▫️ Английский язык на уровне чтения технической документации
❓ А меня возьмут? Я юрист/пекарь/бухгалтер, мне 30/40/50
— Если вы хорошо знаете основы java, приятны в общении и сообразительны, то вам будут рады. Последние два пункта не менее важны, чем первый!
👍6
Как войти в айти, часть 2: полезные материалы
В среду я выставляла опрос про java курсы и их эффективность. Большинство ответивших устроились на работу сразу после курсов.
Я удивилась, обычно люди с курсов редко впечатляют своими знаниями, но хотят много денег. Поэтому было интересно почитать 13 историй тех, кто смог.
В основном это те, кто проходил интенсивные курсы: job4j, JavaMentor. Ребята учились по 20-40 часов в неделю несколько месяцев, часто с неравнодушным ментором.
Три человека прошли все уровни JavaRush со стажировкой и написали, что этого хватило.
Меня больше интересовали курсы типа скиллбокс, где обещают обучить с нуля до сеньора за 3 месяца. Мне написали несколько ребят, которые получили оффер джуниора после такого обучения. Что им помогло:
🔸 Инженерный или математический бэкграунд, высокий интерес к компьютерам и IT
🔸 Дисциплина и самостоятельность. Ребята сами углубляли темы с курсов - читали книги, статьи, смотрели видео с конференций
🔸 Скромность - готовность работать на старте за 30к, а не требовать сразу 100
У дорогих курсов нет секретного секрета. Бюджетные курсы могут быть не хуже, а иногда и лучше. Для начинающих есть много материалов за бесплатно или небольшую цену. Примерный список ниже. Сама не проходила, но слышала хорошие отзывы.
Итак, как войти в айти за 6 шагов:
Шаг 1. Начать писать java код
Вариант А: если вы никогда не писали код
Курс на степике - бесплатный
JavaRush - 1800 рублей в месяц, огромное количество заданий для тренировки
Книга Head First Java как дополнение
Вариант Б: вы уже писали код
Знаете питон, ходили в кружок программирования в школе и тд. Этот курс на степик поможет привыкнуть к синтаксису java.
Шаг 2. Углубляемся в ООП и библиотеки
Многие хвалят трек Java Backend Developer в Jet Brains Academy
Шаг 3. Изучаем важное
▫️ Git: Теория, тренажёр на русском, тренажёр на английском
▫️Что такое системы сборки
▫️ Spring: посмотрите видео, например, такое по темам Spring Core, Spring MVC, Spring Boot, Spring Data
▫️Паттерны GoF
▫️SQL: учебник-тренажёр 1, учебник-тренажер 2
▫️Курс по алгоритмам
Вы вряд ли будете использовать сложные алгоритмы в работе, но рекомендую пройти курс. Потому что
🔹Алгоритмы спрашивают на собеседованиях
🔹Это отличный тест на профпригодность. Справитесь с курсом - справитесь с большинством энтерпрайзных задач
Шаг 4: Шлифуем теорию и готовимся к собеседованиям
Списков миллион, можно для начала пройтись по этому, к нему прилагается телеграм бот с вопросами @DevInterviewBot
Бонусный шаг: найти ментора и сделать сервис, где будет Spring, базы данных, JUnit и HTTP-запросы. Выложить проект на гитхаб и прикрепить ссылку к резюме.
Шаг 5: прокачиваем навык собеседований
Идем по циклу:
🔸 Сходить на собеседование
🔸 Проработать вопросы, на которые не ответили
Повторяем, пока не найдём работу🙂
В среду я выставляла опрос про java курсы и их эффективность. Большинство ответивших устроились на работу сразу после курсов.
Я удивилась, обычно люди с курсов редко впечатляют своими знаниями, но хотят много денег. Поэтому было интересно почитать 13 историй тех, кто смог.
В основном это те, кто проходил интенсивные курсы: job4j, JavaMentor. Ребята учились по 20-40 часов в неделю несколько месяцев, часто с неравнодушным ментором.
Три человека прошли все уровни JavaRush со стажировкой и написали, что этого хватило.
Меня больше интересовали курсы типа скиллбокс, где обещают обучить с нуля до сеньора за 3 месяца. Мне написали несколько ребят, которые получили оффер джуниора после такого обучения. Что им помогло:
🔸 Инженерный или математический бэкграунд, высокий интерес к компьютерам и IT
🔸 Дисциплина и самостоятельность. Ребята сами углубляли темы с курсов - читали книги, статьи, смотрели видео с конференций
🔸 Скромность - готовность работать на старте за 30к, а не требовать сразу 100
У дорогих курсов нет секретного секрета. Бюджетные курсы могут быть не хуже, а иногда и лучше. Для начинающих есть много материалов за бесплатно или небольшую цену. Примерный список ниже. Сама не проходила, но слышала хорошие отзывы.
Итак, как войти в айти за 6 шагов:
Шаг 1. Начать писать java код
Вариант А: если вы никогда не писали код
Курс на степике - бесплатный
JavaRush - 1800 рублей в месяц, огромное количество заданий для тренировки
Книга Head First Java как дополнение
Вариант Б: вы уже писали код
Знаете питон, ходили в кружок программирования в школе и тд. Этот курс на степик поможет привыкнуть к синтаксису java.
Шаг 2. Углубляемся в ООП и библиотеки
Многие хвалят трек Java Backend Developer в Jet Brains Academy
Шаг 3. Изучаем важное
▫️ Git: Теория, тренажёр на русском, тренажёр на английском
▫️Что такое системы сборки
▫️ Spring: посмотрите видео, например, такое по темам Spring Core, Spring MVC, Spring Boot, Spring Data
▫️Паттерны GoF
▫️SQL: учебник-тренажёр 1, учебник-тренажер 2
▫️Курс по алгоритмам
Вы вряд ли будете использовать сложные алгоритмы в работе, но рекомендую пройти курс. Потому что
🔹Алгоритмы спрашивают на собеседованиях
🔹Это отличный тест на профпригодность. Справитесь с курсом - справитесь с большинством энтерпрайзных задач
Шаг 4: Шлифуем теорию и готовимся к собеседованиям
Списков миллион, можно для начала пройтись по этому, к нему прилагается телеграм бот с вопросами @DevInterviewBot
Бонусный шаг: найти ментора и сделать сервис, где будет Spring, базы данных, JUnit и HTTP-запросы. Выложить проект на гитхаб и прикрепить ссылку к резюме.
Шаг 5: прокачиваем навык собеседований
Идем по циклу:
🔸 Сходить на собеседование
🔸 Проработать вопросы, на которые не ответили
Повторяем, пока не найдём работу🙂
Stepik: online education
Легкий старт в Java. Вводный курс для чайников
Вводный курс по языку программирования Java. Доступно изложенный материал и большое количество задач.
👍7
Два полезных телеграм канала
На этой неделе продолжу тему с развитием карьеры. А на следующей вернёмся в технические дебри джавы 🚀
Сегодня расскажу про два полезных телеграм канала.
1️⃣ Для начинающих - канал Code Review
У него очень классная идея. Это даже не канал, а коммьюнити, где можно
🔸 Оставить свой код на ревью
🔸 Сделать задание и отправить его на ревью
🔸 Сделать ревью другим ребятам
Для начинающих полезно побыть со всех сторон - и показать свой код, и посмотреть, как пишут код другие. Получить конструктивную обратную связь и дать её другим.
Как всё проходит:
▫️ С понедельника по среду подаются заявки на ревью
▫️ С четверга по воскресенье собирается фидбэк
Всё быстро и просто. Надеюсь, что проект будет развиваться, поэтому поучаствую в ближайшей java ревью-сессии как приглашённый эксперт😊
2️⃣ Для продолжающих - канал Хороший разработчик знает
Канал ведёт Павел - разработчик с 15-летним опытом, сейчас работает в Германии. Пишет посты с уклоном в soft skills, менеджмент и верхнеуровневый инжиниринг:
🔹 Как я стал principal engineer - часть 1, часть 2
🔹 Как выбрать процессор в облаке
🔹 Как рассчитать расходы на инфраструктуру
Чем выше по карьерной лестнице, тем важнее эти темы.
У обоих каналов пока немного подписчиков, но ребята делают очень хорошее дело. Давайте их поддержим!
На этой неделе продолжу тему с развитием карьеры. А на следующей вернёмся в технические дебри джавы 🚀
Сегодня расскажу про два полезных телеграм канала.
1️⃣ Для начинающих - канал Code Review
У него очень классная идея. Это даже не канал, а коммьюнити, где можно
🔸 Оставить свой код на ревью
🔸 Сделать задание и отправить его на ревью
🔸 Сделать ревью другим ребятам
Для начинающих полезно побыть со всех сторон - и показать свой код, и посмотреть, как пишут код другие. Получить конструктивную обратную связь и дать её другим.
Как всё проходит:
▫️ С понедельника по среду подаются заявки на ревью
▫️ С четверга по воскресенье собирается фидбэк
Всё быстро и просто. Надеюсь, что проект будет развиваться, поэтому поучаствую в ближайшей java ревью-сессии как приглашённый эксперт😊
2️⃣ Для продолжающих - канал Хороший разработчик знает
Канал ведёт Павел - разработчик с 15-летним опытом, сейчас работает в Германии. Пишет посты с уклоном в soft skills, менеджмент и верхнеуровневый инжиниринг:
🔹 Как я стал principal engineer - часть 1, часть 2
🔹 Как выбрать процессор в облаке
🔹 Как рассчитать расходы на инфраструктуру
Чем выше по карьерной лестнице, тем важнее эти темы.
У обоих каналов пока немного подписчиков, но ребята делают очень хорошее дело. Давайте их поддержим!
👍3
Ментор: зачем нужен и как договориться
Работа с ментором - очень удобный способ прокачать свои навыки. Подойдёт для карьерных подвигов любого уровня:
🔸 Войти в айти
🔸 Джуниор → мидл
🔸 Мидл → сеньор
🔸 Сеньор → тимлид/архитектор/проджект/продакт
Если серьёзно нацелены на изучение технологии, фреймворка или новой области, лучше делать это под надзором того, кто уже прошёл этот путь. Кто знает все подводные камни и короткие дорожки.
❓ Что делает ментор?
❌ НЕ берёт ответственность за вас
❌ НЕ читает лекции
❌ НЕ контролирует каждый шаг
✅ Помогает составить план развития
✅ Даёт оценку вашим навыкам со стороны
✅ Подсказывает материалы для изучения
❓ Где найти ментора?
Внутри компании, в общих чатах, на конференциях и митапах. Если разработчик общителен, любит делиться знаниями и находится в вашей точке Б, то он прекрасный кандидат в менторы.
Мне не пишите, пожалуйста, я все силы отдаю ребятам с курса многопоточки😊
❓ Как договориться о сотрудничестве?
Сообщение вроде "привет, хочу стать сеньором" не сработает. Даже если потенциальный ментор - добрый человек и готов поделиться опытом, он не хочет лишних забот. У него есть работа и жизнь помимо работы. Покажите, что вы чётко знаете, чего хотите и готовы работать самостоятельно.
Как может выглядеть сообщение:
Здравствуйте, Диана!
Меня зовут Антон, я студент 4 курса по специальности Инженер-технолог. Последние 2 года увлёкся программированием и понял, что хочу развиваться в этом направлении.
(описываем цель)
Моя цель - к концу года пройти собеседование на Junior Java разработчика в Сбере или в другой крупной компании.
(рассказываем текущую ситуацию)
Я прошёл все курсы, которые вы рекомендовали в этом посте и начал делать пет-проджект. С чем мне нужна помощь:
▫️ Сделать пет-проджект достойным для прикрепления к резюме
▫️ Прохождение собеседований. Отвечаю на вопросы вроде правильно, но ни одного оффера пока не получил
(небольшой комплимент и просьба уделить время)
Давно читаю ваш канал, мне откликается стиль написания постов - всё просто и понятно, многие вещи понимаю гораздо чётче. Хотел бы с вами посоветоваться по поводу своей цели. Думаю, разговор не займёт больше часа.
Как вы на это смотрите?
Если знаете, что человек уже занимается менторингом, можно попросить об этом напрямую.
На встрече обсудите и зафиксируйте комфортный для обоих формат, сроки и расписание. Формат может быть любой:
▫️ Небольшие домашние задания
▫️ Сеанс парного программирования
▫️ Имитация собеседования
▫️ Код-ревью домашнего проекта
Встречи могут быть как 2 раза в неделю, так и раз в месяц.
Если человек отказался - попросите небольшой совет или обратную связь, а затем продолжите поиски.
Работа с ментором - очень удобный способ прокачать свои навыки. Подойдёт для карьерных подвигов любого уровня:
🔸 Войти в айти
🔸 Джуниор → мидл
🔸 Мидл → сеньор
🔸 Сеньор → тимлид/архитектор/проджект/продакт
Если серьёзно нацелены на изучение технологии, фреймворка или новой области, лучше делать это под надзором того, кто уже прошёл этот путь. Кто знает все подводные камни и короткие дорожки.
❓ Что делает ментор?
❌ НЕ берёт ответственность за вас
❌ НЕ читает лекции
❌ НЕ контролирует каждый шаг
✅ Помогает составить план развития
✅ Даёт оценку вашим навыкам со стороны
✅ Подсказывает материалы для изучения
❓ Где найти ментора?
Внутри компании, в общих чатах, на конференциях и митапах. Если разработчик общителен, любит делиться знаниями и находится в вашей точке Б, то он прекрасный кандидат в менторы.
Мне не пишите, пожалуйста, я все силы отдаю ребятам с курса многопоточки😊
❓ Как договориться о сотрудничестве?
Сообщение вроде "привет, хочу стать сеньором" не сработает. Даже если потенциальный ментор - добрый человек и готов поделиться опытом, он не хочет лишних забот. У него есть работа и жизнь помимо работы. Покажите, что вы чётко знаете, чего хотите и готовы работать самостоятельно.
Как может выглядеть сообщение:
Здравствуйте, Диана!
Меня зовут Антон, я студент 4 курса по специальности Инженер-технолог. Последние 2 года увлёкся программированием и понял, что хочу развиваться в этом направлении.
(описываем цель)
Моя цель - к концу года пройти собеседование на Junior Java разработчика в Сбере или в другой крупной компании.
(рассказываем текущую ситуацию)
Я прошёл все курсы, которые вы рекомендовали в этом посте и начал делать пет-проджект. С чем мне нужна помощь:
▫️ Сделать пет-проджект достойным для прикрепления к резюме
▫️ Прохождение собеседований. Отвечаю на вопросы вроде правильно, но ни одного оффера пока не получил
(небольшой комплимент и просьба уделить время)
Давно читаю ваш канал, мне откликается стиль написания постов - всё просто и понятно, многие вещи понимаю гораздо чётче. Хотел бы с вами посоветоваться по поводу своей цели. Думаю, разговор не займёт больше часа.
Как вы на это смотрите?
Если знаете, что человек уже занимается менторингом, можно попросить об этом напрямую.
На встрече обсудите и зафиксируйте комфортный для обоих формат, сроки и расписание. Формат может быть любой:
▫️ Небольшие домашние задания
▫️ Сеанс парного программирования
▫️ Имитация собеседования
▫️ Код-ревью домашнего проекта
Встречи могут быть как 2 раза в неделю, так и раз в месяц.
Если человек отказался - попросите небольшой совет или обратную связь, а затем продолжите поиски.
👍5
JUnit - самая популярная библиотека для юнит-тестов на java. Сейчас в ходу две версии - четвёртая и пятая.
О чём поговорим на этой неделе:
🔸 В первой части опишу основные фичи JUnit 5
🔸 Во второй и третьей расскажу про проблемы JUnit 4, и как они решались в JUnit 5
Я часто пишу, что разобранный в деталях чужой опыт - это почти свой🙂 Таким вот кейсам и посвящена 2 и 3 часть.
О чём поговорим на этой неделе:
🔸 В первой части опишу основные фичи JUnit 5
🔸 Во второй и третьей расскажу про проблемы JUnit 4, и как они решались в JUnit 5
Я часто пишу, что разобранный в деталях чужой опыт - это почти свой🙂 Таким вот кейсам и посвящена 2 и 3 часть.
Какой основной тестовый фреймворк у вас на проекте?
Anonymous Poll
25%
JUnit 4
57%
JUnit 5
6%
TestNG
11%
Что-то другое
👍2
JUnit, часть 1: джентельменский набор
Список фич, которые пригодятся для большинства тестов. Если что-то не видели - почитайте, вдруг пригодится. У JUnit чудесная документация, так что подробно расписывать не буду.
1️⃣ Жизненный цикл теста
Каждый тест - это метод с аннотацией
Через аннотацию
Чтобы выполнить что-то до или после выполнения теста, используются методы с аннотациями
Благодаря этому тесты выполняются независимо.
Этим JUnit отличается от TestNG, где создаётся один экземпляр класса на все тестовые методы. Если хочется как в TestNG, добавьте над классом аннотацию
Сердце каждого теста - методы с приставкой assert*:
3️⃣ Группировка тестов
Аннотация
Можно указывать тэги в системе сборки и при запуске тестов из IDE.
4️⃣ Отключение тестов
Аннотация
▫️ операционной системы
Помогают запустить один тест с разными аргументами. Выглядит так:
Вместо готового списка можно брать значения
🔸 из CSV файла
▫️ Через ассерт
▫️ Hamсrest, AssertJ - расширенные библиотеки методов-ассертов
▫️ Mockito для заглушек. Добавляете библиотеку в pom.xml или build.gradle, а в тест - аннотацию
▫️ Java Faker - генератор данных для тестов
Список фич, которые пригодятся для большинства тестов. Если что-то не видели - почитайте, вдруг пригодится. У JUnit чудесная документация, так что подробно расписывать не буду.
1️⃣ Жизненный цикл теста
Каждый тест - это метод с аннотацией
@Test. Через аннотацию
@DisplayName задаётся симпатичное имя теста в отчёте.Чтобы выполнить что-то до или после выполнения теста, используются методы с аннотациями
▫️ @Before, @BeforeAllJUnit создаёт новый экземпляр класса на каждый тестовый метод. Класс
▫️ @After, @AfterAll
ServiceTest с пятью методами @Test во время запуска превратится в 5 экземпляров класса ServiceTest.Благодаря этому тесты выполняются независимо.
Этим JUnit отличается от TestNG, где создаётся один экземпляр класса на все тестовые методы. Если хочется как в TestNG, добавьте над классом аннотацию
@TestInstance(Lifecycle.PER_CLASS)
2️⃣ ПроверкиСердце каждого теста - методы с приставкой assert*:
🔸 assertTrueВ самом JUnit мало методов, более удобные ассерты есть в библиотеках Hamсrest и AssertJ. AssertJ, на мой взгляд, более читабельный, но Hamсrest используется чаще.
🔸 assertEquals
🔸 assertInstanceOf
3️⃣ Группировка тестов
Аннотация
@Tag("groupName") объединяет тесты в группы. Работает и для одного теста, и для класса.Можно указывать тэги в системе сборки и при запуске тестов из IDE.
4️⃣ Отключение тестов
Аннотация
@Disabled. Продвинутые варианты для: ▫️ операционной системы
@DisabledOnOs(WINDOWS)▫️ версии java
@DisabledOnJre(JAVA_9)▫️ системных переменных:
@DisabledForJreRange(min = JAVA_9)
@DisabledIfSystemProperty(named = "ci-server", matches = "true")5️⃣ Параметризированные тесты
@DisabledIfEnvironmentVariable(named = "ENV", matches = ".*development.*")
Помогают запустить один тест с разными аргументами. Выглядит так:
@ParameterizedTestТакой тест запустится дважды - с аргументом 100 и -14.
@ValueSource(ints={100,-14})
public void test(int input) {}
Вместо готового списка можно брать значения
🔸 из CSV файла
@CsvSource
🔸 из метода @MethodSource
6️⃣ Проверка таймаута▫️ Через ассерт
assertTimeout(ofMinutes(2), ()->{});
▫️ Через аннотацию@Timeout(value=42,unit=SECONDS)7️⃣ Полезные библиотеки
▫️ Hamсrest, AssertJ - расширенные библиотеки методов-ассертов
▫️ Mockito для заглушек. Добавляете библиотеку в pom.xml или build.gradle, а в тест - аннотацию
@ExtendWith(MockitoExtension.class)
▫️ Testcontainers для запуска внешних компонентов в докере. Добавляем библиотеку, аннотацию @Testcontainers над классом и @Container над компонентом▫️ Java Faker - генератор данных для тестов
❤3
JUnit, часть 2: зачем всё менять?
В JUnit сложилась странная ситуация.
JUnit 4 - топовый java фреймворк для тестов, который используется более чем в 100 тысячах проектов.
JUnit 5 вышел спустя 10 лет и обещает много нового. Но нельзя просто взять и перейти на 5 версию:
▪️ Аннотации вообще другие
▪️ Зависимостей стало больше
▪️ Для совместимости с JUnit 4 надо подключать какой-то винтаж.
Обратная совместимость - обычное дело для java приложений. В новой версии всё работает как раньше. Постепенно добавляешь новые фичи.
Почему JUnit не пошёл по этому пути?
Чтобы ответить на вопрос, нужно копнуть в архитектуру и кейсы использования.
JUnit создавался как удобная библиотека для написания тестов. Для разработчика есть API - аннотации
Дальше эти тесты запускает IDE или система сборки.
И вот им приходится тяжело. В JUnit 4 API для запуска и анализа тестов очень ограниченный, поэтому IDE и сборщики используют рефлекшн и другие обходные пути.
Чем плох такой подход - понятно. Любое изменение внутренней реализации ломает логику внутри IDE/системы сборки.
JUnit 5 учёл эту проблему и содержит три отдельных артефакта:
🔸 Jupiter - апи для разработчиков
🔸 Platform - апи для запуска и анализа тестов. Целевая аудитория - IDE, плагины и системы сборки. Теперь каждый из них может использовать библиотеку, а не писать свой велосипед
🔸 Vintage - для запуска JUnit 4 тестов на новой платформе
Почему у JUnit 4 и 5 разные аннотации?
У JUnit 5 абсолютно другая кодовая база. Для совместимости с 4 версией пришлось бы наворотить много кода. Гораздо практичнее вынести все адаптеры в отдельный компонент.
Тогда
▫️ Старые тесты будут работать
▫️ Чётко видно, где старые тесты, а где новые. А значит есть шанс, что со временем кодовая база с тестами перейдёт на новую версию.
Что здесь особенного?
В целом выглядит как обычный рефакторинг. Продукт развивается, мир меняется, монолит делится на составные части.
Но в этой истории есть две важные детали.
1️⃣ На страничке принципов разработки команды JUnit есть такие строки:
▫️ JUnit has never tried to be a swiss army knife
▫️ Third party developers move more quickly than we do
Отсюда видна ещё одна мотивация: поощрение развития других библиотек и фреймворков.
Другие разработчики тестовых библиотек теперь могут использовать JUnit платформу и автоматически получать поддержку библиотек во всех IDE и системах сборки.
2️⃣ Вторая инициатива команды JUnit - проект Open Test Alliance for the JVM.
В чём суть: есть много тестовых фреймворков и библиотек. Все они работают по-разному - бросают разные исключения, отличается формат и набор данных и тд. IDE и системам сборки приходится учитывать все особенности.
Идея проекта - создать общую спецификацию для тестовых библиотек. Проект поддержали TestNG, Spock, Hamcrest, AssertJ, Eclipse, IntelliJ, Gradle, Maven и Allure.
Неизвестно, закончится ли эта история удачно, но идея классная.
Здорово, когда компания делает не только хороший продукт, но и способствует развитию отрасли в целом😇
В JUnit сложилась странная ситуация.
JUnit 4 - топовый java фреймворк для тестов, который используется более чем в 100 тысячах проектов.
JUnit 5 вышел спустя 10 лет и обещает много нового. Но нельзя просто взять и перейти на 5 версию:
▪️ Аннотации вообще другие
▪️ Зависимостей стало больше
▪️ Для совместимости с JUnit 4 надо подключать какой-то винтаж.
Обратная совместимость - обычное дело для java приложений. В новой версии всё работает как раньше. Постепенно добавляешь новые фичи.
Почему JUnit не пошёл по этому пути?
Чтобы ответить на вопрос, нужно копнуть в архитектуру и кейсы использования.
JUnit создавался как удобная библиотека для написания тестов. Для разработчика есть API - аннотации
@Test, @Before, методы assertEquals и тд. Здесь всё классно.Дальше эти тесты запускает IDE или система сборки.
И вот им приходится тяжело. В JUnit 4 API для запуска и анализа тестов очень ограниченный, поэтому IDE и сборщики используют рефлекшн и другие обходные пути.
Чем плох такой подход - понятно. Любое изменение внутренней реализации ломает логику внутри IDE/системы сборки.
JUnit 5 учёл эту проблему и содержит три отдельных артефакта:
🔸 Jupiter - апи для разработчиков
🔸 Platform - апи для запуска и анализа тестов. Целевая аудитория - IDE, плагины и системы сборки. Теперь каждый из них может использовать библиотеку, а не писать свой велосипед
🔸 Vintage - для запуска JUnit 4 тестов на новой платформе
Почему у JUnit 4 и 5 разные аннотации?
У JUnit 5 абсолютно другая кодовая база. Для совместимости с 4 версией пришлось бы наворотить много кода. Гораздо практичнее вынести все адаптеры в отдельный компонент.
Тогда
▫️ Старые тесты будут работать
▫️ Чётко видно, где старые тесты, а где новые. А значит есть шанс, что со временем кодовая база с тестами перейдёт на новую версию.
Что здесь особенного?
В целом выглядит как обычный рефакторинг. Продукт развивается, мир меняется, монолит делится на составные части.
Но в этой истории есть две важные детали.
1️⃣ На страничке принципов разработки команды JUnit есть такие строки:
▫️ JUnit has never tried to be a swiss army knife
▫️ Third party developers move more quickly than we do
Отсюда видна ещё одна мотивация: поощрение развития других библиотек и фреймворков.
Другие разработчики тестовых библиотек теперь могут использовать JUnit платформу и автоматически получать поддержку библиотек во всех IDE и системах сборки.
2️⃣ Вторая инициатива команды JUnit - проект Open Test Alliance for the JVM.
В чём суть: есть много тестовых фреймворков и библиотек. Все они работают по-разному - бросают разные исключения, отличается формат и набор данных и тд. IDE и системам сборки приходится учитывать все особенности.
Идея проекта - создать общую спецификацию для тестовых библиотек. Проект поддержали TestNG, Spock, Hamcrest, AssertJ, Eclipse, IntelliJ, Gradle, Maven и Allure.
Неизвестно, закончится ли эта история удачно, но идея классная.
Здорово, когда компания делает не только хороший продукт, но и способствует развитию отрасли в целом😇
👍2
Как вы думаете, во сколько обошлась переделка архитектуры JUnit и написание практически новой кодовой базы?
Anonymous Poll
12%
2 тысячи евро
13%
25 тысяч евро
29%
100 тысяч евро
32%
5 миллионов евро
14%
20 миллионов евро
JUnit, часть 3: модели кастомизации
Изменение архитектуры - не всё, чем JUnit 5 отличается от предыдущей версии. Второе отличие касается модели кастомизации.
В этом посте поговорим, зачем это нужно в тестовом фреймворке, и про разницу между 4 и 5 версией.
Чтобы было понятнее, давайте опишем простую задачу и будем её понемногу усложнять.
Допустим, нужно измерить время выполнения каждого теста: запустить таймер вначале и вывести время выполнения в конце.
Для одного класса это несложно - просто добавляем методы с аннотациями
А как посчитать время для всех классов? Здесь варианта два:
🔸 Вынести общий код в отдельный класс, в каждый класс-тест добавить методы Before и After. Решение рабочее, но придётся копипастить методы в каждый класс.
🔸 Внедрить логику где-то на верхнем уровне и включать/выключать её через настройки или аннотации.
Это и есть кастомизация - предусмотренные библиотекой места "встраивания" новой логики. JUnit 4 и 5 используют для этого разные механизмы. Давайте кратко их обсудим.
JUnit 4 Runner
Переопределяем жизненный цикл теста целиком. Наследуемся от интерфейса
Примеры:
▫️
▫️
▫️
▫️
Главный минус - жизненный цикл только один, значит
JUnit 4 Rule
Переопределяем интерфейс
▪️
▪️
Плюсы-минусы:
✅ Можно использовать несколько rule в одном классе
❌ Работает в рамках одного метода и по сути похож на before/after.
JUnit 5 Extension
Жизненный цикл теста разбивается на 10+ фаз. К каждой из них можно присоединиться, если переопределить нужный интерфейс:
Реализуем нужные интерфейсы, регистрируем класс и готово. Похожий механизм используется в Spring.
✅ Класс может использовать несколько экстеншенов
✅ Можно вклиниться на любых этапах жизненного цикла
✅ В интерфейсах доступен контекст выполнения и вся информация про тесты, в итоге возможностей гораздо больше
В JUnit 5 полностью убрали поддержку
______
Разбирать чужие кейсы полезно, но не всегда увлекательно. Поэтому вот интересный факт про разработку JUnit.
JUnit - опенсорсный проект, где никто никому не платил за работу.
Но рефакторинг назревал много лет. Однажды ребята решили, что такие грандиозные планы требуют фулл тайм и объявили краудфандинг на JUnit 5.
Сумма требовалась небольшая - 25 тысяч евро, меньше двух миллионов рублей. В итоге собрали в 2 раза больше, и уже через 6 недель был готов первый прототип.
Меня это очень впечатляет, особенно в сравнении со стоимостью и скоростью разработки в энтерпрайзе🙈
Изменение архитектуры - не всё, чем JUnit 5 отличается от предыдущей версии. Второе отличие касается модели кастомизации.
В этом посте поговорим, зачем это нужно в тестовом фреймворке, и про разницу между 4 и 5 версией.
Чтобы было понятнее, давайте опишем простую задачу и будем её понемногу усложнять.
Допустим, нужно измерить время выполнения каждого теста: запустить таймер вначале и вывести время выполнения в конце.
Для одного класса это несложно - просто добавляем методы с аннотациями
@Before и @After.А как посчитать время для всех классов? Здесь варианта два:
🔸 Вынести общий код в отдельный класс, в каждый класс-тест добавить методы Before и After. Решение рабочее, но придётся копипастить методы в каждый класс.
🔸 Внедрить логику где-то на верхнем уровне и включать/выключать её через настройки или аннотации.
Это и есть кастомизация - предусмотренные библиотекой места "встраивания" новой логики. JUnit 4 и 5 используют для этого разные механизмы. Давайте кратко их обсудим.
JUnit 4 Runner
Переопределяем жизненный цикл теста целиком. Наследуемся от интерфейса
Runner или абстрактного класса, в нужных местах добавляем нужные действия. Теперь тесты запускаются не по стандартной схеме, а по той, что прописана в новом классе.Примеры:
▫️
@RunWith(Parameterized.class) запускает параметризованные тесты▫️
@RunWith(Suite.class) запускает наборы тестов▫️
@RunWith(SpringJUnit4ClassRunner.class) добавляет спринговые активности до и после запуска теста▫️
@RunWith(MockitoJUnitRunner.class) позволяет использовать заглушкиГлавный минус - жизненный цикл только один, значит
Runner для теста может быть только один. Не получится совместить несколько фич, например, параметризованные тесты с заглушками.JUnit 4 Rule
Переопределяем интерфейс
TestRule и задаём действие до и после выполнения теста. В тестах выглядит как просто поле:@RuleВ JUnit 4 есть несколько готовых правил:
public Timeout globalTimeout = Timeout.seconds(10);
▪️
TemporaryFolder - создать временную папку для теста▪️
ExternalResource - открыть и закрыть внешний ресурс(файл, сокет, БД)Плюсы-минусы:
✅ Можно использовать несколько rule в одном классе
❌ Работает в рамках одного метода и по сути похож на before/after.
JUnit 5 Extension
Жизненный цикл теста разбивается на 10+ фаз. К каждой из них можно присоединиться, если переопределить нужный интерфейс:
▫️BeforeAllCallback - действие перед всеми тестами▫️ParameterResolver - передача параметров в тестРеализуем нужные интерфейсы, регистрируем класс и готово. Похожий механизм используется в Spring.
✅ Класс может использовать несколько экстеншенов
✅ Можно вклиниться на любых этапах жизненного цикла
✅ В интерфейсах доступен контекст выполнения и вся информация про тесты, в итоге возможностей гораздо больше
В JUnit 5 полностью убрали поддержку
Runner и Rule, всё переписано на Extension API. Кодовые базы стали несовместимы между собой, поэтому и нужна библиотека Vintage с адаптерами.______
Разбирать чужие кейсы полезно, но не всегда увлекательно. Поэтому вот интересный факт про разработку JUnit.
JUnit - опенсорсный проект, где никто никому не платил за работу.
Но рефакторинг назревал много лет. Однажды ребята решили, что такие грандиозные планы требуют фулл тайм и объявили краудфандинг на JUnit 5.
Сумма требовалась небольшая - 25 тысяч евро, меньше двух миллионов рублей. В итоге собрали в 2 раза больше, и уже через 6 недель был готов первый прототип.
Меня это очень впечатляет, особенно в сравнении со стоимостью и скоростью разработки в энтерпрайзе🙈
Статистика по микросервисам
К концу года появляется много отчётов и статистики о состоянии JVM экосистемы. В целом ситуация не сильно отличается от прошлого года:
🔸 Самая популярная версия java до сих пор 8, используется на 69% проектов. Java 11 встречается на 36% проектов, а 12 и выше - на 16%.
🔸 Самый популярный фреймворк - Spring Boot: 65% проектов. На втором месте Spring MVC: 40% проектов.
🔸 Самая популярная IDE - Intellij IDEA, система сборки - Maven.
🔸 Трендовые GraalVM, Quarkus и Micronaut нашли применение где-то на 4% проектов, цифра примерно как в прошлом году.
Поэтому в этом посте поделюсь статистикой не по джаве, а по всему, что связано с микросервисами. Данные взяла из JRebel Java Developer Productivity Report 2021 и JetBrains The State of Developer Ecosystem 2021.
Демография: Россия - 3% участников, в основном ответы из США, Китая и Европы.
Итак,
49% проектов используют микросервисы
42% сидят с монолитом
10% применяют serverless архитектуру
На чём пишут микросервисы:
41% Java
37% JavaScript
25% Python
Сколько микросервисов на проекте:
34% Меньше пяти
36% 5-10
14% 10-20
16% 20 и больше
Как микросервисы общаются между собой?
83% HTTP-вызовы
47% Месседж брокер
25% WebSocket
20% RPC
С чем возникает много проблем:
30% Общение между сервисами
26% Масштабирование и производительность
24% Развернуть что-нибудь локально 🥲
14% Проблемы в коде микросервисов
Популярные performance проблемы:
54% Долгий Response Time
39% High CPU Usage
35% Утечки памяти
26% Много открытых соединений
Сколько времени занимает поднятие окружения на удалённой машине:
42% Меньше трёх минут
38% 3-10 минут
21% Дольше 10 минут
Только 20% разработчиков во время деплоя переключаются на другие рабочие задачи. Остальные 80% ходят за чаем, общаются с семьёй и листают соцсети🙂
К концу года появляется много отчётов и статистики о состоянии JVM экосистемы. В целом ситуация не сильно отличается от прошлого года:
🔸 Самая популярная версия java до сих пор 8, используется на 69% проектов. Java 11 встречается на 36% проектов, а 12 и выше - на 16%.
🔸 Самый популярный фреймворк - Spring Boot: 65% проектов. На втором месте Spring MVC: 40% проектов.
🔸 Самая популярная IDE - Intellij IDEA, система сборки - Maven.
🔸 Трендовые GraalVM, Quarkus и Micronaut нашли применение где-то на 4% проектов, цифра примерно как в прошлом году.
Поэтому в этом посте поделюсь статистикой не по джаве, а по всему, что связано с микросервисами. Данные взяла из JRebel Java Developer Productivity Report 2021 и JetBrains The State of Developer Ecosystem 2021.
Демография: Россия - 3% участников, в основном ответы из США, Китая и Европы.
Итак,
49% проектов используют микросервисы
42% сидят с монолитом
10% применяют serverless архитектуру
На чём пишут микросервисы:
41% Java
37% JavaScript
25% Python
Сколько микросервисов на проекте:
34% Меньше пяти
36% 5-10
14% 10-20
16% 20 и больше
Как микросервисы общаются между собой?
83% HTTP-вызовы
47% Месседж брокер
25% WebSocket
20% RPC
С чем возникает много проблем:
30% Общение между сервисами
26% Масштабирование и производительность
24% Развернуть что-нибудь локально 🥲
14% Проблемы в коде микросервисов
Популярные performance проблемы:
54% Долгий Response Time
39% High CPU Usage
35% Утечки памяти
26% Много открытых соединений
Сколько времени занимает поднятие окружения на удалённой машине:
42% Меньше трёх минут
38% 3-10 минут
21% Дольше 10 минут
Только 20% разработчиков во время деплоя переключаются на другие рабочие задачи. Остальные 80% ходят за чаем, общаются с семьёй и листают соцсети🙂
👍4
Intellij IDEA: редактирование кода
Несколько простых приёмов для быстрой работы.
Легендарные комбинации
Удалить всю строку:
Переместить выделенный код:
Несколько простых приёмов для быстрой работы.
Легендарные комбинации
Ctrl + Cработают со всей строкой, на которой стоит курсор, не нужно ничего выделять.
Ctrl + V
Ctrl + X
Удалить всю строку:
Ctrl + YДублировать строку:
Ctrl + DВыделить часть кода:
Ctrl + WПри каждом нажатии W захватывается всё большая область.
Переместить выделенный код:
Ctrl + Shift + ⬆️
Ctrl + Shift + ⬇️👍8
L is for Liskov
— SOLID принципы знаете?
Думаю, нет разработчика, который не слышал на собеседовании такой вопрос.
Расшифровку знают многие. А вот практические знания часто ограничиваются Single Responsibility и Interface Segregation.
Как применять остальные буквы в ежедневной работе — не всегда понятно. Больше всего вопросов возникает насчёт L — Liskov Substitution Principle. О нём и будет сегодняшний пост.
Полное определение звучит так:
Пусть q(x) является свойством верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T.
По-простому: если заменить класс А на подкласс B, то система будет работать корректно и без неожиданных сайд-эффектов.
Как это выглядит на практике:
1️⃣ Выходной тип метода в наследнике такой же как у родителя или расширенный
Базовый класс:
Базовый класс:
3️⃣ Типы входных параметров те же или менее строгие. Пункт для общего понимания, тк для Java это неприменимо
Базовый класс:
4️⃣ Метод подкласса делает то же, что и метод базового класса
Базовый класс: метод
Наследник:
✅ Считает пользователей чуть по-другому
❌ Считает пользователей, обновляет статистику, сохраняет результат в БД
5️⃣ Метод наследника взаимодействует с теми же сущностями:
▪️ Метод родителя увеличивает счётчик - подкласс тоже увеличивает
▪️ Метод родителя не меняет поле - подкласс тоже не меняет
▪️ Метод родителя вызывает другие методы в определённом порядке - подкласс делает то же самое
А что можно вообще?
Если в подклассе объявлены новые поля, то методы подкласса могут делать с ними что угодно. На этом всё🙂
Правила выше - очень строгие. Но и наследование — штука непростая, это самая сильная связь между сущностями. Часто единственный плюс — это краткость кода, но по ходу развития проекта ограничения доставляют всё больше проблем.
Нарушения принципа подстановки — повод пересмотреть иерархию наследования или совсем от неё отказаться.
— SOLID принципы знаете?
Думаю, нет разработчика, который не слышал на собеседовании такой вопрос.
Расшифровку знают многие. А вот практические знания часто ограничиваются Single Responsibility и Interface Segregation.
Как применять остальные буквы в ежедневной работе — не всегда понятно. Больше всего вопросов возникает насчёт L — Liskov Substitution Principle. О нём и будет сегодняшний пост.
Полное определение звучит так:
Пусть q(x) является свойством верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T.
По-простому: если заменить класс А на подкласс B, то система будет работать корректно и без неожиданных сайд-эффектов.
A service1 = new A();Для наблюдателя service1 и service2 ведут себя совершенно одинаково. Класс-наследник дополняет поведение родителя, а не замещает его. В результате система работает более предсказуемо.
A service2 = new B();
Как это выглядит на практике:
1️⃣ Выходной тип метода в наследнике такой же как у родителя или расширенный
Базовый класс:
Info getInfo()
Наследник:✅ BigInfo getInfo()2️⃣ Подклассы не бросают дополнительных исключений, но могут уменьшить их список
❌ Object getInfo()
Базовый класс:
void save() throws FileNotFoundException
Наследник:✅ void save()Java — типизированный язык, поэтому пункты 1 и 2 контролируются компилятором.
❌ void save() throws FileNotFoundEx, InterruptedEx
3️⃣ Типы входных параметров те же или менее строгие. Пункт для общего понимания, тк для Java это неприменимо
Базовый класс:
void add(Account acc)
Наследник:✅ void add(Object acc)Следующие пункты компилятор уже не проверит, это целиком ответственность программиста.
❌ void add(AdminAccount acc)
4️⃣ Метод подкласса делает то же, что и метод базового класса
Базовый класс: метод
countVisitors считает пользователейНаследник:
✅ Считает пользователей чуть по-другому
❌ Считает пользователей, обновляет статистику, сохраняет результат в БД
5️⃣ Метод наследника взаимодействует с теми же сущностями:
▪️ Метод родителя увеличивает счётчик - подкласс тоже увеличивает
▪️ Метод родителя не меняет поле - подкласс тоже не меняет
▪️ Метод родителя вызывает другие методы в определённом порядке - подкласс делает то же самое
А что можно вообще?
Если в подклассе объявлены новые поля, то методы подкласса могут делать с ними что угодно. На этом всё🙂
Правила выше - очень строгие. Но и наследование — штука непростая, это самая сильная связь между сущностями. Часто единственный плюс — это краткость кода, но по ходу развития проекта ограничения доставляют всё больше проблем.
Нарушения принципа подстановки — повод пересмотреть иерархию наследования или совсем от неё отказаться.
👍7❤3