Git Workflow, Firebase Remote Config и разные продукты на помощь…

Немного о решениях с белой этикеткой

Не волнуйтесь, я не буду упоминать какое-либо определение или что-то в этом роде. Я постараюсь объяснить так, чтобы я понял и сам истолковал это.

Итак ... У вас есть продукт, который, по вашему мнению, может использоваться различными компаниями, например, система ERP, система HRMS или что-то подобное. Просто эти компании хотели бы, чтобы на них был свой бренд, чтобы иметь индивидуальный подход к своим пользователям. Таким образом, вы меняете логотип, цвета и шрифты в соответствии с фирменным знаком компании и предоставляете этой компании тот же самый (или с небольшими изменениями) продукт.

Вуаля! Этот продукт является решением с белой этикеткой. Поздравляю, дружище, вы являетесь создателем и владельцем решения с белой этикеткой!

Теперь, когда у вас есть довольно хорошее представление о том, что это такое. Хочу поделиться своим опытом его создания. Поделюсь проблемами, с которыми я столкнулся, и решениями, которые я реализовал. Кроме того, я покажу вам, как сгенерировать новое приложение для нового клиента с полностью индивидуализированной торговой маркой за считанные минуты и при этом сохранить единую структурированную базу кода.

Все началось несколько сотен лет назад…

Я разработал приложения для Android и iOS для одного из продуктов нашей компании. Мы доставили его первому клиенту. Это было огромным успехом!

Потом у нас появился второй клиент по тому же продукту. Потребовались небольшие доработки в приложении, брендинг был очевиден. Помимо брендинга, они также потребовали незначительных изменений. Итак, я сделал то, что делал бы каждый новый разработчик, создал клон этого проекта и внес изменения в новый проект, изменил брендинг и представил его. Вуаля, Удачи !!

Затем последовал третий… История повторилась… Успех повторился !!

А теперь кошмар…

Я получил отчет о сбое от одного из клиентских приложений. Но код был одинаковым для всех клиентских приложений, а это означало, что проблема будет существовать во всех из них. Мне нужно было быстро исправить проблему, скопировать и вставить одно и то же во все проекты, отправить их все в производство и создать APK и IPA для всех из них. И все это при переходе от одного проекта к другому. Уффф… Как-то умудрился весь день оставаться в здравом уме: D

Затем пришел запрос функции от одного из наших клиентов. Опять же, как новый умный разработчик, я прыгнул прямо в репозиторий этого клиента, реализовал эту функцию и запустил ее в производство. Готово и вычищено, верно?

Неа. Не совсем. Через некоторое время тот же запрос функции пришел от другого клиента. Мне пришлось поработать с ранее реализованным кодом, скопировать его и вставить в текущий клиентский проект и выпустить новые обновления. Также не забывайте учитывать двойные усилия, так как нам пришлось обновлять приложения для Android и iOS.

Теперь поддерживать все эти разные проекты для каждого клиента становилось головной болью. Отслеживание исправлений ошибок и новых функций в течение определенного периода времени было кошмаром.

Ароматизаторы продуктов - немного света в этом темном мире!

Теперь, что такое ароматизаторы? По сути, это помогает нам создавать несколько вариантов приложения из единой базы кода. Вы можете настроить ресурсы, брендинг и даже работу приложения.

Теперь для всех разработчиков iOS, которые читают это и задаются вопросом, почему мы еще не натолкнулись на это? Потому что этого нет в iOS, это функция Android. Какой облом! Что ж, если это дает хоть какую-то надежду, люди реплицировали это вручную в iOS с помощью конфигураций сборки, но это уже отдельная статья. Вы можете найти это здесь".

Возвращаясь к Flavors в Android, я бы процитировал здесь строчку из самой документации Android-разработчика, которая может подытожить для вас варианты продукта:

«Вы можете определить базовую функциональность в основном / исходном наборе и использовать исходные наборы ароматов продукта, чтобы изменить брендинг вашего приложения для разных клиентов».

Для разработчиков, желающих узнать больше, вы можете найти это здесь, а небольшой реалистичный пример - здесь.

Черт возьми! Это то, что мы искали, правда?

Что ж, для большого количества клиентов это становится немного сложнее.

