Работа с данными. FOR-архитектура, часть 1

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

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

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

Я хочу подготовить небольшой цикл публикаций про работу с данными:

  1. Общий обзор FOR-архитектуры (эта статья)

  2. Взгляд на валидацию данных и частные применения

  3. Разбор FOR со стороны поставщика данных (ключевая часть, нужная для понимания всей картины)

  4. Гомогенность данных в больших распределенных системах (идея, выросшая из валидации и использующая те же механизмы)

Начнем с определения кому надо

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

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

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

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

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

Моё видение реализации

Data Provider имеет 2 механизма работы:

  1. DataProvider::search($filters, $options, $response) статичный метод на входе, который покрывает 80% задач. Если всё в вашей системе представлено в виде элементов - то данный метод даст высший уровень гибкости вашему API, потому что позволит находить что угодно в рамках свои полномочий.

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

Примеры:

  • CompanyProvider::get_by_id()

  • JobProvider::get_actual()

Конкретика

Архитектура состоит из 2 частей: пользователь и поставщик.

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

(код размещен в папке: DataProvider ElementSearch, эта часть будет подробно разобрана в другой статье) https://gitlab.com/dev_docs/software_architecture/for-architecture/-/blob/main/code_examples/DataProvider%20ElementSearch%20%5Bprototype%5D/BaseFilters.php

  • Работа со всеми данными - выноситься в отдельный слой

  • Вся работа сводится к единообразному подходу

  • Всё в системе приводится к "элементам"

  • Всё есть element и его свойства

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

  • Filters - определяет условия поиска (что и где ищем)

  • Options - определяет область поиска (все что не filter и не response)

  • Response - определяет модификацию / формат ответа (как обработаем ответ)

Примеры запроса будут размещены тут: https://gitlab.com/dev_docs/software_architecture/for-architecture/-/tree/main/code_examples/DataProvider%20ElementSearch%20%5Bprototype%5D/Examples

Реализация внутри системы (back / php)

(код размещен в папке: DataProvider ElementSearch, эта часть будет подробно разобрана в другой статье) https://gitlab.com/dev_docs/software_architecture/for-architecture/-/tree/main/code_examples/DataProvider%20ElementSearch%20%5Bprototype%5D

Фильтр - массив условий, фильтр состоит из:

  • object - объект поиска, состоит из:

    • element_type_id (element_type) - сама сущность (user, sku, company, news, properties ...)

    • element_id - подсущность. к примеру, id свойства или поле, к примеру: user_name или если props, то 69

  • operator_id (operator) - оператор поиска (у меня они все зарегистрированы и есть в виде констант, это лучше, чем их строковое представление) https://gitlab.com/dev_docs/software_architecture/for-architecture/-/blob/main/code_examples/DataProvider%20ElementSearch%20%5Bprototype%5D/Operators.php

  • value - значение поиска (может быть любой тип, все зависит от контекста)

Примеры фильтров:

DataProvider.search(
  {
    filters : 
    [
      {
          object :
          {
              element_type_id : _CONSTANTS.ELEMENT_TYPES.SOME_ELEMENT_TYPE_ID,
              element_id      : 'some_id'
          },
          operator_id : _CONSTANTS.OPERATORS.EQUAL,
          value       : options.element_id
      }
    ]
  }
)
PaymentProvider.search(
{
    filters  :
    [
        {
            object      :
            {
                element_type_id : _CONSTANTS.ELEMENT_TYPES.PAYMENT,
                element_id      : 'payment_id'
            },
            operator_id : _CONSTANTS.OPERATORS.EQUAL,
            value       : this.element_id
        }
    ],
    response :
    {
        structure_mode : 'listing'
    }
})

И немного посложнее

{
  filters :
  [
      {
          object :
          {
              element_type_id   : _CONSTANTS.ELEMENT_TYPES.CATEGORY,
              element_id        : null
          },
          operator_id    : _CONSTANTS.OPERATORS.EQUAL,
          value          : 27
      },
      {
          object :
          {
              element_type_id   : _CONSTANTS.ELEMENT_TYPES.ITEM_STATUS,
              element_id        : null
          },
          operator_id   : _CONSTANTS.OPERATORS.IN,
          value         : [103, 101]
      }
  ],
  response :
  {
      structure_mode : 'listing',
      add :
      {
          relations :
          [
              {
                  relation_id        : 160,    // связь - подчинённые
                  relation_field    : 'master',
                  data_fields        : 'IDS'
              },
              {
                  relation_id        : 125, // связь с должностью
                  relation_field    : 'slave',
                  data_fields        :
                  {
                      general : ['item_full_name']
                  }
              },
              {
                  relation_id        : 163,    // связь с физическим лицом
                  relation_field    : 'slave',
                  data_fields        :
                  {
                      property :
                      [
                          18, // фамилия
                          389 // инициалы
                      ]
                  }
              }
          ]
      }
  }
}

Именно это часть из архитектуры идёт в модель, а затем в БД (если речь про бек) или на апи (если речь про фронт).

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

Response - определяет тот формат (модель, дата-класс, ...) который вы хотите получить или, к примеру, вы хотите получить только ids элементов.

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

Немного рефлексии, для цельности картины:

Основные тезисы, которых точно стоит придерживаться в работе с данными

  1. Абстракции - наше всё

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

  3. Простота - во всём, простой код - легче понять и развить (исправить)

  4. Бизнес логика и отдельные модули - не должны зависеть от поставщика решений (низкая связанность)

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

Источник: https://habr.com/ru/post/587014/


Интересные статьи

Интересные статьи

Вы узнаете, как создавался PowerPoint, какие возможности были в ранних версиях программы и почему сервис Keynote стал ее первым серьезным конкурентом. Мы уже рассказали вам о пер...
В этом посте я хочу рассказать о системе балансировки нагрузки VMware NSX Advanced Load Balancer (by Avi Networks), или NSX ALB. Чуть больше года назад компания VMware купила компанию Avi...
Первую часть статьи ищите тут. Во второй части рассказываю о том, какие я использую инструменты при взаимодействии со спикерами. Читать дальше →
Делиться с сообществом полезной информацией всегда приятно. Мы попросили наших сотрудников посоветовать ресурсы, которые они сами посещают, чтобы быть в курсе событий в мире ИБ. Подборка получи...
Я решил немного отойти от исторических экскурсов и высказаться по другому животрепещущему вопросу. Тем более что наши лунные проекты потихоньку переходят в стадию реализации, так что вопрос д...