Страницы

Поиск по вопросам

среда, 3 октября 2018 г.

Что значит инкапсулировать?

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


Ответ

В разработке ПО есть два схожих понятия – инкапсуляция и сокрытия информации. Кто-то считает, что это синонимы, кто-то нет, но это не так и важно.
Немного истории: Дэвид Парнас в году эдак 70-м в статье “On the Criteria To Be Used in Decomposing Systems into Modules” впервые ввел понятие сокрытия информации, как ключевого инструмента проектирования. Звучал этот принцип примерно так: декомпозиция системы на модули не должна основываться на анализе блок схем или потоков исполнения. Вместо этого, каждый модуль должен прятать внутри некоторое решение (design decision), предоставляя минимальное количество информации о нем своим клиентам.
Вот небольшой пример.
Допустим, вы разрабатываете ынтырпрайз приложение, которое делает что-то важное. Любое нормальное приложение обычно требует некоторой конфигурации: ну, параметры подключения к БД или серверу, и другую ценную информацию. И вот, матерый артихектор (*) вместе с не менее матерым клиентом просят прочитать конфигурацию из конфигурационного файла.
(*) это не опечатка, пожалуйста, не правьте это!
В процессе разговора с ними вы понимаете, что никто толком не знает, почему читать конфигурацию нужно именно из файла, какой должен быть у него формат и что именно там должно храниться.
Теперь вы становитесь перед выбором: вы можете «размазать» сведения о конфигурации ровным слоем по всему приложению. Каждый компонент, которому нужны некоторые параметры, сам полезет в app config, вытянет оттуда нужные данные, пропарсит xml или json и будет готов служить. С другой стороны, очевидно, что решение о том, где именно хранится конфигурация и в каком формате, может измениться в будущем. Поэтому более вменяемым решением будет скрыть информацию о местоположении и формате конфигурации в одном модуле, например, с помощью классов Configuration и ConfigurationProvider. В этом случае, когда (да, именно, «когда», а не «если») требования изменятся, то поменяется лишь реализация класса ConfigurationProvider, а все остальные пользователи этого класса или конфигурации останутся неизменными. Аналогично, при изменении формата, поменяется тоже только процесс парсинга, а не потребители конфигурации.
Этот пример кажется надуманным, но это не так! Мы довольно часто сталкиваемся с изменчивостью требований, но используем, к сожалению, один из двух подходов:
• Полностью игнорируем возможность изменения требований и делаем все в лоб или
• Создаем супер сложное решение с десятком уровней косвенности, которое должно выдержать изменения требований в любом направлении без изменения кода вообще.
Более же разумный подход находится где-то по середине. Каждый раз, когда я начинаю разработку некоторой фичи, я думаю, сколько кусков в коде придется поменять, если требования или детали реализации существенно изменятся. При этом я не стараюсь свести количество изменений к 1 (ну, типа, если мы следуем SRP, то должно быть только одно место, в случае изменения требованй). Я стараюсь, чтобы этих мест было мало, а изменения были простыми.
Собственно, это и есть суть information hiding и его младшей сестры – инкапсуляции.

Комментариев нет:

Отправить комментарий