powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Разработка информационных систем [игнор отключен] [закрыт для гостей] / Необычная реализация бизнес-логики приложения 2
25 сообщений из 30, страница 1 из 2
Необычная реализация бизнес-логики приложения 2
    #37635253
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Удалось сделать движок для настройки бизнес-логики в виде иерархии процессов, операций и команд. Используется паттерн Command. При этом, что самое забавное, потеряла свою актуальность таблица настройки прав.

Это WEB приложение на PHP. Корневой командой является процесс Application. Вообще Command - это базовый класс с методом Exec, он используется только для выполнения логики на стороне сервера, примеры команд: Transaction, SendEmail, Event, Handler.
Operation наследуется от Command и используется уже в качестве диалога с пользователем, т.е. вывести на экран страницу для чтения или для редактирования.
Process наследуется от Operation и предназначен для управления операциями, имеет набор состояний и привязанных к ним операций, в качестве операции можно привязать другой процесс - подпроцесс.

Значит рутовой командой является Application - процесс. Это синглетон для каждого пользователя.
Когда пользователь заходит на сайт, создается объект Application, но пока только на стороне веб-сервера, база данных в стороне.
В состоянии New (это базовое состояние нового экземпляра процесса) доступны:

1. Операция Login
2. Процесс Registration

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

Если пользователь входит повторно, то выполняет операцию Login, в результате чего в базе находится его собственный процесс Application и определяется его состояние.

Теперь для пользователя в состоянии Registered доступны следующие операции:

1. Logout
2. Cabinet
3. ... другие прикладные процессы
4. Unregister

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

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

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

Вуаля. Всё это работает. Бизнес-логику я прописываю в виде иерархических метаданных. В PHP реализую классы наследники операций и команд. А также имеются классы типа Page, которые получают на входе шаблон html и строят по нему DOM-модель, затем идет связка контролом и данных.

Примеры вызова операций: строка GET

1. ...index.php?op=Registration
2. ...index.php?op=Cabinet
3. ...index.php?op=Cabinet/WorkSpace
4. ...index.php?op=Cabinet/WorkSpace/AddPanel&panel=PrivateData
5. ...index.php?op=Cabinet/WorkSpace/RemovePanel&panel=PrivateData
6. ...index.php?op=Estate/Expose&OID=8253

Собственно вопрос, кто-нибудь юзает аналогичную модель настройки бизнес-логики, которая же является системой ограничения прав доступа
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37635288
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nick,
смахивает на ассемблер в современном мире.
Если говорить о "движке", то 2 значение слова - фреймворк.
Они как раз и делают нечто подобное - оборачивают простые REST запросы HTTP в свои команды.
Ты назвал это шаблон Command.
Самое трудное в Веб, это не преобразовать GET из ослика в команду, а отделить Вёрстку-дизайн от бизнес-логики БЛ. Или MVC.

У тебя вроде всё в куче.
Так что сначала, анализ ГОТОВЫХ ДВИЖКОВ\ФРЕЙМВОРКОВ
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37635302
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,

Бизнес-логика от интерфейса отделена. Вообще у меня три слоя:

1. Сущности - классы прокладных и системных сущностей, которые умеют хранить себя в базе данных и восстанавливать себя оттуда. Построено на основании шаблона Фабрика классов

2. Слой бизнес-логики - шаблон Command

3. Слой интерфейса - Базовый класс Control и наследники, в том числе класс Page. А также папка с файлами типа html. Интерфейс всегда можно заменить на другой.
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37635598
Фотография Пионэр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При этом, потеряла свою актуальность таблица настройки прав.
и насколь гибкая настройка прав доступа?

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

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

Я лично привязываю права к экшенам/эвентам и абсолютно не забочусь об иерархии.
Правда и таблицы настройки прав доступа у меня тоже нет)
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37635967
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nick,
это легко проверить.
Покажи как человек не зная твой Command будет верстать страницу.
А ты потом прицепишь бизнес-логику на AJAX
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37637676
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пионэр,

Вот именно, у меня экшены это операции и евенты есть, как вложенные команды к операциям. И если нужно не всё показывать на странице, то основная операция разбивается на подоперации и показываются только те, к которым имеется доступ в зависимости от контекста. Контекст определяется самой операцией
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37637678
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,

