Skip to content

Latest commit

 

History

History
1089 lines (653 loc) · 149 KB

software-design-and-architecture.md

File metadata and controls

1089 lines (653 loc) · 149 KB

Оригинал

Полезные ссылки:

Основные принципы проектирования программного обеспечения и виды архитектур приложений

Принципы проектирования, базирующиеся на понятии «чистого кода»

Чистый код — это код, который легко читать, понимать и поддерживать. Он следует набору принципов, призванных сделать код более читабельным, тестируемым и менее подверженным ошибкам. Вот некоторые из ключевых принципов чистого кода:

  • Ясность: код должен быть легко читаемым и понятным.
  • Простота: код должен быть максимально простым, избегающим ненужной сложности.
  • Комментарии. Комментарии следует использовать с осторожностью и только в случае необходимости для объяснения сложного или неочевидного кода.
  • Именование: переменные, функции и классы должны иметь осмысленные и содержательные имена.
  • Форматирование: код должен быть последовательно отформатирован для повышения читабельности.
  • Функциональность: код должен быть организован в виде небольших функций и классов, выполняющих какую-то одну специализированную задачу.
  • Обработка ошибок: код должен обрабатывать ошибки последовательным и предсказуемым образом.
  • Тестирование: код должен быть тестируемым и иметь высокое покрытие тестами.
  • Повторное использование: код должен быть многократно используемым и модульным.
  • Производительность: код должен быть эффективным и производительным.

Полезные ссылки:

Будьте последовательны при написании кода

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

Полезные ссылки:

Содержательные, понятные названия переменных, не требующие дополнительных комментариев

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

Использование осмысленных имен важно для того, чтобы сделать код понятным, читаемым и легким для понимания. Содержательные имена могут помочь передать назначение и функцию переменных, функций, классов и других элементов кода.

Ниже приведены некоторые примеры использования содержительных имен в системной архитектуре:

  • Используйте описательные и осмысленные имена для переменных, функций, классов и других элементов кода.
  • Используйте принятые командой соглашения об именах во всей кодовой базе, такие как camelCase для переменных и PascalCase для функций и классов.
  • Используйте аббревиатуры и акронимы с осторожностью и только в том случае, если они понятны всем членам команды.
  • Используйте осмысленные префиксы или суффиксы для указания типа или назначения переменной или функции, например «is» или «get» для логических переменных или «list» для переменных-массивов.
  • Избегайте использования однобуквенных имён переменных или ничем не примечательных имён, таких как «temp» или «x», которые не несут никакой смысловой нагрузки.
  • Избегайте использования слишком длинных или сложных имен, которые затрудняют чтение кода.

Полезные ссылки:

Стиль программирования: отступы

Использование отступов позволяет на практике визуально сгруппировать связанные строки кода вместе, что облегчает чтение и понимание структуры кода. Выбор того или иного количества пробелов для отступа относится к соглашениям и рекомендациям, принятым внутри команды, которые используются для форматирования и структурирования кода, по аналогии с соглашениями об именах, комментариях и использовании пробелов.

Наличие единого стиля поможет сделать код более читаемым и понятным, что может повысить удобство сопровождения системы.

Полезные ссылки:

Старайтесь, чтобы создаваемые методы, классы, файлы, были как можно меньше

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

Используйте чистые функции

Чистая функция — это функция определенного типа, удовлетворяющая следующим критериям:

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

Чистые функции считаются более предсказуемыми и их легче тестировать, поскольку их поведение определяется исключительно поступающими на вход данными и их внутренней логикой. Они также облегчают анализ поведения программы, поскольку на результат чистой функции не влияют никакие внешние факторы. Чистые функции часто используются в функциональном программировании, где они считаются важнейшим принципом. Их также используют в конкурентном и параллельном программировании, поскольку они менее подвержены эффектам гонки данных и другим проблемам, связанным с параллелизмом.

Википедия - Чистота функции

Минимизируйте цикломатическую сложность программы

Цикломатическая сложность — это мера структурной сложности программы, которая определяется количеством линейно независимых путей в порядке выполнения программы. Высокая цикломатическая сложность может затруднить понимание, тестирование и сопровождение программы, поэтому часто желательно свести ее к минимуму в архитектуре системы.

Ниже показано несколько способов минимизировать цикломатическую сложность в архитектуре системы:

  • Разбейте сложные функции на более мелкие и простые функции, выполняющие определенные задачи.
  • Используйте управляющие конструкции, такие как операторы if-else и циклы, согласованным и предсказуемым образом.
  • Используйте понятия и методы функционального программирования, такие как неизменяемость и чистые функции, чтобы уменьшить потребность в сложном порядке выполнения.
  • Используйте шаблоны проектирования, такие как шаблон состояния, для упрощения сложного порядка выполнения.
  • Регулярно просматривайте код и реорганизуйте его, чтобы упростить порядок выполнения.
  • Используйте инструменты статического анализа кода, которые могут обнаруживать и сообщать о высокой цикломатической сложности кода.

Следуя этим рекомендациям, архитектура системы будет более удобной в сопровождении, тестируемой и менее подверженной ошибкам.

Полезные ссылки:

Старайтесь не передавать значения типа null и булевого типа

Передача значения типа null или булевых (логических) значений может привести к неожиданному поведению и трудным для отладки ошибкам в программе. Вот несколько способов избежать передачи значения типа null или булевых значений в архитектуре системы:

  • Используйте типы Optionals или Maybe вместо null, чтобы указать на отсутствие значения. Это позволяет понять, когда значение отсутствует, и предотвращает возникновение исключений, связанных с тем, что указатель ссылается на null.
  • Используйте значение по умолчанию для аргументов функции вместо того, чтобы позволять им быть равными null или значениям логического типа. Это устраняет необходимость проверки на null или значения логического типа и снижает вероятность ошибок.
  • Используйте шаблон Null Object для замены значений типа null специальным объектом с определенным поведением. Это устраняет необходимость проверки на null и делает код более читабельным.
  • Используйте тернарный оператор (?:) вместо операторов if-else при работе с логическими значениями. Это может сделать код более компактным и удобным для чтения.
  • Используйте функцию assert, чтобы проверить допустимость аргументов функции и создать исключение, если они не удовлетворяют требованиям.

Следуя этим рекомендациям, архитектура системы будет более надежной и менее подверженной ошибкам.

Следите за тем, что код фреймворка был дистанцирован

Дистанцирование кода фреймворка означает отделение кода приложения от кода фреймворка. Это упрощает независимое обслуживание, тестирование и обновление кодовой базы приложения и фреймворка.

Вот несколько способов, позволяющих отделить код фреймворка от архитектуры системы:

  1. Используйте уровень абстракции, чтобы отделить код приложения от кода фреймворка. Это позволяет писать код приложения без необходимости знать специфику фреймворка.
  2. Используйте внедрение зависимостей, чтобы отделить код приложения от кода фреймворка. Это позволяет коду приложения использовать функциональные возможности фреймворка без необходимости непосредственного создания экземпляров объектов фреймворка.
  3. Избегайте использования специфичных для фреймворка библиотек или классов в коде приложения. Это упрощает переход на другой фреймворк в будущем, если это будет необходимо.
  4. Используйте стандартный интерфейс кода приложения для взаимодействия с фреймворком. Это позволяет писать код приложения без необходимости знать специфику фреймворка.
  5. Располагайте приложение и код фреймворка в отдельных проектах и/или репозиториях.

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

