Пол — это Java
153 subscribers
13 photos
2 videos
2 files
26 links
Канал, в котором живет вымышленный на основе реальных событий разработчик Пол, и вместе с ним мы пробуем узнать, что такое Java и не только👨🏻‍💻

@polyackov_ot
Download Telegram
👋 Привет Пол (и привет всем)

Последние несколько месяцев я проверяю работы студентов-джавистов на курсе по Clean Architecture.

Всё это оказалось очень любопытным и дало мне, надеюсь как и студентам, ряд новых инсайтов.
Например, я заметил, что у большинства студентов есть одинаковые зоны роста -- паттерны в написании кода, улучшив которые, можно повысить его качество.

Одна из таких зон роста – работа с Exception, а именно:

🔸 Использование более конкретного типа ошибки вместо абстрактного
🔸 Добавление детальной информации, текста о контексте ошибки
🔸 Написание качественного теста, который будет способен проверить оба пункта выше

Разберём шаг за шагом на примере, как можно улучшить код.

Дано ⬇️
if (coordinate < MIN_COORDINATE_VALUE || coordinate > MAX_COORDINATE_VALUE) {
throw new RuntimeException("wrong coordinate");
}


Что можно улучшить на основе выделенных выше пунктов:

1️⃣ Вместо абстрактного типа ошибки RuntimeException полезно воспользоваться более конкретным.

Мы видим, что в коде идёт речь про валидацию входных параметров, а потому имеет место более подходящий для ситуации тип IllegalArgumentException

Более конкретный тип ошибки, даже без текста, уже даёт частичное понимание контекста и снижает риск обработки другой ошибки, которая также является наследником базовой.

2️⃣ Выбрав тип ошибки, необходимо определиться, что важно написать в ее тексте.

Хороший message, отвечает на вопрос:
Почему произошла ошибка?


Чтобы ответить на данный вопрос, текст ошибки должен содержать описание -- нарушение чего приводит к возникновению подобной ошибки.

А также пояснение, что было передано в метод и привело к нежелательному результату:
Что я нарушил?
Как я нарушил?
Прочитав такой текст, смогу ли я поправить входные параметры без чтения кода?


После внесения улучшений из пункта 1 и 2 код может выглядеть следующим образом ⬇️
if (coordinate < MIN_COORDINATE_VALUE || coordinate > MAX_COORDINATE_VALUE) {
throw new IllegalArgumentException("Expected coordinate should be between '%d' and '%d'. Actual coordinate is '%d'."
.formatted(MIN_COORDINATE_VALUE, MAX_COORDINATE_VALUE, coordinate));
}


Замечу, что важно переиспользовать константы в формировании текста ошибки. Это защитит код от появления противоречий между их значениями и текстом ошибки при будущем рефакторинге.

Также стоит всегда писать текст ошибки на английском, так как код будет запускаться на проде, и будет неприятно получить
?????? ?????? ?????? ?????? ? ?????? ?? '1' ?? '10'. ?????? ?????? ? '0'.

3️⃣ Negative path не менее важен, чем happy path, поэтому хорошая ошибка и ее текст должны быть закреплены хорошим тестом.

@Test
void create_whenCoordinateIsNotCorrect_thenThrow() {
var actual = assertThrows(IllegalArgumentException.class, () -> Location.create(0, 2));


assertEquals("Expected coordinate should be between '1' and '10'. Actual coordinate is '0'.", actual.getMessage());
}


Буду благодарен, если вы поделитесь в комментариях, что на ваш взгляд должно быть или не быть в хорошей ошибке!

#exception
14🔥53🤔1🗿1