Новые статьи
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Struchkov Mark 2024-09-06 17:05:53 +03:00
parent 8dfab937cd
commit 65abba8ae6
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
15 changed files with 323 additions and 7 deletions

View File

@ -0,0 +1,20 @@
---
aliases:
tags:
- maturity/🌱
date:
- - 2024-03-25
zero-link:
- "[[../../../meta/zero/00 Docker|00 Docker]]"
parents:
linked:
---
При запуске докера создается локальная сеть и поднимается NAT. При запуске контейнера ему выдается IP адрес из этой локальной сети. А когда мы открываем порт для контейнера в iptables добавляется новая запись переадресации с порта хостовой машины на соответсвующий контейнеру IP адрес и порт в локальной сети. Из-за этого немного проседает производительность.
Если контейнер не запущен в какой-то сети, то он будет видеть все остальные контейнеры, которые не привязаны к какой-то конкретной сети. То есть из одного докер контейнера можно средствами терминала подключиться к другому контейнеру используя его локальный IP адрес.
- Контейнер может быть подключен к нескольким сетям (без рестарта)
- Работает Service Discovery
- Можно задать произвольные диапазоны IP адресов
## Дополнительные материалы
- [Изменить IP-адрес подсети Docker по умолчанию](Изменить%20IP-адрес%20подсети%20Docker%20по%20умолчанию.md)

View File