Полезные ссылки:

Используйте надлежащие программные конструкции

С точки зрения принципов чистого кода «использование надлежащих программных конструкций» означает применение соответствующих программных конструкций, таких как циклы, условные операторы и функции, таким образом, чтобы сделать код простым для понимания, поддержки и изменения.

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

Кроме того, фраза «надлежащие конструкции» также означает использование правильных конструкций для соответствующей задачи, например, если вы хотите выполнить итерацию по массиву, воспользуйтесь циклом for вместо рекурсии. А ещё вам следует избегать глобальных переменных и вместо этого использовать аргументы функций и возвращать значения для передачи данных между разными частями кода.

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

Тесты должны выполняться быстро и быть независимыми

Независимость тестов гарантируует, что тесты надежны, воспроизводимы и их легко поддерживать. Когда тесты независимы, изменение одного теста не повлияет на результаты других тестов.

Ниже приведено несколько способов сделать тесты независимыми в архитектуре системы:

  • Используйте внедрение зависимостей, чтобы отделить код теста от кода приложения. Это позволяет запускать тесты без необходимости непосредственно создавать экземпляры объектов приложения.
  • Используйте имитации для реализации объектов или заглушки, чтобы изолировать тест от внешних зависимостей, таких как базы данных, API или другие сервисы.
  • Используйте автономные тестовые данные, не зависящие от внешних данных или состояния.
  • Используйте фреймворк для тестирования, поддерживающий параллельное выполнение тестов, чтобы их можно было запускать независимо друг от друга.
  • Используйте разработку через тестирование (TDD), которая предполагает написание тестов до написания кода приложения. Это гарантирует, что тесты независимы и что код написан с учетом возможности его тестирования.
  • Избегайте глобального состояния и совместно используемого изменяемого состояния, так как это может привести к неожиданным результатам.

Полезные ссылки:

Группируйте код вокруг а́ктора, к которому он относится

«Код вокруг а́ктора» — это методика разработки программного обеспечения, который мотивирует разработчиков организовывать свой код вокруг а́кторов или сущностей, которые с ним взаимодействуют. Áкторами могут быть пользователи, системы или процессы, выполняющие определенную роль или функцию в приложении. Этот подход помогает четко разделить задачи, делая код более модульным, пригодным для повторного использования и более простым для понимания.

Полезные ссылки:

Разделяйте на команды и запросы

Разделение на команды и запросы (Command-Query Separation, CQS) — это принцип разработки программного обеспечения, при котором обязанности метода или функции разделяются на две категории: команды и запросы. Команды — это методы, которые изменяют состояние системы, а запросы — это методы, которые возвращают информацию, но не изменяют состояние системы.

Полезные ссылки:

Избегайте ненужной сложности и осуществляйте рефакторинг как можно чаще

Не спешите создавать абстракции

Создание абстракций — важная часть разработки программного обеспечения, но создание слишком большого количества абстракций или их слишком преждевременное создание может привести к ненужной сложности и затруднить понимание и сопровождение кода.

Вот несколько способов избежать необдуманного создания абстракций в системной архитектуре:

  • Поймите проблему, которую необходимо решить, прежде чем создавать абстракцию.
  • Начните с простого решения и создавайте абстракцию только тогда, когда станет ясно, что решение становится слишком сложным.
  • Используйте методы рефакторинга кода, чтобы упростить код перед созданием абстракции.
  • Избегайте создания абстракций ради создания абстракций.
  • Используйте признанные в сообществе шаблоны и методы проектирования при создании абстракций, но не внедряйте насильно их в код.
  • Используйте автоматизированное тестирование, чтобы гарантировать, что абстракция не приведет к появлению новых ошибок или нарушению существующей функциональности.
  • Создавайте абстракции таким образом, чтобы их было легко тестировать, отлаживать и анализировать.

Полезные ссылки:

  • AHA Programming
  • Фаулер М. Рефакторинг: улучшение существующего кода. - Пер. с англ. - СПб: Символ-Плюс, 2003. - 432 с, ил.

Парадигмы программирования

Парадигма программирования — это фундаментальный стиль или подход к решению проблем с использованием языка программирования. Различные парадигмы программирования предоставляют разные способы организации и структурирования кода и имеют разные сильные и слабые стороны. Некоторые из наиболее распространенных парадигм программирования включают в себя:

  • Императивное программирование
  • Функциональное программирование
  • Объектно-ориентированное программирование
  • Логическое программирование
  • Декларативное программирование

Полезные ссылки:

Структурное программирование

Структурное программирование — это парадигма программирования, которая делает упор на использование структурированных управляющих конструкций, изменющих ход выполнения программы, таких как циклы и условные операторы, для организации кода в логические, простые для понимания блоки. Это способ написания компьютерных программ, в котором особое внимание уделяется использованию процедур и функций, а также структур данных для организации кода и упрощения его понимания, отладки и поддержки. Основная идея структурного программирования состоит в том, чтобы разбить программу на более мелкие части, которые просто контролировать, можно легко понять, протестировать и изменить. Этот подход выступает против использования операторов «goto», которые считаются неструктурированными и могут привести к сложному для чтения и сопровождения коду.

Полезные ссылки:

Функциональное программирование

Функциональное программирование — это парадигма программирования, которая делает упор на использование чистых функций и неизменяемых данных. Это способ написания компьютерных программ, который акцентирует внимание на использовании функций и математических понятий, таких как рекурсия, а не на использование объектов и классов, как в объектно-ориентированном программировании. В функциональном программировании функции являются «объектами первого класса» (функции высших порядков), что означает, что они могут быть переданы в качестве аргументов другим функциям и возвращены в качестве результата.

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

Полезные ссылки:

Объектно-ориентированное программирование

Объектно-ориентированное программирование (ООП) — это парадигма программирования, основанная на понятии «объектов», которые являются экземплярами классов. ООП — это способ организации и структурирования кода, основанный на принципах инкапсуляции, наследования и полиморфизма.

Инкапсуляция — это идея, заключающаяся в том, что внутреннее состояние объекта должно быть скрыто и доступно только через его методы. Это позволяет объекту контролировать, как используются его данные, и не позволяет внешнему коду вносить недопустимые изменения в состояние объекта.

В ООП класс — это шаблон для создания объектов, которые имеют как данные (атрибуты), так и поведение (методы). Основная идея ООП заключается в моделировании объектов реального мира и их взаимодействий, что делает его подходящим для создания сложных и крупномасштабных программных систем.

Полезные ссылки:

Модельно-ориентированный подход к проектированию

Модельно-ориентированный подход к проектированию (MDD) — это методология разработки программного обеспечения, в которой проектирование системы осуществляется с помощью набора моделей, используемые для управления процессом разработки системы. MDD основан на идее, что конструкция системы может быть представлена набором моделей и что эти модели могут быть применены для генерации кода для системы.