На настоящий момент я сам верстаю. Но научить верстать другого легко, достаточно предоставить ему иерархическое описание бизнес-логики, и описать словами, что каждая операция должна показывать и обрабатывать. И он будет связывать шаблоны с операциями. Можно даже админку для этого сделать. Кстати, в планах это есть.
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37637832
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nickдостаточно предоставить ему иерархическое описание
Подъём переворотом делается так... (с)
ПОКАЖИ. А то вдруг ты JSP \ ASP \ DHTML изобрёл.
______________________________________________
"Сделай настолько просто, насколько это возможно, но не проще". © А. Эйнштейн.
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639411
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123, лови
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
	public function Page() {
		
		$reg = new \Controls\Page('registration-confirm');

		$reg->Child('Tag=p,name=person')->Value = $this->Person;
		$reg->Child('Tag=p,name=email')->Value = $this->Email;

		$btn = $reg->Child('Tag=input,name=Submit');
		$btn->value = 'Сформировать аккаунт';
		$handler = $this->GetChild('Post');
		$handler->Params['hash'] = $this->Params['hash'];
		$handler->Bind($btn);

		return $reg;
	}
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639415
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123, или вот

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	public function Page() {
		$page = new \Controls\Page('registration-start');

		$btn = $page->Child('Tag=input,name=Submit');
		$this->GetChild('Post')->Bind($btn);

		$page->Child('Tag=input,name=Email')->value = $this->Email;
		$page->Child('Tag=input,name=Email2')->value = $this->Email2;
		$page->Child('Tag=input,name=Name')->value = $this->Person;

		return $page;
	}
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639420
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,

Объект Page принимает на вход название файла с чистейшим HTML и превращает его в DOM-модель, затем просто теги типа input связывает с данными, а теги типа button или a (ссылка) связываешь с командами (событиями)
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639425
Leonidv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nick,

У вас template подход для формирования HTML?
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639429
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123, вот еще

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
public function Page() {
		$page = new \Controls\Page('object-contactinfo-panel');
		$this->Bind($page);
		return $page;
	}

	public function Bind($control) {
		$this->Estate->ContactInfo->GetField('Person')->Bind($control->Child('Tag=input,name=name'));
		$this->Estate->ContactInfo->GetField('Email')->Bind($control->Child('Tag=input,name=email'));
	}
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639435
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonidv, не знаю, что под этим подразумевается. Дизайнер делает шаблоны, я их складываю по файлам в папку Templates и использую для генерации страниц. Иногда разбиваю на куски, а затем с помощью операций склеиваю
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639437
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonidv, такой подход позволяет при желании полностью заменить интерфейс
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639438
Leonidv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123DHTML изобрёл.
Petro123, продолжаю заниматься твоим образованием.
DHTML это не более чем название HTML+Javascript+CSS. Термин был моден во времена IE4/IE5, продвигался MS. Сейчас уже почти не употребляется.

В данном контексте он абсолютно не в тему.
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639455
Leonidv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old NickLeonidv, такой подход позволяет при желании полностью заменить интерфейс
Ясно. Я задал вопрос до ваших ответов :)
Аналогичный подход используется в wicket'е, только он там гораздо сильнее развит.

Кстати, у вас binding двухсторонний?
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639471
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonidv, на данном этапе нет. Был двусторонний, но показал свою неэффективность
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639615
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а у меня нет желания заниматься твоим (в игноре)
______________________________________________
"Не понял" от Лёни 11906276 и чем всё закончилось 11910058
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639646
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old NickPetro123,
Объект Page принимает на вход название файла с чистейшим HTML и превращает его в DOM-модель, затем просто теги типа input связывает с данными, а теги типа button или a (ссылка) связываешь с командами (событиями)
ты учти, что тут не программисты сидят, а Автоматизаторы с большой буквы.
Потому совет, выложить по этапам - демку
- шаблон "с чистейшим HTML" :), DOM не надо, скрипт преобразвания, скрин.
Удачи!
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37639931
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правила простроения бизнес-логики

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

