«Каждый программист должен создать свой архитектурный паттерн»
Народная мудрость.

Постановка проблемы

На сегодняшний день наиболее известны такие архитектурные паттерны как MVC, MVVM, MVP, Viper, Clean Code.

Все они в той или иной мере работают с тремя основными сущностями - Модель, Вью, Контроллер, добавляя время от времени некоторые дополнительные, например, Presenter.

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

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

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

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

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

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

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

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

При этом, задача понимается как бизнес-процесс.

Что такое бизнес-процесс

Термин “бизнес-процесс” пришёл из концепции реинжиниринга бизнес процессов. Наиболее известная и основополагающая книга по этой теме - Michael Hammer, James Champy. "Reengineering the Corporation: A Manifesto for Business Revolution".

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

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

Существует несколько, достаточно разных, определений бизнес-процесса.

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

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

Бизнес-процесс всегда решает определённую задачу, у него есть цель и результат.

Бизнес-процессы могут взаимодействовать между собой.

Результат одного бизнес-процесса может быть использован другими бизнес-процессами.

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

Выделение бизнес-процесса, различение родительских и дочерних, определяется разработчиками проекта.

Пример бизнес-процессов

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

Таким образом, мы имеем бизнес-процесс “Показать элементы”.

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

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

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

Уровни бизнес-процессов

Полезно различать бизнес-процессы по трём уровням:

1-й уровень: Пользовательский

Это задачи, которые задаёт пользователь.

Например, посчитать количество калорий за день.

2-й уровень. Пользовательско-технический

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

Например: показать на экране список приёмов пищи, а также количество калорий для каждого из них. И отобразить общее количество калорий за день.

3-й уровень. Технический

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

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

Различение этих уровней помогает выделить те или иные бизнес-процессы по ходу разработки программы.

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

Обозначение (называние) бизнес-процессов

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

Идеальный вариант, когда в названии бизнес-процесса используются 2 слова: действие и объект, на который оно направлено. Например, Display Foods.

Но в ряде случаев может использоваться и большее количество слов. Например, Display Editing Meal.

Названия файлов

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

Один файл - одна задача

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

Для этого активно используются расширения.

При этом, файлы с расширениями группируются не по принадлежности к определённым объектам, таким как классы, структуры и т.д., а по принадлежности к определённым бизнес-процессам.

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

Многозадачные файлы

В силу особенностей языка Swift и Xcode соблюдение данного правила - один файл одна задача - не всегда возможно.

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

В этом случае, папка, которая включает в себя файл с объявленным классом, использует слово manage, которое означает, что в данном файле выполняются несколько действий, относящихся к разным задачам и/или бизнес-процессам.

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

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

Пример реализации подхода Бизнес-процесс нотация

Рассмотрим образец реализации Бизнес-процесс нотации на примере приложения, которое отслеживает количество калорий.

Бизнес-процессы верхнего уровня

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

Этот бизнес-процесс включает в себя бизнес-процессы второго уровня, которые показаны на Рис. 1

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

И это обозначение включает в себя как правило действие и объект, которым это действие управляет.

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

Базовые бизнес-процессы приложения

Наибольшую смысловую нагрузку в обработке контента данного приложения несут на себе бизнес-процессы Manage Foods и Manage Meals.

Рассмотрим внутреннюю архитектуру первого из них.

Бизнес-процесс Manage Foods: Папки и дочерние бизнес-процессы

Как видим, бизнес-процесс Manage Foods включает в себя 6 дочерних бизнес-процессов.

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

  • Model Food - моделировать продукт, создать модель объекта Food.

  • Test Foods - тестировать продукты, т.е., в данном случае создать демо-данные для проверки. Разработчик решил их использовать для тестирования, а также оставить их как подсказку пользователям на первых этапах освоения приложения.

  • Load Foods - загрузить данные о продуктах в приложение.

  • Storage Foods - сохранить данные о продуктах в оперативной памяти приложения.

  • Show Foods in the Table - показать данные о продуктах на экране.

  • Edit Foods - редактировать данные о продуктах.

Бизнес-процесс Manage Foods: Файлы и объекты

Опустимся теперь на уровень ниже и посмотрим как оформляются файлы бизнес-процессов. Рассмотрим это на примере дочерних бизнес-процессов родительского бизнес-процесса Manage Foods.

1. Model Food

Первая папка Model Food обозначает код, который решает задачу создать модель объекта Food. И эта папка содержит один файл, который называется Food_Class_Global.swift.

Где:

  • Food — это название объекта.

  • Class — это тип объекта.

  • Global — это локация объекта. В данном случае Global означает, что этот объект находится в глобальной зоне видимости.

2. Test Foods

Следующая папка - Test Foods - включает в себя код, который решает задачу проверки пригодности формата данных о продуктах для использования их в программе. Эта папка также содержит один файл с именем demoFoods_Variable_Global.swift.

При этом demoFoods - это название объекта, Variable - это тип объекта и Global это локация объекта в глобальной зоне видимости. Т.е., по сути, это Stub data.

3. Load Foods

Следующая папка — Load Foods — обозначает бизнес‑процесс загрузки данных в оперативную память приложения. Она включает в себя 2 файла:

loadRealOrDemoFoodsData_Method_ExtFoods.swift

Этот файл содержит в себе метод loadRealOrDemoFoodsData и является расширением класса Foods.

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

Данный файл как раз реализует это правило.

Заодно рассмотрим и его внутреннюю структуру.

