Новое API CRM
Чтобы упростить разработку и привести все к единому знаменателю, в CRM ведется процесс перевода всех сущностей на новые подходы.
Это означает, что методы класса старого ядра
CCrmDeal
Методы: Add, Update, Delete и аналогичные им методы в классах \CCrmLead, \CCrmContact, \CCrmCompany
под капотом делегируют всю логику обработки классам Operation.
Критерии и цели
В рамках работы по реализации смарт-процессов была поставлена задачи обернуть это всё в общее API, которое сможет обеспечить удобную работу не только с элементами смарт-процессов, но и с элементами любых типов сущностей.
Критерии, на которые мы ориентировались, при проектировании нового API:
- Уменьшение дублирования кода.
- Уменьшение связности классов.
- Покрытие тестами.
Основные цели, которые были поставлены:
- Повышение качества кода.
- Уменьшение количества ошибок.
- Ускорение процесса разработки и внедрения нового функционала.
Чтобы сделать код более структурированным, было решено разбить его на сервисы.
Сервис - это объект, как правило, в единственном экземпляре, который выполняет небольшую обособленную часть логики.
Сервисы должны строго следовать принципу единой ответственности. Это означает, что их должно быть довольно много.
Экземпляры сервисов получаются через Service\Container
.
Категории
Помимо сервисов, было написано и существенное количество вспомогательного кода. Весь код можно разделить на несколько категорий:
- Сервисы
- \Bitrix\Crm\Service\Accounting
- \Bitrix\Crm\Service\Container
- \Bitrix\Crm\Service\Context
- \Bitrix\Crm\Service\Converter
- \Bitrix\Crm\Service\Director
- \Bitrix\Crm\Service\DynamicTypesMap
- \Bitrix\Crm\Service\EditorAdapter
- \Bitrix\Crm\Service\EventHandler
- \Bitrix\Crm\Service\EventHistory
- \Bitrix\Crm\Service\Factory
- \Bitrix\Crm\Service\FileUploader
- \Bitrix\Crm\Service\Localization
- \Bitrix\Crm\Service\ParentFieldManager
- \Bitrix\Crm\Service\Router
- \Bitrix\Crm\Service\Scenario
- \Bitrix\Crm\Service\TypesMap
- \Bitrix\Crm\Service\UserPermissions
- Доступ к данным
- Операции над элементами
- Интерфейсы
Точкой входа при работе с новым API является Service\Container
.
Через него получается нужный сервис и у него вызываются нужные методы.
В том случае, если логика программы привязана к какому-то конкретному типу сущности, точкой входа является Service\Factory
.
Концепции
Ниже приведены некоторые базовые концепции, которые надо иметь в виду при работе с этим API.
Developer Experience
При проектировании API большое внимание уделялось положительному Developer Experience.
При работе с кодом не должно возникать сложностей с пониманием, как и что работает. Зачем вызывается тот или иной метод.
Тут много субъективного, и не все решения могут понравиться. Ниже приведены некоторые из особенностей, которые прослеживаются во всём коде.
Правила именования
Для нового API мы старались следовать следующим правилам именования:
- Базовый класс находится в "общем" неймспейсе. Например,
\Bitrix\Crm\Service\Operation
. - Его наследники находятся в папке с таким же названием, как и имя базового класса. Например,
\Bitrix\Crm\Service\Operation\Add
. - При использовании реализаций базового класса в коде необходимо указывать родительский неймспейс. Например,
use Bitrix\Crm\Service\Operation; $addOperation = new Operation\Add();
Сервисы
В CRM сосредоточено большое количество функционала. Чтобы уменьшить связность между классами, большая часть функционала была разбита на сервисы.
Каждый сервис решает какую-то одну задачу. Сервисов получилось довольно много, но так с ними легче работать.
Отделение бизнес-логики
При проектировании API большое внимание уделялось расслоению классов по трем базовым слоям.
- Данные.
- Бизнес-логика.
- Интерфейсы.
Классы и методы работы с бизнес-логикой не должны сами загружать данные. Данные должны приходить на вход в уже готовом виде, это существенно облегчает процесс покрытия тестами.
Unit-тесты
Проектирование классов таким образом, чтобы их можно было протестировать, улучшает структуру классов. И наличие тестов, само по себе, говорит о хорошем качестве кода.
Мы написали довольно много тестов для новых классов (и для некоторых старых тоже).
Обработка ошибок
Большая часть методов, которые выполняют какие-либо изменения, возвращает объект Bitrix\Main\Result
или его наследников.
Это позволяет корректно обработать/отобразить возникшие при работе ошибки.
Сущности
Новое API на данный момент поддерживается сущностями:
- лиды,
- сделки,
- контакты,
- компании,
- коммерческие предложения,
- новые счета,
- смарт-процессы.
Воврат к старому API
Мы работаем над тем, чтобы для разработчиков и клиентов это изменение прошло незаметно. Весь существующий код должен продолжать работать без изменений. Пожалуйста, если вы обнаружили какую-то несовместимость в работе старого и нового API, свяжитесь с техподдержкой.
Если вы подозреваете новое API в том, что добавление/изменение/удаление сделок и других сущностей CRM стало вести себя странно, то вы можете вернуть старое поведение для определенной сущности.
Отключение нового API для сделок из php-консоли:
if (\Bitrix\Main\Loader::requireModule('crm')) { \Bitrix\Crm\Settings\DealSettings::getCurrent()->setFactoryEnabled(false); }
Аналогично можно отключить, перейдя по ссылке в браузере под любым пользователем, у которого есть доступ к сделкам:
{адрес портала}/crm/deal?enableFactory=N
Аналогично новое API можно включить обратно, если вы передумали:
if (\Bitrix\Main\Loader::requireModule('crm')) { \Bitrix\Crm\Settings\DealSettings::getCurrent()->setFactoryEnabled(true); }
или
{адрес портала}/crm/deal?enableFactory=Y
Все описанное выше работает для лидов, сделок, контактов и компаний:
if (\Bitrix\Main\Loader::requireModule('crm')) { // выключить новое API для сделок \Bitrix\Crm\Settings\DealSettings::getCurrent()->setFactoryEnabled(false); // включить его обратно \Bitrix\Crm\Settings\DealSettings::getCurrent()->setFactoryEnabled(true); // аналогично для лидов // выкл \Bitrix\Crm\Settings\LeadSettings::getCurrent()->setFactoryEnabled(false); // вкл \Bitrix\Crm\Settings\LeadSettings::getCurrent()->setFactoryEnabled(true); // аналогично для контактов // выкл \Bitrix\Crm\Settings\ContactSettings::getCurrent()->setFactoryEnabled(false); // вкл \Bitrix\Crm\Settings\ContactSettings::getCurrent()->setFactoryEnabled(true); // аналогично для контактов // выкл \Bitrix\Crm\Settings\CompanySettings::getCurrent()->setFactoryEnabled(false); // вкл \Bitrix\Crm\Settings\CompanySettings::getCurrent()->setFactoryEnabled(true); }
И то же самое в виде ссылок:
//сделки // выкл {адрес портала}/crm/deal?enableFactory=N // вкл {адрес портала}/crm/deal?enableFactory=Y //лиды // выкл {адрес портала}/crm/lead?enableFactory=N // вкл {адрес портала}/crm/lead?enableFactory=Y //контакты // выкл {адрес портала}/crm/contact?enableFactory=N // вкл {адрес портала}/crm/contact?enableFactory=Y //компании // выкл {адрес портала}/crm/company?enableFactory=N // вкл {адрес портала}/crm/company?enableFactory=Y
Проверить, включено ли новое API, можно только через php:
if (\Bitrix\Main\Loader::includeModule('crm')) { // выведет true, если новый API для сделок включен var_dump(\Bitrix\Crm\Settings\DealSettings::getCurrent()->isFactoryEnabled()); //аналогично для других сущностей var_dump(\Bitrix\Crm\Settings\LeadSettings::getCurrent()->isFactoryEnabled()); var_dump(\Bitrix\Crm\Settings\ContactSettings::getCurrent()->isFactoryEnabled()); var_dump(\Bitrix\Crm\Settings\CompanySettings::getCurrent()->isFactoryEnabled()); // Так же можно проверить и через классы \CCrmDeal, \CCrmLead, \CCrmContact, \CCrmCompany $entity = new \CCrmDeal(); var_dump($entity->isUseOperation()); }
Внимание!Мы активно исправляем найденные несовместимости. Когда все несовместимости исправлены, то будет включён новый API принудительно на всех установках, где он был до этого выключен. Через какое-то время и возможность вернуть старое поведение будет убрана из продукта.
Дополнительно
- Сообщение в блоге разработчика: Смарт-процессы и новое API CRM