Pull to refresh

Проблемы инкапсуляции

Reading time3 min
Views3.1K
Недавно мне попалась на глаза интересная статья о проблемах в концепции инкапсуляции — почитайте, если есть время.
Для тех, у кого времени нет, я быстренько перескажу суть: инкапсуляция не выполняет одной из своих основных задач (дать «черный ящик» с описанными входами и выходами) по целому ряду причин:
  1. Программисты не доверяют чужим «черным ящикам».
  2. В чужих «чёрных ящиках» случаются ошибки, которые приходится фиксить, влезая в их внутренности (и ломая этим всю затею).
  3. Входы и выходы не всегда описаны понятно. Иногда бывает проще создать свой велосипед, чем разбираться в том, как поехать на чужом.

Всё это презренная реальность, которую теоретики программирования игнорируют. И как же с этим жить?

Без понятия. Вряд ли тут есть какая-то «серебряная пуля» (да и где она есть?) и в каждом случае нужно решать что-то своё. Рассказ будет об одном подобном случае и одном из вариантов решения.

Попался мне как-то раз один большой проект — его писали уже много лет и много людей. Соответственно, на каждую задачу в духе шифрования\парсинга\архивирования\и т.д. давно были написаны свои модули. Казалось бы — лафа, бери и пользуйся. Вот только беда в том, что модулей этих было так много и написаны они были уже так давно, что никто не помнил ни их авторов, ни деталей их реализации. Классические «черные ящики». Иногда понятные, иногда нет. Иногда работающие, а иногда глючные. Ну как этим пользоваться?

Я немного подумал и решил сделать для каждого используемого класса «обертку», по примерно следующему принципу: вот есть ОГРОМНЫЙ класс для шифрования, который имеет массу опций и вообще монстр. (Кто видел серьёзные классы для шифрования, тот знает о чём я — всякие там инициализационные векторы, константы и прочее). Мне он нужен для одной лишь цели — зашифровать и расшифровать файл по симметричному ключу. И всё. Ну вот значит берём и пишем обёртку из двух методов:
  • ЗашифроватьФайл(что, куда, ключ)
  • РасшифроватФайл(что, куда, ключ)

Внутри методов дергаем сложные методы базового класса. Дальше по коду юзаем свою обёртку. В чём тут плюсы?
  1. Проблема недовоерия ЧУЖОМУ черному ящику решена — теперь везде по коду я использую СВОЙ черный ящик. Я ему верю. Начнёт выкобениваться — поменяем внутренности, чтобы использовал какие-то другие средства шифрования (без изменения интерфейса).
  2. На такую простую обертку я теперь моментально напишу тесты. Чего их писать-то: зашифровал — расшифровал — сверил файлы. 5 строк кода. Плюс проверка на ошибки файловых операций — еще 10. На тот большой и страшный базовый класс писать тесты я бы не взялся — долго и трудно (их вон даже его автор не написал). Более того, мои тесты будут лучше тестов автора класса, даже если бы он их написал. Потому что автор кода всегда имеет какое-то своё представление о том, как этот код будет использоваться. И это отражается не только на коде, но и на тестах. Ну вот верил бы автор, что файлы для шифрования всегда существуют и доступны для чтения — и не проверил бы это в тестах. А я-то знаю, что у меня это не так — и обязательно проверю эти ситуации. Ну потому, что мне это реально надо.
  3. Входы и выходы стали намного понятнее. Ну, мне по крайней мере. Да и другим, я так думаю. И плевать, что я создал еще одну сущность, старик Оккам меня простит.

Под конец статьи ко мне подкралась мысль, что я невольно пересказал какую-то главу книги Фаулера или Макконнелла, столь просто и банально всё звучит. Но вроде бы нет (поправьте, если ошибаюсь).
Update: мне тут из зала подсказывают, что я рассказываю о паттернах Фасад и Адаптер из книги Банды Четырёх — вполне может быть.

Короткая мораль


Если Вы используете чужой код, которому не доверяете — напишите для него обёртку, которая была бы удобна и для тестирования и для реального использования. Тестируйте эту обёртку так, как она будет использоваться реальным кодом.
Tags:
Hubs:
Total votes 55: ↑36 and ↓19+17
Comments36

Articles