Основное преимущество использования MDD заключается в том, что он позволяет четко разделить задачи проектирования и реализации системы. Модели представляют структуру системы, а код генерируется на основе моделей, что упрощает поддержку и развитие системы. Кроме того, MDD также может улучшить качество кода, поскольку модели можно использовать для проверки ошибок проектирования и несоответствий до создания кода.

Полезные ссылки:

Модель предметной области

Модель предметной области — это воплощение конкретной области знаний или бизнеса, которое используется для моделирования объектов и понятий в этой предметной области, а также для определения взаимосвязей и ограничений между ними. В объектно-ориентированном программировании (ООП) модель предметной области обычно представлена набором классов и интерфейсов, где каждый класс или интерфейс представляет определенное понятие или объект в предметной области.

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

Полезные ссылки:

Анемичная модель

Анемичная модель, также известная как анемичная модель предметной области, представляет собой тип модели предметной области, в которой объекты предметной области содержат только данные (атрибуты) и не имеют поведения. Анемичная модель часто приводит к использованию объектов переноса данных (DTO) и сервисного уровня для реализации поведения.

Анемичная модель считается антишаблоном в объектно-ориентированном программировании (ООП), потому что она нарушает принципы инкапсуляции и разделения ответственности. В анемичной модели поведение отделено от данных и обычно реализуется на отдельном сервисном уровне, что может привести к сложному, сильно связанному и сложному в сопровождении коду.

Полезные ссылки:

Многоуровневые архитектуры

Многоуровневая архитектура — это шаблон проектирования программного обеспечения, в котором функциональность системы разделена на набор уровней, при этом каждый уровень имеет определенную ответственность и взаимодействует с уровнями выше и ниже него. Основная идея многоуровневой архитектуры состоит в том, чтобы разделить задачи системы на отдельные и независимые уровни, сделав код более модульным, более простым для понимания, тестирования и модификации.

Существует несколько типов многоуровневых архитектур, но наиболее распространенной является трехуровневая архитектура, состоящая из:

  • Уровень представления (Presentation Layer)
  • Уровень бизнес-логики (Business Layer)
  • Уровень доступа к данным (Data Access Layer)

Полезные ссылки:

Единый язык

Единый язык — это специфический словарь и набор понятий, используемых для описания и общения в определенной области знаний или бизнеса. При разработке программного обеспечения единый язык язык используется для моделирования объектов и понятий в конкретной предметной области, а также для фиксации взаимосвязей и ограничений между ними.

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

Полезные ссылки:

Инварианты класса

Инвариант класса — это набор условий, которые должны выполняться для любого объекта класса в любой момент времени. В объектно-ориентированном программировании (ООП) инварианты классов используются для определения допустимых состояний объекта и гарантирования того, чтобы объект всегда будет оставаться в допустимом состоянии.

Инварианты класса обычно определяются в конструкторе класса и задаются с помощью закрытых методов и атрибутов, которые используются для проверки состояния объекта. Они также проверяются в методах класса до и после любой операции, которая может изменить состояние объекта.

Полезные ссылки:

Особенности парадигмы

Объектно-ориентированное программирование (ООП) — это парадигма программирования, основанная на понятии «объектов», которые являются экземплярами класса. ООП имеет несколько ключевых особенностей, которые отличают его от других парадигм программирования:

  • Инкапсуляция
  • Наследование
  • Полиморфизм
  • Абстракция
  • Классы
  • Объекты
  • Интерфейсы
  • Динамическое (позднее) связывание
  • Передача сообщений

Полезные ссылки:

Абстрактные классы

Абстрактный класс — это класс в объектно-ориентированном программировании (ООП), который не может быть создан. Вместо этого он служит шаблоном или образцом для наследования другими классами. Абстрактный класс может содержать как абстрактные, так и неабстрактные методы (абстрактные методы — это методы, которые не имеют реализации, они просто содержат сигнатуру).

Абстрактные классы используются для предоставления общего интерфейса и реализации для группы связанных классов. Они также применяются для определения общего поведения, которое должно быть реализовано всеми подклассами. Подкласс, который наследуется от абстрактного класса, называется реальным классом, и он должен предоставлять реализацию для всех абстрактных методов, объявленных в родительском классе.

Полезные ссылки:

Реальные классы

Реальный класс — это класс в объектно-ориентированном программировании (ООП), который может быть создан, то есть из него могут быть созданы объекты. Реальный класс — это класс, который обеспечивает реализацию всех абстрактных методов, объявленных в его родительском классе, если он наследуется от абстрактного класса. Реальный класс также может быть классом, который не наследуется от абстрактного класса, в этом случае в нём реализованы все его методы.

Реальные классы используются для предоставления конкретных деталей реализации для группы связанных классов, которые наследуются от общего абстрактного класса. Они также используются для задания уникального поведения для определенного класса. Реальный класс может иметь свои собственные методы и переменные, а также может переопределять методы своего родительского класса.

Полезные ссылки:

Область видимости

Область видимости относится к доступности или видимости переменных, функций и других элементов в программе в зависимости от контекста, в котором они определены. В объектно-ориентированном программировании (ООП) область видимости контролируется с помощью модификаторов доступа, таких как "public" («публичный», «открытый», «общедоступный»), "private" («приватный», «закрытый», «частный») и "protected" («защищённый»).

Общедоступный: к общедоступному элементу можно получить доступ из любой точки программы, как внутри класса, так и за его пределами.

Закрытый: доступ к закрытому элементу возможен только внутри класса, в котором он определен. Он недоступен для других классов, даже если они наследуются от класса.

Защищенный: доступ к защищенному элементу возможен только внутри класса и его подклассов.

Существуют и другие разновидности области видимости в зависимости от языка программирования, но эти являются наиболее распространенными.

Полезные ссылки:

Интерфейсы

В объектно-ориентированном программировании (ООП) интерфейс — это контракт или набор методов, которые должен реализовать класс. Он определяет общий набор методов, которые должен иметь класс, но не предоставляет никаких подробностей реализации. Интерфейс может включать как сигнатуры методов, так и константы.

Интерфейсы используются для определения общего поведения для группы связанных классов и для обеспечения полиморфизма в случае с объектами разных классов. Класс, удовлетворяющий интерфейсу, должен осуществлять реализацию всех методов, объявленных в интерфейсе. Класс может реализовывать несколько интерфейсов, но может наследоваться только от одного базового класса.

Полезные ссылки:

Основные понятия

Существует несколько основных понятий, которые считаются фундаментальными для объектно-ориентированного программирования (ООП). Эти понятия включают в себя:

  • Инкапсуляция: Практика помещения внутренних данных и поведения объекта в определенный интерфейс и сокрытие деталей реализации от внешнего мира.
  • Наследование: способность нового класса наследовать свойства и методы существующего класса, что позволяет повторно использовать код и обеспечивает иерархическую организацию классов.
  • Полиморфизм: способность рассматривать объекты разных классов как объекты общего родительского класса, что позволяет писать более обобщённый и универсальный код.
  • Абстракция: процесс сокрытия деталей реализации объекта и раскрытия только его основных функций, что снижает сложность и улучшает модульность кода.
  • Классы: шаблон для создания объектов, которые имеют как данные (атрибуты), так и поведение (методы).
  • Объекты: Экземпляры класса, имеющие собственное уникальное состояние и поведение.

