Руководство по разработке на платформе SberMobile

В этой главе описаны рекомендованные стандарты по разработке на платформе SberMobile. Следование данным рекомендациям позволит упростить как разработку приложений, так и последующее их сопровождение.

Именование объектов

Camelcase

При добавлении любого объекта (устройства, модели, переменной и т.д.) для него необходимо заполнить поле Name. При этом рекомендуется использовать стиль lowerCamelCase - все составные слова пишутся слитно, без пробелов, каждое слово в фразе начинается с заглавной буквы, кроме первого, как в приведенных ниже примерах:

Понятные имена

Имя должно всегда отражать основную суть объекта (устройства, модели, переменной и т.д.). При разработке приложения постоянно приходится обращаться к объектам, например получить данные из переменной, и в таком случае, правильное имя поможет быстрее найти ее в списке других переменных. В дальнейшем, если возникнет необходимость доработать приложение или исправить баги, понятные имена объектов в коде выражения упростят его понимание.

Примеры именования объектов:

  • Предположим, проект содержит несколько настроенных экранов, реализованных при помощи инструментальных панелей. Из названия инструментальной панели должно быть понятно, какую функциональную роль она имеет: startPage, monitoringSettings, alertsHistory.
  • Предположим, модель содержит несколько функций с похожим функционалом. Использование имен "findUser1" и "findUser2" может вызвать путаницу и непонимание. Правильнее будет указать в имени более полную информацию, показывающую назначение функции, например, "findUserByName" и "findUserById".

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

Именование функций и наборов правил

Любая функция или набор правил в модели, не зависимо от сложности, всегда выполняют определенное действие. Именно поэтому, их имя должно отвечать на вопрос “Что делает эта функция/набор правил?”, чтобы упростить их использование из любого места приложения. Имена должны всегда начинаться с глагола. Кроме того, при сортировке списка функций/наборов правил в модели по имени, они будут отсортированы еще и по логическому смыслу (например, сначала будут идти все функции по чтению переменных, потом все функции по обновлению данных в переменных и т.д.).

Примеры именования фукнций и наборов правил:

  • Предположим, что есть устройство, которое выходит на связь раз в сутки. В модели создана привязка, которая при выходе устройства на связь выполняет функцию getDeviceTelemetry. Благодаря имени функции сразу стало понятно назначении привязки - при выходе устройства на связь получить телеметрию с утройства.
  • Другие примеры имен для функций: createSensor, getUserInformation, sendAlertsListByEmail

Так как наборы правил это те же функции, только находящиеся в другой таблице модели, возможна ситуация совпадения имен. Это приведет к конфликту при вызове функции. Чтобы гарантированно избежать этого, для каждого набора правил можно добавлять постфикс "RuleSet".

Заполнение полей с описаниями и комментариями

Всегда заполняйте поля с описанием и комментариями объектов (устройств, моделей, переменных и т.д.), если они предусмотрены.  Краткие и емкие описания объектов позволяют легко определить назначение объектов, что сильно помогает при разработке и обслуживании приложения.  

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

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

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

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

Примеры заполнения полей описания и комментариев:

  • Предположим, есть функция, которая показывает информацию об указанном во входящих параметрах пользователя. Ей можно дать имя getUserInformation, а в описании указать более подробную информацию “Получить информацию об указанном пользователе”
  • По информации в комментарии набора правил мы понимаем назначение шага, даже не читая его код:

Удаление закомментированных фрагментов кода выражений

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

Единая модель именования объектов для тестирования и отладки приложения

Для тестирования приложения лучше использовать отдельные, специально предназначенные для этого объекты (устройства, модели, переменные и т.д.). В описание такого объекта необходимо добавлять специальный префикс или постфикс (например, "test"). Это очень пригодится на финальном этапе разработки, когда надо будет приводить приложение в порядок и убирать все мусорные ресурсы.

Примеры:

  • Предположим, в наборе правил есть шаг, который возвращает таблицу с телеметрией указанного устройства. Полученные данные используются в дальнейших шагах набора правил, но доступа к устройству временно нет, и проверить работоспособность становится невозможным. В таком случае можно создать копию нужного шага, в комментарии указать "test" и вместо исходного выражения указать таблицу нужного формата с тестовыми данными. В оригинальной строке в графе с условием пропишите “false”, чтобы она не отработала. Таким образом можно проверить работоспособность набора правил, и все строки с тестовыми данными будут сразу видны, что позволит легко все вернуть на место.
  • В примере выше можно поступить другим образом. Создайте копию самого набора правил. В оригинальном наборе правил добавьте префикс “на отладке”, а в  описании копии допишите “для тестирования”. В новом наборе правил замените все ресурсы, к которым нет доступа, на константы или тестовые данные. По окончании работ, можно будет легко найти набор правил с тестовыми данными, удалить его, а оригинальный вернуть на место.

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

Использование справочников и развязочных таблиц вместо прямых ссылок и констант

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

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

