Данная статья является продолжением предыдущей. На этот раз мы на примерах рассмотрим директиву use и магический метод __using__, магический, потому что подобные методы с двумя подчеркиваниями используют в Питоне, называя магическими.
Довольно часто мы пишем use GenServer, или require Logger, давайте разберемся в чем же разница?
Различие между require и use
Если объяснять на пальцах, то use расширяет модуль, в котором он используется: дополняет его методами и зависимостями, описанными в __using__, поэтому может возникнуть конфликт имен. Используйте use осторожно.
Пример:
Тем самым мы расширили модуль Foo, добавив в него функцию twenty_five.
require компилирует макросы, описанные в модуле, и обращаться к ним можно только через namespace модуля. На примере того же Logger’а:
На примере my_awesome_app_web.ex — модуль феникса, предоставляющий интерфейсы для view, controller, channel, router. Рассмотрим использование директивы using, и разберемся, почему она так полезна. После этого одной загадкой станет меньше, и в фениксе для вас не останется никакой магии.
Чем нам в данном случае помогает using? А тем, что мы не описываем в каждом представлении, контроллере, канале и маршруте список импортируемых и используемых модулей. Так же, например, мы можем расширить все контроллеры какой-либо функцией, добавив её в фукнцию controller.
use & __using__ на примерах:
Пример №1
Разделим роутер нашего веб-приложения на несколько файлов, после чего элегантно объединим их в одном файле.
Представим, что у нас довольно большое приложение, в котором есть маршруты для админки, api и browser-клиента. Они все описаны в одном файле на 500 строк. Такой файл неудобно поддерживать, особенно когда маршруты можно разделить на части по специфике контекста.
В итоговом файле осталось всего лишь использовать наши модули с маршрутами:
Теперь мы можем помещать какие-то специфичные маршруты в разные файлы и использовать их в роутере, не нагромождая тем самым файл роутера.
Пример №2
Расширим стандартный GenServer, чтобы он по умолчанию имел функцию именованного запуска и запускался сразу с Logger’ом, который логирует информацию о запуске.
И так, мы написали обертку над GenServer’ом, которая дополнительно подключает Logger и логирует информацию о запуске. Давайте применим её при создании GenServer’a.
Теперь у нас нет необходимости повторно указывать require Logger, он уже доступен в данном модуле.
Давайте запустим NamedGenServer и посмотрим как он работает:
На этом закончили рассмотрение use и __using__, если остались какие-то вопросы — спрашивайте в комментариях, с радостью на них отвечу.