Полезные ссылки:

Наследование

Наследование — это фундаментальное понятие объектно-ориентированного программирования (ООП), которое позволяет новому классу наследовать свойства и методы существующего класса. Класс, от которого наследуется, называется родительским или суперклассом, а класс, который наследует, называется дочерним или подклассом. Наследование позволяет повторно использовать код и обеспечивает иерархическую организацию классов, при которой дочерний класс может наследовать свойства и методы своего родительского класса и потенциально добавлять или переопределять их. Основное преимущество наследования заключается в том, что оно позволяет реализовать понятный и организованный способ повторного использования кода и пользоваться единожды написанным функционалом как в родительском, так и в дочерних классах.

Полезные ссылки:

Полиморфизм

Полиморфизм — это понятие объектно-ориентированного программирования (ООП), которая позволяет рассматривать объекты разных классов как объекты общего родительского класса. Это достигается путем определения общего интерфейса для всех классов, которые необходимо рассматривать полиморфно. Слово «полиморфизм» («многообразие форм», «многообразный») происходит от греческих слов «поли» (πολύ), что означает «много» и «морф» (μορφ) — «форма».

Существует два типа полиморфизма:

  • Полиморфизм времени компиляции (также называемый статическим полиморфизмом или ранним связыванием) возникает, когда тип объекта, с которым будут проводиться определенные действия, определяется во время компиляции. Это достигается за счет перегрузки методов, которая позволяет нескольким методам иметь одно и то же имя, но разные параметры в одном классе.
  • Полиморфизм времени выполнения (также называемый динамическим полиморфизмом или поздним связыванием) возникает, когда тип объекта определяется во время выполнения. Это достигается за счет переопределения методов, что позволяет дочернему классу предоставлять конкретную реализацию метода, который уже определен в его родительском классе.

Полезные ссылки:

Абстракция

Абстракция — это понятие объектно-ориентированного программирования (ООП), которое относится к процессу сокрытия деталей реализации объекта и раскрытию только его основных функций. Это позволяет использовать объекты без необходимости понимать всю сложность их внутренней структуры и поведения.

Существует два типа абстракции:

  • Абстракция данных: относится к сокрытию внутреннего представления данных и выдаче их в упрощенном виде с помощью набора четко определенных интерфейсов.
  • Абстракция поведения: относится к сокрытию внутреннего поведения объекта и реализация в упрощенной форме его возможностей с помощью набора четко определенных интерфейсов.

Полезные ссылки:

Инкапсуляция

Инкапсуляция — это понятие объектно-ориентированного программирования (ООП), которое относится к практике помещения внутренних данных и поведения объекта в определенный интерфейс и сокрытия деталей реализации от внешнего мира. Это одна из фундаментальных понятий ООП, тесно связанная с принципами сокрытия данных и сокрытия информации.

Инкапсуляция достигается за счет использования модификаторов доступа (таких как "public", "private" и "protected") для управления областью видимости и доступностью данных и методов объекта. Например, атрибуты класса могут быть объявлены как закрытые (приватные, "private"), т. е. доступ к ним возможен только с помощью методов внутри класса, а методы могут быть объявлены как открытые (публичные, "public"), т. е. их можно вызывать из любой части кода, имеющей ссылку на объект.

Полезные ссылки:

Принципы проектирования программного обеспечения

Существует множество принципов проектирования программного обеспечения, направленных на то, чтобы разрабатываемое программное обеспечение было легко понять, поддерживать и расширять. Некоторые из наиболее распространенных включают в себя:

  • Принципы SOLID (принцип единой ответственности, принцип открытости/закрытости, принцип подстановки Лисков, принцип разделения интерфейсов и принцип инверсии зависимостей)
  • DRY (Не повторяйтесь)
  • YAGNI (Вам это никогда не понадобится)
  • KISS (Чем проще, тем лучше)
  • LoD (Закон Деметры)
  • Используйте композицию, а не наследование
  • Инкапсулируйте то, что изменяется
  • Голливудский принцип
  • Пишите программы, основываясь на абстракциях

Следуя этим принципам проектирования, программное обеспечение может быть разработано таким образом, чтобы его было легко понять, поддерживать и расширять, а также оно было менее подвержено ошибкам.

Полезные ссылки:

Используйте композицию, а не наследование

Композиция вместо наследования — это принцип программирования, который предполагает, что лучше использовать композицию, механизм сборки объектов, для создания сложных объектов, а не использовать наследование, которое представляет собой механизм создания новых классов на основе существующих.

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

Полезные ссылки:

Инкапсулируйте то, что изменяется

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

Инкапсуляция того, что меняется обеспечивает бóльшую гибкость кода. Когда необходимы изменения, их можно внести в инкапсулированные части, не затрагивая остальную часть кода. Это облегчает понимание, тестирование и сопровождение кода.

Полезные ссылки:

Пишите программы, основываясь на абстракциях

Программируйте на уровне интерфейсов, а не реализации

Программирование на основе абстракций — это принцип программирования, который предполагает, что код должен быть написан таким образом, чтобы он не был привязан к конкретным реализациям, а к абстракциям. Это достигается путем определения интерфейсов или абстрактных классов, которые задают поведение группы связанных классов без указания их реализации.

Программирование на основе абстракций обеспечивает бóльшую гибкость кода. Когда необходимы изменения, они могут быть внесены в реализацию абстракций, не затрагивая код, который их использует. Это облегчает понимание, тестирование и сопровождение кода.

Полезные ссылки:

Голливудский принцип

Голливудский принцип — это принцип разработки программного обеспечения, который гласит: «Не звоните нам, мы сами вам позвоним». Он предполагает, что высокоуровневые (интерфейсы), а не низкоуровневые компоненты (реализации) должны определять порядок выполнения кода в приложении.

Этот принцип часто используется в контексте инверсии управления (Inversion of Control, IoC) и внедрения зависимостей. Обычно при разработке программного обеспечения низкоуровневые компоненты отвечают за создание и управление высокоуровневыми компонентами, от которых они зависят. В IoC высокоуровневые компоненты задают порядок выполнения кода, а низкоуровневые компоненты создаются и управляются с помощью отдельного механизма.

Полезные ссылки:

SOLID

SOLID — это аббревиатура, обозначающая пять принципов объектно-ориентированной разработки программного обеспечения, впервые представленных Робертом С. Мартином в начале 2000-х годов. А именно:

  • Принцип единой ответственности (SRP, Single Responsibility Principle)
  • Принцип открытости/закрытости (OCP, Open/Closed Principle)
  • Принцип подстановки Лисков (LSP, Liskov Substitution Principle)
  • Принцип разделения интерфейсов (ISP, Interface Segregation Principle)
  • Принцип инверсии зависимостей (DIP, Dependency Inversion Principle)

Полезные ссылки:

DRY

