Привет, Хабр! Меня зовут Олег Бондарь, я архитектор решений в CDEK. В этой статье расскажу о стандартах — сводах правил и требований, которые позволяют всем участникам процесса быть в общем контексте, действовать единообразно и совершать меньше ошибок. Кроме того делают взаимодействие между людьми и системами немного проще.

Статья будет полезна менеджерам проектов, разработчикам, тестировщикам, аналитикам и другим IT‑специалистам. Поговорим о способах выработки и применении стандартов, их влиянии на проектирование, разработку, тестирование и стабильность системы в целом. Для примера возьмем ERP CDEK, которая ежедневно обеспечивает работу десятков тысяч пользователей, нескольких сотен тысяч клиентов и позволяет нам обрабатывать до полумиллиона заказов в день.

Содержание

Атом вместо утки. Экскурс в историю стандартизации

Человечество задумывалось о стандартах с первых шагов современной цивилизации. В Древнем Египте при строительстве использовались кирпичи постоянного размера, а контролем соответствия размеров занимались специальные государственные служащие. Традиционные европейские системы измерения были унаследованы от древнеримских единиц, основанных на понятных каждому обывателю объектах: «палец» — дюйм, «ступня» — фут, «тысяча двойных римских шагов» — миля. Вес в древнем мире измерялся в волах, утках, зернах ячменя или пшеницы (например, один сикль равнялся весу 180 зерен ячменя).

Древний Египет. Взвешивание сердца умершего человека на суде Осириса. Источник

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

В 19-м веке стандартизацией начали заниматься «в промышленных масштабах». Были предложены метрические единицы измерения сантиметр‑грамм‑секунда, появились прототипы эталонов метра и килограмма. В 20-м веке принята Международная система единиц (СИ), наиболее широко используемая в мире на сегодняшний день. В 2019 году единицы измерения СИ были полностью отвязаны от материальных эталонов и стали рассчитываться на основе физических свойств атома.

Важным этапом стало появление Международной организации по стандартизации (ISO), которая занимается выпуском стандартов. В 80-х годах прошлого века был организован Инженерный совет Интернета (IETF), оказывающий значительное влияние на современную IT‑отрасль.

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

Для организации эффективного бизнес‑процесса (в том числе и процесса разработки ПО) применяются регламенты, технические требования и практические рекомендации, которые если и не названы стандартами, по сути, ими являются.

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

История первая. «Планёр Гимли»

В 1983 году Boeing 767–233 авиакомпании Air Canada выполнял внутренний рейс по маршруту Монреаль‑Эдмонтон с посадкой в Оттаве. Вскоре после вылета из Оттавы, на высоте 12,5 километров в кабине пилотов прозвучал сигнал «Отказ всех двигателей». В самолете отключилось электричество и большая часть приборов на панели перестала функционировать. Пилоты взяли курс на Виннипег, но из‑за неработающих двигателей приняли решение совершить аварийную посадку на военной авиабазе Гимли. При посадке у самолета сложилась передняя стойка шасси и начался небольшой пожар, который удалось потушить. 10 пассажиров получили травмы, но к счастью, серьёзно никто не пострадал.

Самолёт проехал передней частью по бетону во время аварийной посадки. Фото: Роберт Пирсон

Эта авария произошла в то время, когда Канада переходила на метрическую систему. Наземная команда ошиблась при заправке самолета — неправильно рассчитала массу топлива (использовала коэффициент для британского имперского фунта вместо килограмма), из‑за чего вместо 20 тысяч литров было заправлено всего 5 тысяч.

История вторая. «Mars Climate Orbiter»

В 1998 году NASA проводило миссию по исследованию марсианского климата. Их космический аппарат Mars Climate Orbiter, запущенный в декабре, в течение года должен был выйти на орбиту Марса для исследования атмосферы и фотосъемки поверхности. 23 сентября 1999 года аппарат начал заходить на запланированную орбиту и после прохождения с обратной стороны планеты должен был выйти на связь. Однако больше никаких сигналов от спутника не поступало.

