Как вы храните бизнес логику

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

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

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

Каковы ваши предпочтения относительно структуры папок бизнес-уровня, поэтому, если вы просматриваете ее в обозревателе решений, какие папки и подпапки вы предпочитаете / предпочитаете создавать?

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

user5149542 14 окт ’18 в 12:57 2018-10-14 12:57
2018-10-14 12:57

2 ответа

Вы задаете фундаментальный вопрос архитектуры: «У меня много логики. как мне ее структурировать?» Трудно ответить на такой общий вопрос вкратце, так как многочисленные книги написали о различных аспектах этой проблемы.

Postgres-вторник №10. Бизнес-логика в БД: за и против. Олег Правдин, CTO LinguaLeo

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

user3036123 14 окт ’18 в 13:17 2018-10-14 13:17
2018-10-14 13:17

«Папка» не будет слишком простой для организации вашего решения. Хотя, если вы работаете с относительно небольшой проблемой, этого должно быть достаточно. Думая о наслоении и сохраняя свою бизнес-логику жесткой и последовательной, я бы посоветовал вам прочитать больше об DDD от Эрика Эванса.

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

Посмотрите на пример Microsoft, он отражает суть DDD. Есть также книга DDD Vaughn Vernon, в которой дается практический подход к пониманию ее использования.

Источник: stackru.com

Как вы храните бизнес логику

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

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

Масштабирование производительности. У приложений и базы данных различные возможности масштабирования при росте нагрузки на систему. Для масштабирования обычных приложений на современных фреймворках достаточно запустить несколько копий на разных серверах. А база остается одна. Чтобы снизить нагрузку на чтение, применяют репликацию master-slave.

Что такое бизнес-логика и как ее изолировать

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

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

Автоматизация разработки. БД как хранилище данных — стандартная практика. Для упрощения разработки в такой парадигме есть развитые инструменты — библиотеки ORM, которые умеют, в частности, автоматически генерировать скрипты миграции структуры БД. Изменение бизнес-логики в коде облегчается средствами среды разработки: автодополнением, автоматическим рефакторингом. Пользовательские функции в БД придется изменять полностью вручную.

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

Читайте также:  Наемный менеджер или свой бизнес

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

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

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

Я долго не мог докопаться до настоящей причины, пока не сделал добавление записей из кода, а не из триггера. Оказалось, что вставка иногда не срабатывает из-за ошибки типа unique constraint violation на автоинкрементном первичном ключе. Стандартный механизм исключений и логирование помогли отследить эту ошибку.

Админы подтвердили, что это известная проблема в MySQL 5.6, но быстро перевести production на 5.7 они не могли. Пришлось переключить тип таблицы с InnoDB на MyISAM. Проблема исчезла.

Не храните бизнес-логику в базе данных.

Источник: parpalak.com

ReactJs + Redux: бизнес логика в Акторах

«Та чего уж там париться — прямо в компонентах.» — скажут некоторые. И в некоторых ситуациях это правильное и удобное решение.

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

Как написано на сайте reactjs.org, React — это библиотека для создания UI.

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

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

Слои

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

Что? Не храните в разных файлах? Не, ну пусть даже вы назвали это duck подходом и запихнули все в один файл, вы все равно имеете в виду что он состоит из разных слоев.

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

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

Деление на слои помогает разделить работу между разработчиками.

Итак, деление на слои — это хорошо.

Что нам даёт отдельный слой бизнес логики?

Как правило когда мы выводим пользователю какою-то страницу с десятком компонентов, то все эти компоненты не сами по себе, они взаимодействуют друг с другом ради одного общего дела. Многие делают ошибку — инкапсулируют логику в отдельные соответствующие компоненты.

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

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

Читайте также:  Кто из звезд шоу бизнеса

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

Размещать бизнес логику в корневом компоненте — это хорошо.

Слой бизнес логики без Redux

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

Хуки для бизнес логики — это хорошо

Redux

Первое, чего не хватает при работе с хуками и то что даёт редакс — это общее состояние всего приложения.

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