DRY (Don’t Repeat Yourself, «Не повторяйтесь») — это принцип разработки программного обеспечения, который предполагает, что код не должен иметь повторяющихся частей. Идея состоит в том, чтобы максимально упростить кодовую базу, устранив избыточность и дублирование. Цель заключается в том, чтобы уменьшить сложность и улучшить удобство сопровождения, гарантируя, что каждая часть знаний выражается в системе единым и недвусмысленным способом.

Принцип DRY тесно связан с принципом единой ответственности (SRP) и принципом открытости/закрытости (OCP), которые являются частью принципов SOLID. Принцип DRY пытается уменьшить количество повторяющегося кода за счет создания абстракций, которые можно повторно использовать в системе.

Полезные ссылки:

YAGNI

YAGNI (You Ain’t Gonna Need It, «Вам это никогда не понадобится») — это принцип разработки программного обеспечения, который предполагает, что разработчики не должны добавлять функциональные возможности в кодовую базу, если в этом нет немедленной необходимости. Идея состоит в том, чтобы избежать создания ненужной сложности в кодовой базе, добавляя только тот функционал, который действительно необходим.

Принцип YAGNI тесно связан с принципом единой ответственности (SRP) и принципом открытости-закрытости (OCP), которые являются частью принципов SOLID. YAGNI стремится максимально упростить кодовую базу, избегая создания ненужных абстракций и функциональных возможностей.

Полезные ссылки:


  1. Фримен Э., Робсон Э., Сьерра К., Бейтс Б. Head First. Паттерны проектирования. Обновленное юбилейное издание. — СПб.: Питер, 2018. — 656 с.: ил. — (Серия «Head First O’Reilly»).

Шаблоны проектирования

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

Существует несколько различных шаблонов проектирования, а именно:

  • Порождающие шаблоны
  • Структурные шаблоны
  • Поведенческие шаблоны
  • Архитектурные шаблоны

Полезные ссылки:

GoF шаблоны проектирования

Шаблоны проектирования «Банда четырех» (GoF, Gang of Four) — это набор шаблонов проектирования для разработки объектно-ориентированного программного обеспечения, которые впервые были описаны в книге «Паттерны объектно-ориентированного проектирования» Эриха Гаммы, Ричарда Хелма, Ральфа Джонсона, и Джон Влиссидес (также известные как «Банда четырех»).

Шаблоны проектирования GoF делятся на три категории: порождающие, структурные и поведенческие.

  • Порождающие шаблоны
  • Структурные шаблоны
  • Поведенческие шаблоны

Полезные ссылки:

PoSA шаблоны

POSA (Patterns of Scalable and Adaptable Software Architecture, Шаблоны масштабируемой и адаптируемой архитектуры программного обеспечения) — это набор шаблонов проектирования для разработки программных систем, которые могут масштабироваться и адаптироваться к изменяющимся требованиям. Эти шаблоны были впервые описаны в книге «Шаблоны масштабируемых, надежных сервисов» Кевина Хоффмана.

Шаблоны POSA делятся на четыре категории:

  • Разделяющие шаблоны
  • Размещающие шаблоны
  • Маршрутизирующие шаблоны
  • Объединяющие шаблоны

Полезные ссылки:

Архитектурные принципы

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

Полезные ссылки:

Компонентно-ориентированное программирование

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

  • Сильная связность
  • Слабая связанность
  • Разделение ответственности
  • Проектирование на основе интерфейсов
  • Возможность повторного использования
  • Тестируемость
  • Модульность
  • Совместимость

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

Полезные ссылки:

Стратегия vs детали реализации

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

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

Детали - это низкоуровневые реализации, которые необходимы для осуществления стратегических решений. К ним относятся определённые алгоритмы, структуры данных и код, из которых состоят компоненты системы. Детали часто реализуются разработчиками и отвечают за фактическое функционирование системы.

Полезные ссылки:

  • G6: Код на неверном уровне абстракции. Мартин Р. Чистый код: создание, анализ и рефакторинг. Библиотека программиста. — СПб.: Питер, 2013. — 464 с.: ил. — (Серия «Библиотека программиста»).

Связанность (coupling) и связность (cohesion)

Связанность (coupling) и связность (cohesion) — это два принципа в архитектуре программного обеспечения, которые используются для измерения степени взаимозависимости между компонентами в системе.

Связанность (coupling) относится к степени, зависимости одного компонента от другого. Сильная связанность означает, что изменение в одном компоненте, вероятно, повлияет на другие компоненты, что усложнит понимание, тестирование и обслуживание системы. Слабая связанность, напротив, означает, что изменения в одном компоненте оказывают минимальное влияние на другие компоненты, что делает систему более модульной и более простой для понимания, тестирования и обслуживания.

Связность (cohesion), в свою очередь, определяет насколько связаны друг с другом задачи, выполняемые некоторым конкретным компонентом. Сильная связность означает, что компонент имеет одну четко определенную цель и что весь его функционал и данные связаны с этой целью. Слабая связность, с другой стороны, означает, что компонент имеет несколько несвязанных между собой обязанностей, что затрудняет его понимание, тестирование и поддержку.

Полезные ссылки:

Границы частей приложения

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

Границы важны, потому что они определяют точки взаимодействия между различными компонентами или системами и задают, как эти компоненты или системы будут взаимодействовать друг с другом. Определение четких границ облегчает понимание, тестирование и обслуживание системы, поскольку взаимодействие между компонентами или системами четко определено и о них легко рассуждать.

Полезные ссылки:

Архитектурные стили

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

Некоторыми распространенными архитектурными стилями в программном обеспечении являются:

  • Микросервисы: когда система построена как набор небольших, независимых и слабо связанных сервисов.
  • Событийно-ориентированный: когда система реагирует на определённые события, которые происходят, а не постоянно опрашивается на наличие изменений.
  • Многоуровневый: система разделена на ряд уровней, каждый из которых имеет определенную ответственность и взаимодействует с другими уровнями через четко определенные интерфейсы.
  • Сервис-ориентированный: система построена как набор сервисов, к которым можно получить доступ через сеть.
  • Ориентированность на данные: система ориентирована на хранение, поиск и манипулирование данными, а не на их обработку.
  • Компонентно-ориентированный: когда система состоит из повторно используемых и независимых программных компонентов.
  • Предметно-ориентированный: система организована вокруг смыслового ядра и сущностей бизнеса.

Полезные ссылки:

по типу обмена сообщениями

Обмен сообщениями является ключевым понятием в нескольких архитектурных стилях, включая событийно-ориентированную архитектуру (EDA), микросервисы и архитектуру, управляемую сообщениями (MDA).

  • Событийно-ориентированная архитектура (EDA)
  • Микросервисы
  • Архитектура, управляемая сообщениями (MDA)

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

Полезные ссылки:

событийно-ориентированная

Событийно-ориентированная архитектура (EDA) — это шаблон проектирования программного обеспечения, в котором система реагирует на определенные происходящие события, а не постоянно опрашивается на наличие изменений. В EDA события — это сообщения, которые асинхронно отправляются компонентам, а компоненты реагируют на интересующие их события.

