
Привет, Хабр! Меня зовут Олег Бондарь, я архитектор решений в 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) и даже количество котиков в офисе в расчете на квадратный метр.

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