В верхней части файла обозначается задача, которую решает код в этом файле. Второй строкой комментария добавляются детали данной реализации. После чего идёт тело расширения и сам метод.

Таким образом, структура файла проста и понятна. Обозначена задача и код решает эту задачу.

Как известно, именно к такой, простой и понятной структуре файла следует стремиться.

viewDidLoad_Method_ExtFoods.swift

Второй файл в этой папке также является расширением класса Foods и содержит в себе, как видно из названия файла , стандартный метод viewDidLoad.

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

4. Storage Foods: Бизнес-процессы разработки и бизнес-процессы выполнения программы

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

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

Именно этот момент и иллюстрирует Рис. 4, где папка Load Foods и соответствующий ей бизнес-процесс, предшествует папке Storage Foods. И файл с объявленным классом Foods появляется в навигационном дереве уже после используемых своих же расширений.

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

Это второй случай файла с многозадачностью. Т.е., файл с классом Foods используется в первую очередь для хранения данных в оперативной памяти. В нем размещаются все свойства класса.

5. Show Foods in the Table

Следующий бизнес-процесс - показ данных на экране, в данном случае в таблице: Show Foods in the Table. Он содержит один файл, названный TableDataSource_Methods_ExtFoods.

Как видим, в названии этого файла используется слово не Method, а Methods, что означает, что в этот файл включены несколько методов.

Но в отличие от предыдущего файла с классом Foods, внутри которого может находиться несколько блоков кода для решения разных задач, внутри этого файла находится несколько методов, которые решают одну и ту же задачу - передача данных из оперативной памяти в таблицу, т.е., в видимую для пользователя часть приложения. Это типовые методы numberOfSections(in:), tableView(:numberOfRowsInSection:) и tableView(:cellForRowAt:).

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

Компоновка всех этих трёх методов в отдельное расширение класса Foods позволяет разгрузить базовый файл класса и сгруппировать код по принципу решения определённой бизнес-задачи.

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

Режимы показа данных

В этом же бизнес-процессе - Show Foods in the Table - есть два своих дочерних процесса: Sort Foods и Search and Filter Foods.

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

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

В целом, следует отметить, что активное использование расширений базового класса, в том числе вынос в них стандартных методов, таких как viewDidLoad и TableViewData Source методов, позволяет освободить, разгрузить базовый файл класса и таким образом нивелировать проблему Massive View Controller.

6. Edit Foods

Рассмотрим теперь дочерние процессы бизнес-процесса Edit Foods. Они показаны на Рис. 5.

Бизнес-процесс Edit Foods включает в себя следующие дочерние бизнес-процессы:

  • Delete Food

  • Pass Food to Edit

  • Load Editing Food

  • Storage Editing Food

  • Prevent Input Error

  • Pass Edited Food Back to Foods

  • Get Edited Food in Foods

  • Persist Edited Foods

Как видно из этого перечня бизнес-процессов, здесь выстраивается определённая последовательность действий по реализации задачи Edit Foods. Например, элемент передаётся для редактирования, получается, сохраняется, изменяется, возвращается обратно, получается и изменения сохраняются на диск.

Каждая задача в этом блоке реализуется в своём отдельном файле, что можно увидеть на Рис. 6.

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

Например, prepareForSegue, viewDidLoad, unwindSegue и др. Это позволяет легче ориентироваться в коде.

И теперь, на примере этих бизнес-процессов, необходимо сделать очень важное замечание.

Что такое Модель?

Что, в упомянутых в начале этой статьи архитектурных паттернах, понимается под Моделью?

В одном случае под Моделью понимается структура данных, модель объекта. Например, структура или класс могут включать в себя ряд свойств и методов.

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

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

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

Это и есть целостная модель приложения, его внутренняя архитектура.

Примечание

Создание программ часто сравнивают с постройкой дома. С этой точки зрения, традиционная группировка кода по техническим характеристикам (view, model, service и т.д.) похожа на ситуацию, когда дом рассматривается просто как набор строительных материалов, например, кирпичи, оконные рамы, трубы для водопровода и т.д. Отсюда, во многом теряется видение дома как целостного объекта с его интенцией. То же происходит и с программами, что потом проявляется в трудностях, связанных с целостным пониманием кода и с его управлением.

Типовые бизнес-процессы. Типовая архитектура

Рассмотрим ещё одну интересную особенность, выявленную в ходе структуризации кода на основе бизнес-процессов приложения.

На Рис. 7 показаны дочерние процессы двух базовых бизнес-процессов приложения: Manage Foods и Manage Meals.

Как видим они полностью совпадают и включают в себя по 6 дочерних процессов:

  • Model

  • Test

  • Load

  • Storage

  • Show

  • Edit

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

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

Заключение

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

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

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

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

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

P.S.

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

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

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

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


  1. 0pauc0
    13.12.2024 11:56

    Скажите, чем вам вместо невнятного и расплывчатого термина "бизнес-процесс" не нравится, ну например термин "операция" (речь же в статье идет о реальных производственных или цифровых делах)?

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

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

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


    1. AppCrafter Автор
      13.12.2024 11:56

      Вопрос конечно интересный))

      Я бы не сказал, что "бизнес-процесс" невнятный и расплывчатый термин. Он очень даже активно используется. Тот же Google выдаёт несколько тысяч результатов по нему.

      А ChatGPT показал следующее соотношение между этими двумя терминами:

      • Бизнес-процесс состоит из множества операций, объединенных общей целью.

      • Операция — это более мелкая "единица работы", которая выполняется в рамках бизнес-процесса.

      Это выглядит достаточно логично.