Основное преимущество использования EDA заключается в том, что она позволяет четко разделить ответственность между компонентами и может улучшить масштабируемость и отказоустойчивость системы. Кроме того, она допускает слабую связь между компонентами, т. е. компоненты не знают о существовании друг друга и могут разрабатываться, развертываться и масштабироваться независимо.

Полезные ссылки:

издатель/подписчик

Шаблон издатель/подписчик — это шаблон обмена сообщениями, в котором издатель отправляет сообщение в определенную катетогию, и любое количество подписчиков может подписаться на эту категорию, чтобы получить сообщение. Шаблон издатель/подписчик также известен как «шаблон наблюдателя» и представляет собой способ реализации взаимодействия между различными частями приложения так, чтобы они не были связаны.

Основное преимущество использования шаблона издатель/подписчик заключается в том, что он позволяет четко разделить обязанности между издателем и подписчиками и может повысить гибкость и масштабируемость системы. Кроме того, он допускает слабую связь между компонентами, т. е. издатель и подписчики не знают о существовании друг друга и могут разрабатываться, развертываться и масштабироваться независимо.

Полезные ссылки:

по способу взаимодействия в распределенной сети

Распределенные системы - это способ разработки и организации программных компонентов, при которой они распределены по нескольким устройствам или локациям, подключены через сеть и работают вместе для достижения общей цели. Основная проблема при проектировании распределенных систем заключается в том, чтобы справиться со сложностью, присущей распределению компонентов и обмену данными между ними, и для улучшения масштабируемости, отказоустойчивости и производительности требуются такие методы, как балансировка нагрузки, репликация и партицирование/секционирование. Кроме того, безопасность и координация также являются важными аспектами распределенных систем.

Полезные ссылки:

клиент-сервер

Архитектура клиент-сервер — это распространенный архитектурный шаблон, используемый в распределенных системах, где клиент (или несколько клиентов) отправляет запросы на сервер, а сервер отвечает на эти запросы. Клиент и сервер — это отдельные субъекты, которые обмениваются данными по сети, такой как Интернет или локальная сеть.

Клиент отвечает за представление пользовательского интерфейса и обработку пользовательского ввода, а сервер — за обработку запросов и возврат соответствующего ответа. Сервер также может выполнять такие задачи, как хранение данных, безопасность и бизнес-логика.

Полезные ссылки:

одноранговое, децентрализованное или пиринговое (peer-to-peer, P2P)

Одноранговая (P2P) архитектура — это архитектура распределенных вычислений, в которой каждый узел (peer, пир) в сети ведёт себя как клиент и сервер. В архитектуре P2P нет центрального органа или сервера, который управляет сетью, и каждый узел напрямую взаимодействует с другими узлами для обмена информацией, совместного использования ресурсов и выполнения вычислений.

Основное преимущество использования P2P архитектуры заключается в том, что она позволяет создать более децентрализованную и отказоустойчивую систему. Поскольку нет центрального органа, нет единой точки отказа, и сеть может продолжать функционировать, даже если некоторые узлы выходят из строя. Кроме того, P2P архитектура также может улучшить масштабируемость по мере увеличения количества узлов в сети.

Полезные ссылки:

по внутренней структуре

Под структурой в архитектуре программного обеспечения следует понимать организацию и композицию компонентов программной системы, а также то, как они взаимодействуют друг с другом. Она имеет дело с физической организацией системы и взаимосвязями между различными компонентами.

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

  • Монолитная: когда система построена как единый, интегрированный и автономный элемент.
  • Многоуровневая: система разделена на ряд уровней, каждый из которых имеет определенную ответственность и взаимодействует с другими уровнями через четко определенные интерфейсы.
  • Микросервисы: когда система построена как набор небольших, независимых и слабо связанных сервисов.
  • Событийно-ориентированная: когда система реагирует на определенные происходящие события, а не постоянно опрашивается на наличие изменений.
  • Клиент-сервер: клиент отправляет запросы на сервер, а сервер отвечает на эти запросы.
  • Пиринговая: каждый узел в сети ведёт себя как клиент и сервер.
  • Компонентно-ориентированная: когда система состоит из повторно используемых и независимых программных компонентов.
  • Предметно-ориентированная: система организована вокруг смыслового ядра и сущностей бизнеса.

компонентно-ориентированная

В архитектуре программного обеспечения компонентно-ориентированное проектирование (CBD) — это подход к проектированию программных систем путем их составления из набора повторно используемых и независимых программных компонентов. Эти компоненты содержат определенные функциональные возможности и могут быть легко интегрированы в различные части системы, обеспечивая ей более модульную и гибкую конструкцию.

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

Полезные ссылки:

монолитная

В архитектуре программного обеспечения монолитная архитектура — это подход к проектированию, при котором программная система строится как единая, интегрированная и автономная единица. В монолитной архитектуре все компоненты системы сильно связаны и зависят друг от друга. Это означает, что изменения в одной части системы могут повлиять на другие.

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

Полезные ссылки:

многоуровневая

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

Многоуровневая архитектура часто используется для больших и сложных систем, где необходима масштабируемость и гибкость. Каждый уровень в многоуровневой архитектуре отвечает за определенную функциональность и может рассматриваться как «черный ящик» с четко определенным интерфейсом. Уровни взаимодействуют друг с другом через эти интерфейсы, что позволяет четко разделить ответственность.

Полезные ссылки:

Архитектурные шаблоны

Архитектурные шаблоны — это набор решений, хорошо зарекомендовавших себя для определенных типов программных систем. Они формируют словарь часто используемых терминов и набор передовых методов проектирования и создания программных систем, а также могут помочь разработчикам принимать более обоснованные проектные решения. К наиболее часто применяемым архитектурным шаблонам относят:

  • Модель-представление-контроллер (Model-View-Controller, MVC): шаблон для разделения пользовательского интерфейса, бизнес-логики и компонентов для хранения данных системы.
  • Микросервисы: шаблон построения систем как набора небольших, независимо развертываемых сервисов, которые обмениваются данными по сети.
  • Событийно-ориентированный: шаблон для построения систем, которые реагируют на события и выполняют действия в ответ.
  • Многоуровневый: шаблон для организации системы по уровням, где каждый уровень предоставляет определенный набор сервисов вышестоящему уровню.
  • Каналы и фильтры (Pipe-and-Filter): шаблон построения систем в виде последовательности независимых повторно используемых обрабатывающих элементов, соединенных вместе в конвейер.
  • Разделение ответственности на команды и запросы (Command-Query Responsibility Segregation (CQRS)): шаблон, отделяющий обработку команд (которые изменяют состояние системы), от обработки запросов (которые извлекают информацию из системы).
  • «Доска объявлений»: шаблон для создания централизованного хранилища информации, к которому могут обращаться и изменять несколько независимых модулей или подсистем.
  • Микроядро: шаблон, целью которого является минимизация объема кода, выполняемого в режиме ядра, и перенос максимально возможного количества функций в процессы пользовательского режима.
  • Бессерверный: шаблон проектирования, который позволяет разработчикам создавать и запускать приложения и службы без необходимости выделения серверов и управления ими.
  • Очереди и потоки сообщений: шаблон, который разделяет различные компоненты системы и обеспечивает асинхронную связь между ними.
  • Генерация событий (Источники событий, Event Sourcing): шаблон, в котором сохраняются все изменения состояния системы в виде последовательности событий, а не только текущего состояния.