Примеры использования справочников:

  • Хороший пример использования справочника - справочник единиц измерения, который можно разделить на три поля: код, краткое наименование, полное наименование. В дальнейшем значения этого справочника будут использованы во всем проекте. Для переменных есть возможность привязать значения другой переменной в качестве допустимых значений. В формате переменной необходимо добавить соответствующую запись в привязках. В качестве цели указывается поле, к которому надо привязать справочник с параметром #choices:

В выражении пишется специальная функция с указанием пути к справочнику и именам полей, которые будут использоваться в качестве имени и описания выбранного поля переменной:

  • Другой полезный вариант использования справочников - развязочная таблица с кодами ошибок. В функции может быть предусмотрен механизм останова сценария  при определенных условиях, например, если пришла неверная контрольная сумма пакета. Если функция будет вместо текста возвращать код ошибки, а в системе будет специальная развязочная таблица таких сообщений, то будет гораздо легче и удобнее реагировать на ошибки и информировать пользователя. Давайте сравним.

На одном из шагов набора правил идет проверка контрольной суммы. Если контрольная сумма окажется неверной, происходит выход из набора правил. В результате возвращается текстовое сообщение, указанное в выражении. Обрабатывать такую строку не очень удобно:

Для более удобной работы в подобных случаях лучше использовать справочник. В рассмотренном выше примере текст сообщения надо заменить на код ошибки:

В справочнике для данного кода ошибки заполнены поля с кратким и полным описанием ошибки на нескольких языках.

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

Правило обработки получает на вход  номер ошибки. Затем в зависимости от роли текущего пользователя и используемого им языка из справочника будет подбираться нужное сообщение об ошибке.

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

Расположение параметров функции в столбик

В языке выражений для большинства функций необходимо задавать различные параметры. В описании каждой функции указаны ее параметры, записанные в одну строку через запятую. Если параметров меньше трех и они достаточно короткие, то допустимо в коде выражения писать их в одну строку. Однако, в большинстве случаев необходимо указывать параметры в столбик. Это значительно облегчает работу с функцией и делает ее более читаемой. Например, сразу видно, сколько у функции параметров, где они начинаются и заканчиваются, некоторые из них можно очень легко закомментировать для быстрой отладки. При таком подходе все разделители строки (знак "," или "+") необходимо ставить в начале строки. Это помогает понять, где начинается новый параметр, и облегчает работу с кодом.

Примеры:

  • Допустим, в выражении собирается одна таблица на основе другой. В результате, параметров у функции становится довольно много и перечисление их одной строкой приведет к трудностям чтения такого кода:

Если же параметры расположить в столбик, то код становится намного более читаемый и понятный:

  • Благодаря тому, что символ ",” стоит в начале строки, можно не только легче определить, какие и сколько параметров используется в функции, но и упростить отладку - один или несколько параметров легко закомментировать, а при необходимости вместо них подставить нужное значение:

Разбивка длинных строк

В языке выражений параметры во многих функциях задаются в формате строки (String). Их длина может быть довольно большой, что затрудняет восприятие выражения. В таких случаях рекомендуется разбивать одну строку на несколько. Чтобы разбить строковое выражение, необходимо в нужном месте поставить закрывающие кавычки, затем написать знак “+” и открыть кавычки перед оставшейся частью текста. Этим способом очень удобно разделять параметры вложенных функций.

Очень важно все разделители ставить в начале строки. К ним относятся:

  • "+" (плюс) - отделяет части одного строкового выражения
  • " " (пробел) - разделяет слова в строке
  • "," (запятая) - разделяет параметры в функциях

В примере показано разделение строки при работе с SQL запросом. Запрос может обращаться ко множеству контекстов, таблиц данных, переменных. Если все они будут записаны одной строкой, работать с запросом может быть проблематично. Разделение длинной строки на несколько маленьких не только облегчит восприятие кода, но и поможет в дальнейшей работе и отладке. Указав в запросе каждую переменную с новой строки, а также условие для фильтрации, любую из них можно очень быстро закомментировать, добавить, удалить или заменить:

Использование табуляции для вложенных функций

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

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

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

Декомпозиция длинных выражений

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

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

Пример декомпозиции длинного выражения:

Допустим, для реализации функции необходимо выполнить нескольких последовательных действий. Если записать их одной строкой, то выражение становится трудно понять:

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

Использование валидаторов

Валидаторы - очень важная часть любого проекта. Их грамотное использование позволит избежать непредсказуемого поведения различных элементов проекта. Особенно важно использовать валидаторы там, где пользователь должен вводить какие-то данные. При этом ограничения должны быть обоснованными, например для ввода IP адреса будет 4 блока с цифровыми значениями от 0 до 255. Также очень важно информировать пользователя об ограничениях, установленных в системе, чтобы ему не пришлось гадать, почему не работает функция или не принимается параметр.

Примеры использования валидаторов:

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

  • Еще один вариант валидации - создание маски ввода. Задав нужные условия, можно не только ограничить пользователя в вводимых данных, но и более наглядно показать информацию. Данный метод очень удобно применять в виджетах и инструментальных панелях. Один из самых удачных примеров использование маски - поле с номером телефона: