Обновление
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Struchkov Mark 2024-11-24 20:43:38 +03:00
parent 10a5cd0b97
commit 6d903d4988
No known key found for this signature in database
GPG Key ID: A3F0AC3F0FA52F3C
30 changed files with 536 additions and 39 deletions

View File

@ -0,0 +1,43 @@
---
aliases:
- Ограниченный контекст
- ограниченных контекстов
- ограниченного контекста
tags:
- maturity/🌱
date: 2024-11-24
---
Ограниченный контекст (Bounded Context) — это ==логическая граница, внутри которой используется своя уникальная модель предметной области.== Он применяется в разработке для структурирования сложных систем, особенно когда бизнес-логика состоит из множества разрозненных частей.
Основные характеристики:
- **Локализация моделей:** Модель, используемая внутри одного контекста, не должна быть напрямую применима в других контекстах. Например, "Заказ клиента" в контексте управления складом может включать данные о весе и объеме, а в контексте бухгалтерии — только финансовую информацию.
- **Изоляция логики и терминологии:**. Один и тот же термин может означать разные вещи в разных контекстах. Например, "Клиент" в маркетинговом контексте — это целевая аудитория, а в контексте продаж — это покупатель с историей заказов.
- **Границы и ответственность:** Каждый контекст имеет свои четко определенные границы, и все, что относится к этому контексту (термины, сущности, события), остается внутри этих границ.
- **Интеграция контекстов:** Разные контексты взаимодействуют через явно определенные способы, такие как события, API, шины сообщений. Это позволяет минимизировать зависимость между контекстами.
Представим систему интернет-магазина. Возможные ограниченные контексты:
- **Каталог продуктов** — управление списком товаров и их характеристиками.
- **Управление заказами** — отслеживание состояния заказов.
- **Склад** — управление инвентарем и логистикой.
- **Бухгалтерия** — расчеты, счета и налоги.
Каждый из этих контекстов оперирует своей моделью данных и логикой, при этом данные могут пересекаться. Например, "Товар" есть в каталоге и на складе, но в каждом из контекстов он будет описан по-разному.
Польза
- [[../efficiency/Снижение когнитивной нагрузки при разработке|Снижение когнитивной нагрузки]] за счет локализации сложных моделей.
- Улучшение читаемости и тестируемости кода.
- Уменьшение зависимости между различными частями системы.
***
## Мета информация
**Область**::
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
- [[Single Responsibility Principle]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,40 @@
---
aliases:
- separate data store
tags:
- maturity/🌱
date: 2024-11-24
---
В [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]] [[Паттерн проектирования|паттерн]] "Database per Service" означает, что у каждого сервиса есть своя собственная, независимая [[../../meta/zero/00 Реляционная база данных|база данных]]. Это позволяет полностью изолировать данные, что обеспечивает независимость и автономность каждого микросервиса. При таком подходе, на этапе выполнения, сервисы не блокируют друг друга, и ни одному из них не приходится ждать из-за конкуренции за доступ к общей базе данных.
Этот паттерн подразумевает, что каждый [[микросервис]] владеет своим хранилищем данных и несёт ответственность за его структуру и управление. ==Это не означает, что для каждого сервиса необходимо выделять отдельный сервер базы данных — вполне возможно использование одного физического сервера с несколькими логически изолированными базами данных== или базой с разными схемами для разных сервисов.
**Преимущества подхода:**
1. **Изоляция данных**. Каждый сервис владеет своими данными, и другие сервисы не имеют прямого доступа к этим данным. Это повышает безопасность и уменьшает вероятность ошибок, вызванных некорректным использованием данных другими сервисами.
2. **Независимость разработки и деплоя**. Каждый микросервис может развиваться, тестироваться и развёртываться независимо, так как изменение структуры данных в одном сервисе не затрагивает другие.
3. **Устранение конкуренции за ресурсы**. Сервис не будет блокирован другим сервисом, который интенсивно использует общую базу данных. Это улучшает производительность и уменьшает задержки.
4. **Масштабируемость**. Каждый сервис может масштабироваться независимо, в том числе и его база данных. Это позволяет учитывать конкретные требования к нагрузке каждого сервиса.
Проблемы
- **Невозможность глобальных транзакций (ACID)**. В случае, когда бизнес-логика требует согласованности данных на уровне нескольких микросервисов, использование ACID-транзакций на уровне всего приложения становится невозможным. Для решения этой проблемы применяются паттерны, такие как [Saga](Реализация%20повествования%20(Saga).md), которые позволяют координировать распределённые транзакции через цепочку локальных операций.
- [[Избыточность данных|Избыточность данных]] и консистентность. Поскольку каждый микросервис владеет своими данными, иногда возникает необходимость дублирования данных между сервисами для обеспечения эффективной работы. Это может привести к проблемам с поддержанием консистентности данных и усложняет управление изменениями.
- **Усложнение запросов**. Если бизнес-логика требует данных из нескольких микросервисов, выполнение сложных запросов становится трудной задачей, поскольку прямое обращение к базе данных другого сервиса не разрешено. В таких случаях приходится использовать API или механизмы синхронизации данных, что усложняет архитектуру.
Лучшие практики
- **Чёткие границы владения данными**. Определите чёткие границы владения данными для каждого сервиса, - [[Bounded Context|Ограниченный контекст]]. Это помогает избежать пересечений и зависимостей между сервисами, а также упрощает управление данными.
- [[../../../../_inbox/Событийно-ориентированное программирование|Событийно-ориентированная архитектура]]. Для обеспечения согласованности данных между микросервисами можно использовать события. Например, при изменении данных в одном сервисе он отправляет событие, на которое подписаны другие сервисы, которым эти данные могут быть нужны.
- **Реализация паттернов для согласованности**. Используйте паттерны, такие как [Saga](Реализация%20повествования%20(Saga).md), чтобы координировать действия между несколькими микросервисами и гарантировать согласованность данных без использования глобальных транзакций.
- **API вместо прямого доступа к данным**. Доступ к данным одного микросервиса другими должен осуществляться только через публичные API. Это помогает соблюдать [[Инкапсуляция|инкапсуляцию]] и обеспечивает безопасное взаимодействие между сервисами.
***
## Мета информация
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
- [[Shared Database|Shared Database]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -16,7 +16,7 @@ linked:
**Как соблюдать DIP** **Как соблюдать DIP**
1. **Работайте с абстракциями:** Замените зависимости на интерфейсы или абстрактные классы. 1. **Работайте с абстракциями:** Замените зависимости на интерфейсы или абстрактные классы.
2. **Инвертируйте зависимости:** Используйте внедрение зависимостей ([[Dependency Injection]]) через конструктор, сеттер или контейнеры. 2. **Инвертируйте зависимости:** Используйте внедрение зависимостей ([[Dependency Injection]]) через конструктор, сеттер или контейнеры.
3. **Минимизируйте жёсткую связанность:** Высокоуровневые модули должны оставаться независимыми от деталей реализации низкоуровневых модулей. 3. Минимизируйте жёсткую [[связанность]]: Высокоуровневые модули должны оставаться независимыми от деталей реализации низкоуровневых модулей.
**Преимущества соблюдения DIP** **Преимущества соблюдения DIP**
1. **Гибкость:** Замена низкоуровневых модулей (реализаций) не требует изменения высокоуровневых модулей. 1. **Гибкость:** Замена низкоуровневых модулей (реализаций) не требует изменения высокоуровневых модулей.

View File

@ -13,7 +13,7 @@ date: 2024-09-27
- **Интерфейсы** или **абстрактные классы**, которые задают общую структуру поведения. - **Интерфейсы** или **абстрактные классы**, которые задают общую структуру поведения.
- [[Полиморфизм]], позволяющий создавать новые реализации без изменения базового кода. - [[Полиморфизм]], позволяющий создавать новые реализации без изменения базового кода.
Следование OCP снижает связанность модулей, делает код проще в тестировании и облегчает внедрение новых функций. Следование OCP снижает [[связанность]] модулей, делает код проще в тестировании и облегчает внедрение новых функций.
**Преимущества соблюдения OCP:** **Преимущества соблюдения OCP:**
1. **Гибкость кода:** Добавление нового функционала не требует изменений существующего кода, что снижает риск ошибок. 1. **Гибкость кода:** Добавление нового функционала не требует изменений существующего кода, что снижает риск ошибок.

View File

@ -0,0 +1,33 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-24
---
Подход "Shared Database" предполагает, что все микросервисы используют одну общую базу данных для хранения данных. Сервисы взаимодействуют напрямую с таблицами, которые принадлежат другим сервисам, что создает зависимости на уровне данных и разрушает [[Инкапсуляция|инкапсуляцию]] между микросервисами.
В [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]] подход, при котором все сервисы общаются с одной общей базой данных, считается скорее анти-паттерном. Несмотря на то, что в некоторых случаях это может показаться более простым решением, такой подход ведет к серьёзным ограничениям и проблемам, особенно в масштабируемых системах. Использование общей базы данных приводит к проблемам с разделением ответственности и нарушает принципы слабой [[Связанность|связанности]] и высокой [[Связность|связности]], которые являются основными в микросервисной архитектуре.
**Проблемы подхода Shared Database**
- Сильная [[связанность]] между сервисами. Общая база данных приводит к явным и неявным зависимостям между сервисами. Это может проявляться через использование триггеров или процедур, которые затрагивают данные разных сервисов. Например, один сервис может использовать процедуру, изменяющую данные, которые принадлежат другому сервису. Такие зависимости делают каждый сервис уязвимым к изменениям в других сервисах.
- **Отсутствие независимости**. Микросервисы должны быть автономными, чтобы их можно было разрабатывать, тестировать и развёртывать независимо друг от друга. Использование общей базы данных приводит к необходимости координации изменений между разными сервисами, что нарушает эту независимость и замедляет процесс разработки.
- **Проблемы с масштабируемостью**. Когда все сервисы используют одну базу данных, её сложно масштабировать. Один сервис может использовать значительное количество ресурсов, создавая нагрузку на базу данных и замедляя работу остальных сервисов. Это делает независимое масштабирование отдельных компонентов практически невозможным.
- **Трудности с тестированием**. Тестирование сервисов в изолированном окружении становится гораздо сложнее, так как все они зависят от одной базы данных. Чтобы протестировать один сервис, нужно воссоздать всю структуру данных, что может потребовать значительных усилий.
**Лучшие практики для избежания Shared Database**
- [[Database per Service]]. Каждый микросервис должен владеть своей собственной базой данных. Это позволяет сохранять автономность сервисов и исключает возможность прямого доступа к данным другого сервиса.
- **Событийная синхронизация.** Если данные одного сервиса нужны другому, лучше использовать [[../../../../_inbox/Событийно-ориентированное программирование|событийную архитектуру]]. Сервис, владеющий данными, может отправлять события, на которые подписываются другие сервисы, что помогает синхронизировать информацию без необходимости прямого доступа к общей базе данных.
- **Использование API для доступа к данным**. Вместо того чтобы обращаться к базе данных другого сервиса напрямую, следует использовать публичные API. Это позволяет соблюсти инкапсуляцию данных и уменьшить связанность между сервисами.
***
## Мета информация
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
- [[Database per service]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -3,6 +3,7 @@ aliases:
- SRP - SRP
- принцип единственной ответственности - принцип единственной ответственности
- Single Responsibility - Single Responsibility
- единственная ответственность
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-09-27 date: 2024-09-27
@ -43,7 +44,7 @@ public class UserManager {
``` ```
Класс `UserManager` выполняет две разные задачи: управление данными пользователя и отправку уведомлений. ==Это нарушает принцип единственной ответственности, так как задачи имеют разные причины для изменения.== Такой подход увеличивает связанность кода, усложняет его поддержку и повышает риск ошибок. Класс `UserManager` выполняет две разные задачи: управление данными пользователя и отправку уведомлений. ==Это нарушает принцип единственной ответственности, так как задачи имеют разные причины для изменения.== Такой подход увеличивает [[связанность]] кода, усложняет его поддержку и повышает риск ошибок.
Разделите обязанности на отдельные классы: Разделите обязанности на отдельные классы:
@ -71,7 +72,7 @@ public class EmailService {
**Создана**:: [[2024-09-27]] **Создана**:: [[2024-09-27]]
**Автор**:: **Автор**::
### Дополнительные материалы ### Дополнительные материалы
- - [[Bounded Context|Ограниченный контекст]]
### Дочерние заметки ### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -12,7 +12,7 @@ date: 2024-10-01
## Классификация ## Классификация
На уровне системы: На уровне системы:
- [[../../../../wiki/zero/Микросервисная архитектура|Микросервисная архитектура]] - [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
- [[../../../../_inbox/Событийно-ориентированное программирование|Событийно-ориентированное программирование]] - [[../../../../_inbox/Событийно-ориентированное программирование|Событийно-ориентированное программирование]]
- [[Асинхронное программирование]] - [[Асинхронное программирование]]
- [[Реактивное программирование|Реактивное программирование]] - [[Реактивное программирование|Реактивное программирование]]
@ -35,10 +35,11 @@ date: 2024-10-01
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Событийно-ориентированное программирование]] - [[Событийно-ориентированное программирование]]
- [[Микросервисная архитектура]]
- [[Inversion of Control]] - [[Inversion of Control]]
- [[Асинхронное программирование]]
- [[Много клиентов — один поток]] - [[Много клиентов — один поток]]
- [[Один клиент — один поток]] - [[Один клиент — один поток]]
- [[Паттерн проектирования]] - [[Паттерн проектирования]]
- [[Асинхронное программирование]] - [[Реактивное программирование]]
- [[00 Микросервисная архитектура]]
<!-- SerializedQuery END --> <!-- SerializedQuery END -->

View File

@ -1,6 +1,7 @@
--- ---
aliases: aliases:
- брокерами сообщений - брокерами сообщений
- очереди сообщений
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-07-02 date: 2024-07-02

View File

@ -0,0 +1,48 @@
---
aliases:
- размер микросервиса
- гранулярность микросервисов
tags:
- maturity/🌱
date: 2024-11-24
---
Гранулярность микросервисов — это один из ключевых вопросов при проектировании распределённых систем. От неё зависит многое: гибкость архитектуры, масштабируемость, время разработки и стоимость поддержки. Однако определение оптимального размера каждого сервиса — задача не из лёгких.
Гранулярность в контексте микросервисной архитектуры — это уровень разделения логики системы на отдельные сервисы. Слишком крупные сервисы рискуют превратиться в монолиты, теряя преимущества микросервисного подхода. Слишком мелкие, наоборот, создают сложности в управлении и коммуникации, что приводит к росту накладных расходов.
Основной вызов заключается в нахождении оптимального баланса. Микросервисы должны быть достаточно маленькими, чтобы можно было легко управлять их жизненным циклом и развивать независимо от других компонентов. В то же время они должны оставаться самодостаточными и функциональными.
**Принципы определения гранулярности**
1. **Бизнес-ориентированность**. Микросервис должен отражать конкретный бизнес-процесс или функциональную область. Если сервис охватывает слишком много бизнес-логики, его стоит разделить на более специализированные компоненты. Например, в системе для интернет-магазина логика управления заказами и обработка платежей должны быть разделены на два сервиса.
2. **Правило единственной ответственности**. Каждый микросервис должен выполнять одну задачу и делать это хорошо. Если сервис отвечает за множество разнородных функций, вероятно, его стоит разделить. Например, сервис, отвечающий и за авторизацию, и за управление профилем пользователя, нарушает принцип единственной ответственности.
3. **Слабая связанность и высокая когезия**. Сервисы должны быть слабо связаны друг с другом, чтобы изменения в одном не требовали изменений в других. В то же время внутренняя логика сервиса должна быть максимально когерентной — все функции должны быть тесно связаны и иметь смысл как единое целое.
4. **Коммуникационные накладные расходы**. При излишнем разделении микросервисов коммуникация между ними может стать значительной проблемой. Каждое взаимодействие требует сетевых запросов, которые увеличивают время отклика и усложняют тестирование. Избежать этого можно, объединяя сервисы, которые часто взаимодействуют друг с другом.
5. **Масштабируемость и независимость деплоя**. Один из ключевых факторов в пользу микросервисов — возможность масштабировать и развертывать сервисы независимо друг от друга. При этом важно помнить, что слишком мелкие микросервисы могут превратиться в головную боль для команды DevOps из-за увеличения количества деплоя и инфраструктурных задач.
**Подходы к выбору гранулярности**
- **Разбиение по доменным областям**. Этот подход предполагает разделение микросервисов по бизнес-доменам. Например, в системе для электронной коммерции могут существовать отдельные сервисы для управления каталогом товаров, работы с корзиной и обработкой платежей.
- **Использование событий**. Событийная архитектура позволяет разделять микросервисы на основе того, как данные движутся через систему. Это помогает уменьшить связанность, так как каждый сервис реагирует только на те события, которые ему необходимы.
- **Практика "Strangler Fig"**. Этот метод подразумевает постепенное выделение функциональности из монолита в микросервисы. Это помогает определить оптимальную гранулярность, анализируя, какие части системы требуют частых изменений и могут быть разделены без излишних коммуникационных накладных расходов.
**Ошибки, которых следует избегать**
1. **Слишком крупные сервисы (микромонолиты)**. Они теряют преимущество независимости и приводят к тому, что разработчики вновь оказываются в рамках монолита, но с более сложной архитектурой деплоя и управления.
2. **Излишняя гранулярность**. Чрезмерное разделение приводит к лавине коммуникаций и делает систему неуправляемой. Это может также вызвать рост сложности в управлении транзакциями и согласованностью данных.
3. **Игнорирование бизнес-логики**. Определение границ микросервисов только на основе технических аспектов, без учёта бизнес-логики, приводит к нарушению когезии и снижению эффективности разработки.
**Практические рекомендации**
- **Начинайте с более крупных сервисов** и постепенно выделяйте их части, когда возникает потребность в независимом развитии и деплое. Это поможет избежать излишней сложности на начальных этапах.
- **Автоматизируйте тестирование и деплой**. Большое количество микросервисов требует высокой степени автоматизации, чтобы поддерживать скорость разработки и гарантировать стабильность.
- **Анализируйте связи между сервисами**. Регулярный анализ зависимостей и коммуникационных потоков поможет понять, не стали ли отдельные сервисы слишком тесно связаны и не следует ли их объединить.
***
## Мета информация
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -1,6 +1,7 @@
--- ---
aliases: aliases:
- домена - домена
- доменных областях
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-09-27 date: 2024-09-27

View File

@ -0,0 +1,44 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-24
---
В [[../../meta/zero/00 HighLoad|высоконагруженных системах]] часто возникает необходимость хранить одни и те же данные в разных формах, чтобы оптимизировать работу различных частей системы. Это один из архитектурных [[Паттерн проектирования|паттернов]], который позволяет справиться с разными требованиями к доступу и обработке данных. Избыточность данных может быть полезной для повышения производительности и удобства работы с различными типами запросов.
Представим ситуацию, когда система хранит переписку между пользователями. Допустим, эта переписка отображается только двум участникам, и в интерфейсе показывается сразу вся история общения. В этом случае данные можно хранить в одном месте — например, даже в виде файла, который легко доступен для обоих пользователей.
Но что если нам нужно вывести список всех переписок пользователя с отображением только последнего сообщения каждой из них? Хранение всей переписки в одном файле становится неудобным, так как для получения последнего сообщения нам нужно будет прочитать все файлы и выбрать необходимую информацию, что занимает много времени и ресурсов.
Правильное решение в такой ситуации — ввести избыточность. Это означает, что вместо попытки хранить все данные в одном месте, необходимо создавать дополнительные структуры данных, которые оптимизированы под разные сценарии использования.
В случае с перепиской можно хранить данные следующим образом:
1. **Основное хранилище для переписок**. Вся история переписки между двумя пользователями хранится в одном месте, что позволяет удобно отображать её целиком, когда это необходимо.
2. **Индекс с последними сообщениями**. Дополнительно создаётся индекс, в котором хранятся только идентификаторы переписок и последние сообщения из каждой из них. Это позволяет быстро получать список переписок с последними сообщениями для отображения на экране.
Преимущества избыточности данных
1. **Оптимизация под разные схемы доступа**. Хранение данных в разных формах позволяет оптимизировать производительность системы под различные сценарии использования. Например, быстрый доступ к последним сообщениям, не читая всю историю переписки.
2. **Увеличение скорости работы**. Избыточность помогает сократить количество операций чтения и уменьшить время выполнения запросов. В случае переписки пользователю не нужно ждать, пока система обработает весь массив данных для получения последних сообщений.
3. **Повышение отказоустойчивости**. Хранение данных в нескольких местах и формах также помогает повысить устойчивость к сбоям. В случае потери одного источника данных, другой может частично компенсировать потерю информации.
Недостатки избыточности данных
1. **Сложность синхронизации**. Поддержание согласованности между несколькими копиями данных — сложная задача. Необходимо следить за тем, чтобы все изменения, внесённые в одну копию, корректно синхронизировались с другими копиями.
2. **Увеличение объёма хранилища**. Хранение данных в нескольких формах требует больше места в хранилище. Для высоконагруженных систем с большими объёмами данных это может стать значительным фактором.
Лучшие практики для работы с избыточностью данных
1. **Продуманная архитектура синхронизации**. Используйте [[Событийно-ориентированное программирование|событийную архитектуру]], чтобы поддерживать согласованность данных. Например, при добавлении нового сообщения можно отправить событие, которое обновит индекс последних сообщений.
2. **Оценка необходимости избыточности**. Вводите избыточность только там, где это действительно необходимо для повышения производительности или удобства работы. Не стоит избыточно усложнять систему там, где этого можно избежать.
3. **Мониторинг консистентности**. Внедряйте механизмы проверки и восстановления консистентности данных между копиями. Это поможет вовремя обнаружить и устранить расхождения.
***
## Мета информация
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,28 @@
---
aliases:
- микросервисы
- сервис
- микросервисов
- сервисов
tags:
- maturity/🌱
date: 2024-11-24
---
Идеальный микросервис:
- [[Single Responsibility Principle|Единственная ответственность]]
- [[Bounded Context|Ограниченный контекст]]. Микросервисы часто строятся вокруг ограниченных контекстов. Один контекст может соответствовать одному микросервису, что упрощает его разбиение, разработку и поддержку. Однако, важно помнить, что ограниченный контекст — это не архитектурный паттерн, а концепция предметной области. Поэтому очень часто за обработку данных одного контекста отвечает множество сервисов.
- [[Связанность]] и [[связность]]
- Принцип проектирования пакетов/сборок
***
## Мета информация
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -29,7 +29,7 @@ linked:
**Кто использует этот подход** **Кто использует этот подход**
- [[../../meta/zero/00 Nginx|Nginx]]. Один из самых известных примеров событийно-ориентированного сервера, использующий асинхронный подход. Nginx эффективно обрабатывает множество клиентских запросов с минимальными затратами ресурсов. - [[../../meta/zero/00 Nginx|Nginx]]. Один из самых известных примеров событийно-ориентированного сервера, использующий асинхронный подход. Nginx эффективно обрабатывает множество клиентских запросов с минимальными затратами ресурсов.
- **Node.js.** Однопоточная архитектура с использованием событийной петли, которая позволяет одному потоку обрабатывать множество запросов одновременно. Node.js широко применяется для построения масштабируемых серверов и микросервисов. - **Node.js.** Однопоточная архитектура с использованием событийной петли, которая позволяет одному потоку обрабатывать множество запросов одновременно. Node.js широко применяется для построения масштабируемых серверов и микросервисов.
- Vert.x и [[../../meta/zero/00 Quarkus|Quarkus]]. Эти фреймворки используют реактивные подходы для обработки запросов, обеспечивая высокую производительность и асинхронную обработку данных в [[../../../../wiki/zero/Микросервисная архитектура|микросервисной архитектуре]]. - Vert.x и [[../../meta/zero/00 Quarkus|Quarkus]]. Эти фреймворки используют реактивные подходы для обработки запросов, обеспечивая высокую производительность и асинхронную обработку данных в [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]].
- Netty. Асинхронный сетевой фреймворк, который широко используется для создания высокопроизводительных сетевых приложений на Java, таких как серверы и клиентские приложения. - Netty. Асинхронный сетевой фреймворк, который широко используется для создания высокопроизводительных сетевых приложений на Java, таких как серверы и клиентские приложения.
*** ***
## Мета информация ## Мета информация

View File

@ -6,12 +6,12 @@ date: 2024-09-27
zero-link: zero-link:
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]" - "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
parents: parents:
- "[[Домен|Домен]]" - "[[Доменная область|Доменная область]]"
linked: linked:
--- ---
**Модель** — это представление [[Домен|домена]] в коде. Она описывает, как сущности и объекты [[Домен|домена]] связаны между собой и взаимодействуют в системе. Модель может включать классы, структуры данных, правила валидации, бизнес-логику и отношения между объектами. **Модель** — это представление [[Доменная область|домена]] в коде. Она описывает, как сущности и объекты [[Доменная область|домена]] связаны между собой и взаимодействуют в системе. Модель может включать классы, структуры данных, правила валидации, бизнес-логику и отношения между объектами.
Хорошо спроектированная модель точно описывает доменные объекты и их поведение. Основная задача модели — предоставлять разработчику инструменты для работы с объектами [[Домен|домена]], обеспечивая соответствие бизнес-правилам и логике. Хорошо спроектированная модель точно описывает доменные объекты и их поведение. Основная задача модели — предоставлять разработчику инструменты для работы с объектами [[Доменная область|домена]], обеспечивая соответствие бизнес-правилам и логике.
*** ***
## Мета информация ## Мета информация
**Область**:: **Область**::

