From 0bb526597a3cdae6e57284000526d8eecb2a5db0 Mon Sep 17 00:00:00 2001 From: Struchkov Mark Date: Tue, 17 Sep 2024 07:58:08 +0300 Subject: [PATCH] =?UTF-8?q?=D0=93=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=D0=BC=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20Tuple=20=D0=B8=20Pair=20=D0=B2=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B5.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ицы применимости Tuple и Pair в разработке.md | 142 ++++++++++++++++++ meta/zero/00 Java разработка.md | 1 + psychology/Восходящая спираль.md | 26 ++++ psychology/Нисходящая спираль.md | 29 ++++ 4 files changed, 198 insertions(+) create mode 100644 dev/java/Границы применимости Tuple и Pair в разработке.md create mode 100644 psychology/Восходящая спираль.md create mode 100644 psychology/Нисходящая спираль.md diff --git a/dev/java/Границы применимости Tuple и Pair в разработке.md b/dev/java/Границы применимости Tuple и Pair в разработке.md new file mode 100644 index 00000000..5893a477 --- /dev/null +++ b/dev/java/Границы применимости Tuple и Pair в разработке.md @@ -0,0 +1,142 @@ +--- +aliases: +tags: + - maturity/🌱 + - type/opinion +date: 2024-09-17 +zero-link: + - "[[../../meta/zero/00 Java разработка|00 Java разработка]]" +parents: +linked: +--- +## Тезисы +- Публичные методы интерфейсов должны быть самодокументируемыми и понятными без дополнительных комментариев. +- `Tuple` в публичных методах снижает читаемость и может запутать других разработчиков. +- `Tuple` в аргументах метода также может снизить ясность и увеличить вероятность ошибок. +- В приватных методах `Tuple` допустим, если используется внутри класса и не нарушает ясность. +- В реактивных пайпах `Tuple` могут быть полезны для временного объединения значений. +- Извлечение данных из `Tuple` в локальные переменные улучшает читаемость реактивных пайпов. +- Если вы на проекте один и никто другой код читать не будет, можете использовать `Tuple` как угодно 😁 +*** +Некоторые языки программирования, такие как Go, позволяют возвращать из функции несколько значений сразу. В Java, однако, метод может вернуть только одно значение, и зачастую хочется вернуть сразу два — например, пару связанных данных. Конечно, правильный подход — создать объект с двумя полями, но часто на практике оказывается, что проще и быстрее использовать готовые решения вроде классов `Tuple` и `Pair`, которые служат обертками. + +Но прежде чем полагаться на эти классы, важно понять их границы применимости. Для упрощения дальнейшего объяснения я буду использовать `Tuple` как пример, но все сказанное ниже также относится и к `Pair`. +## Возвращаем Tuple в публичном методе +Публичные методы интерфейсов — это своего рода контракты между вами, разработчиком функциональности, и клиентом, то есть другим разработчиком, который будет использовать ваш код для решения своих задач. + +==Так как большую часть времени разработчик не пишет, а читает чужой код, важно, чтобы этот контракт был понятен без дополнительных пояснений и комментариев.== + +Представим, что вам нужно вернуть имя пользователя и его возраст. На первый взгляд, использование `Tuple` может показаться удобным решением: не нужно создавать новый класс, а возвращать сразу несколько значений — легко и быстро. + +И ваш контракт (интерфейс) выглядит следующим образом: + +```java +public interface UserService { + Tuple getUserData(String userId); +} +``` + +Посмотрев на контакт `getUserData(userId)` сможет ли другой разработчик сказать какие результаты он получит? Вряд ли. + +Недостатки такого использования: +- **Снижение читабельности кода:** Клиенту интерфейса будет неочевидно, что именно содержится в возвращаемом `Tuple`. В отличие от специально созданного класса с понятными именами полей, `Tuple` не говорит напрямую, что первое значение — это имя, а второе — возраст. Это усложняет понимание и использование метода. +- **Отсутствие самодокументируемости:** Хорошо продуманные классы и методы сами по себе выступают как документация, тогда как `Tuple` требует дополнительных пояснений или комментариев, чтобы разработчики понимали, что происходит. ==Вы заставляете других разработчиков тратить больше времени на понимание логики метода.== +- **Повышенная вероятность ошибок:** Использование неименованных полей увеличивает риск случайных ошибок, например, при изменении порядка полей. Разработчики могут легко перепутать значения и передать их неправильно. Особенно если тип у значений совпадает. +- **Сложности с расширяемостью:** Если в будущем потребуется расширить возвращаемые данные, интерфейс с `Tuple` станет менее гибким. +## Tuple в аргументах метода +Когда методы принимают несколько параметров, иногда может возникнуть желание объединить их в `Tuple`, чтобы упростить сигнатуру метода или передать параметры в одном объекте. На первый взгляд, это кажется удобным, особенно если типы данных уже известны, и не хочется создавать отдельный класс. + +Особенно сильно такое желание возникает, когда вы вызываете публичный метод, который возвращает `Tuple`, и вам нужны все его результаты. В таких ситуациях кажется логичным продолжать работать с `Tuple`, чтобы избежать излишней детализации и создавать меньше кода. [[../../psychology/Нисходящая спираль|Нисходящая спираль]] закручивается 😊 + +Представим, что ваш метод выглядит следующим образом. И в этот метод приходит другой разработчик, которому нужно добавить новую фичу или исправить баг и он видит вот это: + +```java +public void processUserData(Tuple userData) { + // Логика обработки данных +} +``` + +Какие проблемы могут возникнуть при таком подходе. На самом деле все те же: +- **Пониженная читаемость и ясность кода:** Как и в случае с возвращаемыми значениями, использование `Tuple` не даёт ясности о том, что именно передаётся в метод. Из сигнатуры метода непонятно, что строка представляет имя пользователя, а целое число — возраст. +- **Нарушение принципа самодокументируемого кода +- **Увеличение вероятности ошибок** +- **Сложности с изменениями и расширением кода** +## Возвращаем Tuple в приватном методе +В отличие от публичных методов, приватные методы находятся внутри границ одного класса и, не участвуют в контрактах. Это дает больше свободы в выборе структур данных для внутренних операций. + +Возвращение `Tuple` из приватного метода может оказаться разумным решением, когда нужно быстро вернуть несколько значений без создания дополнительных классов. Например: + +```java +private Tuple fetchUserData() { + // Логика получения данных + return new Tuple<>("John Doe", 30); +} +``` + +Когда использовать `Tuple` уместно: +- Если данные возвращаются только внутри приватного метода и используются в узком контексте, где значение каждого элемента `Tuple` очевидно из контекста вызова. +- Если метод временный и планируется рефакторинг, или когда требуется быстрое прототипирование. + +Преимущества использования `Tuple` в приватных методах: +- **Удобство и скорость реализации:** Использование `Tuple` может значительно сократить время на реализацию, особенно когда речь идет о простых данных и методах, которые используются в узких контекстах. +- **Снижение избыточности кода:** Если данные нужны только внутри класса и их использование ограничено несколькими методами, создание отдельного класса может казаться избыточным. `Tuple` позволяет избежать ненужной сложности и дополнительных файлов. + +Тем не менее, стоит помнить о проблемах Tuple. Если логика метода со временем усложниться, читаемость кода может понизится. + +**Когда стоит задуматься о создании отдельного класса:** +- Если структура данных становится сложной или используется в нескольких местах внутри класса. +- Если потребуется передавать данные в другие классы в будущем. +- Если работа с данными требует дополнительной логики, такой как валидация или преобразование. +## Tuple в реактивном программировании +В [[../../../../knowledge/dev/Реактивное программирование|реактивном программировании]], особенно с использованием [[../../meta/zero/00 Quarkus|Quarkus]] и Mutiny, часто возникает необходимость передачи нескольких значений между стадиями реактивного потока данных. `Tuple` может быть удобным решением для объединения значений, особенно когда результат остаётся внутри потока и не становится частью публичного API. + +Например, в реактивных пайпах могут использоваться такие структуры, как `Tuple2`, `Tuple3` и далее: + +```java +Uni userUni = getUser() + ... + .onItem().invoke(tuple -> { + String name = tuple.getItem1(); + int age = tuple.getItem2(); + // Дальнейшая обработка + }); +``` + +Здесь `Tuple2` используется для объединения имени и возраста пользователя, ==и значения извлекаются в локальные переменные с понятными именами.== Если нужно объединить больше значений, можно использовать `Tuple3`, `Tuple4` и так далее: + +```java +Uni orderUni = getOrder() + ... + .onItem().invoke(tuple -> { + String orderId = tuple.getItem1(); + double total = tuple.getItem2(); + LocalDate date = tuple.getItem3(); + // Дальнейшая обработка + }); +``` + +Когда использование различных Tuple оправдано: +- **Переходные стадии в пайпах:** Внутри реактивных потоков, `Tuple2`, `Tuple3` и другие позволяют временно объединять нужное количество значений для обработки, сохраняя компактность и удобство. +- **Локальные переменные для улучшения читаемости:** Извлечение значений `Tuple` в локальные переменные с осмысленными именами значительно улучшает читаемость кода и упрощает понимание логики. + +Ограничения: +- **Сложность при увеличении количества элементов:** Чем больше значений объединяется в `Tuple` (например, `Tuple4`, `Tuple5` и далее), тем сложнее становится поддерживать и понимать код. В таких случаях лучше рассмотреть создание именованных классов. +- **Не использовать в публичных методах:** Если `Tuple` выходит за границы класса, в публичные методы или интерфейсы, использование именованных структур данных предпочтительнее для улучшения читаемости и поддержки. +## Заключение +Использование `Tuple` в различных сценариях — будь то публичные методы, приватные методы или реактивные пайпы — всегда требует баланса между удобством и читаемостью кода. `Tuple` может быть полезным инструментом в определённых ситуациях, но стоит помнить, что ясность и поддерживаемость кода зачастую важнее мгновенного выигрыша в скорости разработки. Создание именованных классов или record помогает сделать код самодокументируемым, снижает вероятность ошибок и упрощает дальнейшую поддержку. + +Однако, если вы на проекте один и точно уверены, что других разработчиков там никогда не появится, то можете использовать Tuple как хотите 😁 + +Но в большинстве случаев, лучше следовать правилам и заботиться о тех, кто будет работать с вашим кодом в будущем. Ведь читаемость и ясность всегда остаются ключевыми аспектами качественного программирования. +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Java разработка|00 Java разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2024-09-17]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + diff --git a/meta/zero/00 Java разработка.md b/meta/zero/00 Java разработка.md index 56675b8a..5fb969bd 100644 --- a/meta/zero/00 Java разработка.md +++ b/meta/zero/00 Java разработка.md @@ -25,6 +25,7 @@ title: Java разработка - [Сравнение enum в Java](../../dev/java/Сравнение%20enum%20в%20Java.md) - [Не используйте @Data](../../dev/java/Не%20используйте%20@Data.md) - [Возвращайте пустую коллекцию вместо null](../../dev/java/Возвращайте%20пустую%20коллекцию%20вместо%20null.md) +- [[../../dev/java/Границы применимости Tuple и Pair в разработке|Границы применимости Tuple и Pair в разработке]] ## Версии Java - [[Java 1]] - [Java 7](Java%207.md) diff --git a/psychology/Восходящая спираль.md b/psychology/Восходящая спираль.md new file mode 100644 index 00000000..bc4526dd --- /dev/null +++ b/psychology/Восходящая спираль.md @@ -0,0 +1,26 @@ +--- +aliases: +tags: + - maturity/🌱 +date: "[[2023-10-24]]" +zero-link: + - "[[../meta/zero/00 Психология|00 Психология]]" + - "[[../meta/zero/00 Продуктивность|00 Продуктивность]]" +parents: +linked: + - "[[Нисходящая спираль]]" +author: + - "[[Алекс Корб]]" +--- +Восходящая спираль - это цепочка событий, в которых одно хорошее решение приводит к следующему. Например, вы хорошо выспались, поэтому чувствовали себя лучше и продуктивнее в течение дня, что позволило вам сделать зарядку, а зарядка помогла лучше заснуть. +*** +## Мета информация +**Область**:: [[../meta/zero/00 Продуктивность|00 Продуктивность]], [[../meta/zero/00 Психология|00 Психология]] +**Родитель**:: +**Источник**:: +**Автор**:: [[../../../wiki/people/Алекс Корб|Алекс Корб]] +**Создана**:: [[2023-10-24]] +### Дополнительные материалы +- [[Нисходящая спираль]] +### Дочерние заметки + diff --git a/psychology/Нисходящая спираль.md b/psychology/Нисходящая спираль.md new file mode 100644 index 00000000..06657887 --- /dev/null +++ b/psychology/Нисходящая спираль.md @@ -0,0 +1,29 @@ +--- +aliases: + - нисходящая спираль + - замкнутый круг +tags: + - maturity/🌱 +date: "[[2023-10-24]]" +zero-link: + - "[[../meta/zero/00 Продуктивность|00 Продуктивность]]" + - "[[../meta/zero/00 Психология|00 Психология]]" +parents: +linked: + - "[[Восходящая спираль]]" +author: + - "[[Алекс Корб]]" +--- +Нисходящая спираль это цепочка событий, в которых ==одно деструктивное действие ведет к другому==, и с каждым витком становится все хуже. Например, вы не выспались, на следующий день были разбиты, поэтому не сделали зарядку, да еще и переели, расстроились из-за этого легли спать позже и так далее. +*** +## Мета информация +**Область**:: [[../meta/zero/00 Продуктивность|00 Продуктивность]], [[../meta/zero/00 Психология|00 Психология]] +**Родитель**:: +**Источник**:: +**Автор**:: [[../../../wiki/people/Алекс Корб|Алекс Корб]] +**Создана**:: [[2023-10-24]] +### Дополнительные материалы +- [[Восходящая спираль]] +### Дочерние заметки + +