Имеется четыре базовых класса Command, Operation, Process, Application

1. Command представляет собой логику, которая выполняется последовательно и непрерывно на стороне сервера
2. Operation представляет собой частный случай Command и является интерактивной командой, которая взаимодействует
с клиентом (под клиентом понимается любое клиентское приложение)
3. Process представляет собой частный случай операции и является долгоиграющей операцией, которая время от времени
сохраняет свое текущее состояние на сервере независимо от времени жизни клиентского приложения. Process
имеет набор состояний и к каждому состоянию привязывается определенный набор операций, доступных в этом
состоянии, в том числе в качестве операции процесса может выступать другой процесс, в результате чего он
становится подпроцессом.
4. Application представляет собой частный случай процесса и является синглетоном в разрезе клиентов. То есть
каждый клиент (клиентское приложение) имеет экземпляр приложения, причем единственный. При этом Application
является корнем приложения. Его точкой входа и выхода.

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

Рассмотрим в качестве примера площадку для проведения аукционов, реализованную в виде WEB-приложения
Попасть на площадку может любой пользователь, в том числе не зарегистрированный на площадке. Тем не менее,
такой пользователь имеет доступ к некоторому функционалу:

1. Посмотреть описание площадки
2. Прочитать новости площадки
3. Посмотреть список торгов
4. Залогиниться (если есть аккаунт)
5. Зарегистрироваться

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

Оформим иерархию

Код: plaintext
1.
2.
3.
4.
5.
6.
- Application
  - New 
    - Description
    - News
    - AuctionList
    - Login
    - Registration

Application - экземпляр класса Application (процесс - синглетон)
New - состояние процесса (стартовое)
Description - операция, которая выводит страницу с описанием функционала площадки
News - операция, показывает страницу со списком последних новостей площадки
AuctionList - операция, выводит на экран список актуальных торгов
Login - операция, позволяющая пользователю авторизоваться на площадке
Registration - процесс, который даёт пользователю возможность создать аккаунт на площадке

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

http://www.ets24.ru/index.php?op=Login

Операция проверит в базе наличие аккаунта и соответствие пароля, инициализирует процесс (Application)
и вернет его состояние: Registered. Теперь надо в дереве бизнес-логики определить какие операции стали доступны

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
- Application
  - New 
    - Description
    - News
    - AuctionList
    - Login
    - Registration
  - Registered
    - Description
    - News
    - AuctionList
    - Logout
    - Cabinet
    - OrganizeAuction

Рассмотрим последние три операции:

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

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

С учетом вышеизложенной информации можно перестроить дерево бизнес-логики

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
- Application
  - Description
  - News
  - AuctionList
  - New
    - Login
    - Registration
  - Registered
    - Logout
    - Cabinet
    - OrganizeAuction

Теперь попробуем расписать процесс регистрации нового пользователя на площадке

- Registration

Теперь целиком наше дерево будет выглядеть так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
- Application
  - Description
  - News
  - AuctionList
  - New
    - Login
    - Registration
      - New 
        - SelectSubjectType
        - CreatePersonRequest
        - CreateInidividRequest
        - CreateLegalRequest
      - Template
        - ViewRequest
        - EditRequest
        - PrintRequest
        - DeleteRequest
        - SignRequest
        - SendRequest
      - Sent
        - ViewRequest
        - PrintRequest
        - RecallRequest
  - Registered
    - Logout
    - Cabinet
    - OrganizeAuction

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

1. Синхронный запуск - означает, что процесс, внутри которого синхронно запущен дочерний процесс, становится
недоступным пока свою работу не завершит дочерний процесс
2. Асинхронный запуск - означает, что родительский процесс не ждет завершения дочернего и дает доступ к запуску
других подпроцессов.
3. Инициирующий запуск - означает запуск зависимого подпроцесса, предназначенного для другого субъекта, например,
запуск процесса проверки заявки на регистрацию, предназначенного для оператора. Инициирующий запуск может быть
как синхронным, так и асинхронным.
4. Множественный запуск - означает, что можно запустить несколько вложенных процессов одного и того же типа, иначе
повторный запуск подпроцесса будет приводить к доступу уже имеющегося подпроцесса.

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

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

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