View File

@ -4,6 +4,7 @@ aliases:
- объектно ориентированного программирования - объектно ориентированного программирования
- объектно ориентированное программирование - объектно ориентированное программирование
- объектно-ориентированное программирование - объектно-ориентированное программирование
- объектно-ориентированном программировании
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-09-27 date: 2024-09-27
@ -27,5 +28,6 @@ linked:
### Дочерние заметки ### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Инкапсуляция]]
- [[Полиморфизм]] - [[Полиморфизм]]
<!-- SerializedQuery END --> <!-- SerializedQuery END -->

View File

@ -3,6 +3,7 @@ aliases:
- паттерн - паттерн
- шаблон проектирования - шаблон проектирования
- шаблонов проектирования - шаблонов проектирования
- паттернов
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2023-11-05 date: 2023-11-05

View File

@ -0,0 +1,40 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-24
---
Распределенный монолит — это архитектурный [[Паттерн проектирования|паттерн]], в котором компоненты системы, хотя и развернуты в виде отдельных [[Микросервис|сервисов]], фактически зависят друг от друга настолько, что не могут развиваться и масштабироваться независимо.
Внешне такая архитектура выглядит как микросервисная, но из-за сильной [[Связанность|связанности]] и отсутствия независимости деплоя она теряет все преимущества микросервисного подхода и в итоге становится даже более сложной и неудобной в поддержке, чем традиционный [[../../../../_inbox/Монолитная архитектура|монолит]].
Признаки распределенного монолита:
- Высокая [[Связанность|связанность]] между сервисами, требующие координации при деплое. Из-за этого невозможно обновить или развернуть один сервис без изменения других
- **Глобальные транзакции**, которые охватывают несколько сервисов, что приводит к сильной связанности и усложняет управление согласованностью данных
- **Отсутствие автономности** сервисов. Если один сервис не может работать без другого, и их логика тесно переплетается, то, вероятно, вы имеете дело с распределенным монолитом.
- **Общие схемы данных**. Использование общей базы данных или общей схемы между сервисами приводит к тесной связанности и усложняет внесение изменений без координации между командами.
Причины появления распределенного монолита
- **Недостаточное понимание микросервисных принципов**. При переходе от монолита к микросервисам важно пересмотреть подходы к разработке и взаимодействию между компонентами. Не все команды понимают, что микросервисы требуют не только разбиения на отдельные сервисы, но и пересмотра способов их взаимодействия и управления данными.
- Излишняя [[Гранулярность микросервисов|гранулярность микросервисов]]. Желание сделать сервисы как можно более маленькими и специализированными иногда приводит к обратному результату — коммуникационные накладные расходы становятся слишком большими, и система превращается в распределенный монолит с большим количеством зависимостей.
- **Общие ресурсы**. Использование общих баз данных ([[Shared Database|Shared Database]]) или сервисов, которые нельзя изменить независимо, приводит к тому, что сервисы не могут быть развернуты или изменены самостоятельно.
- **Плохой дизайн API**. Сервисные интерфейсы, которые создают жесткие зависимости и требуют координации между разными сервисами, также способствуют появлению распределенного монолита.
Как избежать создания распределенного монолита
- **Слабая связанность и независимость деплоя**. Стремитесь к тому, чтобы сервисы были как можно более независимыми друг от друга. Это касается не только разработки, но и данных. Каждому микросервису должна принадлежать своя база данных ([[Database per service|Database per service]]), чтобы минимизировать зависимость от других сервисов.
- **Декомпозиция по бизнес-доменам**. Разделение системы на сервисы должно основываться на бизнес-логике и [[Доменная область|доменных областях]]. Сервисы должны быть построены вокруг конкретных бизнес-процессов, а не технических компонентов, что поможет избежать тесной связанности.
- [[../../../../_inbox/Событийно-ориентированное программирование|Событийно-ориентированное программирование]]. Использование событийной модели взаимодействия позволяет уменьшить тесную связанность сервисов и избавиться от необходимости прямого взаимодействия между ними. Сервисы реагируют на события, а не вызывают друг друга напрямую, что повышает автономность.
- **Асинхронные коммуникации**. Использование асинхронных методов взаимодействия, таких как [[Брокер сообщений|очереди сообщений]], снижает связанность между сервисами и позволяет им работать независимо друг от друга.
***
## Мета информация
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,39 @@
---
aliases:
- coupling
- связанности
- связанность
tags:
- maturity/🌱
date: 2024-11-24
---
Связанность (coupling) — это мера зависимости между модулями компонента. Если модули сильно связаны, изменение одного модуля требует изменения и в других модулях, что затрудняет их поддержку и развитие. Идеальной является слабая связанность (loose coupling), когда модули минимально зависят друг от друга.
**Преимущества слабой связанности**
- **Упрощение модификации**. Система, состоящая из слабо связанных модулей, легче модифицируется, так как изменения в одном модуле минимально затрагивают другие.
- **Улучшение тестируемости**. Слабо связанные модули проще тестировать изолированно, что способствует выявлению и устранению ошибок на ранних стадиях.
**Примеры применения**
1. [[../../../../wiki/zero/00 Микросервисная архитектура|Микросервисная архитектура]]. При проектировании микросервисной архитектуры важно, чтобы каждый сервис был слабо связан с другими, что позволяет им развиваться независимо. Сервис с высокой связанностью сосредоточен на конкретной бизнес-задаче, например, управлении пользователями или платежами.
2. **Пакеты в монолитной системе**. В монолитных системах правильное разделение на пакеты может значительно снизить связанность. Например, отдельный пакет для работы с базой данных должен иметь минимальные зависимости от бизнес-логики.
3. **Классы в объектно-ориентированном программировании**. Слабая связанность между классами позволяет изменять один класс без значительного влияния на другие.
**Антипаттерны и частые ошибки**
- [[Циклические зависимости сервисов]]. Модули не должны иметь циклические зависимости, так как это сильно увеличивает связанность и затрудняет поддержку системы. Решением может быть введение интерфейсов или абстракций для разрыва циклов.
**Рекомендации**
- **Применение интерфейсов и абстракций**. Использование интерфейсов помогает уменьшить связанность, так как модули взаимодействуют через абстракции, а не напрямую.
- Регулярный [[../efficiency/Рефакторинг кода|рефакторинг]]. Постоянное улучшение кода помогает устранить чрезмерные зависимости и поддерживать слабую связанность между модулями.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
- [[Связность|Связность]]
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,104 @@
---
aliases:
- Cohesion
- связности
tags:
- maturity/🌱
date: 2024-11-24
---
Связность (cohesion) — это мера того, насколько функции внутри одного модуля связаны друг с другом и работают вместе для выполнения конкретной задачи. Высокая связность означает, что модуль фокусируется на одной задаче и все его компоненты направлены на достижение этой цели. Например, модуль обработки платежей включает только функции, связанные с платежами, что делает его логически целостным.;
Примеры применения
- [[../../../../wiki/zero/00 Микросервисная архитектура|Микросервисная архитектура]]. Сервис с высокой связностью сосредоточен на конкретной бизнес-задаче, например, управлении пользователями или платежами. Это позволяет эффективно выполнять свою функцию и поддерживать независимость сервиса. Например, сервис управления пользователями может добавлять, обновлять и удалять пользователей без взаимодействия с другими сервисами, что делает его легким в поддержке.
- **Пакеты в монолитной системе**. В монолитных системах правильное разделение на пакеты может значительно улучшить связность. Например, отдельный пакет для работы с базой данных должен иметь высокую связность внутри себя, чтобы все его компоненты были направлены на работу с данными.
- Классы в [[ООП|объектно-ориентированном программировании]]. Классы с высокой связностью содержат методы, направленные на выполнение одной конкретной задачи, что упрощает их поддержку и тестирование.
**Преимущества высокой связности**
- **Повышение переиспользуемости**. Высокая связность модулей позволяет их легче переиспользовать, так как все необходимые функции сосредоточены в одном месте.
- **Упрощение модификации**. Модуль с высокой связностью легче модифицировать, так как все его компоненты работают вместе для достижения одной цели.
**Антипаттерны и частые ошибки**
- **Божественный объект (God Object)**. Это пример нарушения принципа высокой связности, когда один класс или модуль берет на себя слишком много обязанностей и имеет зависимости на многие другие части системы. Такой дизайн затрудняет понимание и модификацию кода.
**Рекомендации**
- [[Single Responsibility Principle|Принцип единственной ответственности]] (SRP). Каждый модуль или класс должен иметь одну четко определенную ответственность, что повышает связность и облегчает поддержку кода.
- Регулярный [[../efficiency/Рефакторинг кода|рефакторинг]]. Постоянное улучшение кода помогает повысить связность внутри модулей, устраняя излишние обязанности и сосредоточивая функции на одной задаче.
## Антипример микросервисной архитектуры
Рассмотрим пример интернет-магазина, в котором реализовано три разных вида доставки: доставка в пункт выдачи, доставка курьером и доставка в магазин. Для каждой из этих задач были созданы отдельные микросервисы: `PickupPointService`, `CourierDeliveryService` и `StoreDeliveryService`.
На первый взгляд, это выглядит как хороший подход, однако на практике каждое из этих решений может развиваться в разных направлениях и иметь различные бизнес-требования. В будущем может оказаться, что добавление новых функций в один из сервисов требует изменения логики и усложняет взаимодействие между сервисами, что может привести к дублированию бизнес-логики в нескольких местах.
Кроме того, чтобы посчитать время доставки, каждый из этих сервисов должен знать и запросить время комплектации заказа. Это означает, что одно и то же время комплектации будет запрашиваться несколько раз разными сервисами, что приводит к избыточным обращениям и усложняет координацию между сервисами.
В таких случаях объединение этой логики могло бы уменьшить сложность и избежать проблем с несогласованностью изменений в разных сервисах. Это пример того, когда дублирование и разделение по типу доставки могут изначально выглядеть оправданными, но на практике могут усложнить поддержку системы.
## Примеры кода
Высокая связность (Good Cohesion)
```java
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User createUser(String name, String email) {
// Логика создания пользователя
User user = new User(name, email);
return userRepository.save(user);
}
public User getUserById(Long id) {
// Логика получения пользователя по ID
return userRepository.findById(id);
}
}
```
В этом примере класс `UserService` имеет высокую связность, так как все его методы связаны с управлением пользователями и взаимодействием с `UserRepository`. Высокая связность делает класс легче поддерживаемым, поскольку все функции находятся в одном месте, что упрощает внесение изменений и тестирование, а также способствует лучшей организации кода и уменьшению сложности.
Низкая связность (Bad Cohesion)
```java
public class UserUtility {
private final UserRepository userRepository;
private final EmailService emailService;
public UserUtility(UserRepository userRepository, EmailService emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
public User createUser(String name, String email) {
// Логика создания пользователя
User user = new User(name, email);
return userRepository.save(user);
}
public void sendWelcomeEmail(User user) {
// Логика отправки приветственного письма
emailService.sendEmail(user.getEmail(), "Welcome!");
}
public void deleteUser(Long id) {
// Логика удаления пользователя
userRepository.deleteById(id);
}
}
```
В этом примере класс `UserUtility` имеет низкую связность, так как в нем сочетаются разные обязанности: управление пользователями, отправка email, удаление пользователей. Такой класс сложно поддерживать и тестировать, так как его методы не связаны одной конкретной задачей.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -12,7 +12,7 @@ linked:
Циклические зависимости между сервисами возникают, когда сервисы взаимно внедряются друг в друга. Например, сервис А внедряет сервис Б, но в тоже время сервис Б внедряет сервис А. В этом случае [SpringBoot](../../meta/zero/00%20SpringBoot.md) и [Quarkus](../../meta/zero/00%20Quarkus.md) не знают, как создать такие бины и внедрить их друг в друга. Циклические зависимости между сервисами возникают, когда сервисы взаимно внедряются друг в друга. Например, сервис А внедряет сервис Б, но в тоже время сервис Б внедряет сервис А. В этом случае [SpringBoot](../../meta/zero/00%20SpringBoot.md) и [Quarkus](../../meta/zero/00%20Quarkus.md) не знают, как создать такие бины и внедрить их друг в друга.
> [!WARNING] > [!WARNING]
> Обычно такая ситуация сигнализирует о плохо продуманной архитектуре приложения. > Обычно такая ситуация сигнализирует о плохо продуманной архитектуре приложения. Модули не должны иметь циклические зависимости, так как это сильно увеличивает [[связанность]] и затрудняет поддержку системы.
Пример циклической зависимости в Spring: Пример циклической зависимости в Spring:

