Чистая архитектура: главы 1-2
Начала читать книгу Clean architecture Роберта Мартина.
Давно чувствую в этой теме какой-то пробел. Идея о непорочной бизнес-логике мне нравится, но на практике я не видела хороших примеров.
Видела сервисы, которые задумывались как "чистые", но в итоге становились проблемными. Протекающие слои, костыли, проблемы с транзакциями и атомарностью в целом. Не всегда понятно, как вписать некоторые задачи в рамку чистой архитектуры.
У меня нет больших ожиданий. Книга 2017 года, да и Мартин вряд ли плотно работал в энтерпрайзе, когда её писал. Но мне интересно почитать первоисточник и идейную составляющую.
И по первым впечатлениям - книга очень противоречивая.
Поднимается много тем - от парадигм программирования до структуры папок в проекте. Есть что обсудить👌
Но книгу читать сложно. Бесконечно много исторических справок и отступлений. Не всегда понятно, что хочет сказать автор, и как это связано с чистой архитектурой.
Поэтому решила делиться с вами процессом чтения. Это не будет подробный конспект, скорее спидран/реакция/саммари. Буду отмечать, что мне показалось интересным. Думаю, получится полезно.
Главы 1 и 2 - это введение. Большой смысловой нагрузки пока нет.
⭐️ Глава 1 ⭐️
Чем лучше архитектура, тем меньше усилий требуется на новые фичи и поддержку. Поддерживать плохую архитектуру со временем становится долго и дорого. При этом разработчики грустят, и менеджеры проваливают сроки
⭐️ Глава 2 ⭐️
Бизнес всегда требует работать над функционалом. Следить за архитектурой и состоянием системы, отстаивать необходимость рефакторинга и времени на проектирование - обязанность инженера.
Собственно, и всё.
Согласна с основной идеей второй главы, но читать крайне не рекомендую. В тексте очень много снобизма. Красной нитью идет мысль, что большинство разработчиков и менеджеров - узколобые макаки, которым плевать на архитектуру и лишь бы закрыть задачки поскорее.
В целом, Мартин кажется противоречивым персонажем, поэтому интересно, что будет дальше. Идеалистические концепты? Конкретные инструкции? 400 страниц воды? Посмотрим, обсудим
Начала читать книгу Clean architecture Роберта Мартина.
Давно чувствую в этой теме какой-то пробел. Идея о непорочной бизнес-логике мне нравится, но на практике я не видела хороших примеров.
Видела сервисы, которые задумывались как "чистые", но в итоге становились проблемными. Протекающие слои, костыли, проблемы с транзакциями и атомарностью в целом. Не всегда понятно, как вписать некоторые задачи в рамку чистой архитектуры.
У меня нет больших ожиданий. Книга 2017 года, да и Мартин вряд ли плотно работал в энтерпрайзе, когда её писал. Но мне интересно почитать первоисточник и идейную составляющую.
И по первым впечатлениям - книга очень противоречивая.
Поднимается много тем - от парадигм программирования до структуры папок в проекте. Есть что обсудить👌
Но книгу читать сложно. Бесконечно много исторических справок и отступлений. Не всегда понятно, что хочет сказать автор, и как это связано с чистой архитектурой.
Поэтому решила делиться с вами процессом чтения. Это не будет подробный конспект, скорее спидран/реакция/саммари. Буду отмечать, что мне показалось интересным. Думаю, получится полезно.
Главы 1 и 2 - это введение. Большой смысловой нагрузки пока нет.
⭐️ Глава 1 ⭐️
Чем лучше архитектура, тем меньше усилий требуется на новые фичи и поддержку. Поддерживать плохую архитектуру со временем становится долго и дорого. При этом разработчики грустят, и менеджеры проваливают сроки
⭐️ Глава 2 ⭐️
Бизнес всегда требует работать над функционалом. Следить за архитектурой и состоянием системы, отстаивать необходимость рефакторинга и времени на проектирование - обязанность инженера.
Собственно, и всё.
Согласна с основной идеей второй главы, но читать крайне не рекомендую. В тексте очень много снобизма. Красной нитью идет мысль, что большинство разработчиков и менеджеров - узколобые макаки, которым плевать на архитектуру и лишь бы закрыть задачки поскорее.
В целом, Мартин кажется противоречивым персонажем, поэтому интересно, что будет дальше. Идеалистические концепты? Конкретные инструкции? 400 страниц воды? Посмотрим, обсудим
🔥114👍47❤22🎄4👎3
Чистая архитектура. Главы 3-5
Продолжаем спидран по Clean Architecture Роберта Мартина.
⭐️ Глава 3. Парадигмы программирования ⭐️
определяют способы написания и организации кода. Их 3:
▫️ Структурная - ход программы описывается явно через условия и циклы. Используется для описания алгоритмов
▫️ Обьектно-ориентированная - программа описывается как взаимодействие объектов. Используется полиморфизм, ход работы не всегда очевиден
▫️ Функциональная - базируется на неизменяемости
⭐️ Глава 4. Структурное программирование ⭐️
Код делится на небольшие функции, которые можно протестировать. Но если тесты проходят - не факт, что программа работает корректно. Большую часть главы занимают истории, как Дейкстра боролся против goto и пытался математически доказать корректность программ.
⭐️ Глава 5. Обьектно-ориентированное (ОО) программирование ⭐️
Роберт рассуждает, что полезного и нового предлагает ООП
▫️ Инкапсуляция - не уникальна для ООП, плюс в современных языках не решает свою задачу.
Исходная цель инкапсуляции - скрыть данные и дать пользователю ограниченный набор методов.
В С (предшественник С++) определение функции и реализация разнесены по разным файлам, там инкапсуляция нормальная. В современных ОО языках инкапсуляция слабая. Нет разделения на определение и реализацию. Чтобы посмотреть, что умеет класс, надо зайти в класс, и тут открывается вся его внутрянка. Детали реализации как на ладони.
(мысль интересная, но с текущими IDE это не актуально. Выпадающие списки методов делают большой вклад в сокрытие сложности)
▫️ Наследование - всего лишь переопределение переменных/функций в ограниченном контексте. Добавочной ценности для архитектуры нет.
▫️ Полиморфизм легко и безопасно реализован в ОО языках, и в этом его главная ценность. Благодаря полиморфизму расцвел концепт инверсии зависимостей.
Дальше автор объясняет dependency inversion. Тут меня знатно побомбило.
DI - базовый кирпичик и первый шаг к чистой архитектуре. Это самая важная часть раздела. И она объяснена очень плохо:
▪️ Роберт вводит 2 типа стрелочек: source code dependency и flow of control. Не объясняя, что это такое
▪️ Рисует схему, где стрелочки идут вместе
▪️ Добавляет в схему ещё один квадрат (интерфейс) и поворачивает одну стрелку в другую сторону
На этом всё. Ни одного примера с кодом, только квадратики и стрелки. Этого недостаточно, чтобы каждый читатель понял, что нужно делать и в чём инверсия. Просто добавить интерфейс к каждому классу? Service и ServiceImpl это и есть тот самый power move?
Особенно дико такое объяснение выглядит на контрасте с менее важными темами. Рядом есть детальный разбор
✔️ разницы инкапсуляции в С и С++
✔️ как в С (язык без классов) можно имитировать наследование
✔️ как работают атомики в Clojure
Всё это разжевано гораздо подробнее, чем DI🤦
В 11 главе Роберт сделает второй заход в dependency inversion, но (спойлер) всё останется на уровне "просто добавь интерфейс". Это рекомендации по форме, но не по содержанию.
Интерфейсом может быть не только дополнительный квадратик, но и набор публичных методов класса. Чем больше этот набор скрывает детали реализации и упрощает работу с классом, тем лучше. И чтобы уменьшить связность, не обязательно множить сущности.
Продолжаем спидран по Clean Architecture Роберта Мартина.
⭐️ Глава 3. Парадигмы программирования ⭐️
определяют способы написания и организации кода. Их 3:
▫️ Структурная - ход программы описывается явно через условия и циклы. Используется для описания алгоритмов
▫️ Обьектно-ориентированная - программа описывается как взаимодействие объектов. Используется полиморфизм, ход работы не всегда очевиден
▫️ Функциональная - базируется на неизменяемости
⭐️ Глава 4. Структурное программирование ⭐️
Код делится на небольшие функции, которые можно протестировать. Но если тесты проходят - не факт, что программа работает корректно. Большую часть главы занимают истории, как Дейкстра боролся против goto и пытался математически доказать корректность программ.
⭐️ Глава 5. Обьектно-ориентированное (ОО) программирование ⭐️
Роберт рассуждает, что полезного и нового предлагает ООП
▫️ Инкапсуляция - не уникальна для ООП, плюс в современных языках не решает свою задачу.
Исходная цель инкапсуляции - скрыть данные и дать пользователю ограниченный набор методов.
В С (предшественник С++) определение функции и реализация разнесены по разным файлам, там инкапсуляция нормальная. В современных ОО языках инкапсуляция слабая. Нет разделения на определение и реализацию. Чтобы посмотреть, что умеет класс, надо зайти в класс, и тут открывается вся его внутрянка. Детали реализации как на ладони.
(мысль интересная, но с текущими IDE это не актуально. Выпадающие списки методов делают большой вклад в сокрытие сложности)
▫️ Наследование - всего лишь переопределение переменных/функций в ограниченном контексте. Добавочной ценности для архитектуры нет.
▫️ Полиморфизм легко и безопасно реализован в ОО языках, и в этом его главная ценность. Благодаря полиморфизму расцвел концепт инверсии зависимостей.
Дальше автор объясняет dependency inversion. Тут меня знатно побомбило.
DI - базовый кирпичик и первый шаг к чистой архитектуре. Это самая важная часть раздела. И она объяснена очень плохо:
▪️ Роберт вводит 2 типа стрелочек: source code dependency и flow of control. Не объясняя, что это такое
▪️ Рисует схему, где стрелочки идут вместе
▪️ Добавляет в схему ещё один квадрат (интерфейс) и поворачивает одну стрелку в другую сторону
На этом всё. Ни одного примера с кодом, только квадратики и стрелки. Этого недостаточно, чтобы каждый читатель понял, что нужно делать и в чём инверсия. Просто добавить интерфейс к каждому классу? Service и ServiceImpl это и есть тот самый power move?
Особенно дико такое объяснение выглядит на контрасте с менее важными темами. Рядом есть детальный разбор
✔️ разницы инкапсуляции в С и С++
✔️ как в С (язык без классов) можно имитировать наследование
✔️ как работают атомики в Clojure
Всё это разжевано гораздо подробнее, чем DI🤦
В 11 главе Роберт сделает второй заход в dependency inversion, но (спойлер) всё останется на уровне "просто добавь интерфейс". Это рекомендации по форме, но не по содержанию.
Интерфейсом может быть не только дополнительный квадратик, но и набор публичных методов класса. Чем больше этот набор скрывает детали реализации и упрощает работу с классом, тем лучше. И чтобы уменьшить связность, не обязательно множить сущности.
👍64❤25🔥17👎5
Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфигурация ниже. Настройки прогона тестов стандартные. Сколько времени займет выполнение этих тестов?
@SpringBootTest
public class UserIT{...}
@ActiveProfiles("test")
@SpringBootTest
public class BidProcessingIT{...}
@SpringBootTest(properties = {
"user.rebalance.enabled=true"
})
public class RebalanceAccountIT{...}
@ActiveProfiles("test")
@SpringBootTest
public class AccountProcessingIT{...}
❤5
Сколько времени займет общий прогон тестов выше?
Anonymous Poll
16%
Чуть больше 2 минут
10%
Чуть больше 4 минут
17%
Чуть больше 6 минут
20%
Чуть больше 8 минут
15%
(количество методов с аннотацией @Test)*2
22%
👀
Как переиспользовать контекст в интеграционных тестах
Сегодня расскажу базовый минимум для написания интеграционных тестов в Spring: как работать с контекстом, чтобы тесты шли не по 2 часа.
В спринге интеграционным тестом называется тот, для которого нужен контекст. Контекст - это набор бинов, свойств, профилей и тд. Поднимать его для каждого теста долго, поэтому Spring по возможности переиспользует созданные ранее контексты.
Если в коде теста какой-то бин помечен
К новому контексту приводит переопределение свойств, указание профиля, конфигурация MockMvc и тд
Ответ на вопрос перед постом - прогон тестов будет занимать чуть больше 6 минут, потому что формируется 3 контекста. Для тестов BidProcessingIT и AccountProcessingIT используется один контекст.
🤔 Как оптимизировать выполнение тестов?
Популярный прием, который помогает зафиксировать контекст - базовый класс с тестовой конфигурацией. В базовом классе настраивается тестовый конфиг, тестконтейнеры, решается вопрос с секьюрити, наполнением и очисткой БД и тд
Остальные классы наследуются от базового:
При такой схеме важно следить, чтобы в наследниках не заменялись бины, свойства и тд. Иначе для них будет создан новый контекст.
На практике редко используется один базовый класс, чаще это иерархия под разные случаи. При грамотном проектировании и сознательности разработчиков интеграционные тесты выполняются за адекватное время даже для больших проектов👌
Сегодня расскажу базовый минимум для написания интеграционных тестов в Spring: как работать с контекстом, чтобы тесты шли не по 2 часа.
В спринге интеграционным тестом называется тот, для которого нужен контекст. Контекст - это набор бинов, свойств, профилей и тд. Поднимать его для каждого теста долго, поэтому Spring по возможности переиспользует созданные ранее контексты.
Если в коде теста какой-то бин помечен
@MockitoBean, @MockitoSpyBean или @TestBean, Spring создает для него прокси. Получается уникальный контекст, который нужно поднимать отдельно и нельзя в дальнейшем переиспользовать.К новому контексту приводит переопределение свойств, указание профиля, конфигурация MockMvc и тд
Ответ на вопрос перед постом - прогон тестов будет занимать чуть больше 6 минут, потому что формируется 3 контекста. Для тестов BidProcessingIT и AccountProcessingIT используется один контекст.
🤔 Как оптимизировать выполнение тестов?
Популярный прием, который помогает зафиксировать контекст - базовый класс с тестовой конфигурацией. В базовом классе настраивается тестовый конфиг, тестконтейнеры, решается вопрос с секьюрити, наполнением и очисткой БД и тд
@SpringBootTest
@AutoConfigureMockMvc
@TestPropertySource(…)
@TestExecutionListeners(…)
@ActiveProfile("test")
// куча других аннотаций
public abstract class BaseIntegrationTest {
// тестконтейнеры
// заглушки
}
Остальные классы наследуются от базового:
class UserIT extends BaseIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void shouldCreateUser() {…}
}При такой схеме важно следить, чтобы в наследниках не заменялись бины, свойства и тд. Иначе для них будет создан новый контекст.
На практике редко используется один базовый класс, чаще это иерархия под разные случаи. При грамотном проектировании и сознательности разработчиков интеграционные тесты выполняются за адекватное время даже для больших проектов👌
❤57👍35🔥21👎2