op=Cabinet - открыть личный кабинет (корневая команда Application опускается). Кабинет откроется, только если
Application находится в состоянии Registered

op=Cabinet/WorkSpace - откроется рабочий стол личного кабинета. Вызов операции

op=WorkSpace напрямую ни к чему не приведёт (кроме сообщения об отсутствии доступа), т.к. внутри Application
такой операции нет, и она появляется, только когда инициализируется операция Cabinet

И соответственно вызвать команды AddPanel и RemovePanel, которые зарегистрированы в операции WorkSpace также не
получится, пока не зайдешь в WorkSpace

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

op=Registration&OID=8253

При этом на стороне сервера происходит проверка принадлежности процесса вызывающему собъекту (по полю Subject в
процессе).

Для запуска нового процесса нужно указать родительский процесс (кроме Application, который всегда инициализируется
и является синглетоном), его идентификатор и имя вложенного процесса, например

op=Registration/SendRequest&OID=8253

При этом запуск подпроцесса SendRequest будет возможен только в том случае, если процесс Registration с
идентификатором OID=8253 принадлежит пользователю и находится в состоянии, в котором доступен подпроцесс

В итоге имеем одновременно способ описания бизнес-логики и средство разграничения прав доступа











Внутренняя реализация классов Command, Operation, Process и Application


Класс Command простой до безобразия. Имеет виртуальный метод Exec($params), где $params - ассоциативный массив,
где ключ - название параметра, а value - значение параметра

В наследниках класса Command в перекрытом методе Exec пишется логика. Примеры команд на текущий момент

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

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
class Transaction extends Command {

	public $OnExec;
	public $Error;

	function __construct($parent=null)
	{
		parent::__construct($parent);
	}

	public function Exec($params) {
		try
		{
			$this->Error = null;
			$this->DBManager->BeginTran();
			if($this->OnExec)
				$this->OnExec->Exec($params);
			$this->DBManager->CommitTran();
		}
		catch (\Exception $e)
		{
			$this->DBManager->RollbackTran();
			$this->Error = $e->getMessage();
		}
	}
}



Sendmail - команда, которая отправляет электронное письмо

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
class SendMail extends Command {
    
	public $Receiver;
	public $Theme;
	public $Header;
	public $Body;

	function __construct($parent=null)
	{
		parent::__construct($parent);
	}

	public function Exec($params) {
		$mailOID = $this->DBManager->GetOID('Mail.System');
		$mail = $this->DBManager->CreateObject($mailOID);
		$mail->Subject($this->Theme);
		$mail->To($this->Receiver);
		$mail->body = $this->Body;
		$mail->Send();
	}
}




Операция регламентирует бизнес-логику более жестко. Основным также является метод Exec
Но в наследниках он не перекрывается. Метод Exec выглядит так:

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
public function Exec($params)
{
	try
	{
		// Запоминаем параметры вызова
		$this->Params = $params;

		// Инициализируем вложенные операции
		$this->Init();

		$op = null;
		if(isset($this->Params['op']))
			$op = $this->Params['op'];

		if($op)
		{
			$root = $this->GetRootPath($op);
			$last = $this->GetLastPath($op);
			if($root)
			{
				$params['op'] = $last;
				$this->Active = $this->GetChild($root);
				if(!isset($this->Active))
					throw new \Exception('Operation '.$root.' not found');
				$this->Active->Exec($params);
			}
		}
		else
			$this->ExecDefault();	// Выполняем логику по-умолчанию

		$this->Run();
	}
	catch(\Exception $e)
	{
		$this->HandleError($e->getMessage());
	}
}




Сначала идёт вызов виртуального метода Init, который регистрирует вложенные операции и команды, которые
как раз и будут доступны внутри данной операции, пример реализации метода Init

Код: php
1.
2.
3.
4.
5.
protected function Init() {
	$this->AddChild('WorkSpace', new WorkSpace($this));
	$this->AddChild('PrivateData', new PrivateData($this));
	$this->AddChild('MyObjects', new MyObjects($this));
}



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