View File

@ -1,6 +1,7 @@
--- ---
aliases: aliases:
- рефакторинг - рефакторинг
- рефакторинга
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-11-24 date: 2024-11-24

View File

@ -2,6 +2,7 @@
aliases: aliases:
- когнитивную нагрузку - когнитивную нагрузку
- снижать когнетивную нагрузку - снижать когнетивную нагрузку
- Снижение когнитивной нагрузки
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-11-24 date: 2024-11-24
@ -13,6 +14,7 @@ date: 2024-11-24
- [[Рефакторинг кода]] - [[Рефакторинг кода]]
- Документация и [[../Комментарии в коде|комментирование кода]] - Документация и [[../Комментарии в коде|комментирование кода]]
- [[Don't Repeat Yourself]] - [[Don't Repeat Yourself]]
- [[../architecture/Bounded Context|Bounded Context]]
- **Разделение задач на мелкие части**. Разделение больших задач на мелкие и четко определенные части позволяет легче управлять процессом разработки и снижает когнитивную нагрузку. Выполнение небольшой задачи проще и требует меньше усилий, чем работа с большим блоком, который трудно полностью удержать в голове. - **Разделение задач на мелкие части**. Разделение больших задач на мелкие и четко определенные части позволяет легче управлять процессом разработки и снижает когнитивную нагрузку. Выполнение небольшой задачи проще и требует меньше усилий, чем работа с большим блоком, который трудно полностью удержать в голове.
- **Инструменты автоматизации** Инструменты, которые автоматизируют повторяющиеся действия, значительно снижают когнитивную нагрузку. Например, использование систем CI/CD для автоматической сборки и тестирования, статического анализа кода и инструментов мониторинга позволяет не отвлекаться на рутину и сосредоточиться на решении более сложных задач. - **Инструменты автоматизации** Инструменты, которые автоматизируют повторяющиеся действия, значительно снижают когнитивную нагрузку. Например, использование систем CI/CD для автоматической сборки и тестирования, статического анализа кода и инструментов мониторинга позволяет не отвлекаться на рутину и сосредоточиться на решении более сложных задач.
*** ***

