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



Разумеется, Badoo не остается в стороне от этих тенденций. Мы постоянно совершенствуем свой чат и расширяем его функциональность, но возможности существующей кодовой базы и архитектуры едва успевают за требованиями современности. Некогда упорядоченный и хорошо протестированный код разрастается непредсказуемым образом, накапливая «технический долг». Анализируя пути решения этой проблемы, мы столкнулись с дилеммой, которая знакома любому разработчику: переписать код или сделать рефакторинг?

В конечном итоге мы решили, что лучше все-таки его переписать. Такой выбор был обусловлен следующими причинами:
Внушительный успех Chatto (фреймворк чата Badoo для iOS) помог нам понять, чего мы можем достичь.
С момента разработки кодовой базы нашего чата появились и набрали популярность несколько архитектурных концепций для Android, и некоторые из них помогли бы нам значительно упростить код.
Наша приверженность концепции открытого исходного кода. Мы всегда стремились принимать участие в таких проектах и сами выступали инициаторами разработки решений с открытым исходным кодом. Кроме того, у нас был шанс занять практически свободную нишу для Android.
Но это было лишь начало большого пути, оставалось еще много вопросов. Какую архитектуру мы хотим создать? Как, когда и какой именно код мы сделаем открытым? Каких конкретных результатов мы хотим достичь?

Постановка целей


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

  • Легкость расширения. Необходимо максимально упростить добавление новых функций (например, поддержку файлов GIF, стикеров, голосовых сообщений) и сделать так, чтобы их добавление не влияло на другие функции чата.
  • Легкость интеграции. Необходимо обеспечить простую интеграцию фреймворка в приложения, вне зависимости от типа используемой архитектуры или серверной платформы.
  • Легкость понимания. Код должен быть простым и понятным, чтобы в нем мог разобраться человек, который не является членом нашей команды разработчиков.
  • Легкость тестирования. Чат предусматривает различные сложные функции взаимодействия пользователей и, как следствие, здесь имеется широкий простор для потенциальных ошибок. Чтобы обеспечить возможность рефакторинга и расширения кодовой базы, необходимо максимально упростить тестирование (как модульное, так и интеграционное).
  • Высокая производительность. В фреймворке не должны использоваться абстракции или шаблоны, которые заметно снижают производительность.

Чтобы решить поставленные задачи, нужно было подобрать подходящие инструменты и оптимальную архитектуру…

Оптимальная архитектура для Chateau


Сам фреймворк Chateau был написан с нуля, однако в его архитектуре использовался многолетний опыт написания компонентов и функций для чата Badoo.



Поскольку в других своих приложениях мы уже использовали шаблон проектирования MVP (Model-View-Presenter) и он позволил нам создать хорошо тестируемый код, это был естественный выбор для Chateau. Конечно, не все реализации шаблона MVP одинаковы, и нам потребовалось выбрать один из множества существующих вариантов. Подробнее об этом можно прочитать в нашей документации.

Еще одним элементом мозаики стала концепция Clean Architecture («чистая архитектура»), предложенная Робертом Мартином (Robert C. Martin), который также известен как @unclebobmartin. В соответствии с этой концепцией мы делим приложение на несколько слоев, и для всех взаимодействий между слоями должно соблюдаться «правило зависимостей». Зависимости в коде всегда должны идти сверху вниз (в нашем случае верхние слои — это пользовательский интерфейс, и сверху вниз мы проходим через слои представлений (View), «презентеров» (Presenter), сценариев использования (Use case) и хранилищ/источников данных).

Преимущества концепции Clean Architecture для нас были аналогичны преимуществам концепции MVP, реализованной на верхних уровнях приложения. Благодаря этому мы смогли создать независимые компоненты, которые могут быть протестированы по отдельности с использованием быстрых модульных тестов вместо тестов на платформе Android. Кроме того, такой подход позволил сделать фреймворк Chateau полностью модульным, что позволяет использовать другое хранилище данных, пользовательский интерфейс или альтернативную реализацию сетевого кода.

Чему мы научились


Разработка Chateau была очень увлекательной (кстати, мы еще не закончили!) и веселой. В процессе работы мы смеялись, плакали и набивали шишки. Вот некоторые из извлеченных уроков:

  • Нелегко найти золотую середину между двумя крайностями — полнофункциональным чатом (с пользовательским интерфейсом, кешированием и сетевым кодом) и платформой, которую можно было бы использовать в качестве основы для собственного чата. Конечно, здорово создать что-то сразу готовое к использованию, но все же нельзя забывать про возможность полной замены отдельных модулей (например, пользовательского интерфейса или сетевого уровня). Мы решили создать образец приложения для Chateau, чтобы показать, каким мы представляем себе полнофункциональный чат;
  • Изучать библиотеку RxJava непосредственно в процессе разработки фреймворка, в котором она используется, — задача не из легких. Кроме того, в нашем случае это привело к более частому рефакторингу (еще один отличный повод для того, чтобы обеспечить хорошее покрытие кода);
  • Создание библиотеки и варианты ее использования лучше спланировать заранее, чтобы убедиться, что процесс разработки соответствует как внутренним, так и внешним потребностям. Мы хотели распространять библиотеки через jCenter, а также включать их как обычную зависимость Gradle-проекта при создании наших приложений (для упрощения кросс-модульного рефакторинга). Кроме того, с помощью git subrepo мы сделали так, чтобы библиотеки Chateau отображались в виде отдельной папки основного git.


Что дальше?


Пока что в фреймворке Chateau реализованы не все функциональные возможности (например, варианты реализации пользовательского интерфейса и представлений, а также поддержка определенных серверных платформ). Эти функции необходимо добавить или реализовать в самом приложении, в котором используется Chateau. В будущем мы планируем сократить объем кода, необходимого для полной интеграции с Chateau. В идеале мы хотели бы обеспечить максимальную универсальность Chateau — при условии совместимости с серверной платформой, конечно.
Мы также работаем над созданием оптимального макета или платформы для тестирования, которые можно использовать с образцом приложения. Следите за новостями в нашем блоге на Хабре, а также на странице проекта GitHub.
Поделиться с друзьями
-->

Комментарии (4)


  1. Delphinum
    03.06.2016 14:41
    +1

    Слой «Сценариев использования», я так понимаю, это старые добрые Transaction Script?


    1. mutable
      03.06.2016 17:37

      Судя из описания Transaction Script очень похоже на то, что мы имеем в слое Use Case'ов.

      В оригинальной идее Дяди Боба (хехе) он пропагандирует использование терминологии Use Case (interactor), а мы спорить не стали.

      Спасибо за наводку на Transaction Script.

      Век живи, век учись :)


  1. comerc
    05.06.2016 00:18

    Чистая архитектура — есть перевод: https://habrahabr.ru/post/269589/


    1. Delphinum
      05.06.2016 00:28

      А где вы там сущности увидели?