Смотрите, как Android продолжает добавлять ароматы в виде папок в ваш исходный код, чтобы вы могли разделить здесь собственный код / ​​ресурсы для каждой разновидности. Кроме того, если вам нужно просто немного изменить функциональность, вы можете использовать If Else в своем классе для разделения клиентских функций. Поначалу это звучит великолепно, но, поскольку ваша клиентура расширит возможности управления и чтения этого кода позже с большим количеством If и Else в вашей кодовой базе, это станет головной болью.

Кроме того, на более высоком уровне, если в какой-то момент вы захотите, чтобы отдельные разработчики обрабатывали отдельные клиенты параллельно, это было бы невозможно.

То же самое и с iOS, даже если вам удастся воспроизвести работу Flavors с помощью конфигураций сборки, вы окажетесь в том же месте, что и наши коллеги-разработчики Android.

Рабочий процесс GitFlow (немного измененный!)

Когда я столкнулся со всем этим на Земле-1, мой двойник с Земли-88 занимался исследованием реализации рабочего процесса Git для команды. Он сталкивается с различными рабочими процессами Git здесь и отправляет мне ссылку по электронной почте. Да, электронная почта работает во всей мультивселенной!

Существовали два рабочих процесса, которые я мог реализовать для своего сценария - GitFlow Workflow и Forking Workflow. Вы можете прочитать о рабочих процессах по ссылке Atlassian link.

В рабочем процессе Forking вы можете выделить репо для каждого клиента из вашего базового проекта, но поскольку я хотел сохранить кодовую базу такой же и хотел управлять одним репозиторием, поскольку это был единый продукт, я решил остаться с GitFlow Workflow.

Теперь для тех, кто знаком с рабочим процессом GitFlow или тех, кто проходил по указанной выше ссылке, может возникнуть вопрос, что нет такой вещи, как управление несколькими клиентами с помощью рабочего процесса GitFlow.

И ты прав! Я придумал это, немного изменив рабочий процесс и установив некоторые правила!

Типы филиалов в приложении:

  • Основная ветвь: всегда будет содержать последний стабильный код.
  • Ветвь разработки: будет содержать последний объединенный код из ветвей разработчиков / ветвей функций.
  • Ветвь разработчика: отдельная ветвь каждого разработчика.
  • Разветвление выпуска: будет создано во время выпуска и будет удалено после объединения кода в Мастер и Разработку.
  • Ветка функции: ветвь определенной функции. Будет несколько веток функций, каждая для отдельной функции.
  • Ветвь исправления: будет создана из мастера, когда проблема появится в производственном коде.

Когда появляется новый клиент:

  • Новая ветка будет создана из главного Branch = ›ClientName-master
  • Будет создана новая ветка из ClientName-master = ›ClientName-development.
  • Все фирменные настройки и индивидуальные настройки клиента будут происходить в ветке ClientName-development.
  • Как только дата выпуска будет установлена, мы запланируем дату «отправки в QA» и создадим ветку ClientName-release в ClientName-development на эту дату, а APK и IPA будут генерируется из ветви ClientName-release.
  • Если есть список проблем, которые необходимо исправить, мы планируем дату следующего выпуска, все исправления ошибок будут выполнены в ветви ClientName-release, а затем будут созданы новые APK и IPA, которые снова будут переданы в QA.
  • Как только релиз будет готов к запуску, мы объединим ClientName-release с ClientName-master и ClientName-development и удалим ветку ClientName-release. Мы пометим фиксацию в ветке ClientName-master на конкретный номер версии, создадим APK и IPA и отправим их клиенту.

Если проблема обнаружена в реальном приложении:

  • Если это проблема индивидуальной настройки клиента, мы создадим новую ветку из ClientName-master = ›ClientName-hotfix и исправим проблему в этом, а после тестирования объединим эту ветку обратно в ClientName-master. и ClientName-development, а затем удалите эту ветку ClientName-hotfix.
  • Если проблема не связана с клиентом, то есть в базовом коде, мы создадим новую ветку из master = ›hotfix и исправим проблему в этом, а после тестирования объединим эту ветку обратно в master, development , ClientName-master, ClientName-development, а затем удалите эту ветку Hotfix.

Для каждого клиента это будут филиалы:

  • ClientName-master
  • ClientName-разработка
  • ClientName-release
  • ClientName-имя функции
  • ClientName-hotfix

НИКОГДА изменения не будут объединены ИЗ клиентских филиалов В основные филиалы. Поток всегда будет от основных ветвей к клиентским ветвям.

Эта маленькая проблема ...

