Регламент разработки АБС ЦФТ
Термины, определения, сокращения
Тип данных – описание совокупности элементов, удовлетворяющих определённым свойствам и условиям.
Базовое понятие (БП) – совокупность сущностей, имеющих единое назначение в рамках банковской предметной области и обладающих характерным набором реквизитов и операций.
Исходя из базовых понятий, в системе строится иерархия Типов Базовых Понятий (ТБП), которые являются структурными типами, «дочерними» по отношению к ним.
Для любого ТБП при необходимости могут быть созданы вспомогательные элементы, определяющие свойства экземпляров данного типа и возможности работы с этими экземплярами. Такие элементы в совокупности называются компонентами ТБП: реквизит, операция, представление, состояние, переход.
Соглашение об именах
- Идентификаторы локальных ТБП а также операции, библиотеки, реквизиты в дистрибутивных ТБП, должны начинаться с префикса Банка (3 символа и подчёркивание); короткие имена представлений должны содержать префикс Банка после VW_CRIT_ или VW_RPT_.
- Наименования локальных ТБП а также операции, библиотеки, реквизиты, представления в дистрибутивных ТБП должны начинаться с наименования Банка.
- К идентификаторам и наименованиям операций, библиотек, реквизитов, представлений локальных ТБП правило префикса не применяется.
- Идентификаторы ТБП, компонентов ТБП (реквизиты, операции, представления, состояния, переходы и т.п.), параметры и переменные должны состоять из заглавных латинских букв, цифр и символа «_».
- Общие правила именования
- SNAKE_CASE для идентификаторов ТБП, операции, реквизитов, представлений, переменных и параметров (на вкладке «Переменные» и «Параметры»):
::[DEPN].[DATE_BEGIN]
::[DEPN].[NEW_AUTO]
- lowerCamelCase для идентификаторов констант, пользовательских типов, курсоров, функций и процедур, идентификаторов переменных и параметров (кроме вкладки «Переменные» и «Параметры») и т.п. (без учёта префикса):
procedure initSaldo(p_acc ref [ACC_FIN])
vDepnBeginDate [SUMMA]
- Правило оформления переменных
- идентификаторы переменных, определенных на вкладке переменные, в операции должны начинаться с префикса «V_», в коде их следует использовать в верхнем регистре;
- идентификаторы параметров, определенных на вкладке параметры, должны начинаться с префикса «P_», в коде их следует использовать в верхнем регистре;
- для остальных идентификаторов допускается использование только указанных ниже префиксов и суффиксов:
- идентификатор структуры должен иметь суффикс «Str», например, depnStr;
- идентификаторы локальных переменных операции (вкладка локальные описания) должны начинаться с префикса «v_»;
- идентификаторы переменных, определенных в декларации функций и процедур и в блоке «DECLARE», должны начинаться с префикса «v» без подчёркивания;
- идентификаторы параметров процедур и функций должны начинаться с префикса «p_», для функции где используется переменная для возврата значения необходимо помечать её префиксом «ret_»;
- идентификаторы локальных констант (вкладка «Локальные описания») должны начинаться с префикса «cn_»; идентификаторы глобальных констант (вкладка «Глобальные описания») должны начинаться с префикса «gcn_»;
- идентификаторы локальных пользовательских типов должны начинаться с префикса «t_»; идентификаторы глобальных пользовательских типов должны начинаться с префикса «gt_»;
- идентификаторы локальных курсоров должны начинаться с префикса «cur_»; идентификаторы глобальных курсоров должны начинаться с префикса «gcur_»;
- переменные-итераторы в циклах должны начинаться с префикса «i_».
- Наименование служебных операции должно иметь префикс «Служебная. » после наименования банка.
- Наименование операций начальной загрузки, нормализации данных для внедрения должно иметь префикс «Внедрение.» после наименования банка.
- Отладочные или временные операции должны иметь префикс «TMP».
- Значимая часть идентификатора должна отражать суть его назначения. Не допускается бессмысленных названий. Бессмысленным считается идентификатор, по которому нельзя определить для чего используется идентификатор в контексте алгоритма, например, I, t, date и т.п.
- Имена должны быть осмысленными словами английского языка:
- имена ТПБ и реквизитов ТБП - существительные или словосочетания в значении существительных в единственном числе ([LETTER_OF_CREDIT])
- имена операций - глаголы (либо словосочетания, отражающие действия), в названии следует использовать глаголы, которые как можно более точно и полно описывают то, что выполняет метод
- имена методов, выполняющих чтение/изменение значений атрибутов, должны начинаться на «get»/«set» (getDepositPriv); исключение — методы, возвращающие значения полей типа boolean, они должны начинаться на «is» (isOK);
- имена методов, выполняющих преобразование к другому типу данных, должны начинаться на «to» (toString);
- имена методов, которые создают и возвращают созданный объект, должны начинаться на «create» (createDeposit);
- имена методов, инициализирующие переменные, должны начинаться на «init» (initMainDoc).
Требования к комментариям
1. Обязательным является описание назначения функций, процедур а также их параметров при объявлении на закладке «Глобальные описания».
2. Если смысл хотя бы одного из принимаемых или возвращаемых значений, или выбрасываемых исключений не является интуитивно понятным, то комментарий должен содержать описание всех указанных выше элементов.
3. Обязательным является описание принципов действия алгоритма перед сложными блоками кода.
4. В случае использования операторов «break» и «continue» обязательно наличие комментария в строке, предшествующей одному из указанных операторов.
5. Комментарии не должны содержать орфографических и пунктуационных ошибок.
6. Любое изменение кода должно быть ограждено комментарием с указанием номера доработки (при его наличии).
-- 27.12.2020 a.gerastovskiy (IFT-12345): кратко об изменениях
КОТ
Требования к коду [ii]
Базовые принципы
- Все требования, описанные в «Соглашение об именах», относятся и к коду:
- в коде идентификаторы ТПБ должны быть написаны заглавными буквами, обрамлены квадратными скобками, впереди два двоеточия;
- наименования реквизитов и операций должны быть написаны заглавными буквами в квадратных скобках;
- и т.п.
- Наличие отступов во вложенных конструкциях обязательно; отступы должны оформляться строго по табуляции.
- Каждый оператор должен быть размещен на отдельной строке.
- После запятых, между логическими и арифметическими блоками необходимо использовать пробел.
- Ключевые слова loop, else, elsif, when должны быть размещены на новой строке.
- Запятая должна стоять перед разделяемыми элементами, параметры вызова, операторы и значения выровнены.
- Ключевые слова SQL выровнены по правому краю в оператора SQL.
- Скобки используются, когда необходимо или полезно уточнить конструкцию.
Прикладные принципы
- После написания кода изучить все предупреждения компилятора и устранить те, которые являются ошибками / потенциальными ошибками.
- Запрещается при обработке исключений в программном коде использовать блок «exception when others» без особой на то причины.
Для обработки прикладных исключений необходимо использовать набор предопределенных исключений, использование которых однозначно показывает, какое событие разработчик собирается обработать.
Если без others не обойтись, то далее в программном коде после обработки этих исключений должен следовать либо raise, либо комментарий, почему необходим перехват всех исключений.
Да, хорошую обработку ошибок тяжело написать, и она делает код длиннее и труднее для чтения. Но игнорирование ошибок просто заметает проблему под ковёр, где ничего не подозревающий пользователь однажды её обнаружит.
- Запрещается пересечение идентификаторов переменных с переменными-итераторами в циклах.
- Запрещается использование параметров типа string.
- Тело процедуры / функции может быть создано только на вкладке «Локальные описания» (запрещается объявление процедур/функции в блоках декларации на вкладках «Тело» и «Проверка»). И только при необходимости использования процедуры / функции в других операциях допускается (но не рекомендуется за исключением библиотек) объявление её public.
- Запрещается использование оператора «goto».
- Запрещается использование оператор «locate.
- Не допускается применение циклов «for» по выборке «select», где можно применить цикл «for» по ТБП, при условии, что это не сказывается на общей производительности. Разумеется, для отчётов, групповых операций и т.п. необходимо применять циклы «for» по выборке «select», при этом в «select» следует включать все используемые внутри цикла реквизиты для исключения использования вызовов интерфейсных пакетов при обработке внутри цикла.
- Не допускается использование pl/sql вставки в случаях, когда задачу можно решить иначе (т.е. почти всегда). В 2MCA (Java) использование просто запрещено.
- Не допускается использование вместо конструкторов ТБП SQL инструкций update, delete за исключением случаев, когда это оправдано (например, в отчётах, нормализации или миграции для ускорения выборки данных).
- Запрещается использование несколько операторов-модификаторов подряд к одной переменой (например, v_sd%parent%state)[ii].
- Запрещается использование savepoint <имя точки> и rollback <имя точки>. Вместо этого необходимо использовать макросы &sp (<имя точки>) и &rp(<имя точки>)[iii].
- Рекомендуется использовать один оператор «return» в функции, не рекомендуется использование оператора «return» в процедурах.
- Не рекомендуется использование типа данных «Варианты», при использовании в комментарии должны быть отражены описание всех используемых значений.
- Предпочтительней использование кода, компилируемого в курсоры PL/SQL (без вызова интерфейсов Z#%#INTERFACE).
Например, если требуется выполнить действие над несколькими реквизитами ссылочного типа предпочтительнее сохранить ссылку в структуру и уже работать с ней, т.к. это избавит от нескольких обращений к базе (за исключением простой операции при включенном режиме кэширования экземпляра) при получении или изменении данных.
- Крайне аккуратно относится к типизации
- не допускается различия типов передаваемых параметров и параметров функции/процедуры;
- не допускается использование конструкции типа «[ATTR] := substr(value, 1, [ATTR]%size)» при сохранении данных;
- везде стараться использовать атрибут %type (tablename.columnname%type), это избавит от проблем несоответствия типов в различных блоках а также возможных будущих проблем при обновлении схемы;
- при работе с id экземпляров необходимо помнить, что
- integer / [INTEGER] компилируется в pls_integer [-2 147 483 648 до 2 147 483 647],
- а SEQ_ID может принимать большие значения, поэтому следует использовать [NUMBER ][1.0E - 130; 1.0E126 - 1];
- и т.п.
- По возможности избегать использования клиент-скрипта VBScript, если использования не избежать (GRID, работа с элементами формы в части видимости, доступности и т.п.), то стремиться помещать его в одном место (либо на закладку "Проверка" (предпочтительнее), либо - "Клиент-скрипт") для удобства чтения.
VBS интерпретируется, а не компилируется, что может оказаться неприятной неожиданностью при работе операции.
При использовании клиент-скрипта на закладке "Проверка" он отработает не в момент заполнения, а по завершении серверной части / при следующей проверки (в зависимости от настроек операции), что неприятно роднит его с оператором "goto".
- Не желательно использовать получение значения через %модификатор (class, state) для атрибутов типа обобщённая ссылка / обобщённый массив [REFERENCE] / [COLLECTION].
Т.к. в этом случае выполняются запросы к OBJECTS, COL2OBJ, REFS, что отрицательно скажется на производительности.
Требования к проектированию [iv]
Базовые принципы [v]
- Простота (принцип KISS: «Keep it simple, stupid»)
Все должно быть изложено так просто, как только возможно, но не проще.
Не используйте инструменты, реальная (а не гипотетическая) польза применения которых не превышает ущерб от усложнения и запутывания кода.
- Правило наименьшего удивления
Выбирайте наиболее очевидное решение для своих задач, чтобы не сбить с толку других разработчиков и сделать код более понятным.
- Уникальность функционала (принцип DRY: «Don't repeat yourself»)
каждая функциональная единица системы, должна быть представлена в коде только один раз.
Реальный совет для практического использования в любом проекте — решайте проблему дублирования кода сразу после ее обнаружения (но не раньше!), и делайте это наиболее простым и очевидным способом, доступным в текущей ситуации.
Всегда можно заменить простое решение на более высокоуровневое, и сделать это будет намного проще, чем применять сложный рефакторинг к сырому коду на позднем этапе, когда дубликаты уже разбросаны по всей системе.
- Вам это не понадобится (принцип YAGNI: «You Ain’t Gonne Need It»)
Работайте над решением текущих задач, не пишите код только потому, что думаете, будто он пригодится вам в дальнейшем.
Прикладные принципы
- Запрещается создание методов, выполняющих две или более самостоятельные операции, каждый такой подлежит разбиению на более мелкие.
- Запрещается использование глобальных переменных.
- Использование локальных переменных должно быть оправдано.
- Руководитель проекта определяет используемый способ отладки - &debug / debug_pipe(…, 1-10) / отдельная операция а-ля "dbg" с прописанной логикой, который является обязательным и единым для всего кода в рамках проекта. Оператор debug_pipe(…, 0) разрешается использовать только для отладки, не допускается поставка с использованием данного оператора (ограничение не касается служебных операций и операций миграции).
- Возможность использования интерфейсных пакетов определяет руководитель проекта:
- с точки зрения проектирование их использование оправдано, но с точки зрения реализации и отладки – нет (за исключением случаев, когда интерфейсные пакеты действительно выполняют роль интерфейсов с прописанной дополнительной логикой, исправляющей ошибки проектирования вызываемых методов);
- в п.1.2.2.7. «Правила создания и модификации прикладных объектов Приложений (Редакция 1.6)» в явном виде указано «взаимодействие Локальных Объектов/Дополнительных Приложений с Базовыми Приложениями системы «ЦФТ-Банк» (версия 11.13 и выше) на уровне «операция – операция» необходимо осуществлять через вызов интерфейсных операций / процедур / функций этих Приложений».
- Библиотеки необходимо создавать в том классе, с данными которого они работает.
- Запрещается создание расширений на локальные операции и дистрибутивные hook.
- Запрещается создавать массивы на основе ссылки. Вместо массива ссылок необходимо создавать сразу структуру, содержащую «интересующую» ссылку, и использовать массив, созданный на основе этой структуры.
Причины такого подхода в том, что при необходимости, добавить / удалить / изменить структуру полей массива вас нечего не ограничивает. В случае, использования массива ссылок невозможно будет добавить в данный массив новое поле.
- Использование методов по работе с контекстом сессии setcontext/syscontext за исключением вырожденных случаев (в фильтрах для представлений) допускается только по согласованию с руководителем проекта.
- Использование оператора «commit» / «rollback» допускается только по согласованию с руководителем проекта.
- Использование макросов за исключением (&debug, &sp/&rb) допускается только по согласованию с руководителем проекта.
- По возможности использовать базовые дистрибутивные методы (остаток на счёте, сумма прописью и .п.) ТБП [RUNTIME] (stdlib, F, FD, FDP и т.д.) [vi].
- Объем кода [vii]
- избегайте раздутых функций, у которых очень много задач, лучше делать несколько мелких функций (раздутые функции со скрытым смыслом трудно понять, модифицировать и, особенно, тестировать);
- избегайте методов с более чем 200 строками код, если получилось длиннее, разделите на более короткие куски;
- избегайте методов с более чем 5 аргументами, используйте структуры/типы для передачи большого числа параметров;
- одна строка кода не должна иметь длину более 120 символов.
Подведем итоги.
Хороший код это
- работающий код;
- код, который
- легко читать,
- легко менять,
- достаточно быстр,
- и покрыт тестами в нужном количестве.
[i] совершенный код, как Макконнелл завещал
[ii] п. 2.2.5 правил оформления программного кода
[iii] п. 2.2.9 правил оформления программного кода
[iv] Подумать (в светлом будущем) над добавления
- примеров а-ля https://habr.com/post/266969/
- связанности - https://ru.wikipedia.org/wiki/Зацепление_(программирование)
- части шаблонов проектирования - https://ru.wikipedia.org/wiki/Шаблон_проектирования
- части принципов SOLID https://ru.wikipedia.org/wiki/SOLID_(объектно-ориентированное_программирование)
[v] это общие принципы, дискуссию на тему как они уживаются и какие первичные проводить не будем, для желающих есть множество ресурсов, например, http://sergeyteplyakov.blogspot.com/2016/08/yagni.html
[vi] не мне об этом говорить, необходимо провести их анализ и вывести основные
[vii] обсуждаемо