shikhalev.*
Картинка для привлечения внимания

При написании inat-channel я столкнулся вот с какой проблемой: с одной стороны, более-менее сложные действия должны быть декомпозированы, то есть разбиты на модули и отдельные методы в них; с другой — глубокая декомпозиция заставляет писать длинные обращения к методам типа INat­Chan­nel::​Te­le­gram::​send_​ob­ser­va­ti­on, что неудобно, да и не эстетично. По хо­ро­ше­му вообще нужно верхний уровень методов ин­клю­дить и писать send_observation в основной программе, но если писать все как включаемые методы модулей, то во-первых, они все из всех модулей попадут в финале в одно пространство имен, а во-вторых, туда же попадут и приватные методы.

Для подобных случаев и предназначен паттерн «Фасад» — мы создаем отдельный программный модуль — в данном случае это модуль же в терминах Ruby — который содержит только нужные извне методы, делегируя их в основной нормально де­ком­по­зи­ро­ван­ный код. И затем его спокойно ин­клю­дим в ко­де основного скрипта.

Собственно, именно так я и сделал, определив модуль IC и заполняя его методами в тех же файлах, где они определены. Туда же отправились некоторые методы, не нужные вовне, а используемые слабо логически связанными модулями — здесь речь скорее не о логике и отделении фасада, а о сокращении (текстовом) кросс­мо­дуль­ных вызовов. Впрочем, по мере разрастания структуры вопрос, что считать внутренним, а что внешним, становится не очень однозначным.

Подумав немного на эту тему, я решил вынести абстракцию в код и написал is-dsl — гем, упрощающий, а главное — структурирующий делегирование методов и констант фасаду. Подробнее — в README репозитория (есть русская версия), а также в yard-документации. Здесь коротко обозначу основные особенности:

  • Помимо основного модуля фасада формируется теневой модуль — для использования внутри библиотеки. Все, что попадает в основной, попадает и в теневой, обратное неверно. См. shadow-методы.

  • Можно делегировать как статически сингл­тон-методы классов и модулей, так и лениво методы произвольных сингл­тон-объектов, где сам объект создается или получается через вызов блока. См. lazy-ме­то­ды. Предполагается применение с ме­то­дом класса instance в пер­вую очередь.


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