Код: php
1.
2.
3.
4.
5.
protected function Init() {
	$this->AddChild('WorkSpace', new ProxyOperation($this, 'WorkSpace'));
	$this->AddChild('PrivateData', new PrivateData($this));
	$this->AddChild('MyObjects', new MyObjects($this));
}



Это уже оптимизация быстродействия

Затем в методе Exec операции определяется подоперация, если она указана. Смотрим параметр op.
К слову сказать, в $params сидит $_GET. В каждую операцию в параметре op приходит строка, в которой
уже вырезана рутовая часть, относящаяся к текущей операции, т.е. в операции Application строка op
выглядит так op=Cabinet/WorkSpace, а в операции Cabinet строка op выглядит так: op=WorkSpace

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

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

И если всё же произошла ошибка, то выполняем метод HandleError, передав ему текст ошибки.

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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
-- Операции
exec RegisterOperation 'Registration', 'Регистрация'
exec RegisterOperation 'Login', 'Вход'
exec RegisterOperation 'Logout', 'Выход'
exec RegisterOperation 'EstateAdd', 'Добавить объект'
exec RegisterOperation 'EstateEdit', 'Изменить параметры объекта'
exec RegisterOperation 'ExpositionExpose', 'Опубликовать объект'
exec RegisterOperation 'ChangeProfile', 'Изменить профиль'
exec RegisterOperation 'Cabinet', 'Личный кабинет'
go

-- Процессы
exec RegisterProcess 'Application', 'Приложение'
exec RegisterProcess 'EstateProcess', 'Недвижимость'
exec RegisterProcess 'Exposition', 'Публикация'
go

-- Операции процессов
exec RegisterProcessOperation 'Application', 'New', 'Login', 'Login'
go
exec RegisterProcessOperation 'Application', 'New', 'Registration', 'Registration'
exec RegisterProcessOperation 'Application', 'Registered', 'Cabinet', 'Cabinet', 1
exec RegisterProcessOperation 'Application', 'Registered', 'Estate', 'EstateProcess'
exec RegisterProcessOperation 'Application', 'Registered', 'Logout', 'Logout'
exec RegisterProcessOperation 'Application', 'Registered', 'ChangeProfile', 'ChangeProfile'
go

exec RegisterProcessOperation 'Exposition', 'New', 'Expose', 'ExpositionExpose', 1
go

exec RegisterProcessOperation 'EstateProcess', 'New', 'Add', 'EstateAdd', 1
exec RegisterProcessOperation 'EstateProcess', 'Template', 'Expose', 'Exposition', 1
exec RegisterProcessOperation 'EstateProcess', 'Template', 'Edit', 'EstateEdit'
go



Сначала регистрируются операции, затем процессы, затем операции привязываются к состояниям процессов.
Таким метод Init процесса обращается к базе данных, читает настройки и регистрирует доступными операции,
причем не все, а только те, что привязаны к текущему состоянию. Состояние определяется по переданному
OID процесса. Если OID не передан, то значит это новый процесс и состояние = New

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






Как необходимо разрабатывать новые прикладные классы бизнес-логики. Посколько Application и Process являются
самодостаточными, то остаётся разработка операций и команд. Про разработку команд выше уже сообщалось. Нужно
просто перекрывать метод Exec, поэтому рассмотрим подробно разработку операций. Сделаем это на примере админки.

Создадим операцию Administration. Прикрепим ее к Application в состоянии Registered. Доступ к ней должен получать
только администратор системы. Для этого есть два способа:

1. В методе Init вызывать хранимую процедуру, которая будет проверять является ли пользователь администратором
и если нет, то создавать исключение.
2. Привязать операцию к процессу по условию, то есть добавить к связке процесс-состояние-операция еще Conditon
(IsAdministrator). Тогда все, кто не админ, не будут получать доступ к операции

Выберем первый способ (чисто для примера, на практие я реализую второй способ)

1. Зарегистрируем ее в базе.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
exec RegisterOperation 
  'Administration', -- системное имя
  'Администрирование' -- пользовательское имя

exec RegisterProcessOperation 
  'Application',   -- процесс, к которому привязываем
  'Registered',    -- состояние, к которому привязываем
  'Admin',         -- алиас, под которым операция будет сидет в процессе
  'Administration' -- класс операции (системное имя)



