Ответ
Да, активно использовал Sourcery — инструмент для метапрограммирования в Swift, который генерирует код на основе аннотаций в исходниках и шаблонов (Stencil).
Типичные сценарии применения:
- Автоматизация boilerplate-кода: Генерация реализаций протоколов
Equatable,Hashable,Codableдля моделей. - Моки для тестирования: Автоматическое создание мок-объектов, которые реализуют протоколы зависимостей, что упрощает unit-тестирование.
- Линтинг и проверки: Генерация кода для проверки, что все случаи в
enumобработаны вswitch. - Динамические шаблоны UI: Генерация кода для таблиц или коллекций на основе моделей данных.
Пример шаблона Sourcery (.stencil) для автоматической генерации Equatable:
// AutoEquatable.stencil
{% for type in types.structs|enum where type.implements.Equatable %}
// MARK: - AutoEquatable for {{ type.name }}
extension {{ type.name }}: Equatable {
static func ==(lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
{% for variable in type.storedVariables %}
guard lhs.{{ variable.name }} == rhs.{{ variable.name }} else { return false }
{% endfor %}
return true
}
}
{% endfor %}
Аннотация в исходном коде Swift, которая активирует шаблон:
// sourcery: AutoEquatable
struct User {
let id: Int
let name: String
var email: String?
}
Преимущества:
- Снижение рутинной работы и ошибок при написании повторяющегося кода.
- Единообразие сгенерированного кода по всему проекту.
- Упрощение рефакторинга — при изменении модели достаточно перегенерировать код.
Недостатки / сложности:
- Настройка в CI/CD: Генерацию нужно интегрировать в процесс сборки (например, как
Run Script Phaseв Xcode). - Отладка: Сложнее отследить источник ошибки, если она в сгенерированном коде. Необходимо проверять шаблоны и входные аннотации.
- Зависимость от инструмента: Добавляет ещё одну зависимость в проект.
Ответ 18+ 🔞
Слушай, а вот этот ваш Sourcery — это ж просто песня, а не инструмент! Ну, в смысле, метапрограммирование в Swift, когда код сам себе код пишет. Представляешь? Сидит такой код, пьёт кофе, и параллельно штампует себе подобных. Красота!
Где эту штуку впихивали, чтобы жизнь мёдом не казалась:
- Автоматизация скукотищи: Вместо того чтобы вручную, как обезьяна, писать
Equatable,Hashable,Codableдля каждой своей структурки — он это делает за тебя. Ты просто аннотацию накатал, а он уже тебе готовый extension подсовывает. Волшебство, ёпта! - Моки для тестов: О, это вообще отдельная история. Надоело для каждого протокола-зависимости городить свой мок-объект с кучей заглушек? Sourcery берёт протокол и генерирует тебе готового солдатика-заглушку. Unit-тесты пишутся почти сами, блядь.
- Линтинг на стероидах: Можешь заставить его генерировать код, который проверит, не забыл ли ты в каком-нибудь
switchобработать все кейсыenum. Типа превентивный удар по будущим багам. - UI из коробки: Если у тебя таблицы или коллекции строятся по однотипным моделям, можно шаблон накатать, и он тебе ячейки, datasource и прочую муть сгенерирует. В общем, лень — двигатель прогресса, а Sourcery — её верный слуга.
Вот, смотри, как это выглядит изнутри. Шаблон (.stencil) для автоматического Equatable:
// AutoEquatable.stencil
{% for type in types.structs|enum where type.implements.Equatable %}
// MARK: - AutoEquatable for {{ type.name }}
extension {{ type.name }}: Equatable {
static func ==(lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
{% for variable in type.storedVariables %}
guard lhs.{{ variable.name }} == rhs.{{ variable.name }} else { return false }
{% endfor %}
return true
}
}
{% endfor %}
А в твоём коде ты просто вешаешь волшебную бирочку:
// sourcery: AutoEquatable
struct User {
let id: Int
let name: String
var email: String?
}
И всё! Sourcery это видит, шаблон применяет, и бац — у User появляется реализация ==. Чистая магия, только без факира.
Что хорошего, спросишь?
- Рутины и ошибок — ноль ебать. Перестаёшь тупо копипастить одно и то же. Мозг освобождается для действительно важных вещей. Например, чтобы подумать, почему этот блядский API опять отдаёт 500-ю ошибку.
- Всё единообразно. Сгенерированный код по всему проекту выглядит одинаково, не как у страшного Змея Горыныча — три головы, три разных почерка.
- Рефакторить не страшно. Добавил поле в модель? Не надо бегать по всему проекту и править
==,hash,encode. Просто перегенерировал код — и порядок. Удивление пиздец, как жили без этого раньше.
Но и подводных ебуч, конечно, хватает:
- Настройка в CI/CD. Это тебе не вручную кнопочку ткнуть. Надо интегрировать генерацию в процесс сборки, обычно как
Run Script Phaseв Xcode. Если накосячишь — проект не соберётся, и вся команда будет тебя ненавидеть. Ответственность, блядь! - Отладка — тот ещё квест. Если ошибка в сгенерированном коде, искать её источник — это как искать иголку в стоге сена, который сам себя сгенерировал. Придётся лезть в шаблоны и смотреть, что там понавводили в аннотациях.
- Зависимость. Проект обрастает ещё одним инструментом, за которым нужно следить, обновлять, и который может в один прекрасный день сломаться. Доверия ебать ноль к таким вещам, но игра стоит свеч.
Короче, инструмент мощный, но не для слабонервных. Как скальпель хирурга — в умелых руках творит чудеса, а в руках идиота — одно сплошное увечье.