Полезные ссылки:

SOA

SOA (сервис-ориентированная архитектура) — это архитектурный шаблон, который используется для проектирования и организации программных систем как набора сервисов, к которым можно получить доступ по сети. Эти сервисы представляют собой автономные, самостоятельные, функциональные единицы, которые можно повторно использовать и комбинировать для создания новых функциональных возможностей. SOA сервисы спроектированы так, чтобы быть слабо связанными, т. е. они не зависят от деталей реализации других сервисов, они взаимодействуют друг с другом через четко определенные интерфейсы, обычно с использованием протокола, такого как HTTP или SOAP. SOA обеспечивает ряд преимуществ по сравнению с другими архитектурными шаблонами, например возможность повторного использования, модульность, совместимость и масштабируемость. Его можно реализовать с помощью различных технологий, таких как веб-сервисы, REST и микросервисы.

Полезные ссылки:

CQRS

CQRS (Разделение ответственности на команды и запросы, Command Query Responsibility Segregation) — это архитектурный шаблон, который используется для разделения обязанностей чтения и записи данных в программной системе. В CQRS архитектуре система разделена на две отдельные части: команды и запросы.

Команды отвечают за обработку команд и обновление состояния системы, а запросы — за считывание текущего состояния системы и возврат результатов клиенту. Команды и запросы могут использовать разные модели данных, механизмы хранения и даже разные технологии.

Полезные ссылки:

Предметно-ориентированное проектирование

Предметно-ориентированное проектирование (DDD) — это архитектурный шаблон, который используется для проектирования программных систем, на основе смыслового ядра и сущностях бизнеса. Он ориентирован на создание четкого и точного представления предметной области в программной системе, а также на согласование программной системы с целями и задачами бизнеса. DDD имеет ряд преимуществ по сравнению с другими архитектурными шаблонами, например, соответствие целям и задачам бизнеса, более эффективное взаимодействие между экспертами в предметной области и разработчиками, четкую и выразительную модель предметной области, а также улучшенную масштабируемость и удобство сопровождения. Он реализуется с использованием набора принципов и шаблонов, таких как стратегическое проектирование, подобласти, ограниченный контекст, сущности, объекты-значения, агрегат и репозиторий.

Полезные ссылки:

Модель-представление-контроллер (Model-View-Controller)

Модель-представление-контроллер (MVC) — это архитектурный шаблон, который разделяет задачи программной системы на три отдельных компонента: модель, представление и контроллер, где модель олицетворяет данные и бизнес-логику системы, представление — пользовательский интерфейс системы, а контроллер действует как посредник между моделью и представлением. Основная цель MVC — разделить отвесттвенность в системе, упрощая ее понимание, поддержку и развитие. Он широко используется в веб-разработке.

Полезные ссылки:

Микросервисы

Микросервисы — это архитектурный шаблон, который используется для проектирования программных систем как набора небольших, независимых и слабо связанных сервисов. Каждый сервис отвечает за определенный функционал и может разрабатываться, развертываться и масштабироваться независимо. Основное преимущество архитектуры микросервисов заключается в том, что она позволяет сделать систему более гибкой и масштабируемой, а также улучшает локализацию ошибок и ускоряет развертывание. Он часто используется в сочетании с другими архитектурными шаблонами и стилями, такими как событийно-ориентированная архитектура, CQRS и сервис-ориентированная архитектура.

Полезные ссылки:

Шаблон Blackboard («доска объявлений»)

Архитектурный шаблон «Доска объявлений» — это шаблон проектирования программного обеспечения, который позволяет создавать централизованное хранилище информации, к которому могут обращаться и изменять несколько независимых модулей или подсистем. «Доска» служит механизмом связи и координации между этими модулями, позволяя им обмениваться информацией и взаимодействовать для достижения общей цели. Этот шаблон часто используется в системах искусственного интеллекта и принятия решений, где несколько процессов или агентов должны совместно использовать сложные данные и анализировать их.

Полезные ссылки:

Микроядро

Микроядро — это архитектурный шаблон, используемый при разработке операционной системы, целью которого является минимизировать объем кода, работающего в режиме ядра (т. е. привилегированный режим с прямым доступом к аппаратным ресурсам), и вместо этого перенести как можно больше функций в пользовательский режим. Это достигается за счет создания небольшого минималистического ядра, которое выполняет только основные задачи, такие как управление памятью, планирование процессов и межпроцессное взаимодействие (IPC), а весь остальной функционал реализуется в процессах пользовательского режима.

Полезные ссылки:

Бессерверная архитектура

Бессерверная архитектура — это шаблон проектирования, который позволяет разработчикам создавать и запускать приложения и сервисы без необходимости выделения серверов и управления ими. Вместо этого эти приложения и сервисы выполняются в полностью управляемой среде, такой как AWS Lambda, Azure Functions или Google Cloud Functions, где инфраструктура и масштабирование выполняются автоматически поставщиком облачных услуг.

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

Полезные ссылки:

Очереди сообщений / потоки

Очереди сообщений и потоки — это архитектурные шаблоны, которые используются для разделения различных компонентов системы и обеспечения асинхронной связи между ними.

Очереди сообщений: Очередь сообщений — это программный компонент, который позволяет нескольким системам или приложениям взаимодействовать друг с другом путем передачи сообщений между ними. Сообщения хранятся в очереди и каждое сообщение обрабатывается одним потребителем. Этот шаблон полезен для систем, в которых существует высокая степень изменчивости скорости создания и потребления сообщений, и где отправитель и получатель не должны быть активны в одно и то же время. Примерами систем очередей сообщений являются Apache Kafka, RabbitMQ и Amazon SQS.

Полезные ссылки:

Генерация событий (Источники событий, Event Sourcing)

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

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

Полезные ссылки:

Шаблоны корпоративных приложений

Шаблоны корпоративных приложений — это набор шаблонов проектирования, которые обычно используются при разработке корпоративного программного обеспечения. Эти шаблоны содержат словарь часто употребляемых терминов и набор лучших практик для решения часто встречающихся проблем, возникающих при разработке больших и сложных программных систем. Ниже приведены некоторые примеры шаблонов корпоративных приложений:

  • Предметно-ориентированное проектирование (DDD)
  • Модель-представление-контроллер (MVC)
  • Сервис-ориентированная архитектура (SOA)
  • Принцип разделения ответственности на команды и запросы (CQRS)
  • Генерация событий (Источники событий, Event Sourcing)
  • Микросервисы
  • Событийно-ориентированная архитектура (EDA)

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

Полезные ссылки:

Объекты переноса данных (DTOs)

Шаблон проектирования Объект переноса данных — это один из архитектурных шаблонов корпоративных приложений, который требует использовать объекты, объединяющие и инкапсулирующие данные для передачи. Объект переноса данных, по сути, подобен структуре данных. Он не должен содержать никакой бизнес-логики, но должен содержать механизмы сериализации и десериализации.