Все звучало хорошо? Ага! Это просто крошечная проблема Android. Это идентификатор приложения или, с точки зрения разработки iOS, идентификатор пакета. Идентификатор приложения в Android выглядит как имя пакета. Те, кто работал с Android, могут знать, что в отличие от iOS, где Bundle ID является просто параметром в файле .plist, здесь на самом деле это структура папок приложения. Поэтому, когда мы говорим, что пакет называется «com.company.product», есть папка «com» ​​, внутри которой находится еще одна папка с именем «company» , внутри которого находится еще один «product».

Но в чем проблема?

Что ж, когда мы создаем клиентские ветки из основной ветки, имя пакета остается прежним. С их брендингом они также могут захотеть иметь имя своего пакета или конфигурации подписи и т. Д. Кроме того, вы можете захотеть установить на вашем устройстве несколько APK для разных клиентов для целей тестирования / отладки, что требует уникального идентификатора приложения для каждого APK.

Doppelgänger спешит на помощь!

Чувствую ли я здесь тупик? Нет, не совсем. Помните моего двойника с Земли-88? Он отправляет мне по электронной почте эту ссылку о функции в Android Product Flavors, где вы можете определить Application ID для каждого продукта. Черт возьми !!

Итак, я создал один Flavor с именем «client» (не имя клиента) в базовой кодовой базе. Теперь, когда я оформляю заказ и создаю новые ветки клиента, я просто перехожу к блоку аромата и обновляю параметр идентификатора приложения.

Кроме того, как я сказал выше, в iOS с этим можно довольно просто справиться, обновив Bundle ID в каждой ветви клиента.

Теперь все настройки, специфичные для конкретных клиентов, находились в их собственных ветках, а также позволяли мне обновлять единую базу кода со всеми моими функциями и обрабатывать сбои и ошибки в нескольких приложениях, как профессионал.

Поднимите его на новый уровень с Firebase Remote Config!

Угадай, что? Мой двойник всегда на шаг впереди! На этот раз он пишет мне по электронной почте Firebase Remote Config.

Вы можете обновить внешний вид своего приложения, включить удаленное отключение некоторых функций, не отправляя обновление в свое приложение. Действительно? Мы можем это сделать?

Да, как оказалось, мы можем удаленно управлять всем этим с помощью Firebase Remote Config. Поэтому, если вы планируете использовать решение white label, могут быть некоторые функции, которые, по вашему мнению, могут зависеть от того, примет его клиент или нет. Или вы можете захотеть иметь некоторые премиум-функции или по другой причине. Такой набор функций есть всегда. Вам просто нужно подумать и записать эти особенности из первых рук. Создайте конфигурацию типа «feature name: true», где ключи могут быть именами ваших функций, а значение может быть логическим флагом, чтобы определить доступность этой функции в приложении. Теперь при разработке приложения проверьте наличие этих флагов и соответствующим образом отобразите / скройте эти функции.

Время для заключения!

Перед настройкой рабочего процесса о том, как вы собираетесь строить свою кодовую базу, есть несколько вопросов, на которые вы, возможно, захотите сначала ответить.

Насколько большие настройки вы готовы выполнить для каждого клиента?

Превратят ли эти изменения мое приложение или продукт в нечто вроде совершенно нового индивидуального решения?

Если это так, я бы предпочел использовать рабочий процесс Git Forking и поддерживать целый другой репозиторий для таких клиентов.

Кроме того, попробуйте выяснить динамические особенности вашего продукта, которые могут изменить клиента. Реализуйте их, используя удаленную конфигурацию Firebase, или вы также можете создать собственную инфраструктуру удаленной конфигурации с помощью вашей группы Backend.

Кроме того, если вы планируете свести клиентуру к минимуму, что, я уверен, никому не нужно. Но все же, если это так, я бы посоветовал использовать только Product Flavors без клиентского GitFlow.

На этом все. Если вам понравилась эта статья, и если она хоть как-то помогла, то спамите эту кнопку до упора. Кроме того, я хотел бы услышать, как вы справляетесь с такими сценариями, а также, если у вас есть какие-либо предложения, пожалуйста, снимайте их.

Если вам это интересно, скорее всего, вы тоже найдете мою ленту в Твиттере! Я продолжаю ежедневно делиться статьями и прочим, связанным с разработкой, дизайном и производительностью. Так что подпишитесь на меня в Twitter и наслаждайтесь познавательной поездкой!

До следующей статьи…