В ходе расследования первопричин аварии NASA сообщило, что субподрядчик в ПО аппарата использовал единицы измерения СИ, в то время как в центре управления на Земле использовались британские единицы. Предполагается, что аппарат прошел над поверхностью Марса на высоте 57 км вместо расчетных 110 км и распался в атмосфере. Данная ошибка привела к потере 327,6 миллионов долларов США, согласно оценкам NASA.

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

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

Стандарты? Не, не слышали

На момент моего прихода в CDEK, в 2019 году, в компании происходил отказ от морально устаревшей монолитной ERP‑системы, написанной на C++. Активно разрабатывалась новая версия с применением микросервисной архитектуры. На тот момент уже работало несколько десятков сервисов, написанных на Java (большая часть ядра системы), PHP (в основном витрины и интеграции) и JavaScript (фронт). При этом какая‑либо стандартизация хранения, обработки и обмена данными по большей части отсутствовала. Поэтому разработчики руководствовались в работе собственным опытом и интуицией, не применяя на практике унифицированный подход к данным.

Одной из самых распространенных проблем был подход к работе с датами и временем. Приведу небольшой список констант из уже вышедшей из употребления корпоративной Java‑библиотеки, которая использовалась для преобразования даты со временем в строку и обратно:

String SERVER_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
String VIEW_DATETIME_FORMAT_STRING = "d.MM.yyyy H:mm:ss";
String VIEW_DATESHORTTIME_FORMAT_STRING = "d.MM.yyyy H:mm";
String ORACLE_DATETIME_FORMAT_STRING = "dd.MM.yyyy HH:mm:ss";
String NSPCMAIL_DATETIME_FORMAT_STRING = "dd.MM.yyyy HH:mm:ss";
String ELASTIC_DATETIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss.SSS";
String ELASTIC_DATE_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss";
String FILE_NAME_DATE_FORMAT_STRING = "dd.MM.yyyy-HH_mm_ss";
String VIEW_DATETIME_SHORT_FORMAT_STRING = "dd.MM.yyyy HH:ss";

Принцип использования достаточно простой: при конвертации данных (например, из строки в JSON объекте) по очереди перебирались все возможные варианты представления и при некоторой доле везения, результат записывался в типизированную переменную. При этом, например, в Java использовался безнадежно устаревший тип java.util.Date.

Легко заметить, что во всех приведённых форматах даты и времени отсутствует указание временной зоны. Фактически значение могло быть указано как в локальной таймзоне, так и неявно в UTC, по Московскому или Новосибирскому времени. Иногда формат и временная зона указывалась в комментарии к полю объекта или столбцу БД. Чаще всего приходилось выяснять это проводя натурные эксперименты, разбираясь в коде проекта. Или же искать ответственного за данный объект разработчика.

Валюты идентифицировались в ERP‑системе пятью способами: внутренний числовой идентификатор системы, уникальный идентификатор (uuid), цифровой и буквенный коды ISO 4217, причем как в верхнем, так и нижнем регистрах. Глядя на строковое поле, содержащее код валюты в произвольном обменном объекте, решительно невозможно было понять: в каком именно формате будет представлена валюта на самом деле. Это мешало не только разработке, но и анализу инцидентов. Просто представьте, что просматривая логи, вы видите 1000 единиц в валюте № 14 или 500 у.е. в валюте с идентификатором 18117342-cff4-4fa4-a2cf-c3d332c27330.

Коды языков, локалей и стран могли быть представлены в произвольном, иногда выдуманном разработчиками виде. Например, Беларусь появлялась в виде кода BR, относящегося в ISO 3166 к Бразилии. А в списке языков мог появиться казахский с кодом «kz», которого вовсе не существует в стандарте ISO 639.