Полезные ссылки:

Коллекции объектов (Identity Maps)

Коллекции объектов — это шаблон, используемый при разработке корпоративных приложений для поддержки карты объектов, которые были загружены из базы данных, где ключом является их уникальный идентификатор. Они используются для предотвращения создания в памяти нескольких копий одного и того же объекта при многократном доступе к одним и тем же данным.

Шаблон Коллекция объектов обычно используется в сочетании с таким инструментом как ORM (объектно-реляционным отображением). Перед тем как объект извлекается из базы данных, сначала происходит сверка с коллекцией объектов, чтобы убедиться, что он уже не был загружен ранее. Если он уже находится в коллекции, то возвращается существующий объект, а не создается новая копия.

Полезные ссылки:

Особые случаи использования (Use Cases)

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

Особый случай использования — это описание последовательности действий, которые система выполняет в ответ на запрос пользователя для достижения определенной цели. Особый случай использования обычно включает в себя:

  • Áктор (пользователь), который инициирует действие
  • Цель, которую хочет достичь а́ктор
  • Шаги, необходимые для достижения цели, включая любые альтернативные пути или условия, приводящие к ошибке
  • Ожидаемый результат взаимодействия

Особые случаи использования часто являются основопологающими при проектировании и разработке системы, поскольку они обеспечивают чёткое и более глубокое понимание требований к ней.

Полезные ссылки:

Репозитории (Repositories)

Репозитории — это шаблон, используемый при разработке корпоративных приложений для обеспечения согласованного и абстрактного способа доступа к хранилищу данных. Репозитории по сути являются уровнем абстракции между приложением и хранилищем данных, предоставляя согласованный и простой API для доступа к данным и манипулирования ими.

Репозиторий — это шаблон, который можно использовать для организации кода доступа к данным и инкапсуляции логики извлечения и хранения объектов. Репозитории обеспечивают отделение проблемы доступа к данным от остальной части приложения, позволяя писать код приложения для интерфейса, а не для конкретной технологии хранения данных.

Полезные ссылки:

Преобразователи (Mappers)

Преобразователи — это шаблон, используемый при разработке корпоративных приложений для обеспечения согласованного и абстрактного способа сопоставления между различными моделями данных. Они по сути представляют собой уровень абстракции между приложением и хранилищем данных, предоставляя согласованный и простой API для преобразования данных.

Преобразователь — это компонент, который можно использовать для перевода данных из одного формата или модели в другой. Например, его можно использовать для преобразования данных из модели базы данных в модель предметной области или из модели предметной области в объект переноса данных (DTO).

Полезные ссылки:

Сценарий транзакции (Transaction Script)

Сценарий транзакции — это шаблон, используемый в разработке корпоративных приложений, который организует бизнес-логику в единый процедурный сценарий. Он часто используется для простых операций CRUD (создание, чтение, обновление, удаление), где вся логика для конкретной транзакции содержится в одном скрипте или функции. Этот шаблон прост в реализации и понятен, но может стать громоздким по мере увеличения сложности приложения. Альтернативные шаблоны, такие как предметно-ориентированное проектирование (DDD) и шаблон Active Record, могут лучше подходить для более сложных приложений.

Полезные ссылки:

Команды / Запросы (Commands / Queries)

Шаблон разделения ответственности на команды и запросы (CQRS) — это методика, используемая при разработке корпоративных приложений для разделения обязанностей по обработке операций, связанных с записью (команд), от операций, связанных с чтением (запросов), для выполнении действий, которые изменяют состояние системы, таких как создание, обновление или удаление данных. Эти операции реализуются обработчиками команд, которые отвечают за проверку данных и выполнение соответствующей бизнес-логики.

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

Полезные ссылки:

Объекты-значения (Value Objects)

Объекты-значения — это шаблон, используемый в разработке корпоративных приложений для представления простых неизменяемых значений, используемых для моделирования понятий предметной области. Обычно они используются для инкапсуляции данных, которые не являются сущностью, но важны для предметной области.

Объект-значение определяется своим значением, не имеет собственной идентичности, уникальности, что означает, что два объекта-значения с одинаковым значением считаются равными, независимо от их идентичности.

Полезные ссылки:

Модели предметной области (Domain Models)

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

Модель предметной области — это набор объектов, которые представляют реальные понятия и сущности предметной области. Эти объекты обычно моделируются как классы или типы и инкапсулируют данные и поведение, специфичные для предметной области. Они несут ответственность за представление состояния и поведения бизнес-концепций, которые они моделируют, а также за соблюдение правил и ограничений предметной области.

Полезные ссылки:

Сущности (Entities)

Сущности — это шаблон, используемый в разработке корпоративных приложений для представления бизнес-концепций с уникальным идентификатором и временем существования. Обычно они используются для моделирования реальных объектов или понятий, которые имеют четкую идентичность и жизненный цикл, например клиент, заказ или учётная запись.

Сущность определяется своей идентичностью, что означает, что две сущности с одной и той же идентичностью считаются одним и тем же, независимо от их состояния. Сущности обычно имеют уникальный идентификатор, например первичный ключ, который используется для их идентификации. У них также есть связанный набор свойств или атрибутов, описывающих их состояние.

Полезные ссылки:

Объектно-реляционные отображения (ORMs)

ORM расшифровывается как Object-Relational Mapping (Объектно-реляционное отображение), это методика, используемая при разработке корпоративных приложений для сопоставления между моделью объектно-ориентированного программирования и моделью реляционной базы данных. Это позволяет разработчикам работать с объектами в своем коде, в то время как инструмент ORM заботится о переводе этих объектов в соответствующие операции с базой данных.

ORM предназначены для того, чтобы абстрагироваться от сложности работы с реляционной базой данных и позволить разработчикам взаимодействовать с базой данных с помощью объектно-ориентированного API более высокого уровня. Они предоставляют набор библиотек и инструментов, которые сопоставляют объекты в коде с таблицами и строками в базе данных и наоборот. Это позволяет разработчикам работать с данными, используя знакомую объектно-ориентированную парадигму, вместо того, чтобы писать сложные SQL-запросы.

Полезные ссылки:


  1. Вервов Вон. Предметно-ориентированное проектирование: самое основное.: Пер. с англ. - СпВ.: ООО "Альфа-книга". 2017. - 160 с.: ил. - Парал. тит. англ.
  2. Вернов Вон. Реализация методов предметно-ориентированного проектирования.: Пер. с англ. - М.: ООО "И.Д. Вильямс", 2016. - 688 с.: ил. - Парал. тит. англ.
  3. Фаулер, Мартин. Шаблоны корпоративных приложений.: Пер. с англ. - М.: ООО "И. Д. Вильямс", 2016. - 544 с.: ил. - Парал. тит. англ.
  4. Эванс Эрик. Предметно-ориентированное проектирование (DDD): структуризация сложных программных систем.: Пер. с англ. М.: ООО "И. Д. Вильямс", 2011. - 448 с.: ил. - Парал. тит. англ.

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