View File

@ -16,7 +16,7 @@ linked:
В отличие от традиционной виртуализации ([Гипервизор](../../../../_inbox/Гипервизор.md)), где каждая виртуальная машина работает со своей собственной операционной системой, контейнеры делят одну и ту же операционную систему хоста, но остаются изолированными друг от друга. Это достигается благодаря использованию [Namespace](Namespace.md) и [Control group](Control%20group.md) в Linux, которые обеспечивают изоляцию и управление ресурсами на уровне процессов. В отличие от традиционной виртуализации ([Гипервизор](../../../../_inbox/Гипервизор.md)), где каждая виртуальная машина работает со своей собственной операционной системой, контейнеры делят одну и ту же операционную систему хоста, но остаются изолированными друг от друга. Это достигается благодаря использованию [Namespace](Namespace.md) и [Control group](Control%20group.md) в Linux, которые обеспечивают изоляцию и управление ресурсами на уровне процессов.
**Плюсы:** **Плюсы:**
- **Легковесность**: Контейнеры требуют меньше ресурсов, чем традиционные виртуальные машины, поскольку они делят ядро хост-системы и не нуждаются в своей собственной операционной системе. Это делает их идеальными для [микросервисной архитектуры](Микросервисная%20архитектура.md) и облачных приложений. - **Легковесность**: Контейнеры требуют меньше ресурсов, чем традиционные виртуальные машины, поскольку они делят ядро хост-системы и не нуждаются в своей собственной операционной системе. Это делает их идеальными для [микросервисной архитектуры](../../../../wiki/zero/00%20Микросервисная%20архитектура.md) и облачных приложений.
- **Портативность**: Приложения в контейнерах инкапсулируют все свои зависимости, что обеспечивает их безопасное и последовательное выполнение в любой среде, будь то локальный компьютер разработчика, тестовая среда или облачная инфраструктура. - **Портативность**: Приложения в контейнерах инкапсулируют все свои зависимости, что обеспечивает их безопасное и последовательное выполнение в любой среде, будь то локальный компьютер разработчика, тестовая среда или облачная инфраструктура.
- **Быстрое развертывание и масштабирование**: Контейнеры можно создавать, запускать и останавливать за секунды, что делает процесс развертывания и масштабирования приложений быстрым и эффективным. - **Быстрое развертывание и масштабирование**: Контейнеры можно создавать, запускать и останавливать за секунды, что делает процесс развертывания и масштабирования приложений быстрым и эффективным.
- **Эффективность использования ресурсов**: Контейнеры позволяют более эффективно использовать системные ресурсы, повышая общую утилизацию инфраструктуры. - **Эффективность использования ресурсов**: Контейнеры позволяют более эффективно использовать системные ресурсы, повышая общую утилизацию инфраструктуры.

