Книга Чистая архитектура. Искусство разработки программного обеспечения, страница 32. Автор книги Роберт Сесил Мартин

Разделитель для чтения книг в онлайн библиотеке

Онлайн книга «Чистая архитектура. Искусство разработки программного обеспечения»

Cтраница 32
Сопровождение

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

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

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

Сохранение разнообразия вариантов

Как говорилось в главе 2, всякая программная система имеет две ценности: поведение и структуру. Вторая из них больше, потому что именно она делает программное обеспечение гибким.

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

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

Любую программную систему можно разложить на два основных элемента: политику и детали. Политика воплощает все бизнес-правила и процедуры. Политика — вот истинная ценность системы.

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

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

Например:

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

• Не нужно на ранних этапах разработки выбирать тип веб-сервера, потому что высокоуровневая политика не должна даже знать, что она доставляется через Веб. Если высокоуровневая политика не зависит от HTML, AJAX, JSP, JSF и прочих технологий, применяемых в веб-разработке, вы сможете отложить принятие решения о выборе веб-системы до более поздних этапов. Фактически вы даже не должны принимать решения, что система будет предоставлять свои услуги через Веб.

• Не нужно на ранних этапах разработки приспосабливать интерфейс REST, потому что высокоуровневая политика не должна зависеть от интерфейса с внешним миром. Также не нужно приспосабливаться под архитектуру микрослужб или SOA [34]. Высокоуровневая политика не должна зависеть от подобных деталей.

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

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

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

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

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

Хороший архитектор максимизирует количество непринятых решений.

Независимость от устройства

Чтобы понять суть, вернемся ненадолго в 1960-е годы, когда компьютеры были совсем юными, а большинство программистов были математиками или инженерами из других областей (и треть или даже больше были женщинами).

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

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

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

PRTCHR, 0

        TSF

        JMP .-1

        TLS

        JMP I PRTCHR

PRTCHR — это подпрограмма, печатающая один символ на телепринтере. Ячейка памяти с нулем в начале подпрограммы использовалась для хранения адреса возврата. (Не спрашивайте, что это такое.) Инструкция TSF пропускает следующую за ней инструкцию, если телепринтер готов напечатать символ. Если телепринтер занят, TSF просто передавала управление следующей за ней инструкции JMP .-1, выполняющей переход обратно на инструкцию TSF. Если телепринтер готов, TSF передавала управление инструкции TLS, которая посылала символ в регистр A телепринтера. Затем инструкция JMP I PRTCHR возвращала управление вызывающему коду.

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

Вход
Поиск по сайту
Ищем:
Календарь
Навигация