Когда размер команды растет, вполне естественно, что мы хотим определить какие-то общие практики, чтобы сохранять единообразие во время работы. Такие практики предотвращают Git-конфликты, создают более однородную базу кода и помогают людям чувствовать себя комфортно с кодом, написанным их коллегами.
В некоторых случаях эти методы трудно обеспечить формально и автоматически. Например, использование Protocol или ProtocolWitness не может быть внедрено формально — это скорее стиль программирования. Есть много других случаев, когда возможно возникновение подобных ситуаций. Например, мы можем попросить компилятор предупредить нас, когда мы принудительно приводим один тип к другому.
В сегодняшней статье мы собираемся изучить некоторые инструменты, которые мы можем добавить в наш проект, чтобы обеспечить соблюдение таких правил и создать более последовательную базу кода.
SwiftLint
SwiftLint — это инструмент, созданный Realm, который применяет правила для создания согласованного стиля кода.
Вы можете установить его с помощью brew или использовать pod во время разработки. У нас также есть несколько альтернатив в том, как мы можем его использовать. Мы можем:
- Запустите его из командной строки с помощью команды swiftlint.
- Прикрепите его к коммиту в Git.
- Прикрепите его как этап предварительной сборки в Xcode, чтобы он запускался каждый раз при сборке.
Шаг 3 можно выполнить, добавив следующий фрагмент в Xcode перед этапом сборки.
if which swiftlint >/dev/null; then swiftlint else echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" fi
Мы даже можем запустить инструмент в режиме автозамены. Вы может исправить некоторые из простейших случаев, просто вызвав swiftlint autocorrect в командной строке (или добавив флаг autocorrect в приведенный выше сценарий). В этом случае инструмент фактически сам изменит ваши файлы, применяя некоторые правила.
Все правила можно настроить, создав и отредактировав файл .swiftlint.yml, который читает SwiftLint.
SwiftFormat
SwiftFormat (не тот, что от Apple) похож на SwiftLint. Однако его цель не в том, чтобы принуждать к использованию некоторых стилистических правил, а в форматировании кода, чтобы все, что мы пишем, имело правильный отступ, скобки открывались и закрывались в нужном месте и т.д.
Как и SwiftLint, мы можем установить его с помощью brew или добавить в наш проект в виде pod. Мы можем использовать его так же, как и предыдущий инструмент:
- Из командной строки.
- На этапе предварительной сборки.
- В качестве хука перед коммитом.
Синтаксис для его вызова из командной строки:
swiftformat .
Точка в команде — путь. В этом примере он отформатирует все файлы с расширением swift в текущем каталоге. Можно указать пути к файлам или подпапки, если мы хотим запустить swiftformat по определенному пути.
Примечание. SwiftFormat заменит ваш файл. Если вы не хотите изменять исходный файл, но хотите создать второй файл, вы можете использовать флаг —output.
Если вы хотите использовать SwiftFormat на этапе предварительной сборки, фрагмент для копирования и вставки в Xcode будет следующим:
if which swiftformat >/dev/null; then swiftformat . else echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" fi
Все правила можно настроить, создав и отредактировав файл .swiftformat.
CommitLint
Не совсем инструмент Swift, но чрезвычайно полезный инструмент для работы с Git. CommitLint обеспечивает соблюдение правил семантической фиксации для наших коммитов.
Следуя семантической фиксации, наши сообщения фиксации должны подчиняться некоторым определенным правилам:
- Первая часть должна быть типом фиксации. Это может быть новая функция (используйте feat), fix или что-то связанное с некоторой конфигурацией (используйте chore). Это всего лишь несколько примеров, но вы можете настроить его в соответствии со своими стандартами.
- Затем вы можете указать scope между (). Область (scope) — это подкатегория задач, связанных с типом. Мы в Bending Spoons не очень часто используем области, но, возможно, вы найдете им хорошее применение в своей организации.
- Затем у нас есть двоеточие “:”.
- Наконец, сообщение коммита.
- Сообщение не должно заканчиваться точкой.
Чем полезна семантическая фиксация? Потому что это открывает возможность сделать некоторую полезную автоматизацию и улучшить рабочий процесс:
- Это заставляет разработчиков делать хорошо организованные коммиты. Например, нельзя смешивать fix с refactor.
- Это позволяет легко отменить сломанный коммит. Например, мы можем отменить неправильное исправление, не удалив важную функцию, которая была отправлена вместе с исправлением.
- Это позволяет нам автоматически создавать журнал изменений.
- Это позволяет нам автоматически обрабатывать семантическое управление версиями. Например, если мы собираемся выпустить новую версию нашего программного обеспечения, в которой все коммиты являются исправлениями, ее можно выпустить как patch.
Примечание. При семантическом управлении версиями новый выпуск программного обеспечения идентифицируется как минимум тремя числами в формате x.y.z. Первое число представляет основную часть версии; y представляет минорную часть, и, наконец, z представляет patch. Тип выпуска зависит от того, как изменился код по сравнению с предыдущим выпуском.
Если API сильно изменился, это должно быть серьезное изменение (major).
Если новые функции были добавлены без нарушения публичного интерфейса, это должно быть второстепенный релиз (minor).
В противном случае это должен быть патч (patch).
Чтобы установить CommitLint, мы можем ввести следующую команду в оболочке.
npm install --save-dev @commitlint/{config-conventional,cli} echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
Тогда лучший способ использовать его — это хук перед коммитом. Чтобы установить его, мы можем запустить следующие команды.
# Install Husky v5 npm install husky --save-dev # Active hooks npx husky install # Add hook npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
В этой конфигурации всякий раз, когда мы пытаемся закоммитить что-то в Git, будет по хуку запускаться CommitLint, чтобы убедиться, что сообщение соответствует рекомендациям по семантической фиксации.
Есть несколько способов настройки правил для CommitLint. Например, мы можем изменить файл .commitlintrc.yml или .commitlintrc.json.
Sourcery
Каждый разработчик хоть раз писал очень много повторяющегося кода. В Swift это было особенно актуально несколько лет назад, когда язык не мог синтезировать реализацию для Codable.
В таких случаях мы можем использовать Sourcery. Это инструмент, который позволяет нам определять некоторые stencil файлы (трафареты), которые затем можно использовать в качестве шаблонов для автоматической генерации кода.
Как и предыдущие инструменты, Sourcery можно установить разными способами.
- Как pod.
- Из brew.
Его использование немного более продвинуто, чем предыдущие инструменты. Я настоятельно рекомендую потратить некоторое время на изучение руководств и статей раздела «Как приступить к работе» в файле readme.
BartyCrouch
При работе с локализацией мы должны создать файлы с именем InfoPlist.strings в определенном пути нашего проекта. Их родительская папка определяет языки содержащихся в них строк.
Так, например, path/to/Localization/en.lproj/InfoPlist.strings содержит пары строк <key>=<translation>; для английского языка. Путь path/to/Localization/it.lproj/InfoPlist.strings содержит те же пары с теми же ключами, но с итальянским переводом.
Магия осуществляется NSLocalizedString API, предоставляемым Apple. Этот API требует от нас передачи ключа в качестве параметра. Во время выполнения ОС заменяет переданные строки на значения, соответствующие ключу из выбранного файла с нужным языком. Язык зависит от настроек устройства.
Если вы когда-либо работали с этим, вы, вероятно, следовали этому процессу:
- Используйте NSLocalizedString там, где вам нужно, добавив ключ.
- Откройте все InfoPlist.strings и добавьте ключ с переводами.
- Вернитесь к файлу Swift и продолжайте программирование.
Иногда довольно сложно вспомнить, создали ли мы клавишу «ОК» или у Purchase_button должны быть разные тексты в зависимости от экрана, на котором она используется.
На помощь приходит BartyCrouch. Он немного меняет поток:
- Мы определяем наши строки <key>=<translation>; в файле InfoPlist.string.
- Мы запускаем bartycrouch transform, чтобы создать строго типизированные свойства и функции, которую мы можем использовать вместо ключей.
- В нашем коде мы используем пространство имен L10n для доступа ко всем сгенерированным строкам.
Наш код из такого…
self.title = NSLocalizedString("onboarding.first-page.header-title", comment: "")
превращается в такой…
self.title = L10n.Onboarding.FirstPage.headerTitle
Он не только короче, но и мы можем использовать автодополнение Xcode и не можем допустить опечатки.
BartyCrouch можно установить с помощью brew.
SwiftGen
Подобно BartyCrouch, SwiftGen работает с изображениями и другими ресурсами. Он работает даже для локализованных строк, а это означает, что, используя этот инструмент, вы можете избежать использования BartyCrouch. Однако помните, что BartyCrouch также имеет другие функции. Поэтому потратьте некоторое время на анализ обоих инструментов и выберите тот, который подходит вам лучше всего.
Идея инструмента аналогична BartyCrouch: избегайте опечаток и используйте строго типизированные функции нашего любимого языка. Сколько раз мы ошибались при вводе UIImage(named: «AppIcon») из-за того, что имя изображения писали с заглавной буквы?
С SwiftGen мы можем автоматически генерировать некоторые расширения в нашем коде. Затем мы можем получить доступ к appIcon, набрав Asset.icons.appIcon.image и забыв о фактическом имени файла. Более того, Xcode предлагает подсказку того, как пишутся все части пути!
SwiftGen можно установить как pod или через brew. Как и многие другие инструменты, нам нужно запустить его, прежде чем мы начнем использовать его в нашем коде. Чтобы запустить его, просто введите в терминале swiftgen. Мы даже можем добавить его в качестве шага перед сборкой, чтобы убедиться, что все ресурсы и переменные доступны перед сборкой проекта.
SwiftGen работает с множеством разных элементов. Он работает с assets, colors, fonts, strings, plist и многими другими вещами. Взгляните на его readme для более углубленного понимания.
Tuist
Tuist помогает создать проект и рабочую область Xcode, начиная с определения файла Swift.
Однако он делает гораздо больше. Он включает SwiftGen, поэтому автоматически генерирует все ресурсы, обрабатываемые вышеупомянутым инструментом. Кроме того, он обобщает доступ к пакетам, поэтому мы можем добавлять ресурсы к подцелям и легко получать к ним доступ.
Вы даже можете использовать Tuist для настройки всех инструментов, которые мы описали выше, как этапы предварительной сборки, настроив схемы с целевыми действиями pre и post.
Это очень хороший кандидат для того, чтобы собрать все описанное выше вместе и применить все эти передовые методы в вашей команде.
Вывод
В сегодняшней статье мы кратко рассмотрели несколько инструментов, которые могут помочь каждой команде обеспечить хорошее форматирование кода и избежать опечаток при использовании локализованных строк и ресурсов.
Мы даже изучили, как их установить, чтобы они запускались автоматически, и вы могли бы забыть о них.
Имейте в виду, что мы лишь слегка коснулись всех этих инструментов: они делают гораздо больше, чем то, что я пытался обобщить в этой статье, поэтому, если вы собираетесь использовать какой-либо из них, не торопитесь и прочитайте их документацию.