📚Чтение исходного кода
Часто вижу в комментариях, что довольно сложно понимать исходный код Java Core, фреймворков или инструментов вроде Maven и Gradle, когда я показываю его в своих видео.
Так и должно быть! И как минимум потому, что вы впервые видите чужой код и нужно больше времени, чтобы проанализировать новую информацию.
А демонстрирую я исходный код по несколько другим более важным причинам:
1️⃣ Как нужно подходить к изучению любого фреймворка или инструмента, с которым ты сталкиваешься впервые, чтобы понимать, что происходит
2️⃣ Как решать проблемы или задачи, которые отходят от базовых понятий или стандартных/шаблонных решений
3️⃣ Улучшаются code review навыки и чтение кода в принципе
4️⃣ Ты видишь интересные решения и архитектурные подходы, которые в последующем можешь переиспользовать у себя или даже комбинировать! Ибо эти решения действительно проверены на практике
Часто вижу в комментариях, что довольно сложно понимать исходный код Java Core, фреймворков или инструментов вроде Maven и Gradle, когда я показываю его в своих видео.
Так и должно быть! И как минимум потому, что вы впервые видите чужой код и нужно больше времени, чтобы проанализировать новую информацию.
А демонстрирую я исходный код по несколько другим более важным причинам:
1️⃣ Как нужно подходить к изучению любого фреймворка или инструмента, с которым ты сталкиваешься впервые, чтобы понимать, что происходит
2️⃣ Как решать проблемы или задачи, которые отходят от базовых понятий или стандартных/шаблонных решений
3️⃣ Улучшаются code review навыки и чтение кода в принципе
4️⃣ Ты видишь интересные решения и архитектурные подходы, которые в последующем можешь переиспользовать у себя или даже комбинировать! Ибо эти решения действительно проверены на практике
👍70🔥6🙏2❤1
Презентация финального веб-проекта по окончании 2-ой ступени менторства DMdev
С такими навыками каждого будут рады видеть в достойной компании на позиции сильного Junior Java Developer.
💻 В проекте использовались:
- Apache Maven для автоматизированной сборки
- JUnit 5 для покрытия кода unit и integration тестами
- Hibernate как основной ORM framework
- Liquibase для миграции SQL скриптов
- Spring Boot с Embedded Tomcat
- Множество различных Spring Starters (data-jpa, web, security, validation, thymeleaf, test, etc)
Более детальное описание можно найти в техническом задании
Смотри видео, задавай вопросы по проекту в комментариях.
А для тех, кто хочет стать участником менторства 2 ступени
👉 ссылка для записи с подробной информацией.
- старт 30 января - осталось1 место 0 мест (ко мне)
- старт 6 февраля - осталось4 2 места (к ментору Илье)
P.S. Дай знать, если видео было интересным.
Тогда я опубликую полную версию защиты всех проектов со второй ступени менторства последнего потока.
С такими навыками каждого будут рады видеть в достойной компании на позиции сильного Junior Java Developer.
💻 В проекте использовались:
- Apache Maven для автоматизированной сборки
- JUnit 5 для покрытия кода unit и integration тестами
- Hibernate как основной ORM framework
- Liquibase для миграции SQL скриптов
- Spring Boot с Embedded Tomcat
- Множество различных Spring Starters (data-jpa, web, security, validation, thymeleaf, test, etc)
Более детальное описание можно найти в техническом задании
Смотри видео, задавай вопросы по проекту в комментариях.
А для тех, кто хочет стать участником менторства 2 ступени
👉 ссылка для записи с подробной информацией.
- старт 30 января - осталось
- старт 6 февраля - осталось
P.S. Дай знать, если видео было интересным.
Тогда я опубликую полную версию защиты всех проектов со второй ступени менторства последнего потока.
🔥33👍14❤1👎1🤔1
This media is not supported in your browser
VIEW IN TELEGRAM
🔐 Lead Level on YouTube
Со стороны пользователя - мне бы было удобно, чтобы все курсы были на одной единственной платформе.
Со стороны автора и в целом бизнеса - это также было бы удобно, желательно на своей собственной платформе 😁
Eсли бы не тысячи НО… которые усложняют такую реализацию. А после начала военных событий и вовсе почти “поставили на коленки”.
Именно поэтому мне и пришлось предоставлять доступ для граждан РФ на еще одной площадке GetCourse, а теперь и поддерживать ее.
Но как показывает практика, хоть официально на YouTube и Udemy жителям РФ запрещено совершать покупки - вы все-равно как-то это делаете 😅
💥 Поэтому сейчас будет, наверное, долгожданная новость и изменения в доступах к курсам DMdev на YouTube.
Добавился новый четвертый уровень спонсорства Lead, по которому открыт доступ ко всем курсам DMdev.
За 14,99$/месяц открывается доступ к Java Core, SQL, JDBC, HTTP.Servlets, Maven, JUnit 5, Groovy, Gradle, Hibernate, Spring, Bash и…к последующим курсам!
Приятного просмотра 🍿
Со стороны пользователя - мне бы было удобно, чтобы все курсы были на одной единственной платформе.
Со стороны автора и в целом бизнеса - это также было бы удобно, желательно на своей собственной платформе 😁
Eсли бы не тысячи НО… которые усложняют такую реализацию. А после начала военных событий и вовсе почти “поставили на коленки”.
Именно поэтому мне и пришлось предоставлять доступ для граждан РФ на еще одной площадке GetCourse, а теперь и поддерживать ее.
Но как показывает практика, хоть официально на YouTube и Udemy жителям РФ запрещено совершать покупки - вы все-равно как-то это делаете 😅
💥 Поэтому сейчас будет, наверное, долгожданная новость и изменения в доступах к курсам DMdev на YouTube.
Добавился новый четвертый уровень спонсорства Lead, по которому открыт доступ ко всем курсам DMdev.
За 14,99$/месяц открывается доступ к Java Core, SQL, JDBC, HTTP.Servlets, Maven, JUnit 5, Groovy, Gradle, Hibernate, Spring, Bash и…к последующим курсам!
Приятного просмотра 🍿
👍39❤🔥14🔥10😁2
This media is not supported in your browser
VIEW IN TELEGRAM
Я получаю сотни комментариев в виде обратной связи от вас по моим курсам, и понял одну вещь: один курс отличается от всех остальных.
И это JUnit 5.
В нем нет большого практического занятия, где я как обычно объединяю и закрепляю предыдущий пройденный материал.
Дабы предотвратить и избежать ситуаций с видео, я подготовил большой практический урок.
Ведь это оказалось действительно существенным в понимании материала.
И это JUnit 5.
В нем нет большого практического занятия, где я как обычно объединяю и закрепляю предыдущий пройденный материал.
Дабы предотвратить и избежать ситуаций с видео, я подготовил большой практический урок.
Ведь это оказалось действительно существенным в понимании материала.
🔥40👍8🏆5🙏1
Практика JUnit 5
📊 Немного статистики:
- продолжительность видео 1:03:39
- затрачено времени на создание ~8 часов
- доступно на всех платформах
+ новая домашка для самостоятельного закрепления
👀 Смотреть на YouTube в свободном доступе
📊 Немного статистики:
- продолжительность видео 1:03:39
- затрачено времени на создание ~8 часов
- доступно на всех платформах
+ новая домашка для самостоятельного закрепления
👀 Смотреть на YouTube в свободном доступе
🔥83👍29🎉7❤🔥1🏆1
Scheduled Job
Как-то раз мне нужно было реализовать периодический процесс, который запускался бы раз в 5-10 минут и выполнял определенную работу:
- анализ/изменения данных в базе
- отправка сообщений в Kafka
- отправка пуш уведомлений затронутым пользователям
- многое другое
Без изменений текущий архитектуры приложения, такой процесс мог бы быть всего один в один момент времени, иначе велика вероятность повредить данные или отправить одних и тех же сообщений пользователю несколько раз.
Первое, что приходит на ум - это конечно Scheduled Job в одном потоке. Но in-memory вариант не подходил, потому что было несколько instances приложения. А значит на каждом запустилась бы такая Job.
Поэтому нужно прибегать к централизации запуска через базу данных. Здесь напрашивается опять же готовое решение Quartz scheduler. Но хотелось чего-то более легковесного и менее затратного в конфигурации, избегая кучи новых таблиц в базе данных только для поддержки Quartz.
И тут на помощь пришли Named Locks в MySQL (в PostgreSQL они называются Advisory Locks).
С их помощью в своей Scheduled Job просто необходимо выполнить предварительно SQL запрос вида:
Главное в конце не забыть отпустить Lock:
P.P.S. На картинке представлен пример использования такого подхода на чистом Java Core
Как-то раз мне нужно было реализовать периодический процесс, который запускался бы раз в 5-10 минут и выполнял определенную работу:
- анализ/изменения данных в базе
- отправка сообщений в Kafka
- отправка пуш уведомлений затронутым пользователям
- многое другое
Без изменений текущий архитектуры приложения, такой процесс мог бы быть всего один в один момент времени, иначе велика вероятность повредить данные или отправить одних и тех же сообщений пользователю несколько раз.
Первое, что приходит на ум - это конечно Scheduled Job в одном потоке. Но in-memory вариант не подходил, потому что было несколько instances приложения. А значит на каждом запустилась бы такая Job.
Поэтому нужно прибегать к централизации запуска через базу данных. Здесь напрашивается опять же готовое решение Quartz scheduler. Но хотелось чего-то более легковесного и менее затратного в конфигурации, избегая кучи новых таблиц в базе данных только для поддержки Quartz.
И тут на помощь пришли Named Locks в MySQL (в PostgreSQL они называются Advisory Locks).
С их помощью в своей Scheduled Job просто необходимо выполнить предварительно SQL запрос вида:
SELECT GET_LOCK(‘anyUniqueNameOfLock’, 5);Если запрос вернул 1, значит Lock получен и можно выполнять работу, иначе - другой instance твоего сервиса уже ее выполняет и можно ничего не делать.
Главное в конце не забыть отпустить Lock:
SELECT RELEASE_LOCK(‘anyUniqueNameOfLock’);P.S. В Advisory Lock можно и этого не делать - после окончания транзакции lock будет автоматически снят, что действительно облегчает работу и не нужно обрабатывать дополнительно исключения в случае проблем с RELEASE_LOCK.
P.P.S. На картинке представлен пример использования такого подхода на чистом Java Core
👍63🔥19❤3
Февраль месяц хоть и маленький, но тянулся для меня очень долго. А все потому, что он был насыщен большим количеством событий, происходящих в моей жизни: подготовка к отцовству, покупка квартиры в Варшаве, Google layoffs, планирование отпуска и переезда, тренировки к соревнованиям по бегу на 5 км и т.д.
Тем не менее, все это время я продолжал тщательную подготовку следующего курса. Я старался меньше отвлекаться на социальные сети, которые забирают не только кучу времени, сколько очень много твоего внимания - а все это дорогой и ограниченный человеческий ресурс.
Я прочел 2 книги, штудировал официальную документацию и исследовал свои предыдущие проекты в поисках практического применения и полезности тех или иных фич изучаемого инструмента.
Могу сказать, что почему-то до сих пор ни один источник не может предоставить полной картины происходящего. Уже в который раз убеждаюсь, что невозможно систематизировать знания и передать их в полном объеме используя лишь один источник информации: книги, видео, исходный код или даже примеры в реальных проектах.
И все же, на этой неделе я планирую выпустить первое видео на своем YouTube канале. Это будет новый курс, в котором я как обычно попытаюсь изложить материал, опираясь лишь на основы, которые у вас уже есть после просмотра предыдущих курсов DMdev.
Так что следи за новостями!
Тем не менее, все это время я продолжал тщательную подготовку следующего курса. Я старался меньше отвлекаться на социальные сети, которые забирают не только кучу времени, сколько очень много твоего внимания - а все это дорогой и ограниченный человеческий ресурс.
Я прочел 2 книги, штудировал официальную документацию и исследовал свои предыдущие проекты в поисках практического применения и полезности тех или иных фич изучаемого инструмента.
Могу сказать, что почему-то до сих пор ни один источник не может предоставить полной картины происходящего. Уже в который раз убеждаюсь, что невозможно систематизировать знания и передать их в полном объеме используя лишь один источник информации: книги, видео, исходный код или даже примеры в реальных проектах.
И все же, на этой неделе я планирую выпустить первое видео на своем YouTube канале. Это будет новый курс, в котором я как обычно попытаюсь изложить материал, опираясь лишь на основы, которые у вас уже есть после просмотра предыдущих курсов DMdev.
Так что следи за новостями!
👍100🔥41❤🔥7🎉3❤2🏆1
Релиз нового курса - первое видео уже на YouTube!
PS. Будет доступен по подписке Lead и со временем на других платформах (Udemy, GetCourse).
PS. Будет доступен по подписке Lead и со временем на других платформах (Udemy, GetCourse).
🔥108👍14🤩3💋3🏆2❤🔥1❤1🎉1
С ужасом заметил, что последний пост я написал тут больше месяца назад.
Как так вышло?
На самом деле все просто:
Был фокус и четкий план на телеграм = были посты
Нет фокуса = нет постов
Хочу вдохнуть новую жизнь сюда, ибо формат телеграма мне очень нравится!
Для этого нужна ваша помощь🙏
Буду очень благодарен, если накидаете в комменты, какие посты/рубрики/активности и в каком формате хотелось бы тут наблюдать.
Это может быть что-то разовое или на постоянной основе, что-то вроде традиции
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥54👍8🫡4❤🔥1👨💻1
Часто мне задают вопросы такого плана - когда не понятно как реализовать или упростить уже существующий функционал.
Как раз реальная задача, которая требует действительно гибкого решения, ибо время показало, что этот
Как можно было бы изменить код, чтобы автоматически при добавлении нового обработчика для определенного типа - не требовалось менять основную логику с добавлением еще одного if-else?
Можно словами в комментариях, можно прям скринами с кодом.
Если наберем несколько интересных вариантов, то я напишу свои мысли по этому поводу 😎
#dmdev_qa
Как раз реальная задача, которая требует действительно гибкого решения, ибо время показало, что этот
код меняется часто, а значит требует рефакторинга
. Как можно было бы изменить код, чтобы автоматически при добавлении нового обработчика для определенного типа - не требовалось менять основную логику с добавлением еще одного if-else?
Можно словами в комментариях, можно прям скринами с кодом.
Если наберем несколько интересных вариантов, то я напишу свои мысли по этому поводу 😎
#dmdev_qa
👍25❤🔥4🔥3
Общими усилиями в комментариях мы пришли к гибкому решению!
Его я отобразил на картинке.
Единственное что я изменил - это тип процесса, сделав его Class<T> вместо enum для демонстрации альтернативного подхода.
- не нужно заводить перечисления (enum) и делать соответствия между ним и процессом
- не нужно передавать в ProcessService дополнительно этот enum, когда мы хотим получить обработчик процесса (или добавлять доп поле в каждый процесс)
- во время выполнения мы не получим ошибки, что получили из Map не тот обработчик (класс процесса сам же является и ключом)
Минусы:
- без enum не виден весь список возможных процессов
- не напишешь хороший тест, что на каждый процесс есть свой обработчик
- пришлось в ProcessService сделать явное приведение типов, потому что метод getClass в классе Object возвращает Class<?>
Что бы ты выбрал все-таки: enum vs Class<T>?
#dmdev_qa
Его я отобразил на картинке.
Единственное что я изменил - это тип процесса, сделав его Class<T> вместо enum для демонстрации альтернативного подхода.
В этом есть свои плюсы и минусы, как и в любом решении.
Плюсы:- не нужно заводить перечисления (enum) и делать соответствия между ним и процессом
- не нужно передавать в ProcessService дополнительно этот enum, когда мы хотим получить обработчик процесса (или добавлять доп поле в каждый процесс)
- во время выполнения мы не получим ошибки, что получили из Map не тот обработчик (класс процесса сам же является и ключом)
Минусы:
- без enum не виден весь список возможных процессов
- не напишешь хороший тест, что на каждый процесс есть свой обработчик
- пришлось в ProcessService сделать явное приведение типов, потому что метод getClass в классе Object возвращает Class<?>
Что бы ты выбрал все-таки: enum vs Class<T>?
#dmdev_qa
🔥16👍9❤1🤔1
Backwards compatibility
При создании любого открытого API, будь то HTTP, gRPC endpoint, public метод в Java - необходимо помнить про обратную совместимость.
А суть его в следующем:
код существующих клиентов открытого API не должен сломаться при обновлении этого API. Старые клиенты должны уметь работать с новой версией API.
К сожалении, не всегда очевидно - обратно совместимо ли какое-то изменении в API или нет.
Но есть несколько правил, которых можно придерживаться для этого:
1. Новые компоненты (поля, методы, перечисления) - можно добавлять без проблем. Главное на стороне клиентов не делать строгую валидацию (например, фейлить ответ от сервера, если пришло новое поле)
2. Не делать поля обязательными в существующих сообщениях (в новых сообщениях тоже стараться делать поля optional)
3. Не удалять или переименовать уже существующие компоненты (переименование - это аналог “удалить + добавить поле”). Более того, придется продолжать заполнять старые поля, даже если они стали избыточными (redundant)
4. Не менять типы существующих полей
5. Осторожно работать с enum: если используется только в запросах - то добавить новое значение безболезненно, чего нельзя сказать про новые значения в ответах от сервера, где уже нужно писать клиент соответствующим образом
Вывод
Не так-то просто писать открытый API, особенно если им пользуется большое количество клиентов.
Да и становится понятно, почему в Java Core столько старых классов и методов 🙂
При создании любого открытого API, будь то HTTP, gRPC endpoint, public метод в Java - необходимо помнить про обратную совместимость.
А суть его в следующем:
код существующих клиентов открытого API не должен сломаться при обновлении этого API. Старые клиенты должны уметь работать с новой версией API.
К сожалении, не всегда очевидно - обратно совместимо ли какое-то изменении в API или нет.
Но есть несколько правил, которых можно придерживаться для этого:
1. Новые компоненты (поля, методы, перечисления) - можно добавлять без проблем. Главное на стороне клиентов не делать строгую валидацию (например, фейлить ответ от сервера, если пришло новое поле)
2. Не делать поля обязательными в существующих сообщениях (в новых сообщениях тоже стараться делать поля optional)
3. Не удалять или переименовать уже существующие компоненты (переименование - это аналог “удалить + добавить поле”). Более того, придется продолжать заполнять старые поля, даже если они стали избыточными (redundant)
4. Не менять типы существующих полей
5. Осторожно работать с enum: если используется только в запросах - то добавить новое значение безболезненно, чего нельзя сказать про новые значения в ответах от сервера, где уже нужно писать клиент соответствующим образом
Вывод
Не так-то просто писать открытый API, особенно если им пользуется большое количество клиентов.
Да и становится понятно, почему в Java Core столько старых классов и методов 🙂
👍34🔥6❤🔥3💩1
Сode review н-нада?
Многие поддержали данное предложение, что ж, давайте попробуем реализовать его!
Кто хочет, чтобы я провел code review вашего кода - присылайте ссылку на github в комменты под этим постом.
Я рандомно выберу один проект и в следующем посте опубликаю краткое резюме по коду с ссылкой на код с моими комментариями
Условия участия:
- Проект опубликован на github
- Весь код в виде одного пул реквеста или коммита
- Чем больше кода - тем больше добавить описания о нем в README файле (чтобы я понимал о чем проект)
- Не удалять пул реквест или коммит после code review
- Согласие на то, что ваш разбор попадет в этот канал
- Ссылки жду до 6 мая включительно
P.S.Если зайдет рубрика, то можем ввести ее на постоянной основе, например, каждое первое число
#dmdev_code_review
Многие поддержали данное предложение, что ж, давайте попробуем реализовать его!
Кто хочет, чтобы я провел code review вашего кода - присылайте ссылку на github в комменты под этим постом.
Я рандомно выберу один проект и в следующем посте опубликаю краткое резюме по коду с ссылкой на код с моими комментариями
Условия участия:
- Проект опубликован на github
- Весь код в виде одного пул реквеста или коммита
- Чем больше кода - тем больше добавить описания о нем в README файле (чтобы я понимал о чем проект)
- Не удалять пул реквест или коммит после code review
- Согласие на то, что ваш разбор попадет в этот канал
- Ссылки жду до 6 мая включительно
P.S.
👍47🔥16👏2❤🔥1
15.000 подписчиков на YouTube!
Это в 1,5 раза больше людей, чем в городе, котором я вырос.
И всех этих людей связывает один общий интерес - Java.
3 года прошло, как я создал канал DMdev.
И он совсем не похож на среднестатистический канал ютуба.
Во-первых, он не для широкой массы людей, а очень узкоспециализирован.
Во-вторых, на канале не хаотичный и развлекающий контент, а последовательные образовательные курсы по Java программированию.
За это время:
- уже более 1.000.000 просмотров
- 666 видео
- 12 курсов (пройдя которые - действительно можно стать разработчиком)
Благодарю каждого за доверие и активное участие!
Без вас - ничего этого не было бы🙌🏻
P.S. 🔔 Напоминаю, что сегодня последний день, как я жду ваши ссылки на гитхаб для code review(подробнее в посте выше)
Это в 1,5 раза больше людей, чем в городе, котором я вырос.
И всех этих людей связывает один общий интерес - Java.
3 года прошло, как я создал канал DMdev.
И он совсем не похож на среднестатистический канал ютуба.
Во-первых, он не для широкой массы людей, а очень узкоспециализирован.
Во-вторых, на канале не хаотичный и развлекающий контент, а последовательные образовательные курсы по Java программированию.
За это время:
- уже более 1.000.000 просмотров
- 666 видео
- 12 курсов (пройдя которые - действительно можно стать разработчиком)
Благодарю каждого за доверие и активное участие!
Без вас - ничего этого не было бы🙌🏻
P.S. 🔔 Напоминаю, что сегодня последний день, как я жду ваши ссылки на гитхаб для code review
🔥82👍16🎉8❤🔥2😈1
#dmdev_code_review
Как и обещал, выбрал одного из участников, чтобы провести code review.
Хотелось бы отметить общие частовстречаемые ошибки, которые в то же самое время очень важны:
1. Не следует изменять статические поля в нестатическом контексте. Чаще всего это приводит к ошибкам в многопоточности или попросту неверно работает код.
2. Четко разбивать приложение на слои и следовать строгой коммуникации между ними. Например, избегая выполнения sql запросов напрямую из сервлетов. Иначе это приведет к спаггети коду и тесной взаимосвязи всего со всеми, что в принципе делает возможность рефакторинга крайне затруднительной.
3. Не стоит писать код на исключениях - клиентский код потом становится громоздким с кучей try/catch блоков. Пробрасывать исключения следует тогда, когда действительно произошла ИСКЛЮЧИТЕЛЬНАЯ ситуация, которую никак не избежать. Например, гораздо приятнее возвращать true/false в методе delete вместо пробрасывания исключения, если такой сущности не оказалось по переданному id.
4. Связанно с предыдущим пунктом: не нужно проглатывать исключение, пробрасывая свое кастомное - иначе теряется stacktrace рутовой ошибки и будет очень сложно понять что произошло. Если нужно обернуть одно исключение в другое - просто передавайте его как параметр в конструктор:
6. Давать хорошие имена переменным, методам, классам - всему в коде. Иначе очень сильно усложняется чтение кода, на которое программист тратит большую часть своего рабочего времени. Особенно избегать таких имен, которые подразумевают только ЧТЕНИЕ, а по факту там происходит изменения состояния объектов - т.е. ЗАПИСЬ. Например,
P.S. Весь список комментариев по code review можно найти в пул реквесте по ссылке
P.P.S. Если есть вопросы по коду/моим замечаниям, что я оставил - то можете задавать их прям здесь под постом в комментариях
Как и обещал, выбрал одного из участников, чтобы провести code review.
Хотелось бы отметить общие частовстречаемые ошибки, которые в то же самое время очень важны:
1. Не следует изменять статические поля в нестатическом контексте. Чаще всего это приводит к ошибкам в многопоточности или попросту неверно работает код.
2. Четко разбивать приложение на слои и следовать строгой коммуникации между ними. Например, избегая выполнения sql запросов напрямую из сервлетов. Иначе это приведет к спаггети коду и тесной взаимосвязи всего со всеми, что в принципе делает возможность рефакторинга крайне затруднительной.
3. Не стоит писать код на исключениях - клиентский код потом становится громоздким с кучей try/catch блоков. Пробрасывать исключения следует тогда, когда действительно произошла ИСКЛЮЧИТЕЛЬНАЯ ситуация, которую никак не избежать. Например, гораздо приятнее возвращать true/false в методе delete вместо пробрасывания исключения, если такой сущности не оказалось по переданному id.
4. Связанно с предыдущим пунктом: не нужно проглатывать исключение, пробрасывая свое кастомное - иначе теряется stacktrace рутовой ошибки и будет очень сложно понять что произошло. Если нужно обернуть одно исключение в другое - просто передавайте его как параметр в конструктор:
new DatabaseException(sqlException)
5. Разумно подходить к использованию Optional & Streams. Какой-то код лучше писать в функциональном стиле, какой-то в императивном, какой-то в комбинации двух предыдущих. Но в любом случае стоит граммотно использовать все подходы. Возьмем простой случай: возвращать Optional из метода, который может вернуть null. И, наоборот, если метод всегда возвращает объект - то не стоит оборачивать его в Optional, ибо это доставляет неудобства клиенту.6. Давать хорошие имена переменным, методам, классам - всему в коде. Иначе очень сильно усложняется чтение кода, на которое программист тратит большую часть своего рабочего времени. Особенно избегать таких имен, которые подразумевают только ЧТЕНИЕ, а по факту там происходит изменения состояния объектов - т.е. ЗАПИСЬ. Например,
findProduct(productId)
- а внутри изменение состояния объекта Product.P.S. Весь список комментариев по code review можно найти в пул реквесте по ссылке
P.P.S. Если есть вопросы по коду/моим замечаниям, что я оставил - то можете задавать их прям здесь под постом в комментариях
🔥49👍11❤🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Ребят, в конце июня стартую последнюю 2-ую ступень менторства в этом году
Осталось4 места 0 мест.
Так что, кто желает окунуться в интенсивное обучение Java со мной - welcome.
Записаться и почитать подробнее можно по ссылке:
https://dmdev.tilda.ws/second-level
Осталось
Так что, кто желает окунуться в интенсивное обучение Java со мной - welcome.
Записаться и почитать подробнее можно по ссылке:
https://dmdev.tilda.ws/second-level
😁20❤🔥3🔥3
1. Если описать тремя словами, как для тебя прошло менторство?
2. С позиции уже выпускника, как считаешь, кому будет полезно идти на менторство?
К чему нужно быть готовым/чего ожидать?
3. И какой совет дашь для тех, кто думает/сомневается - идти или не идти
Ответы на фото👆
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍8❤🔥5
#dmdev_qa - под этим хештегом отвечаю на ваши вопросы.
Вопрос на фото, ответ ниже👇
Этот подход зародился очень давно, можно сказать, исторически так сложилось. Даже в книгах писалось, что так нужно делать. Раньше это считалось best practices.
Потому что:
1️⃣ Ты легко можешь создать Dynamic Proxy, не прибегая к сторонним библиотекам и делая прокси через наследование, ибо у тебя есть интерфейс со всеми методами. Но сейчас по умолчанию даже Spring делает cglib прокси через наследование, ибо этот подход оказался более жизнеспособным.
2️⃣ Ты можешь описывать документацию над методами в интерфейсах или выносить туда константы (например, длинные SQL запросы для Repository), чтобы не делать этого в классах. Но сейчас тоже не актуально, ибо интерфейсы созданы именно для функционала, а не как хранилище констант, и второе - современные среды разработки и так умеют сворачивать документацию над методами, чтобы не смущать программистов.
3️⃣ Удобно было раньше создавать всякие заглушки в тестах или тестовых окружениях - просто создавая еще одну реализацию от интерфейса и ее подставлять вместо реального объекта. Но Mockito и без этого справляется и опять же через наследование.
Вопрос на фото, ответ ниже👇
Этот подход зародился очень давно, можно сказать, исторически так сложилось. Даже в книгах писалось, что так нужно делать. Раньше это считалось best practices.
Потому что:
1️⃣ Ты легко можешь создать Dynamic Proxy, не прибегая к сторонним библиотекам и делая прокси через наследование, ибо у тебя есть интерфейс со всеми методами. Но сейчас по умолчанию даже Spring делает cglib прокси через наследование, ибо этот подход оказался более жизнеспособным.
2️⃣ Ты можешь описывать документацию над методами в интерфейсах или выносить туда константы (например, длинные SQL запросы для Repository), чтобы не делать этого в классах. Но сейчас тоже не актуально, ибо интерфейсы созданы именно для функционала, а не как хранилище констант, и второе - современные среды разработки и так умеют сворачивать документацию над методами, чтобы не смущать программистов.
3️⃣ Удобно было раньше создавать всякие заглушки в тестах или тестовых окружениях - просто создавая еще одну реализацию от интерфейса и ее подставлять вместо реального объекта. Но Mockito и без этого справляется и опять же через наследование.
👍26❤4🔥4❤🔥2