View File

@ -4,7 +4,7 @@ tags:
- maturity/🌱 - maturity/🌱
date: 2024-04-12 date: 2024-04-12
--- ---
- Подходит для [[../../../../wiki/zero/Микросервисная архитектура|микросервисных архитектур]] для межсервисного общения. - Подходит для [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисных архитектур]] для межсервисного общения.
## Как работает? ## Как работает?
![[../../meta/files/images/Pasted image 20241103005832.png]] ![[../../meta/files/images/Pasted image 20241103005832.png]]

View File

@ -4,6 +4,7 @@ tags:
- maturity/🌱 - maturity/🌱
date: 2024-11-05 date: 2024-11-05
--- ---
- [[2024-11-24]]. (6/10) [Гранулярность микросервисов. Как мелко нарезать? / Руслан Сафин (Byndyusoft) - YouTube](https://www.youtube.com/watch?v=x1xqlXnyXp8)
- [[2024-11-05]]. (4/10) [Топ ошибок со стороны разработки при работе с PostgreSQL / Алексей Лесовский (Data Egret) - YouTube](https://www.youtube.com/watch?v=HjLnY0aPQZo&t=17s) - [[2024-11-05]]. (4/10) [Топ ошибок со стороны разработки при работе с PostgreSQL / Алексей Лесовский (Data Egret) - YouTube](https://www.youtube.com/watch?v=HjLnY0aPQZo&t=17s)
- [[2024-11-05]]. (7/10) [Владимир Ситников — B-Tree индексы в базах данных на примере Spring Boot-приложений, PostgreSQL, JPA - YouTube](https://www.youtube.com/watch?v=y-Wtyvme4gE) - [[2024-11-05]]. (7/10) [Владимир Ситников — B-Tree индексы в базах данных на примере Spring Boot-приложений, PostgreSQL, JPA - YouTube](https://www.youtube.com/watch?v=y-Wtyvme4gE)
- [[2024-11-05]]. (8/10) [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s) - [[2024-11-05]]. (8/10) [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s)

View File

@ -0,0 +1,61 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-24
---
Часто в программировании дублирование кода считается антишаблоном, и существует стремление избежать его с помощью [[efficiency/Рефакторинг кода|рефакторинга]] и выделения общего функционала в отдельные методы или классы.
Однако не каждое дублирование кода — это плохо, и иногда оно может быть оправдано. Например, ==дублирование может быть оправдано, когда участки кода выполняют похожие задачи, но с потенциалом для различного развития в будущем==, или когда абстракция добавит ненужную сложность и снизит [[Читаемый код|читаемость]].
Одним из примеров, когда дублирование кода не является ошибкой, является ситуация, когда код выполняет похожие, но не идентичные задачи. Такие ==дублирующиеся участки могут иметь разные цели и эволюционировать независимо, в зависимости от требований==. Например, методы обработки данных для разных типов клиентов могут развиваться с учетом специфики каждого случая, сохраняя свою уникальность.
**Когда дублирование допустимо**
- **Независимое развитие логики**. Если два участка кода имеют потенциал для разного развития в будущем, лучше оставить их отдельно.
- **Простота понимания**. Иногда небольшое дублирование делает код проще для понимания, поскольку каждый модуль содержит всю необходимую информацию для выполнения своей задачи, без излишней зависимости от общего функционала.
- **Отсутствие преждевременной абстракции**. Преждевременная оптимизация и создание абстракций могут привести к созданию излишне сложных конструкций, которые сложно поддерживать. Дублирование кода может помочь избежать преждевременного усложнения архитектуры.
Рассмотрим ситуацию, когда в системе обработки заказов существует два похожих метода для расчета скидок, но для разных типов клиентов. Допустим, у нас есть метод расчета скидок для розничных клиентов и метод расчета скидок для корпоративных клиентов:
```java
public class RetailCustomerDiscountCalculator {
public double calculateDiscount(Order order) {
// Логика расчета скидки для розничного клиента
double discount = 0;
if (order.getTotalAmount() > 100) {
discount = 10;
}
// Дополнительные условия и правила
return discount;
}
}
public class CorporateCustomerDiscountCalculator {
public double calculateDiscount(Order order) {
// Логика расчета скидки для корпоративного клиента
double discount = 0;
if (order.getTotalAmount() > 500) {
discount = 15;
}
// Дополнительные условия и правила, уникальные для корпоративных клиентов
return discount;
}
}
```
Методы `calculateDiscount` в обоих классах имеют схожую логику, и на первый взгляд их можно объединить в один общий метод. Однако, правила расчета скидок для розничных и корпоративных клиентов могут измениться и развиваться в разных направлениях. Например, для корпоративных клиентов могут добавиться специфические условия, такие как скидки за объем или специальные акции, в то время как для розничных клиентов будут учитываться другие критерии, такие как лояльность или сезонные предложения.
Объединение этих методов в один общий могло бы создать ненужную сильную [[architecture/Связанность|связанность]] между разными бизнес-правилами, что усложнило бы внесение изменений и тестирование. Это может привести к тому, что изменения в одной части логики скидок затр онут другую, даже если для этого нет необходимости, что затруднит дальнейшее развитие. В таких случаях лучше оставить дублирование, чтобы обеспечить гибкость и независимость развития каждой части системы.
***
## Мета информация
**Область**:: [[../meta/zero/00 Эффективная разработка|00 Эффективная разработка]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -5,6 +5,7 @@ aliases:
- читаем код - читаем код
- код пишется для людей, а не для машин - код пишется для людей, а не для машин
- понимания кода - понимания кода
- читаемость
tags: tags:
- maturity/🌱 - maturity/🌱
- content/opinion - content/opinion

View File

@ -52,7 +52,7 @@ aliases:
- Кластеризация - Кластеризация
- Денормализация - Денормализация
- Параллельное выполнение - Параллельное выполнение
- [Избыточность](Избыточность.md) - [Избыточность данных](../../dev/architecture/Избыточность%20данных.md)
- [Допустимая деградация системы](Допустимая%20деградация%20системы.md) - [Допустимая деградация системы](Допустимая%20деградация%20системы.md)
## Улучшения ## Улучшения

View File

@ -1,5 +1,6 @@
--- ---
aliases: aliases:
- Redis
tags: tags:
- maturity/🌱 - maturity/🌱
date: date:
@ -9,7 +10,9 @@ zero-link:
linked: linked:
- "[[Memcached]]" - "[[Memcached]]"
--- ---
Remote Dictionary Service (Redis) — это хранилище данных на основе [[../../../../knowledge/dev/pc/Оперативная память|оперативной памяти]] (RAM) организованное по принципу "[[../../dev/Key-Value хранилище|ключ-значение]]". Работает с использованием [кооперативной многозадачности](../../dev/fundamental/Кооперативная%20многозадачность.md). Redis (Remote Dictionary Service) — это хранилище данных на основе [[../../../../knowledge/dev/pc/Оперативная память|оперативной памяти]], построенное на архитектуре "[[../../dev/Key-Value хранилище|ключ-значение]]". Оно отличается высокой производительностью благодаря использованию IO multiplexing и однопоточному [[../../dev/architecture/Event Loop|event loop]], что позволяет эффективно обрабатывать запросы. Основная область применения Redis — это системы с требованиями к минимальной задержке и высокой скорости обработки данных.
Redis использует однопоточную модель выполнения с использованием multiplexing для работы с запросами, что обеспечивает простоту реализации и высокую производительность.
- [[../../dev/system-design/Конфигурация Redis|Конфигурация Redis]] - [[../../dev/system-design/Конфигурация Redis|Конфигурация Redis]]
- [[../../dev/system-design/Команды Redis-cli|Команды Redis-cli]] - [[../../dev/system-design/Команды Redis-cli|Команды Redis-cli]]
@ -26,27 +29,36 @@ Remote Dictionary Service (Redis) — это хранилище данных н
- Можно включить аутентификацию - Можно включить аутентификацию
- Есть транзакции - Есть транзакции
**Недостатки:** **Преимущества
- Сложный в настройках - Высокая скорость доступа к данным благодаря оперативной памяти.
- Поддержка сложных структур данных.
- Простота интеграции и использования через CLI и клиентские библиотеки.
Redis может использоваться в различных сценариях, как показано на диаграмме: **Недостатки:**
- **Сессии**: Redis может хранить данные пользовательских сессий для их совместного использования между разными сервисами. - Сложность настройки и управления кластером.
- [[../../dev/architecture/Кэширование|Кэширование]]: Использование Redis для кэширования объектов или страниц, особенно для данных с высокой частотой запросов. - Ограниченная надёжность в режиме pub/sub по сравнению с другими системами (например, RabbitMQ).
- **Распределённая блокировка**: Redis может использоваться для установки блокировок между распределёнными сервисами, используя строковые значения. - Использование оперативной памяти ограничивает объём хранимых данных.
- **Счётчик**: Можно использовать для подсчета, например, количества лайков или просмотров статей.
Redis может использоваться в различных сценариях:
- [[../../dev/architecture/Кэширование|Кэширование]]: ускорение обработки данных с частым доступом.
- **Управление сессиями**: хранение данных сессий пользователей.
- Распределённая [[../../dev/fundamental/Блокировка|блокировка]]: установка блокировок между сервисами.
- **Очереди сообщений**: управление сообщениями с использованием структур данных (списки, потоки).
- **Подсчёт данных**: подсчёт просмотров, лайков.
- **Ограничитель частоты запросов**: Redis позволяет устанавливать лимиты на частоту запросов для определённых IP-адресов пользователей. - **Ограничитель частоты запросов**: Redis позволяет устанавливать лимиты на частоту запросов для определённых IP-адресов пользователей.
- **Рейтинги и сортировки**: с помощью сортированных множеств (ZSet).
- **Генератор глобальных ID**: Можно использовать Redis для генерации глобальных идентификаторов с помощью целочисленных значений. - **Генератор глобальных ID**: Можно использовать Redis для генерации глобальных идентификаторов с помощью целочисленных значений.
- **Корзина покупок**: Redis Hash подходит для представления пар ключ-значение в корзине покупок.
- **Расчет удержания пользователей**: Bitmap можно использовать для ежедневного учета входов пользователей и расчета удержания.
- **Очередь сообщений**: Redis List можно использовать как очередь сообщений.
- **Рейтинг**: ZSet можно использовать для сортировки статей и формирования рейтингов.
![[../files/images/Pasted image 20241103034136.png]] ![[../files/images/Pasted image 20241103034136.png]]
- Доступ к данным в RAM как минимум в 1000 раз быстрее, чем произвольный доступ к данным на диске. - Доступ к данным в RAM как минимум в 1000 раз быстрее, чем произвольный доступ к данным на диске.
- Redis использует IO multiplexing и [[../../dev/architecture/Event Loop|single-threaded execution loop]] для повышения эффективности работы. - Redis использует IO multiplexing и [[../../dev/architecture/Event Loop|single-threaded execution loop]] для повышения эффективности работы.
- Кроме того, Redis задействует несколько эффективных низкоуровневых структур данных. - Кроме того, Redis задействует несколько эффективных низкоуровневых структур данных.
Redis поддерживает два типа сохранения данных.
- [[../../dev/system-design/Redis Database Backup|RDB]] создание снимков базы данных через заданные промежутки времени
- [[../../dev/system-design/Append-Only File|AOF]] логирование каждой операции для минимизации потерь данных
Комбинированный подход RDB + AOF позволяет добиться как высокой производительности, так и надёжности. В случае катастрофы Redis сначала восстанавливает данные из последнего RDB-снапшота, а затем воспроизводит команды из AOF, чтобы восстановить данные до актуального состояния.
## Кластеризация ## Кластеризация
Реплики работают только в режиме чтения. Нужно на стороне клиента понять в какую реплику нужно писать ключ. При отправке запроса не в ту реплику, редис ответит ошибкой, указав хост, куда нужно отправить запрос. Реплики работают только в режиме чтения. Нужно на стороне клиента понять в какую реплику нужно писать ключ. При отправке запроса не в ту реплику, редис ответит ошибкой, указав хост, куда нужно отправить запрос.
@ -54,12 +66,5 @@ Redis может использоваться в различных сценар
Есть senitel. Который выступает оркестратором и прокси. Он сам будет отправлять запросы в нужную ноду. Он же будет отвечать за Failover? Есть senitel. Который выступает оркестратором и прокси. Он сам будет отправлять запросы в нужную ноду. Он же будет отвечать за Failover?
## Заметки ## Заметки
Redis поддерживает одновременное использование как RDB, так и AOF. Это даёт возможность гибридного подхода:
- [[../../dev/system-design/Redis Database Backup|RDB]] обеспечивает быстрые резервные копии и восстановление базы данных, снижая нагрузку на производительность.
- [[../../dev/system-design/Append-Only File|AOF]] минимизирует вероятность потери данных, записывая каждую операцию.
В случае катастрофы Redis сначала восстанавливает данные из последнего RDB-снапшота, а затем воспроизводит команды из AOF, чтобы восстановить данные до актуального состояния.
- Порт по умолчанию 6379 - Порт по умолчанию 6379
- Может работать с геолокациями - Может работать с геолокациями
- Показывает лучший результат производительности при использовании подписок, чем [00 RabbitMQ](00%20RabbitMQ.md). Но при этом может страдать надежность доставки.

View File

@ -15,7 +15,7 @@ aliases:
- [[../../dev/architecture/CAP теорема|CAP теорема]] - [[../../dev/architecture/CAP теорема|CAP теорема]]
- [Трёхзвенная структура](../../dev/architecture/Трёхзвенная%20структура.md) - [Трёхзвенная структура](../../dev/architecture/Трёхзвенная%20структура.md)
- [Монолитная архитектура](Монолитная%20архитектура.md) - [Монолитная архитектура](Монолитная%20архитектура.md)
- [Микросервисная архитектура](Микросервисная%20архитектура.md) - [00 Микросервисная архитектура](../../../../wiki/zero/00%20Микросервисная%20архитектура.md)
- [Service Oreinted Architecture](Service%20Oreinted%20Architecture.md) - [Service Oreinted Architecture](Service%20Oreinted%20Architecture.md)
- [[00 HighLoad|HighLoad]] - [[00 HighLoad|HighLoad]]