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

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

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

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

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

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

Важные тезисы

  1. Система понятий, терминов, определений, которые используются при описании требований, должна быть единообразной, конкретной, одинаково пониматься и Заказчиком и Исполнителем.

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

  3. Выполнение требования должно быть достоверно проверяемо, то есть должна существовать такая процедура проверки, которая будет необходима и достаточна для подтверждения выполнения требования.

  4. Способ проверки может быть разным для разных видов требований, выполнение требования может проверяться как аналитически так и фактически - непосредственным наблюдением.

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

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

Тезис про единство и конкретику понятий

Если Заказчик при составлении ТЗ использует разные термины для определения одного и того же, то это может ввести Исполнителя в заблуждение. На мой взгляд, даже синонимы при составлении требований - это зло. Кто даст гарантию, что даже сотрудники Заказчика однозначно понимают набор синонимичных терминов? Никто. И тогда, при изготовлении и приемке системы, изделия - каждый будет ожидать разного.

Пример:

...следует обеспечить обслуживание современных моделей оборудования...

Современные - это сколько месяцев, лет, начиная с какой даты? Современные по технологиям или по дате выпуска?

...должна быть обеспечена высокая скорость сервисного обслуживания...

Высокая - это какая? Какого именно обслуживания?

Ну и так далее...

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

Все это удобно сделать при помощи разработки документа, содержащего разделы "Используемые термины и определения", "Используемые сокращения". Во многих случаях, такие разделы будут включены (и по ГОСТ должны быть включены) в пояснительную записку проекта или научно-технический отчет по работе. Однако хотелось бы обратить внимание, что эти разделы ВАЖНЫ и им следует уделить внимание.

Про ГОСТы

Кстати, ГОСТы в свое время были продуманы очень грамотно. И если их действительно понять, а не просто тупо исполнять, то вероятность сделать качественный продукт существенно повышается.

Каждый термин, используемый в работе должен быть отражен в этом разделе с понятным описанием. Пусть это описание будет прочитано и понято, разъяснено заранее всем участникам работы. Например, определяем:

Современная модель оборудования - модель оборудования, выпущенная не ранее января 2022 года.

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

Тезис про смысл и взаимную увязку требований

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

Если не сформировать при анализе ТЗ представление о том, как между собой связаны понятия и требования, то можно упустить какие-то важные моменты, которые не прописаны в ТЗ явно. Такое упущение может привести к тому, что формально ТЗ будет выполнено безукоризненно, но то, что будет реализовано на основании этого ТЗ, окажется никому не нужным и практически бесполезным.

Пример:

Цель работы: Разработка эффективной системы сервисного обслуживания мобильных устройств.

...следует обеспечить обслуживание современных моделей оборудования...

Мы уже ранее определились, что такое "современная модель". И под это определение вполне подходят устройства, которые недоступны на нашем рынке или крайне не популярны. Можно выполнить ТЗ буквально, но истинная цель работы при этом не будет достигнута! Имеет ли смысл система, умеющая обслуживать современные аппараты, которые никто не покупает или не может купить?

Что касается увязки требований между собой - представьте себе, что эти требования находятся в разных частях ТЗ. А еще можно представить, что устройство заказывается у исполнителя по отдельному частному ТЗ... Сложно все это сопоставить при помощи текста.

Для того, чтобы избежать конфликта требований можно нарисовать первую интересную картинку. Модель понятий. В которой каждый узел представляет термин, а стрелки разного типа - взаимоотношение между терминами. При этом, для каждого узла есть четкое определение задокументированное и согласованное на предыдущем шаге анализа. Типы стрелок удобно взять из нотации UML. Например, это относится к отношению "наследования", где обобщенное понятие, например, "Современное оборудование", может быть конкретизировано до "Мобильного телефона", "Планшета" и "Смарт-часов".

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

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

Картинка 1. Модель понятий
Картинка 1. Модель понятий

Для того, чтобы пользователь обратился в сервис, он должен иметь возможность приобрести оборудование. Чтобы пользователей было много - модель должна быть популярна. Соответственно,имеет смысл уточнить термин:

Современная модель оборудования - модель оборудования, выпущенная не ранее января 2022 года и доступная к приобретению на потребительском рынке, при этом рейтинг модели должен быть не ниже 4 по оценке сайта market.yandex.ru или аналогичного.

Содержимое ТЗ, как правило, содержит:

  • Цель работы

  • Задачи

  • Требования

Цель работы достигается путем решения ряда задач, к выполнению которых предъявлены требования. Задачи могут включать в себя подзадачи. Требования могут предъявляться к структуре, составу, назначению, и т.п.

Эту иерархию удобно представить в виде диаграммы UML типа "Use case", диаграмма использования.

Картинка 2. Диаграмма использования
Картинка 2. Диаграмма использования

Такое представление дает удобный визуальный обзор основных работ, которые предстоит выполнить в ходе выполнения проекта. Ее можно детализировать в зависимости от сложности проекта. Например, можно уточнить, что исполнители бывают разные - Закупщик, Инженер, Менеджер.

Тезисы про проверяемость требований и разные способы проверки

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

Для этого есть диаграмма UML (SysML) "Requirement diagram". Выглядит она примерно так:

Картинка 3. Фрагмент диаграммы тебований
Картинка 3. Фрагмент диаграммы тебований

Это простой фрагмент, на котором показаны следующие вещи:

  1. Взаимосвязь с задачей, для которой эти требования сформулированы

  2. Состав требований, а именно - что подразумевается выполнить для решения задачи

  3. Что предполагается предъявить в качестве доказательства того, что требование было выполнено.

Чаще всего, для проверки выполнения требований выпускают документ, который называется "программа и методики испытаний", ПМИ. В нем подробно описывают что, в каких условиях, какими средствами, каким составом проверяющих, на основании каких процедур и по каким критериям проверяют.

Аналогично ТЗ, и более того - на одной диаграмме, этот документ (ПМИ) может быть представлен графически. Мне представляется это очень удобным, т.к. уже на этапе анализа ТЗ исполнитель продумывает - а как именно можно проверить требование.

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

Уже надоевший в этой статье термин "Современное оборудование" и связанное с ним требование может быть достоверно проверено так: "Убедиться, что представленное оборудование имеет дату выпуска не ранее 2022 года согласно информации на сайте производителя. Убедиться, что оборудование представлено на сайте market,yandex.ru и имеет рейтинг не ниже 4.0". Если все это так - то никаких претензий у Заказчика не возникнет и не может возникнуть. Все предельно конкретно и понятно.

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

Заключение

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

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

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

Если тема графического представления текстовых материалов кого-то интересует - пишите комментарии, есть еще чем поделиться...

:)

