Чистая Архитектура. Часть Ii. Парадигмы Программирования

Данная серия статей представляет собой вольный и очень краткий пересказ книги Роберта Мартина (Дядя Боб) «Чистая архитектура», вышедшей в 2018 году.

Начало здесь .



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

Дисциплина, которая впоследствии стала называться программированием, была основана Аланом Тьюрингом в 1938 году.

В 1945 году он уже писал полноценные программы, работающие на реальном оборудовании.

Первый компилятор был изобретен в 1951 году Грейс Хоппер (бабушкой с татуировкой COBOL).

Затем начали создаваться языки программирования.



Обзор парадигм

Существует три основные парадигмы: структурный , объектно-ориентированный И функциональный .

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

Структурное программирование было открыто Дейкстрой в 1968 году.

Он понял, что goto — это зло, и программы следует строить из трёх основных структур: последовательности, ветвления и цикла.

Объектно-ориентированное программирование было открыто в 1966 году.

Функциональное программирование началось в 1936 году, когда Чёрч изобрел лямбда-исчисление.

Первый функциональный язык LISP был создан в 1958 году Джоном Маккарти.

Каждая из этих парадигм лишает программиста возможностей, а не добавляет их.

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

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

Полиморфизм в ООП необходим для установления связи через границы модуля.

Функциональное программирование определяет, где мы храним данные и как к ним получить доступ.

Структурное программирование помогает реализовать алгоритмы внутри модулей.



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

Дийкстра понял, что программирование — это сложно.

Большие программы слишком сложны, чтобы человеческий мозг мог их контролировать.

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

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

С тех пор оператор goto исчез практически из любого языка программирования.

Таким образом, структурное программирование позволяет проводить функциональную декомпозицию.

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

В реальном программировании стал популярен «более простой» вариант: тесты.

Тесты не могут доказать правильность программ, но могут доказать их некорректность.

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



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

ООП – это парадигма, характеризующаяся наличием инкапсуляция , наследование И полиморфизм .

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

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

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

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

Наследование было возможно в языках до ООП, но в объектно-ориентированных языках оно стало гораздо удобнее.

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

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

Полиморфизм – это ключевое свойство ООП построить грамотную архитектуру.

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

Этот принцип называется инверсия зависимостей , на котором основаны все системы плагинов.

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

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

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

Любую зависимость всегда можно инвертировать .

В этом сила ООП.

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

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

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

Функциональное программирование основано на запрете изменения переменных.

После инициализации переменной ее значение остается неизменным.

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

Однако для этого могут потребоваться большие ресурсы ЦП и памяти.

Используя функциональный подход, мы делим компоненты на изменяемые и неизменяемые.

При этом как можно больше функциональности следует закладывать в неизменяемые компоненты и как можно меньше — в изменяемые.

В изменяемых компонентах приходится работать с изменяемыми данными, которые можно защитить с помощью транзакционной памяти.

Интересный подход к сокращению изменяемых данных — это Event Sourcing. В нем мы храним не сами данные, а история событий , что привело к изменению этих данных.

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

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

Для оптимизации можно использовать снапшоты, которые делаются, скажем, раз в сутки.



Заключение

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

  • ООП не позволяет нам получить доступ к скрытым членам классов и заставляет использовать инверсию зависимостей.

  • FP запрещает изменение переменных.

Продолжение здесь .

Теги: #программирование #архитектура #дизайн #дизайн и рефакторинг #роберт Мартин #дядя боб #дядя боб

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.