2. Создаем класс Administration в PHP, наследуем от Operation

Перекрываем метод Init

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
protected function Init()
{
  // хранимка проверяет принадлежность текущего пользователя к роли
  $sp = new \System\StoredProc('User_CheckRole');
  $sp->AddParam('@Role', DB_STRING, 'Admin');
  $sp->AddParam('@Result, DB_BOOL, false, output);
  $sp->Execute();
  if(!$sp->GetParam('@Result')->Value)
    throw new Exception('Доступ к администрированию разрешен только администратору');

  // Регистрируем дочернюю операцию
  $this->AddChild('Object', new Object($this));
}



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

Что должна делать данная операция по-умолчанию? Наверное, выводить список всех классов.
Перекроем метод ExecDefault.

Код: php
1.
2.
3.
4.
5.
6.
7.
protected function ExecDefault()
{
  $this->Active = new Object($this);
  $params['op'] = 'List';
  $params['class'] = 'Class';
  $this->Active->Exec($params);
}



То есть по-умолчанию будет вызываться операция Object, которая будет вызывать действие объекта List
А класс объекта - Class, то есть выводим список объектов типа Class.

Теперь нужно перекрыть метод Page, который будет выводить html на экран

Код: php
1.
2.
3.
4.
public function Page()
{
  return $this->Active->Page();
}



Предполагаем, что страницу всегда будет формировать вложенная операция.

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

Посколько иерархия бизнес-логики это один из слоев MVC, то вторые два это слой бизнес-сущностей и интерфейса.
Как устроен слой Бизнес-сущностей вы уже знаете. Это иерархия классов бизнес-сущностей, и в каждой
зарегистрирован набор действий Edit, Create, View, Delete, Print и т.д.

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

Таким образом команда вида

op=Admin/Object/Edit&OID=1234

Создасть операцию Admisitration (если есть доступ), затем создаст опреацию Object, которая создаст сущность,
найденную по параметру OID и выполнит его действие Edit.

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

op=Admin/Object/Create&class=Notice
или
op=Admin/Object/List&class=Auction
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37640229
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nick,
тяжёлый случай.
Всё что ты описал, до последней строчки есть паттерн CRUD.
- Т.е. что нвого у тебя по отношению к данному паттерну?
Old NickДоступные операции и состояния прописываются в базе данных, например
-- Операции
exec RegisterOperation 'Registration', 'Регистрация'
exec RegisterOperation 'Login', 'Вход'
вот это 2 хранимых процедуры:
- Registration и Login
..........
В вебе БЛ сейчас не проблема.
Проблема в ГУИ (их даже особым словом назвали - rich ГУИ)
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37640235
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old NickЭто WEB приложение на PHP
это наложило свой отпечаток.
IMHO попробуй Питон. Многие на него с сабжа бегут.
Раз ты занялся бизнес-логикой на PHP
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37640647
Leonidv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Всё что ты описал, до последней строчки есть паттерн CRUD.
- Т.е. что нвого у тебя по отношению к данному паттерну?

Надо бы сначала узнать, что это за новый паттерн такой - CRUD.
http://ru.wikipedia.org/wiki/CRUD - это не паттерн, это акроним.
...
Рейтинг: 0 / 0
Необычная реализация бизнес-логики приложения 2
    #37640650
Leonidv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old Nick,

Petro123 хоть и путается в терминологии, но по сути прав. У вас изложение очень похоже на что-то типа статьи, которые обычно начинают с исследования уже существующих решений, с которыми сравнивается предложенное.
Посмотрите на PHP-фреймворки, или, что интереснее, на RoR или Django. Пока непонятна, в чем прелесть вашего решения и чем мне, как разработчику, оно может помочь. Голый PHP не рассматриваем, сравниваем именно фреймворки (коли вы уж его пишите).
...
Рейтинг: 0 / 0
25 сообщений из 30, страница 1 из 2
Форумы / Разработка информационных систем [игнор отключен] [закрыт для гостей] / Необычная реализация бизнес-логики приложения 2
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]