Комментарии (38)


  1. SpiderEkb
    25.09.2023 06:42
    +1

    Из личного опыта (и той методологии, в которой сейчас работаем) схема немного сложнее.

    То, что хочет заказчик, называется BRD - бизнес-требования. Они согласуются с заказчиком. Все, что делается дальше, уже является внутренними документами исполнителя.

    На основе BRD сначала разрабатывается архитектурное решение - там уже архитектура, дробление на модули, связь между модулями и т.д. и т.п. Это работа архитектора.

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

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

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

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


    1. Txanxs Автор
      25.09.2023 06:42

      схема немного сложнее

      Как говорил один серьезный Заказчик, "Для того, чтобы что-то упростить - надо сначала это усложнить!"

      Заказчику важно получить функционал

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


      1. SpiderEkb
        25.09.2023 06:42

        При этом важно понять даже невнятное изложение требований

        Дело в том, что вам это изложение требований кажется "невнятным". А для заказчика все это понятно и естественно. А все, что вы ему говорите в ответ про "движки" и "фреймворки" для него птичий язык. И тут речь не о том что

        Для того, чтобы что-то упростить - надо сначала это усложнить!

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


        1. Txanxs Автор
          25.09.2023 06:42
          +1

          С этим согласен - на разных уровнях - разные представления.


  1. AlexXYZ
    25.09.2023 06:42

    Лично мне представляется, что разработка какой-то персонифицированной для заказчика системы фактически означает разработку некоторого «движка» для бизнес-процесса заказчика на выбранном наборе фреймворков, поэтому нужно в итоге обсуждений с заказчиком прийти к тому, что его бизнес-требования будут описываться в терминах этого «движка». Всем от этого будет легче - заказчик понимает, что он может хотеть от такой системы в краткосрочной и долгосрочной перспективе, разработка становится более прозрачной для всех - и для заказчика и для исполнителя. Код движка от заказчика может быть закрыт, но тут как договориться участники. У меня был пример, когда в итоге общение с заказчиком свелось к таблицам параметров - они присылали таблицы параметров или изменения в таблицах, мы выставляли счёт, он оплачивал, мы делали. Все были довольны. Отступления от такой схемы рассматривались отдельно.

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


    1. Txanxs Автор
      25.09.2023 06:42

      Ну, тут есть отличие в том, что речь идет не только о программном коде. И акцент идет, действительно, в большей степени на "администрацию". Для исполнителя, если речь вести только о программном коде, конечно есть другие варианты представления требований.

      Можно и просто их оформить, сформулировать, и сложно. Use Case, User Stories, просто постановка задач на разработку функций "на вход то-то, на выходе то-то". Разные варианты.

      По графическому представлению - Use Case (опять таки по мне) - рулит!


    1. SpiderEkb
      25.09.2023 06:42

      Заказчик живет в рамках своей предметной области. И разговаривает на своем языке. И ему все эти "движки", "фреймворки" глубоко безразличны - у него есть бизнес-процесс и он хочет его автоматизировать. И вот для ее автоматизации он и составляет BRD - Business Requirements Document. Вот его он понимает. А все что глубже ему не интересно.

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

      Связь "набора прямоугольников" программным кодом описывается аналитиком в FSD (Functional Specifications Document). Это совсем другой документ и там используется совсем другая терминология - терминология разработчика. Там уже и "движки" и "фреймворки" и все вот это вот. Аналитик в данном случае выступает в качестве переводчика с языка заказчика на язык разработчика.

      Здесь классическая цепочка - "заказчик - организатор - исполнитель" в которой крайние звенья (заказчик и исполнитель) между собой не общаются и друг друга не знают, они связаны только через организатора, роль которого выполняет аналитик.


      1. Txanxs Автор
        25.09.2023 06:42

        Да, ок.

        В понятийном аппарате PMI, документу BRD соответствует Паспорт проекта. Он логичный, содержательный, но... опять таки - сложноватый и весьма формальный.

        На подобные документы, такова жизнь, забивают болт... Особенно в цейтноте.


        1. SpiderEkb
          25.09.2023 06:42

          На подобные документы, такова жизнь, забивают болт... Особенно в цейтноте.

          И ничего хорошего из этого не выходит. Ладно если это разовый проект - спихнул заказчику, взял деньги и свалил в даль светлую. А что там дальше - трава не расти.

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


        1. astoulov
          25.09.2023 06:42

          Паспорт проекта это точно, не BRD. На самом высоком уровне Business Case описывает, что хочет бизнес, а потом это детализируется, но не в Паспорте проекта


          1. Txanxs Автор
            25.09.2023 06:42

            Паспорт - комплексный документ, там есть и стейкхолдеры, и риски, и цели, и ключевые бизнес требования. Естественно, он не точно соответствует BRD.


      1. AlexXYZ
        25.09.2023 06:42

        Аналитик в данном случае выступает в качестве переводчика с языка заказчика на язык разработчика

        Вот это и есть тонкий момент во всей этой системе. Переводчик - это тоже условный термин и вот тут я с этим не очень согласен. Я бы сказал так - «толкователь». Потому что нет каких-то строгих и чётких правил перевода. Этот человек и является очень слабым звеном в этой системе. По хорошему он должен работать на то, чтобы устранить себя из этой системы и это очень противоречивая ситуация для него. Можно было бы предложить получать процент от работы по такому договору в случае изменений с его участием или без. Тогда он может быть заинтересован как можно быстрее настроить систему так, чтобы она работала без него, а он получал пассивный доход.


        1. SpiderEkb
          25.09.2023 06:42

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

          Отсутствие такого человека в системе накладывает на исполнителя (разработчика) требования глубокого понимания предметной области заказчика. А она может быть очень непростой и на вникание в нее могут потребоваться годы (если это, конечно, не формошлепство в виде красивого раскидывания кнопочек и формочек по страничке).


          1. AlexXYZ
            25.09.2023 06:42

            если это, конечно, не формошлепство в виде красивого раскидывания кнопочек и формочек по страничке

            По моему именно к такой форме работы и надо стремиться в каждом конкретном проекте. Не начинать с него, а идти к нему. А как вы считаете?


            1. SpiderEkb
              25.09.2023 06:42

              По моему именно к такой форме работы и надо стремиться в каждом конкретном проекте

              А представьте, что задача заключается в разработке модуля с достаточно сложной логикой, но совершенно без интерфейса... Например, поиск совпадений между элементами одной БД (5-6 таблиц, ~50млн записей) и другой БД (7-8 таблиц, ~300тыс записей) по 5-6 параметрам с формированием списка связей (какие элементы по каким параметрам совпали). Причем, не просто вывести, а проанализировать - что было, но сейчас нет, чего не было, но сейчас появилось, что было, но изменилось...

              Запускается все это по определенному событию. Плюс есть жесткие рамки - временное окно, в которое нужно уложиться и максимально допустимая нагрузка на процессор в рамках временного окна.

              Или контроль платежей. Там порядка десятка проверок на основании которых выносится решение о том, пропустить платеж или отправить его на ручной контроль в финмон. Порядок, параметры и состав комплекса проверок определяется исходя из типа платежа (входящий, исходящий, внутренний) и типов плательщика и получателя (ФЛ, ЮЛ, ИП...). Причем, все это должно быть организовано так, чтобы порядок проверок, их настройки для каждого конкретного случая можно было легко настраивать без изменения кода.

              А с учетом того, что количество платежей в сутки легко может уйти за 100млн, то все это должно работать не просто быстро, а очень быстро.

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

              Так что ИТ - оно не ограничивается сайтами и мобильными приложениями. Есть много отраслей, где приходится работать со сложной логикой, большими объемами данных.


              1. AlexXYZ
                25.09.2023 06:42

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

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


                1. SpiderEkb
                  25.09.2023 06:42
                  +1

                  Я не очень понимаю что такое "стремится к самоустранению".

                  У нас аналитик избавляет разработчика от общения с бизнесом (сталкивался с ситуациями когда разработчик напрямую пытается с бизнесом общаться - они просто не понимают друг друга). Помогает разработчику в предметной области. Занимается компонентным тестированием (первая стадия - тестирование поставки на соответствие FSD).

                  Да, он не пишет ТЗ "до псевдокода" - выбор наиболее эффективного решения всегда за разработчиком. Но описать dataflow - это задача аналитика.

                  Аналитик ведет задачи в Jira (разработчик только меняет статусы на Dev и потом на Dev Done). Занимается актуализацией FSD, которая одновременно является технической документацией по задаче (ее же потом еще надо сопровождать, вносить изменения если изменился бизнес-процесс или какие-то условия - законодательство, требования регулятора...). Также для решения одной задачи может потребоваться создание каких-то подзадач (те же витрины, например). Для решения задачи может потребоваться проектирование БД - это тоже работа аналитика...

                  Аналитик вообще незаменимый человек в процессе. Он и предметную область должен знать и обладать некоторыми навыками алгоритмизации.

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


        1. olku
          25.09.2023 06:42

          Эта роль называется Product Owner. Хороший PO часто знает бизнес заказчика лучше заказчика, потому что общается не только с начальством, но и конечными пользователями. За красивыми BPMN можно скрыть любой ад.


  1. Batalmv
    25.09.2023 06:42
    +1

    Мне кажется - это статья, классический пример тяжеловесного аналитика, который скорее утомит всех своим ТЗ, чем его кто-то поймет

    Во-первых, люди НЕ БУДУТ менять свой словарь ради аналитика. Мы разошлем термины, согласуем в начале, всех заставим говорить на одном языке - это видимость работы и мина замедленого действия. Заказчик понимает свой язык и имеет на то право, так как он платит деньги. Учи его, говори на нем, пиши на нем, если ты входишь в число членом команды, кто общается с ним.

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

    Заказчик имеет деньги, разработчик пишет код. Остальные - обслуга и должны максимально создать комфортные условия первым и вторым, беря на аебя сложности перевода.

    Можно как писали выше, заказчику один документ, команде - сторьки во внутреннем формате. Все равно их декомпозировать технически. Простейший пример, одно требование из ТЗ, хочештили нет, разделится на отдельные требования фронту и бэку. Между которыми API. Не всегда конечно, но очень часто.

    Пример "Современная модель оборудования - модель оборудования, выпущенная не ранее января 2022 года и доступная к приобретению на потребительском рынке, при этом рейтинг модели должен быть не ниже 4 по оценке сайта market.yandex.ru или аналогичного." - это жесть и за такое надо бить. Поясню. Требования к аппаратной части идут от ее свойств, к примеру. Минимальной версии браузера или операционной системы смартфона. Это и есть требованик, техническое. Потому что с изменением версии чего то там отпало в API, и так далее. А за такое, повторюсь, аналитик должен немедлено получить пистон и вымарать этот абзац навсегда.

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


    1. Txanxs Автор
      25.09.2023 06:42

      Мне кажется - это статья, классический пример тяжеловесного аналитика, который скорее утомит всех своим ТЗ, чем его кто-то поймет

      Мне кажется, это классический коммент теоретика, который не сталкивался с реальной реализацией сложных проектов, но книжки читал!


      1. Batalmv
        25.09.2023 06:42

        Вам кажется :)


    1. SpiderEkb
      25.09.2023 06:42

      Ну в целом это то, что пытаюсь донести... ТЗ с точки зрения заказчика - это одно. С точки зрения разработчика - другое. Задача аналитика - свести все это воедино. Не в один документ, а минимум в два - согласованные требования заказчика и описание из реализации для разработчика.

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


      1. Batalmv
        25.09.2023 06:42

        Ну, если писать небольшими сторьками - то проблем нет. Так как они маленькие, и даже если там будут и тех. детали, и бизнес язык - не проблема. Связывание и прочее реализуется в условной Jira линками, иерархией и тэгами.

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

        Если же надо большой документ, то все идет от контракта и условий приемки. Ну реально, если приемка по требованиям - то все будут смотреть туда. Если по ТЗ - то туда. А вот уже потом для команды можно и какие-то детали описать вне конктратного документа

        Заказчик с разработчиками вообще не общается по хорошему :)


        1. SpiderEkb
          25.09.2023 06:42

          Ну, если писать небольшими сторьками - то проблем нет.

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

          Я понимаю, что у меня "профдеформация" - всю свою жизнь в разработке (а это 30+ лет) я практически не занимался интерфейсами, зато очень много реализацией логики разной степени мудрености, которая работает преимущественно в виде фоновых процессов. И там не получалось сделать маленький кусочек и показать заказчику. Оно или работает целиком, или не работает вообще.


          1. Txanxs Автор
            25.09.2023 06:42

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

            Эх, а я вот как раз этим 10+ лет занимаюсь... Картинки (мне) помогают. Собственно и статья то была отчасти про это. Про способы наглядно представить нечто труднодробимое. Ну да ладно, спасибо за комментарии!


          1. Batalmv
            25.09.2023 06:42

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

            Тут скорее проблема в том, что сначала "заходит" архитектор со знанием и декомпозирует решение, а потом уже в рамках декомпозиции детализируются требования

            Ну например, из последнего моего. Чисто фоновый процесс, data pipeline. Тут из названия очевидно, что разбивается на изи.

            Из старого - биллинг оператора связи. Процесс идет дни, но декомпозиция очевидна на много кусочков

            Платежный роутер - тоже режется без проблем.

            Ну правда, напиши свой кейс, или пару


            1. SpiderEkb
              25.09.2023 06:42

              Ну вот из того, с чем до сих пор работаю. "Списки комплаенс".

              Росфин присылает списки всяких злодеев-бармалеев. Из 5 штук разных:

              • ППТ - список подозреваемых в пособничестве терроризму

              • ПЭ - список подозреваемых в экстремизме

              • ПРОМУ - список подозреваемых в распространении оружия массового уничтожения

              • РС - список решений суда

              • СБ ООН - список совета безопасности ООН

              Они все в разных форматах (похожие, но есть отличия). Например, в каких-то списках, если субъект исключается, то явно приходит уведомление что он теперь не списке. А в каких-то он просто не приходит (т.е. если в очередной версии списка его нет, нужно исключить его из БД).

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

              Все это должно быть разложено по нашей БД так, чтобы потом со всем этим можно было работать. А поскольку это нехорошие люди, то там может быть

              она же Анна Ефидоренко, она же Элла Кацнельбоген, она же Людмила Огуренкова, она же Изольда Меньшова, она же Валентина Панеяд (с)

              Т.е. у субъекта может быть несколько имен, ДУЛов (документ, удостоверяющий личность), адресов и т.п.

              Субъекты могут быть ФЛ (ФИО, ДР - день рождения, ДУЛ, ИНН) или ЮЛ (наименование, ИНН).

              Все это раскладывается по нескольким таблицам - данные ФЛ (ИНН, ДР...), данные ЮЛ (ИНН), ФИО ФЛ, наименования ЮД, ДУЛы ФЛ, адреса (их несколько типов - рождения, национальность, проживания и т.п.). Плюс таблица заголовков списков (версия, дата, загружен полностью, откатывался, маркер списка...) Плюс таблица субъектов (типа "оглавления" - идентификатор, тип списка, тип субъекта, активен/не активен), плюс лог изменений по субъектам, плюс еще несколько вспомогательных, плюс на каждую основную таблицу еще "архивная" куда переносится предыдущая версия записи для возможного отката. Плюс есть "основная запись" и есть "остальные". В некоторых списках они разделены явно, в некоторых приходится первую считать основной, следующие "остальными"

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

              Это первая часть задачи. ТЗ с описанием всех форматов и правил раскладки где-то страниц на 150. Кода (не считая описания таблиц в DDS) - под мегабайт. Поставка содержит порядка 180 объектов (программные модули, таблицы, индексы). И эта часть не дробится никак.

              Вторая часть - сверка. Надо сверить всех клиентов (~50млн) со всеми субъектами списков (~300тыс), выявить совпадения (для ФЛ это ФИО+ДР или ИНН или адрес, для ЮЛ - ИНН или наименование, или адрес). Еще надо сверить "субъектов клиентов" (доверенные, уполномоченные лица, представители не являющиеся сами по себе клиентами банка) - у некоторых клиентов таких до десятка может быть. Это дробится легче - сверка по клиентам отдельно, сверка по субъектам клиентов отдельно, сверка по адресам клиентов отдельно, сверка по адресам субъектов отдельно. Плюс каждая сверка еще делится пополам - одна часть запускается каждый день и идет "от клиента к субъекту" с выборкой только тех клиентов, у которых были изменения в данных за прошлый день, вторая часть - "от субъекта к клиенту" - она запускается после загрузки очередной версии списка с выборкой тех субъектов, у которых были изменения. Т.е. один раз прогоняем всех со всеми, дальше работаем по дельте. Тут еще отпочковывается задача по витрине ключевых слов для поиска по ФИО, наименованиям и адресам - чтобы не сравнивать длинные строки, для каждой выбираем "ключевое слово" из строки (с учетом частотного словаря) чтобы по нему можно было делать высокоселективную предвыборку для детального сравнения. Отдельная задача - заполнение витрины (порядка 400млн записей). Дальнейшее ведение витрины уже включается в раскладку при обработке списка.

              Результат сверки заносятся в т.н. "стоплисты" - таблицы связей клиент-субъект списка с указанием по каким параметром найдено совпадение. Тут алгоритм примерно такой - взяли клиента (или субъекта), провели поиск совпадений, составили список "новых свопадений" (может быть пустой), прошли по стоплисту, собрали список "старых совпадений" (тоже может быть пустой), сравнили эти два списка, внесли изменения в стоплист (что-то было, но сейчас нет, чего-то не было, сейчас появилось, чтобы было, есть, но поменялось, что-то осталось без изменений). Стоплисты потом будут использоваться, например, в контроле платежей в системе расчетов (но это уже другая команда).

              Третья часть - комплекс комплаенс проверок. Это поиск совпадений с БД по клиентским данным. Пришел человек - вот его ФИО, ДР, ДУЛ, ИНН... Оператор в ККО заводит клиента, данные автоматом улетают в модуль комплаенс проверок и оттуда приходит "оп-па, он по ФИО+ДР бьется в известным международным террористом...".

              Или кто-то отправляет платёж куда-то - получатель пробивается по БД и приходит отказ - этому нельзя переводить деньги, будет спонсирование терроризма, за такое регулятор может навалять по самое немогу.

              По этим проверкам алгоритм поиска совпадений немного иной чем при составлении стоплистов - там есть "частичные" и "полные" совпадения. Плюс проверка имен/наименований идет с учетом "словоформ" (падежи, транслитерация...).

              Ну и вишенка на торте (четвертая часть) - анкета 499П (уж не помню куда она идет, но это из разряда обязательной отчетности). Там есть блок "история совпадений клиента со списками комплаенс" - вся история когда и по каким параметрам он попадал в стоплисты и по какому списку.

              Такая вот история... Первая и вторая части достаточно объемные Вторая и третья - очень критичные по производительности (там приходится мозг наизнанку выворачивать с алгоритмами чтобы все это работало предельно быстро - тупые решения "в лоб" не проходят - без всех наших наворотов сверка может растянуться на 12-15 часов что недопустимо).

              По комплаенс-проверкам (старая версия, еще до нас была) как-то вот такое пришло от сопровождения

              Коллеги, сервис *** за последние 5 недель увеличил потребление процессорных ресурсов в 3 раза!!!
              Он уже является 2-м по величине сервисом после *****.
              В качестве альтернативы мы рассматриваем перенос запуска сервиса на резервный сервер, но там есть лаг по отставанию до 10 мин.
              Заказчикам сервиса это может не понравиться :(

              Неделю голову ломал как это дело оптимизировать. Но победил в конечном итоге (со второго раза).

              Спасибо!
              Уже утром видим очень хороший результат!!!
              Доработка сокращает потребление процессорных ресурсов почти в 10 раз!

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

              Новую версию уже по образу и подобию делал.


              1. Txanxs Автор
                25.09.2023 06:42

                ТЗ с описанием всех форматов и правил раскладки где-то страниц на 150.

                И это на пять списков? Ничего себе...

                PostgreSQL используете?


                1. SpiderEkb
                  25.09.2023 06:42

                  PostgreSQL используете?

                  DB2 for i. Причем, все изменения в БД у нас делаются не скулем, а специальными модулями (на каждую таблицу три модуля - внешний ввод, валидация данных, запись в таблицу) с журналированием (на каждую таблицу ведется журнал где все изменения - скажем, меняем запись - пишется два образа - до изменения и после изменения.

                  А здесь еще архивные таблицы и эти модули обслуживают и их тоже - если идет изменение записи и при этом поменялся маркер списка, то старая запись из основной таблицы переносится в архивную (журналы тут не проходят т.к. они не для долгосрочного хранения), а модуль это поддерживает дополнительную операцию "восстановление из архива" на случай отката списка.

                  И это на пять списков? Ничего себе...

                  Там не так все просто. В одних списках "деактивация" субъекта приходит в явном виде - признак что субъект не активен. Тогда его сразу деактивируем в процессе обработки.

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

                  В каких-то списках теги русские, в каких-то латинские. В каких-то все более-менее стройно, в каких-то полный разброд и шатание (та же ДР может приходить как тегом DATE_OF_BIRTH внутри тега INDIVIDUAL_ALIAS, так и тегом DATE внутри тега INDIVIDUAL_DATE_OF_BIRTH, а имя как клеиться из тегов FIRST_NAME ... FOURTH_NAME, так и браться из тега ALIAS_NAME внутри тега INDIVIDUAL_ALIAS).

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

                  Короче, там фактически на каждый тип списка свой парсер и при раскладке потом тоже куча условных веток по разным типам списков.

                  И это не считая всяких нормализаций (имена, адреса, ДУЛы), если тип ДУЛ - паспорт РФ (а это тоже нужно определить по ряду признаков - не везде это явно указывается), то еще парсинг паспорта - серия, номер, кем выдан и т.п.

                  Плюс "коды маркировки" обозначающие всякие "ненормальности":

                  • Дата рождения/регистрации не заполнена

                  • ИНН ФЛ не 12 символов

                  • СНИЛС ФЛ не 12 символов

                  • ИНН ЮЛ не 5 и не 10 символов

                  • ОГРН ЮЛ не 13 символов

                  • ФИО содержит больше 3х слов

                  • Присутствуют подозрительные символы

                  • Не определен тип ДУЛ

                  • Не заполнены серия и номер

                  • ДУЛ занесен не полностью

                  • Адрес занесен не полностью

                  • ФИО внесено не полностью

                  • Наименование внесено не полностью

                  • ФИО содержит меньше 3х слов

                  Есть история изменений по субъектам - субъект добавлен, у субъекта изменился список адресов, список наименования, список ДУЛов и т.п.

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

                  Короче, там не просто их XML БД раскидать. Там логики накручено по самые помидоры. В целом - собрать список новых записей, собрать список старых записей, сравнить их и понять что со всем этим теперь делать.

                  Короче, это долго описывать все... Наворочено там преизрядно.


                  1. Txanxs Автор
                    25.09.2023 06:42

                    Мда, это адский ад. Странно, что, вроде бы, "официальные источники" не нормируют свои списки.

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

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


                    1. SpiderEkb
                      25.09.2023 06:42

                      Ну такие себе "источники" - росфинмониторинг...

                      Тут все надо - и история и возможность отката... Парсеры на регулярках будут работать безумно (по нашим понятиям) долго. Да и регулярки там забодаешься писать.

                      Как примеры:

                      ППТ

                      <PPT_CATALOG>
                        <FileDate>16.10.2017</FileDate>
                        <LastMessage>0</LastMessage>
                        <СписокРешений xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
                          <ВерсияФормата>1.0</ВерсияФормата>
                          <ДатаСписка>2017-10-16</ДатаСписка>
                          <СписокАктуальныхРешений>
                            <Решение>
                              <ТипРешения>
                                <Идентификатор>3</Идентификатор>
                                <Наименование>Решение МВК</Наименование>
                              </ТипРешения>
                              <НомерРешения>7-дсп</НомерРешения>
                              <ДатаРешения>2017-03-14</ДатаРешения>
                              <Орган>Межведомственная комиссия по противодействию финансированию терроризма</Орган>
                              <ВидРешения>
                                <Идентификатор>1</Идентификатор>
                                <Наименование>Решение на приостановление (заморозка)</Наименование>
                              </ВидРешения>
                              <СписокСубъектов>
                                <Субъект>
                                  <ИдСубъекта>8349984888</ИдСубъекта>
                                  <ТипСубъекта>
                                    <Идентификатор>2</Идентификатор>
                                    <Наименование>Физическое лицо</Наименование>
                                  </ТипСубъекта>
                                  <ФЛ>
                                    <ФИО>МОЛЧАНОВ МУРАД АНДРЕЕВИЧ</ФИО>
                                    <Фамилия>МОЛЧАНОВ</Фамилия>
                                    <Имя>МУРАД</Имя>
                                    <Отчество>АНДРЕЕВИЧ</Отчество>
                                    <ФИОЛат>MOLCHANOV MURAD ANDREEVICH</ФИОЛат>
                                    <ДатаРождения>1993-08-15</ДатаРождения>
                                    <ГодРождения>1993</ГодРождения>
                                    <МестоРождения>Г. АДЫГЕЙСК ТЕУЧЕЖСКОГО РАЙОНА РЕСПУБЛИКИ АДЫГЕЯ</МестоРождения>
                                    <ИНН>010701070387</ИНН>
                                    <СписокДокументов>
                                      <Документ>
                                        <ТипДокумента>
                                          <Идентификатор>1631726</Идентификатор>
                                          <Наименование>ПАСПОРТ РФ</Наименование>
                                        </ТипДокумента>
                                        <Серия>7907</Серия>
                                        <Номер>503236</Номер>
                                        <ОрганВыдачи>ВЫДАН ТП ОФМС ПО РЕСПУБЛИКЕ АДЫГЕЯ В ТЕУЧЕЖСКОМ РАЙОНЕ РЕСПУБЛИКИ АДЫГЕЯ</ОрганВыдачи>
                                        <ДатаВыдачи>2007-09-11</ДатаВыдачи>
                                      </Документ>
                                    </СписокДокументов>
                                  </ФЛ>
                                  <СписокАдресов>
                                    <Адрес>
                                      <ТипАдреса>
                                        <Идентификатор>6</Идентификатор>
                                        <Наименование>Гражданство</Наименование>
                                      </ТипАдреса>
                                      <ТекстАдреса>РОССИЙСКАЯ ФЕДЕРАЦИЯ</ТекстАдреса>
                                    </Адрес>
                                    <Адрес>
                                      <ТипАдреса>
                                        <Идентификатор>2</Идентификатор>
                                        <Наименование>Адрес места регистрации</Наименование>
                                      </ТипАдреса>
                                      <ТекстАдреса>РЕСП АДЫГЕЯ, Г АДЫГЕЙСК, УЛ ЛЕНИНА, Д 24, КВ 14</ТекстАдреса>
                                      <Страна>
                                        <Наименование>РОССИЙСКАЯ ФЕДЕРАЦИЯ</Наименование>
                                        <Код>643</Код>
                                      </Страна>
                                      <ОКАТО>79403000000</ОКАТО>
                                    </Адрес>
                                    <Адрес>
                                      <ТипАдреса>
                                        <Идентификатор>5</Идентификатор>
                                        <Наименование>Адрес местонахождения</Наименование>
                                      </ТипАдреса>
                                      <ТекстАдреса>РЕСП АДЫГЕЯ, Г АДЫГЕЙСК, УЛ ЛЕНИНА, Д 24, КВ 14</ТекстАдреса>
                                      <Страна>
                                        <Наименование>РОССИЙСКАЯ ФЕДЕРАЦИЯ</Наименование>
                                        <Код>643</Код>
                                      </Страна>
                                      <ОКАТО>79403000000</ОКАТО>
                                    </Адрес>
                                  </СписокАдресов>
                                  <РешениеПоСубъекту>Осуществить замораживание (блокирование) денежных средств и иного имущества, принадлежащих указанному лицу, гуманитарное пособие не назначать.</РешениеПоСубъекту>
                                </Субъект>
                              </СписокСубъектов>
                            </Решение>
                          </СписокАктуальныхРешений>
                        </СписокРешений>
                      </PPT_CATALOG>

                      Этот самый внятный из всех

                      ПЭ

                      <TERRORISTS_CATALOG>
                        <FileName>01.01.2020</FileName>
                        <NUM>362ПЭ</NUM>
                        <DATE>01.01.2020</DATE>
                        <ID>3758452944></ID>
                        <LastMessage>0</LastMessage>
                        <TERRORISTS>
                          <TERRORISTS_NAME>&lt;![CDATA[СУЛТАНОВ ЛЕЧИ РАСУЛОВИЧ* (Mounir el Moutassadeq;Pahlawan Shamsuddin)]]&gt;</TERRORISTS_NAME>
                          <ID_NEW>5639</ID_NEW>
                          <PERSON_TYPE>4</PERSON_TYPE>
                          <IS_TERRORIST>1</IS_TERRORIST>
                          <INN></INN>
                          <BIRTH_DATE>&lt;![CDATA[20.08.1981]]&gt;</BIRTH_DATE>
                          <DESCRIPTION>&lt;![CDATA[В РОЗЫСКЕ]]&gt;</DESCRIPTION>
                          <ADDRESS>&lt;![CDATA[IN PRISON IN GERMANY; IN PRISON IN GERMANY]]&gt;</ADDRESS>
                          <TERRORISTS_RESOLUTION>&lt;![CDATA[]]&gt;</TERRORISTS_RESOLUTION>
                          <BIRTH_PLACE>&lt;![CDATA[СТ. ОРДЖОНИКИДЗЕВСКАЯ СУНЖЕНСКОГО РАЙОНА ЧИАССР]]&gt;</BIRTH_PLACE>
                          <PASSPORT>&lt;![CDATA[ПАСПОРТ РФ: 8303 596899 ВЫДАН БАКСАН РОВД 27.01.2004,ПАСПОРТ РФ: 8309 964133  03.08.2009,ПАСПОРТ РФ: 8314 255832 ВЫДАН ОТДЕЛОМ УФМС РОССИИ ПО КАБАРДИНО-БАЛКАРСКОЙ РЕСПУБЛИКЕ В БАКСАНСКОМ РАЙОНЕ 06.03.2015,]]&gt;</PASSPORT>
                        </TERRORISTS>
                      </TERRORISTS_CATALOG>

                      Тут нет отдельно серии-номера паспорта - парсим регуляркой.

                      ОМУ

                      <OMU_CATALOG>
                        <FileDate>07.11.2018</FileDate>
                        <LastMessage>0</LastMessage>
                        <СписокОМУ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
                          <ВерсияФормата>1.0</ВерсияФормата>
                          <ДатаСписка>2018-11-07</ДатаСписка>
                          <ДатаПредыдущегоСписка>2018-09-07</ДатаПредыдущегоСписка>
                          <АктуальныйСписок>
                            <Субъект>
                              <ИдСубъекта>3569309339</ИдСубъекта>
                              <УНС>IRi.003</УНС>
                              <ТипСубъекта>
                                <Идентификатор>2</Идентификатор>
                                <Наименование>Физическое лицо</Наименование>
                              </ТипСубъекта>
                              <История>
                                <ДатаВключения>2012-04-18</ДатаВключения>
                              </История>
                              <ФЛ>
                                <ФИО>AGHAJANI AZIM</ФИО>
                                <Фамилия>AGHAJANI AZIM</Фамилия>
                                <ФИОЛат>AGHAJANI AZIM</ФИОЛат>
                                <СписокДокументов>
                                  <Документ>
                                    <ТипДокумента>
                                      <Идентификатор>746140005</Идентификатор>
                                      <Наименование>PASSPORT</Наименование>
                                    </ТипДокумента>
                                    <Номер>6620505</Номер>
                                    <ОрганВыдачи>Iran (Islamic Republic of)</ОрганВыдачи>
                                  </Документ>
                                  <Документ>
                                    <ТипДокумента>
                                      <Идентификатор>746140005</Идентификатор>
                                      <Наименование>PASSPORT</Наименование>
                                    </ТипДокумента>
                                    <Номер>9003213</Номер>
                                    <ОрганВыдачи>Iran (Islamic Republic of)</ОрганВыдачи>
                                  </Документ>
                                </СписокДокументов>
                                <СписокДрНаименований>
                                  <ДрНаименование>
                                    <ФИО>Azim Adhajani; Azim Agha-Jani</ФИО>
                                  </ДрНаименование>
                                </СписокДрНаименований>
                                <СписокГражданств>
                                  <Гражданство>Iran (Islamic Republic of)</Гражданство>
                                </СписокГражданств>
                              </ФЛ>
                              <Примечание>Facilitated a breach of paragraph 5 of resolution 1747 (2007) prohibiting the export of arms and related materiel from Iran. [Old Reference #I.AC.50.18.04.12.(1)]</Примечание>
                            </Субъект>
                          </АктуальныйСписок>
                        </СписокОМУ>
                      </OMU_CATALOG>

                      Тут несколько имен в одном теге -

                                <СписокДрНаименований>
                                  <ДрНаименование>
                                    <ФИО>Azim Adhajani; Azim Agha-Jani</ФИО>
                                  </ДрНаименование>
                                </СписокДрНаименований>
                      

                      Их приходится раскручивать в список из строки. Ладно у нас язык позволяет:

                      for-each name in %split(string: ';');

                      ООН

                      <UNL_CATALOG>
                        <FileDate>2023-05-28</FileDate>
                        <LastMessage>0</LastMessage>
                        <INDIVIDUAL>
                          <DATAID>2762998</DATAID>
                          <VERSIONNUM>1</VERSIONNUM>
                          <FIRST_NAME>NAJMUDDIN</FIRST_NAME>
                          <SECOND_NAME>FARAJ</SECOND_NAME>
                          <THIRD_NAME>AHMAD</THIRD_NAME>
                          <UN_LIST_TYPE>Al-Qaida</UN_LIST_TYPE>
                          <REFERENCE_NUMBER>QDi.226</REFERENCE_NUMBER>
                          <LISTED_ON>2006-12-07</LISTED_ON>
                          <COMMENTS1>Mother`s name: Masouma Abd al-Rahman. Photo available for inclusion in the
                            INTERPOL-UN Security Council Special Notice. Review pursuant to Security Council resolution
                            1822 (2008) was concluded on 20 May 2010.Review pursuant to Security Council resolution 2368
                            (2017) was concluded on 24 November 2020. INTERPOL-UN Security Council Special Notice web
                            link: https://www.interpol.int/en/How-we-work/Notices/View-UN-Notices-Individuals</COMMENTS1>
                          <NATIONALITY>
                            <VALUE>Iraq</VALUE>
                          </NATIONALITY>
                          <LIST_TYPE>
                            <VALUE>UN List</VALUE>
                          </LIST_TYPE>
                          <LAST_DAY_UPDATED>
                            <VALUE>2015-12-10</VALUE>
                            <VALUE>2020-11-24</VALUE>
                          </LAST_DAY_UPDATED>
                          <INDIVIDUAL_ALIAS>
                            <QUALITY>Good</QUALITY>
                            <ALIAS_NAME>Mullah Krekar</ALIAS_NAME>
                          </INDIVIDUAL_ALIAS>
                          <INDIVIDUAL_ALIAS>
                            <QUALITY>Good</QUALITY>
                            <ALIAS_NAME>Fateh Najm Eddine Farraj</ALIAS_NAME>
                          </INDIVIDUAL_ALIAS>
                          <INDIVIDUAL_ALIAS>
                            <QUALITY>Good</QUALITY>
                            <ALIAS_NAME>Faraj Ahmad Najmuddin</ALIAS_NAME>
                          </INDIVIDUAL_ALIAS>
                          <INDIVIDUAL_ALIAS>
                            <QUALITY />
                            <ALIAS_NAME />
                          </INDIVIDUAL_ALIAS>
                          <INDIVIDUAL_ALIAS>
                            <QUALITY />
                            <ALIAS_NAME>НАДЖМУДДИН ФАРАДЖ АХМАД</ALIAS_NAME>
                          </INDIVIDUAL_ALIAS>
                          <INDIVIDUAL_ADDRESS>
                            <STREET>Heimdalsgate 36-V</STREET>
                            <CITY>Oslo</CITY>
                            <ZIP_CODE>0578</ZIP_CODE>
                            <COUNTRY>Norway</COUNTRY>
                          </INDIVIDUAL_ADDRESS>
                          <INDIVIDUAL_DATE_OF_BIRTH>
                            <TYPE_OF_DATE>EXACT</TYPE_OF_DATE>
                            <DATE>1956-07-07</DATE>
                          </INDIVIDUAL_DATE_OF_BIRTH>
                          <INDIVIDUAL_DATE_OF_BIRTH>
                            <TYPE_OF_DATE>EXACT</TYPE_OF_DATE>
                            <DATE>1963-06-17</DATE>
                          </INDIVIDUAL_DATE_OF_BIRTH>
                          <INDIVIDUAL_PLACE_OF_BIRTH>
                            <CITY>Olaqloo Sharbajer</CITY>
                            <STATE_PROVINCE>Al-Sulaymaniyah Governorate</STATE_PROVINCE>
                            <COUNTRY>Iraq</COUNTRY>
                          </INDIVIDUAL_PLACE_OF_BIRTH>
                          <INDIVIDUAL_DOCUMENT>
                            <TYPE_OF_DOCUMENT>National Identification Number</TYPE_OF_DOCUMENT>
                            <TYPE_OF_DOCUMENT2>Ration card no.</TYPE_OF_DOCUMENT2>
                            <NUMBER>0075258</NUMBER>
                          </INDIVIDUAL_DOCUMENT>
                          <SORT_KEY />
                          <SORT_KEY_LAST_MOD />
                        </INDIVIDUAL>
                      </UNL_CATALOG>

                      Тут просто жесть - все вперемешку, приходится в два этапа разбирать - сначала все по спискам (имена, ДР, ДУЛы...), потом уже формировать "основная запись" + список "других записей" чтобы не писать для него отдельный раскладчик по БД.

                      Для решений суда под рукой нет, но там тоже что-то свое...

                      Для парсинга есть xml-sax - очень быстрый (быстрее чем DOM т.к. потоковый), хотя и работать с ним муторно.


                      1. Txanxs Автор
                        25.09.2023 06:42

                        Жесть, согласен. :)

                         Парсеры на регулярках будут работать безумно (по нашим понятиям) долго.

                        Это если все целиком засасывать. А если сначала добраться до полей простым парсингом хорошо структурированного XML, а потом, на основе предварительно собранной (у вас же богатая ретроспектива?) статистики значений именно этого поля, причем, возможно даже в разных списках/источниках продумать регулярки и нормализаторы (ну, банально, мусор, пробелы убрать, регистр подправить,...), то выцеплять данные быстро должно. А если еще словари какие-то прицепить, ну, типа эээ... "радужных таблиц" для быстрого сопоставления данных чему-то уже ранее нормализованному, то должно быстро работать.

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

                        У меня на сотнях неструктурированных таблиц до полумиллиарда записей - нормально работает. :)))


                      1. SpiderEkb
                        25.09.2023 06:42
                        +1

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

                        Я описал ниже как работает XML-SAX у нас.

                        Подробнее можно тут:
                        RPGLE XML Parser - XML-SAX and XML-INTO sample code Part 1

                        RPGLE XML Parser - XML-SAX and XML-INTO sample code Part 2

                        XML-INTO штука мощная, но там куча ограничений. Хотя на простых по структуре XML работает. На сложных мне не удалось ее завести.

                        А SAX универсален, хотя и требует больше кода. Но, как написал уже - там все равно какой именно список пришел. Хендлер может быть один на все :-)

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

                        Там непонятно куда и зачем все это... Есть нормализаторы - для строки, для ДУЛ, для ИНН.

                        Нормализатор строки, например, удаляет лишние пробелы, приводит все к верхнему регистру, заменяет Ё на Е (бизнес так захотел - их право), удаляет "плохие" символы (по списку из настроек). Все это работает быстро, за один проход строки.

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

                        str = %concatarr(%split(str));

                        Для замены Ё на Е

                        str = %xlat('Ёё': 'Ее': str);

                        для регистра - %upper / %lower

                        для удаления символов - %scanrpl,

                        но елозить несколько раз по одной строке когда все можно сделать за один проход как-то неправославно :-)

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

                        Большие объемы данных (та же сверка) у нас распараллеливается на несколько заданий.

                        У нас удобнее работать именно с заданиями - job, а не с потоками внутри одного задания - это и сопровождению проще и безопаснее т.к. задания изолированы друг от друга и в случае падения одного (ошибка) остальные не затрагиваются совсем. Да и мониторить состояние задания проще чем поток - на то есть системные апишки для контроля за статусом (активно, завершило работу, выпало в ошибку и т.п.).

                        Есть головное задание - оно запускает нужное количество заданий-обработчиков, затем делает выборку данных для обработки и выкладывает их пачками на "конвейер". Обработчики подхватывают пачки с конвейера и обрабатывают их (каждый свою пачку). В качестве конвейера можно использовать, например, очередь (есть на нашей платформе такие системные объекты - Data Queue, User Queue) - как раз под это дело. Головное задание кладет в очередь данные, обработчики разбирают их оттуда.


                      1. Txanxs Автор
                        25.09.2023 06:42

                        Весьма грамотный подход, надо бы мне тоже в своей системе попробовать распараллеливание.


              1. Batalmv
                25.09.2023 06:42

                Ну смотри, Дробим на лету

                Часть первая:

                У тебя есть 5 источников данных, значит уже 5 ОТДЕЛЬНЫХ лоадеров, каждый из которых парсит свой входной формат и заливает в общий staging area c единой структурой. 5 компонент уже есть :) Пилить можно абсолютно независимо, как только определена структура stage area.

                Слой историчных данных, переливает из stage к себе, решая вопросы откатов, перезаливок и т.д.

                Слой "сведения" в единую модель с бизнес правилами определяющими как быть с данными одного субъекта из разных источников. Переливает из "историчекого" слоя в свой

                По итогу имеет готовую "каноническую" модель з "вычищенными" данными для использования в логике транзакций. Я насчитали минимум 8 компонент, которые минимально зависят другоот друга и могут пилиться независимо, или почти независимо. Более того, при адекватной архитектуре и выбранном стеке все это будет легковестное, масштабируемое и вообще - приятное глазу :)

                Вторая часть: по сути надстройка над "канонической" моделью. Ты ее и сам порезал. Представь себе задачу в виде набора зависимых или независимых data area c перекладкой/трансформацией и т.д. Понятно, что физически это может быть как физические таблицы, так и view/materialized view. Но тут надо детали смотреть

                Третья часть: независимые микросервисы проверок, которые при необходимости можно оркестровать в некотором Decision making module, c настраиваемой логикой. Тут может даже low-code зайти, таких решений валом, в отм числе open source

                Итого, ну честно. Ничего монолитного в фин. моне нет :) С одной стороны - заливка данных их источников, которая разбивается просто в силу слоей приороды на этапы. Главное не стесняться это делать, так как место на дисках - самый дешевый ресурс как капекс, так и опекс.

                Сервисы же проверки легко встраиваются в поток транзакций, так как там идеологически сразу закладывается такая опция, если проектировщик знаком с доменом

                --------------

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


                1. SpiderEkb
                  25.09.2023 06:42

                  Не так просто.

                  У тебя есть 5 источников данных, значит уже 5 ОТДЕЛЬНЫХ лоадеров

                  Источник данных один - очередь. И лоадер (который получает данные из очереди) тоже один.

                  Дальше 5 парсеров. А дальше один раскладчик по БД. Потому алгоритм раскладки одинаковый для всех типов списков и хранится все это в одной БД единообразно.

                  Т.е. задача парсеров - привести все к одному знаменателю - некоемоу единому набору структур, которые потом будут раскиданы по БД.

                  Слой историчных данных, переливает из stage к себе

                  И получаем отлуп с нагрузочного тестирования - слишком много ресурсов потребляет. Почти наверняка.

                  независимые микросервисы проверок, которые при необходимости можно оркестровать в некотором Decision making module, c настраиваемой логикой.

                  Угу. Именно от этого ушли и получили 10-кратный прирост производительности при сокращении ресурсопотребления

                  Надеюсь, есть понимание того, что все это работает не на отдельно выделенной машине, а в некоем временном окне и в условиях жесткого ограничения ресурсов, в первую очередь CPU? Потому что это всего лишь одна небольшая задачка из тысяч (если не десятков тысяч) одновременно работающих на сервере. И плотность вызовов тех же проверок крайне высока. И что там выморщить даже +5% к производительности - это уже очень хороший результат. Любой ценой.

                  Так что все что делается, делается прежде всего из соображений скорости работы и эффективности потребления ресурсов. А не "концептуальности" и "красивости" кода.


                  1. Batalmv
                    25.09.2023 06:42

                    Источник данных один — очередь. И лоадер (который получает данные из очереди) тоже один.

                    Дальше 5 парсеров. А дальше один раскладчик по БД. Потому алгоритм раскладки одинаковый для всех типов списков и хранится все это в одной БД единообразно.

                    Ну видиш, 6-7 независимых компонент :)

                    И получаем отлуп с нагрузочного тестирования - слишком много ресурсов потребляет. Почти наверняка.

                    Не, деление на стейджи обычно не приводит к значительному увеличению, но позволяет сэкономить на времени разработки. Условно, если одна "единица" стоит 5 штук в месяц, но часто это выгоднее. Да и с чего дольше?

                    Ты просто декомпозировал работу на несколько элементов, повысив в разы прозрачность кода и его сопровождаемость. Это схоже на "микросервисы" vs "монолит", только для data pipeline. Накладные расходы на микросервисный подход обычно компенсируются с лихвой более эффективной разработкой.

                    Да и оптимизировать по частям проще.

                    Угу. Именно от этого ушли и получили 10-кратный прирост производительности при сокращении ресурсопотребления

                    Обычно выигрыш в 10 раз получается по другой причине. Нашли эпичный косяк и пофиксили. У меня на последнем проекте тоже кстати стейджинги сначала работали долго. Правильный подход к data engineer ("молоко" или "мясо"), вкупе с конструктивными идеями дал свои плоды. Кстати выигрыш тоже получился на порядок :)

                    Надеюсь, есть понимание того, что все это работает не на отдельно выделенной машине, а в некоем временном окне и в условиях жесткого ограничения ресурсов, в первую очередь CPU? 

                    Не, так не работает. Точнее работает, до первого сбоя. Ну подумай сам. Условно есть задача и к ней требования по RTO около 0. Даже без внесения в условия Disaster Recovery - это минимум наличие двух нод, при этом каждая из нод, в случае сбоя доложна тянуть всю нагрузку. Либо ваша задача - сто двадцать пятое колесо в телеге и вам выдали по минимуму, что маловероятно.

                    Короче не верю :) Тем более, если это на IBM железе, нет никакой проблемы нарезать задачам отдельные пулы :)

                    В любом случае, оптимизация декомпозированной задачи выполняется быстрее. Тем более .. ну камон. У тебя задача загрузки, которую явно можно гонять в не бизнес время. Новые данные явно не поток от IoT, а скорее всего раз в день или около того. Найти окно вне бизнес времени изи. Остается "вылизать" в идеал только ту часть, где критичнен response time. И тут как раз максимально подготовленное представление данных заходит на ура, вплоть до использования альтернативной технологии.

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

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


                    1. SpiderEkb
                      25.09.2023 06:42

                      Ну видиш, 6-7 независимых компонент :)

                      Давайте еще раз.

                      Есть очередь - MQ

                      На ней висит движок HMQ который мониторит очередь и выдергивает оттуда сообщения. Тип сообщения определяется по информации из заголовка. Дальше по типу сообщения в таблице настроек ищется обработчик который запускается с передачей ему тела сообщения.

                      Теоретически. HMQ может запускать несколько экземпляров одного обработчика в разных заданиях. Например, пришло 10 сообщений одного типа - запустилось 10 задний с одним обработчиком и все 10 сообщений обработались параллельно (если логика такое позволяет). Это все через настройки регулируется.

                      Мы пишем только сам обработчик и прописываем его в настройках HMQ.

                      В обработчике в данном конкретном случае две основные части - вытащить из XML нужные данные, сформировать их в виде структуры и разложить по БД. Т.е.

                      • формирование структуры

                      • раскладка ее по БД

                      Структура одинаковая вне зависимости от типа списка - набор данных там всегда одинаковый (плюс-минус). Т.е. процедура раскладки одна на любой список.

                      разбор XML делается встроенным средством языка - XML-SAX

                              // Разбор сообщения
                              xml-sax(e) %handler(XMLHandler : dsCommArea) %xml(uMsgBody : 'ccsid=ucs2');

                      где XMLHandler - callback процедура обработки событий XML, dsCommArea - блок данных, передаваемый в эту процедуру (там как раз и лежит заполняемая данными структура).

                            DCL-PROC XMLHandler export;
                              DCL-PI *N int(10);
                                  CommArea      likeds(t_CommArea);
                                  event         int(10) value;
                                  string        pointer value;
                                  stringLen     int(20) value;
                                  exceptionId   int(10) value;
                              END-PI ;

                      Разборщик работает по принципу конечного автомата - вызывает XMLHandler с кодом события и строкой контекста этого события. Т.е. это потоковый обработчик, он не строит в памяти никаких деревьев, не требует их обхода... Он тупо идет по XML и дергает обработчик событий, передавая ему контекст. Быстро и с минимальными затратами.

                      Например, для

                      <FileDate>2023-05-28</FileDate>

                      будет три вызова XMLHandler:

                      1. event = *XML_START_ELEMENT, strring = 'FileDate'

                      2. event = *XML_CHARS, strring = '2023-05-28'

                      3. event = *XML_END_ELEMENT, strring = 'FileDate'

                      Поскольку выходная структура всегда одинаковая (t_CommArea), нет никакой необходимости плодить лишние сущности - достаточно описать один обработчик на все списки.

                      Действительно, мы знаем что есть пришел тег <UNL_CATALOG> - это список ООН. Если <TERRORISTS_CATALOG> - список ПЭ, <PPT_CATALOG> - ППТ, <OMU_CATALOG> - ОМУ.

                      Идентификатор субъекта приходит в тегах

                      <ИдСубъекта> для списков ОМУ и ППТ или

                      <ID_NEW> для списка ПЭ или

                      <DATAID> для списка ООН

                      Аналогично для всех остальных интересующих полей.

                      Фактически, меня даже не интересует что там "вообще". Интересует только в каких тегах лежит нужная информация - из какого тега в какое поле структуры ее перенести.

                      Не, деление на стейджи обычно не приводит к значительному увеличению, но позволяет сэкономить на времени разработки. Условно, если одна "единица" стоит 5 штук в месяц, но часто это выгоднее. Да и с чего дольше?

                      На чем тут экономия времени разработки? В данном случае один обработчик на все - это тупо "меньше букв".

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

                      Вообще, у нас есть замечательный инструмент PEX - Performance EXplorer. Прогоняешь через него задачу, получаешь статистики и все сразу видно - где вызовы лишние, где лишние обращения к БД, какая процедура сколько процессорного времени отъедает и т.п. И все критичные поставки в рамках НТ прогоняются через PEX.

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

                      Не, так не работает. Точнее работает, до первого сбоя. 

                      Удивительно, но это работает. Без сбоев.

                      Тем более, если это на IBM железе, нет никакой проблемы нарезать задачам отдельные пулы

                      Это напоминает притчу про портного заказчика и шапки:

                      Можно из этого куска материи шапку сшить?
                      Можно
                      А две можно?
                      Можно и две...
                      А три?
                      Да хоть десять...
                      Давай десять!

                      И получил заказчик 10 шапок. Только маленьких. Таких, что разве что на палец лезут.

                      Так и тут - нарезать можно 100500 пулов. Но сервер-то один... И все они будут на одном физическом процессоре работать... И с одной физической памятью.

                      У тебя задача загрузки, которую явно можно гонять в не бизнес время.

                      Банк работает 24/7. Какое время там не бизнес? У нас АБС "реального времени" - это значит что даже во время процесса EOD (закрытие опердня и перехода на следующий день), все банковские процессы продолжают работать (платежи обрабатываются и т.п.) в т.н. "юните ночного ввода" (который потом "вкатывается" в новый день). Тут нет такого время, когда машина пустая и ничего не делает. А списки должны загружаться сразу как только пришли т.к. эта информация сразу используется в комплаенс-процессах - лишние лаги тут недопустимы.

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

                      Это все хорошо для процессов, которые не являются mission critical. Т.е. "хочу сейчас делаю, не хочу потом как-нибудь". У нас таких процессов не так много (ну по крайней мере на уронвне центральных серверов). Разве что отчетность какая...

                      И не надо думать, что АБС банка это монолит. Это очень сильно не монолит. Но это и не набор бессмысленных (по отдельности) микросервисов, каждый из которых выполняет маленький, логический не законченный кусочек задачи и в отдельности ничего цельного не делает (зато активно распаковывет и запаковывает джейсоны с тем, чтобы отдать их другому микросервису, который опять распакует и опять запакует).

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

                      Обычно выигрыш в 10 раз получается по другой причине. Нашли эпичный косяк и пофиксили.

                      "Эпичный косяк" был как раз в неоправденном дроблении. Некий "художник концептуалист" в свое время разделил проверку на три части - ФИО + ДР, ДУЛ и ИНН. Но беда в том, что в каждой из частей есть некоторая "базовая процедура", которая сама по себе дает только промежуточный результат, для бизнеса абсолютно бессмысленный и бесполезный, но является достаточно тяжелой.

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

                      Объединение трех проверок в одну (тем более, что основной сценарий вызова как раз с полным блоком данных - ФИО + ДР + ДУЛ + ИНН) с однократным вызовом тяжелой функции и дал такой вот результат. Плюс сахар в виде кеширования - если вызываем 5 раз с одними значениями ФИО, ДР, ИНН но разными значениями ДУЛ (что тоже входит в список распестренных сценариев), вызов базовой функции и проверок ФИО + ДР и ИНН будет проводиться только в первый раз, все остальные разы будет проводиться только проверка очередного ДУЛ с использование закешированных ранее результатов (в т.ч. и базовой функции).

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