Околоархитектурные Соображения Или Итоги Одного Спора

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

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

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

Последнее не было достигнуто, и все же тем же волевым решением был принят один из вариантов развития существования.

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

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

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

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

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

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

А т.к.

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

(То есть в нашей архитектуре нет четкого понятия, что такое сервис и не указано его высшее предназначение.

Фактически при таком подходе сервис — это класс, который что-то делает)

Околоархитектурные соображения или итоги одного спора

Рис.

1. Иерархия классов первого подхода Пример реализации всего этого счастья можно скачать по ссылке Git-хаб Что мне здесь не нравится: Во-первых, мне не нравится отсутствие четких договоренностей по делегированию полномочий: это оба сервиса, но они делают совершенно разные вещи.

Один занимается обработкой данных, другой — временным хранением.

Во-вторых, мне не нравится класс SessionDataServiceBase, а именно метод T Get(string key, Func getData), который не только работает с сессией, но и обрабатывает данные.

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

Если посмотреть историю развития этого объекта, то изначально в интерфейсе не был описан метод T Get(string key, Func getData) (или его аналог).

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

У этого подхода был минус — это повторяемость кода.

Я это заметил, когда решил добавить использование сессии в один из сервисов.

После непродолжительного расследования было обнаружено большое количество дублирующего кода, точнее это дублирование было во ВСЕХ сервисах.

Это нарушило мою целостность восприятия Вселенной и не позволило мне жить в гармонии с ней.

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

Третья проблема, которую открыл мне Господь Бог, Его Святейшество в двоичном коде – это ключи.

Им были присвоены значения (не боюсь признаться, у меня был в свое время грех) в стиле «кто-то в лес идет, кто-то за дровами».

А метод void Clear(string[] sessionKeyPrefix) иногда давал совершенно неожиданные результаты.

Были и другие проблемы, но мы не будем их касаться; решение этих проблем обеспечивало и грамотное наследование.

Четвертая проблема — тестирование.

После перехода волевым решением в эту структуру все юнит-тесты методов, использующих T Get(string key, Func getData) под капотом провалились.

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

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

Этот подход основан прежде всего на условностях и ограничениях.

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

данные.

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

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

Поэтому будем считать, что базовая сущность для сервисов у нас всё-таки есть, это будет интерфейс IService. Теперь о HttpContextBasedSessionDataService и подобных ему классах.

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

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

В принципе это ближе к репозиториям, чем к сервисам, только репозитории временного хранения, такие как Application, Cache, Session. Назовем базовую сущность IShortermStore и примем, что имена таких классов не будут содержать слова Service. Теперь попробуем на основе этих расчетов построить иерархию классов, которая устранит недостатки предыдущей реализации, и перенесем часть функционала по логике работы с временным хранилищем в базовый сервисный класс, а именно работу с ключи и логика ленивой инициализации.

А теперь давайте взглянем на диаграмму классов, построенную по этой концепции:

Околоархитектурные соображения или итоги одного спора

Рис.

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

Теперь о мнимых недостатках.

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

Но на самом деле с этим проблем нет: если возникнет такая необходимость, то, возможно, стоит подумать о SOLID, в частности о букве I в этой аббревиатуре (Принцип разделения интерфейсов) а не делать монстров, которые умеют «вышивать и пользоваться пишущей машинкой».

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

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

Алексей Михайличенко, разработчик программного обеспечения .

Net, технический руководитель Теги: #архитектура приложения #принципы проектирования #дизайн интерфейсов #дизайн взаимодействия #интерфейсы #разработка веб-сайтов #программирование #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.