@ -12,7 +12,7 @@ parents:
linked:
link: https://struchkov.dev/blog/ru/java-binary-search/
---
### Без рекурсии
## Без рекурсии
```java
public class Binary {
@ -43,7 +43,7 @@ public class Binary {
}
```
### С использованием рекурсии
## С использованием рекурсии
```java
public class Binary {

View File

@ -0,0 +1,137 @@
---
aliases:
tags:
- maturity/🌱
- type/opinion
date:
- - 2024-09-06
zero-link:
- "[[../garden/ru/meta/zero/00 Java разработка|00 Java разработка]]"
parents:
linked:
---
Разработчики Java используют подстановочный знак (`*`) в операторах `import` для добавления всех классов из определенного пакета. Но в ходе ревью большинство из вас, возможно, просили убрать этот подстановочный знак импорта и добавить полное имя класса. Разберемся почему не стоит использовать знак подстановки?
Но прежде, давайте вспомним, что полное имя класса, помимо названия, содержит также пакет, например: `java.util.List`. ==Такая запись позволяет нам иметь классы с одинаковыми именами, которые находятся в разных пакетах.==
```java
package com.example;
public class WithoutImport {
public static void main(String[] args) {
java.util.List myList = new java.util.ArrayList();
}
}
```
Однако, полная запись весьма непрактична, поэтому в Java существует оператор импорта  `import`. Операторы импорта объявляют компилятору источник имен классов, статических переменных и статических имен методов, используемых в коде. Один раз написали полное имя класса, а дальше используем только название класса.
```java
package com.example;
import java.util.ArrayList;
import java.util.List;
public class WithImport {
public static void main(String[] args) {
List myList = new ArrayList();
}
}
```
Если мы скомпилируем и запустим эти примеры, результат будет одинаковым.
Импорт с подстановочными знаками указывает компилятору искать имена классов в данном пакете. Следовательно, при использовании импорта с wildcard производительность во время компиляции может немного снизиться. Но в большинстве случаев это не окажет заметного влияния.
Во время выполнения проблемы с производительностью нет, потому что операторы импорта являются директивами компилятора, и мы не можем найти их в байт-коде. Чтобы пояснить это, мы напишем приведенный выше пример с импортом с подстановочными знаками.
```java
package com.example;
import java.util.*;
public class WithWildCard {
public static void main(String[] args) {
List myList = new ArrayList();
}
}
```
Если мы получим байт-код этого класса, то он будет выглядеть следующим образом
```bytecode
Compiled from "WithWildCard.java"
public class com.example.WithWildCard {
public com.example.WithWildCard();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: return
}
```
Если сравнить его с байт-кодом прошлого примера, то они оба имеют одинаковый байт-код.
Во время выполнения Java использует байт-код, а не исходный код. ==В байт-коде нет операторов импорта.== Из этого ясно следует, что использование импорта с подстановочными знаками не влияет на производительность Java-приложения во время выполнения.
## Недостатки
Так если использование подстановочного знака не приводит к проблемам производительности, то почему бы его не использовать?
### Конфликты имен
Самая серьезная проблема это возможные конфликты именования. Представьте, что у нас есть два класса из разных библиотек `org.test.Parser` и `dev.lib.Parser`. В нашем коде мы используем импорт с wildcard:
```java
import org.test.*
import dev.lib.*
```
Компилятор никак не отреагирует на наличие классов с одинаковыми именами в двух разных пакетах, импортируемых таким образом, если только не бу­дет предпринята попытка воспользоваться одним из этих классов.
Также проблема может возникнуть в будущем, когда вы обновите версию какую-то из библиотек. Допустим у нас была библиотека с классом `org.test.Parser`, а потом разработчик второй библиотеки тоже добавил класс `dev.lib.Parser`, таким образом мы получили конфлик именования в будущем, хотя раньше все было нормально.
### Чистый код
Импорты с подстановочными знаками помогают нам избежать длинного списка импортов. Следовательно, это влияет на читабельность кода, так как читателю может потребоваться прокрутить много страниц в каждом файле исходного кода, прежде чем он доберется до кода, который показывает логику. Несомненно, более читабельный код - это также чистый код.
Эта идея также поддерживается в книге "Чистый код" Роберта К. Мартина. Фактически, книга рекомендует использовать импорты с подстановочными знаками при использовании нескольких классов из одного источника. Другими словами, когда мы импортируем два или более классов, импортированных из пакета, лучше импортировать весь пакет.
Однако, я не считаю это какой-то проблемой, так как IntelliJ IDEA автоматически скрывает все строки импортов.
![](../../meta/files/images/Pasted%20image%2020240906164456.png)
Также читаемость ухудшается, потому что разработчик не получает четкого представления о полном пути классов, используемых в коде.
Однако, это тоже не является проблемой. Достаточно удерживая Ctrl (cmd) навести курсор на класс и вы увидите пакет, в котором этот класс размещается.
![](../../meta/files/images/Pasted%20image%2020240906164524.png)
Таким образом проблемы "чистого кода" более не актуальны.
## Настройки в Idea
Intellij Idea автоматически сворачивает импорты, когда полные импорты из какого-то пакета достигают заданного количества. Эта опция настраивается в раделе Preferences > Editor > Code Style > Java во вкладке imports.
![](../../meta/files/images/Pasted%20image%2020240906164551.png)
Чтобы отключить автоматическое сворачивание импортов достаточно указать число 999. Вот и все, теперь Idea не будет автоматически сворачивать импорты.
## Резюмирую
Использование подстановочных импортов никак не повлияет на производительность программы во время выполнения, но может немного повлиять на производительность во время компиляции.
Также при обновлении библиотек вы можете столкнуться с проблемой конфликта имен. Шанс этой проблемы не велик, но и не нулевой.
Что касается "чистого кода", то с использованием современных IDE эта проблема не является актуальной.

View File

@ -0,0 +1,29 @@
---
aliases:
tags:
- maturity/🌱
- type/opinion
date:
- - 2023-11-20
zero-link:
- "[[00 Java разработка]]"
parents:
linked:
article: https://struchkov.dev/blog/ru/do-not-use-lombok-data/
---
Многие разработчики в принципе против использования Lombok. В общем, это холиварная тема. Но вы используете Lombok в проекте, то не используйте хотя бы спорные и откровенно вредные аннотации.
Одна из таких это `@Data`. Во-первых, [мало кто помнит, что она под собой скрывает](https://projectlombok.org/features/Data).
- `@ToString`. Не помню, когда последний раз переопределял `toString()`. А если объект содержит чувствительную информацию?
- `@EqualsAndHashCode`. Это самая вредная аннотация в @Data. ==Потому что она генерирует `equals()` и `hashCode()` по всем полям.== Обычно вы не хотите, чтобы генерация осуществлялась по всем полям. Например, для сущности достаточно идентификатора.
- `@Getter` / `@Setter`. Здесь ничего плохого.
- `@RequiredArgsConstructor`. Тоже окей.
Основная проблема в `@EqualsAndHashCode`. Можно, конечно, использовать `@EqualsAndHashCode.Exclude`. Эта аннотация запрещает использовать поле при генерации, но вы хотите расставлять это над почти всеми полями в сущности? Потому что `@EqualsAndHashCode.Include` просто не сработает, нельзя объявить только нужные поля, нужно будет именно исключать все ненужные.
Также избегайте всех аннотаций из пакета `experemental`. Все аннотации из этого пакета могут работать не стабильно, и при этом могут быть удалены из следующих версий. Исключением из этого пакета является [@FieldNameConstants](https://projectlombok.org/features/experimental/FieldNameConstants), за пару лет с ней не было никаких проблем, а все имеющиеся альтернативы не очень.
С Lombok код выглядит чище, но, как и в случае с любым другим магическим инструментом, важно понимать, как именно он работает и когда его использовать. В противном случае производительность приложения может снизиться, либо оно вовсе может перестать работать корректно.
## Дополнительные материалы
- [Lombok + JPA: Что может пойти не так? / Хабр](https://habr.com/ru/company/haulmont/blog/564682/)

View File

@ -0,0 +1,32 @@
---
aliases:
tags:
- maturity/🌱
- type/opinion
date:
- - 2023-11-20
zero-link:
- "[[../../meta/zero/00 Java разработка|00 Java разработка]]"
parents:
linked:
article: https://note.struchkov.dev/sravnieniie-enum-v-java/
---
Enum это объект, как и все в Java. Однако это особенный объект. Каждый из объектов енума создаётся только единожды. Давайте на примере:
```java
enum TestEnum {ONE, TWO, THREE}
```
Если мы создадим 10 переменных `TestEnum.ONE`, то все они будут ссылаться на один и тот же объект. И поэтому enum можно сравнивать с помощью `==` и это корректно и будет работать.
Сторонники такого подхода называют следующие преимущества. Давайте их разберем.
**Вы никогда не получите `NullPointerException`.** И это правда, но если вы будете придерживаться правила ["сравнение константы слева"](Сравнение%20константы%20слева%20в%20Java.md), то и при использовании `.equals()` `NullPointerException` вам не страшен.
**Оператор == работает быстрее.** Быстрее чего? Видимо метода `.equals()`. Давайте посмотрим реализацию метода `.equals()` у enum.
![](../../meta/files/images/Pasted%20image%2020231120093026.png)
**Оператор == более понятный синтаксически.** Это еще почему? Для сравнения объектов в Java используется `.equals()`. Enum это объект. Логичнее и очевиднее использовать `.equals()` для сравнения, чтобы не нарушать единообразие сравнения объектов.
На мой взгляд, правильнее использовать `.equals()`, главное не забывать о правиле "[Сравнение константы слева](Сравнение%20константы%20слева%20в%20Java.md)".

View File

@ -0,0 +1,63 @@
---
aliases:
tags:
- maturity/🌱
- type/opinion
date:
- - 2024-09-06
zero-link:
- "[[../../meta/zero/00 Java разработка|00 Java разработка]]"
parents:
linked:
---
Представьте, что у вас есть enum, который отвечает за статус пользователя в системе: "онлайн", "офлайн" и "занят".
```java
public enum UserStatus {
ONLINE, OFFLINE, BUSY
}
```
```java
public class User {
...
@Column(name = "status")
@Enumerated(EnumType.STRING)
private UserStatus status;
...
}
```
Скорее всего для выполнения бизнес-логики вам потребуется проверять статус пользователя
```java
if (user.getStatus().equals(UserStatus.ONLINE)) {
// to do something
}
```
Вроде бы все отлично, миссия выполнена. Но есть одно НО. Что если `getStatus()` вернет вам `null`? Правильно, вы получите `NullPointerException`.
Чтобы этого избежать следует придерживаться правила "Сравнения константы слева". Оно очень простое. В нашем примере, мы точно уверены, что `UserStatus.ONLINE` существует, поэтому `.equals()` стоит вызывать от него.
```java
if (UserStatus.ONLINE.equals(user.getStatus())) {
// to do something
}
```
В остальных подобных ситуациях делайте также, например со строками:
```java
if ("Иванов".equals(user.getLastName())) {
// to do something
}
```
Это простое правило защитит вас от `NullPointerException`.

View File

@ -19,8 +19,9 @@ enableToc: false
- [Java разработка](meta/zero/00%20Java%20разработка.md)
- [Quarkus](meta/zero/00%20Quarkus.md)
- [SpringBoot](meta/zero/00%20SpringBoot.md)
## Чего стоит избегать
> [!WARNING] DISCLAMER
> Приветствуются комментарии по теме заметки для улучшения и исправления фактических ошибок. Но ==не стоит указывать на грамматические ошибки или опечатки.== В первую очередь это мои заметки, которые можн
- [00 Hibernate](meta/zero/00%20Hibernate.md)
- [DevOps](meta/zero/00%20DevOps.md)
- [Docker](meta/zero/00%20Docker.md)
- [Алгоритмы](meta/zero/00%20Алгоритм.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

7
meta/zero/00 DevOps.md Normal file
View File

@ -0,0 +1,7 @@
---
tags:
- type/zero-link
parents:
- "[[00 Разработка]]"
title: DevOps
---

21
meta/zero/00 Docker.md Normal file
View File

@ -0,0 +1,21 @@
---
tags:
- type/zero-link
zero-link:
- "[[00 DevOps|00 DevOps]]"
---
Для изоляции и управления ресурсами контейнеров активно используется [cgroup](Control%20group.md). Так же для изоляции активно используется [Namespace](Namespace.md). Все это функционал ядра Linux, поэтому не оказывает сильного влияния на производительность. Однако, нужно быть осторожным при работе с диском и сетью. С сутью больше всего проблем, например при запуске nginx можно получить просадку в 5%.
Обычно docker запускается от root пользователя.
- [Команды Docker](Команды%20Docker.md)
- [Dockerfile](Dockerfile.md)
- [Docker Network](../../dev/devops/docker/Docker%20Network.md)
- [Структура хранилища файлов Docker](Структура%20хранилища%20файлов%20Docker.md)
- [Очистка мусора в Docker](Очистка%20мусора%20в%20Docker.md)
- [Настройка ротации логов в Docker](Настройка%20ротации%20логов%20в%20Docker.md)
## Полезное
- Утилита для анализа докер образов: [Утилита Dive](Утилита%20Dive.md)
- Утилита [Hadolint](https://github.com/hadolint/hadolint). Проверяет докер файл на плохие практики.
- xfs более производительный
- Native Overlay Diff рекомендуют отключать (docker info)

View File

@ -1,5 +1,5 @@
---
parents:
zero-link:
- "[[00 Java разработка]]"
tags:
- type/zero-link

View File

@ -9,8 +9,14 @@ title: Java разработка
- [Устройство Java](Устройство%20Java.md)
- [Снипеты для Java](../../../garden/ru/meta/zero/00%20Снипеты%20для%20Java.md)
- Фреймворки
- [SpringBoot](00%20SpringBoot.md)
- [Quarkus](00%20Quarkus.md)
- [SpringBoot](00%20SpringBoot.md)
- [Hibernate](00%20Hibernate.md)
## Мои рассуждения
- [Использование wildcard imports в Java](../../dev/java/Использование%20wildcard%20imports%20в%20Java.md)
- [Сравнение константы слева в Java](../../dev/java/Сравнение%20константы%20слева%20в%20Java.md)
- [Сравнение enum в Java](../../dev/java/Сравнение%20enum%20в%20Java.md)
- [Не используйте @Data](../../dev/java/Не%20используйте%20@Data.md)
## Версии Java
- [[Java 1]]
- [Java 7](Java%207.md)