Редакс предоставляет инструменты для дебага общего состояния.

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

Можно пролистать все виды интерфейса пользователя просто меняя состояние.

Общее состояние приложения в одном месте — это хорошо.

Thunk, Saga и Акторы

Т.к. у нас redux, то часть логики приложения попала в редюсеры. Но с редюсерами одна проблема — они синхронные. Нельзя в редюсере сделать запрос на сервер и результат вернуть в редакс. Чтобы добавить асинхронности, разработали несколько расширений для редакса используя специальному механизм — middleware. Этот механизм позволяет выполнить асинхронные действия вместо/до/после реального диспатча экшена.

Я рассматривал два варианта Thunk и Saga и выбрал Thunk. Saga отпала по простой причине — мне не нравятся генераторы. Но принципиально Thunk и Saga ничем не отличаются. Они оба добавляют в поток данных асинхронные действия, при этом поток данных так и остается однонаправленным:

  1. Пользователь вызвал событие в UI.
  2. Выполнился редюсер (изменился стейт) либо вызвался экшен thunk или Saga.
  3. Экшен thunk или Saga сделал асинхронные действия и вызвал один или несколько экшенов редакса что ведет обратно к пункту 1.

Но есть кардинально другой подход — Акторы. Акторы подписываются на изменение состояния и делают асинхронные действия в ответ на изменения какого-то значения в состоянии. Поток данных становится таким:

  1. Пользователь вызвал событие в UI
  2. Вызвался экшен redux и поменялось состояние стора.
  3. Актор подписанный на изменение этого состояния сделал асинхронные действия и вызвал один или несколько экшенов редакса.

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

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

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

Как ни крути, при появлении асинхронности будет как минимум два изменения состояния:

1. Чтобы сообщить что что-то начало грузится/обрабатываться

2. Непосредственно сохранение результата в редакс

Бизнес логика в Redux и Thunk

Тут все просто. Синхронную логику мы заносим в Redux, асинхронную — в Thunk.

Читайте также:  Реклама в гостиничном бизнесе что это

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

Что не так с Thunk и Saga?

Я ничего не имею против Thunk и Saga.

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

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

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

Разработка акторов

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

Я подписался на состояние редакса, При изменении состояния, я проверял что поменялось и вызывал dispatch(action).

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

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

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

Призрак

Единственное что мне не нравилось — это определения. Я пытался вынести бизнес логику из react-компонентов, так как это слой UI, а в результате в проекте у меня опять могли получиться везде компоненты: и UI на react-компонентах и акторы на react-компонентах.

Мне хотелось четко разделить эти слои, поэтому я сделал две функции:

  • ghost — аналог createElement
  • ghosts — аналог Fragment

Да, я прям вот так просто присвоил:

export const ghost = createElement; export const ghosts = createElement.bind(null, Fragment, null);

В переводе с английского означает “призрак”. Мне показалось подходящим названием для противопоставления видимым реакт компонентам.

С одной стороны — это отдельное понятие для слоя бизнес логики, не связанное с UI, а с другой стороны включает в себя весь опыт реакта.

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

const AppActor = (< param1, param2, showModalX >) => ghosts( ghost(MenuActor, < param1 >), ghost(PagesActor, < param2 >), showModalX ghost(ModalXActor) )

Никакого jsx и можно спокойно пользоваться привычными хуками.

const HomePageActor = () => < const dispatch = useDispatch() useEffect(() => < const interval = setInterval(() =>< dispatch() >, 1000) return () => clearInterval(interval) >) // you should explicitly point that this ghost hasn’t child ghosts return null >

Естественно, я создал себе npm модуль react-ghost с этими двумя строчками и уже применил его на нескольких проектах. Результат меня радует, мне получилось с минимальным усложнением провести четкую границу между бизнесс логикой и UI. Но людям в команде все же приходится объяснять что это, зачем это нужно и что вместо thunk достаточно использовать useEffect.

Собственно, поэтому и захотелось поделиться этим подходом и узнать ваше мнение.

  • Разработка веб-сайтов
  • ReactJS

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
Бизнес для женщин