Номера телефонов были полностью непригодны для автоматической обработки, поскольку даже для РФ они имели любой из префиксов «7», «+7», «8» (или не имели его вовсе). Сервисы обрастали «костылями» для обработки номеров телефонов с подсчетом цифр и подменой префиксов. Алгоритмы выглядели монструозно и были ненадёжны.

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

Надо ли говорить, что это значительно усложняло разработку и приводило к неожиданным багам, которые иногда обнаруживались лишь на проде…

Как мы пришли к стандартизации

Для меня, как для специалиста, более 8 лет проработавшего с банковским ПО, где использовалась строгая типизация, а для обмена данными — стандартизированные протоколы вроде SOAP, такой подход оказался весьма неожиданным. Было жаль времени и сил специалистов, которые вместо эффективного решения бизнес‑задач вынуждены тратить время на разрешение неоднозначностей нашей системы.

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

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

Затем были выработаны стандарты, призванные сделать и другие данные компании однозначными и единообразными:

  • Стандарт номеров телефонов — был разработан на основе ITU‑T E.164, преследует целью унификацию представления телефонных номеров (всегда указывается полностью, обязательно начинается с «+» и кода страны, не содержит разделителей);

  • Стандарт валют — основным идентификатором выбран код ISO 4217 Alpha-3, который однозначен и человекопонятен;

  • Стандарт финансовых и монетарных значений — с главной идеей сформулировать неотделимость суммы от валюты; в момент написания этой статьи мне встретился код, где складываются суммы из разных объектов без учета валюты!

  • Стандарт локалей — за основу взято представление локали в Java (страна ISO 639-1 и язык ISO 3166-1 Alpha-2, разделенные подчеркиванием);

  • Стандарт языков — согласно стандарту ISO 639-3;

  • Стандарт временных зон — на основе IANA Timezone Database.

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

Профит

Внедрение стандартов:

  • значительно снизило количество ошибок (количество массовых сбоев уменьшилось на порядок в том числе благодаря внедрению единого подхода к данным);

  • облегчило расследование инцидентов (взаимодействие между сервисами стало проще, а логи — очевиднее);

  • ускорило разработку, тестирование и внедрение задач (время на выпуск бизнес‑фич сократилось до 14 дней);

  • улучшило аналитику, BI (качественные исходные данные — качественный результат);

  • оказало заметное положительное влияние на основной бизнес компании в целом.

Вам нужны стандарты. С чего начать?

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

Если говорить об унификации данных, в первую очередь нужно проанализировать существующие общемировые и общепринятые стандарты, например: ISO, IETF RFC, ICANN, ITU‑T. Для начального ознакомления подойдут и статьи Википедии.

Для создания некоторых стандартов легче и эффективней использовать практическую документацию. Например, для корпоративной стандартизации HTTP‑заголовков вместо исходного RFC 4229 допустимо использовать документацию MDN Web Docs, которая проще для понимания и содержит практические примеры.

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

Стандарты выработаны — что дальше?

А дальше начинается самое сложное. Недостаточно просто сформулировать стандарт — нужно добиться его внедрения. Для этого существует два подхода: административный и технический.

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

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

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

Конечно, стандарты применяются не только в работе с данными. Возможно стандартизировать любые бизнес‑процессы (в этом случае они к тому же проще автоматизируются), процессы разработки (взять за основу хотя бы Agile) и даже количество котиков в офисе в расчете на квадратный метр.

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

Если в процессе работы вы постоянно сталкиваетесь с проблемой «неоднозначности» и «неочевидности» (неважно — в данных или процессах разработки или бизнеса), то самое время подумать о стандартизации: выбрать объект и сформулировать к нему общие правила и требования. Даже если это не принесёт результата в моменте, со временем вы обязательно почувствуете накопленный эффект и положительное влияние на процессы и бизнес компании в целом.

А какие стандарты применяете вы? Как они влияют на процессы в вашем случае и приходилось ли сталкиваться с проблемами при их внедрении? Буду благодарен, если поделитесь своим опытом в комментариях.