Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Нужны советы по проектированию wizard'а  (Прочитано 58466 раз)
0 Пользователей и 1 Гость смотрят эту тему.
neco
Участник

kz
Offline Offline

« : 04-06-2008 19:36 » 

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



класс Order это вроде как и есть визард.
предполагается, что Caller умеет на основании ReqParameters спросить у юзера всё, что надо и это "что надо" передать назад визарду при выполнении CompleteStep (в принципе и при CancelStep тоже, потому как часть параметров юзер может заполнить, а потом захотеть вернуться на предыдущий шаг "просто посмотреть").
в основном интересовало как разорвать поток выполнения внутри визарда и как хранить (когда сохранять и когда читать) данные в xml. Поэтому сосредоточился на этих моментах (их вроде удалось понятно отразить на схеме или нет?), но сам workflow здесь уже как-то некуда воткнуть.
т.е. предполагаю, что визард будет ветвлистым и свой путь будет хранить в связном списке, к примеру. следовательно, перед шагом switch to next step на основании имеющихся в xml данных будет как-то приниматься решение о том, какой Step-класс создавать и ставить следующим в списке. Так же, где-то должна быть логика того, как, при возвращении назад и изменении ранее выставленных параметров, будут изменяться последующие ранее совершённые шаги (некоторые шаги могут уничтожиться, в некоторых могут сброситься параметры.
И вот куда эту дополнительную логику включать, что-то не пойму. Может стоило использовать диаграмму кооперации?

И вообще, в рамках задачи - схема получилась г..но или пойдёт?
Спасибо!
Записан

Всю ночь не ем, весь день не сплю - устаю
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 05-06-2008 03:17 » 

по моему, общая схема для любого визарда или даже простого диалога :
создаём структуру, содержащую всё нас интерисующее, заполняем дефолтами, пишем нужные методы, если надо , и передаём на пережевание визарду/диалогу. Когда визард/диалог закрыли - копаемся в структуре, определяя желания пользователя Улыбаюсь
Записан

neco
Участник

kz
Offline Offline

« Ответ #2 : 05-06-2008 03:24 » 

а если (как в моём случае) визард должен менять будущие шаги в зависимости от предыдущих? та же галочка hide advanced configuration это частный случай того, что я хочу.
а что за "нужные методы" вы имели в виду? можно пример?
Записан

Всю ночь не ем, весь день не сплю - устаю
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 05-06-2008 04:45 » 

neco, что значит - будущие шаги ? Структура заполняется по предыдущим шагам, а каждый новый шаг "смотрит" в структуре, что там ранее было введено и делает, что нужно. А насчёт методов, например (не знаю, только, каой язык исповедуешь Улыбаюсь Я на с++ )

Код:
struct s_MyWizData
{
  bool m_bAdvanced;
  ...
  ...

  s_MyWizData()
  {
     //инициализация
     //....

     SetDefaults();
  }

  void SetDefaults()
  {
     //....
  }

  //что нужно сделать, если юзер отменил шаг № x
  void BackFromStep(int nTheStepToReturnFrom)
  {
     switch(nTheStepToReturnFrom)
     {
          ...
     }
  }

  //что нужно сделать, если юзер завершил шаг № x
  void AfterStep(int nTheStepThatContinued)
  {
     switch(nTheStepThatContinued)
     {
          ...
     }
  }

};

вот примерно так я бы поступил
Записан

Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 05-06-2008 05:57 » 

Алексей1153++, вопрос о проектировании, а не о программировании. Не лезь со своим C++ Улыбаюсь

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

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

С точки зрения реализации в классах и объектах, по-моему, неплохо подойдёт шаблон проектирования "Состояние" (State), в котором состояния - это шаги (экраны) мастера. Он же даёт объяснение, как разорвать поток управления.

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

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

Диаграммы кооперации для конкретного мастера не к месту. Они применимы только в случае, когда разрабатывается абстрактный обобщённый мастер, который затем применяется как основа решения для конкретного мастера. В этом случае конкретные классы конкретного мастера играют роли абстрактных классов обобщённого мастера.
« Последнее редактирование: 05-06-2008 06:00 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 05-06-2008 07:50 » 

dimka, а буду лезть Улыбаюсь И дело не в языке, а в подходе
Записан

Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 05-06-2008 08:08 » 

Алексей1153++, well, well, well
Ты сразу бросаешься писать код.
neco подошел к теме корректно - создание модели, а только затем кодирование.

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

Цитата
И вообще, в рамках задачи - схема получилась г..но или пойдёт?
neco, маленький совет. Никогда  не оценивай свою работу как г-но, и никому не подсказывай об этом. Люди сами тебе об этом скажут. Ты провел работу, пусть не лучшую, но ты потратил свои силы, время, знания, а это уже г-но. Тем более, что это на стадии проекта.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
zubr
Гость
« Ответ #7 : 05-06-2008 09:33 » 

neco, как вариант:
1. Каждый шаг визарда сделать в виде объекта (класса) с возможными методами, свойствами, связями (вот отсюда и надо начинать делать диаграмму развивая ее связями с другими шагами)
2. Все данные шага будут сохраняться в соответствующий объект
3. Сохранение данных в XML по окончании работы визарда (когда юзер нажал Ok)
Записан
neco
Участник

kz
Offline Offline

« Ответ #8 : 05-06-2008 10:16 » 

Спасибо за советы!
Алексей1153++, приблизительно так я и реализовывал мастера раньше - мне кажется, всё-таки это не очень дальновидный подход - каждый новый мастер надо проектировать заново.

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

Цитата: dimka
Надо полагать, что под стрелками, направленными справа налево, ты подразумевал именно возвраты.
ну в книжках рисуется пунктиром, а в программе (какая-то малюсенькая прога, UMLPad что ли) не было пунктирной линии.
вообще, намучался я с поиском нормального редактора - большие надежды возлагал на Rational Rose, но почему-то (у меня 2003) там всё так убого оказалось - что-то серьёзное делать на нервы изойдёшь.
Сейчас дома уже наверное скачался NetBeans шестёрка - вечером попробую на нём.

2zubr:
1. это и есть шаблон state.
2&3 - зачем ещё один объект - почему не сразу в XML? у меня xml и есть промежуточное хранилище - результатом визарда будет запись в БД. В любом случае, это механика.
Записан

Всю ночь не ем, весь день не сплю - устаю
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 05-06-2008 14:27 » 

Цитата: neco
И, мне кажется, соль там в том, чтобы разделить логику поведения в различных состояниях, а также тот момент, что за смену состояния отвечает само состояние. В визарде же, мне казалось, что вроде как логичнее, чтобы следующий шаг выбирал визард, а не шаг.
Похоже, ты как-то разделяешь сам мастер и его шаги (состояния мастера). Это не разные сущности, состояния мастера это свойства сущности. Поэтому не совсем понятно, что значит "логичнее, чтобы следующий шаг выбирал визард, а не шаг"?

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

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

Цитата: neco
ну в книжках рисуется пунктиром, а в программе (какая-то малюсенькая прога, UMLPad что ли) не было пунктирной линии.
В этом случае вообще не рисуются возвраты - предполагается, что они есть. Тем более, когда есть возможность изобразить период активности объекта "колбаской" - прямоугольником на линии жизни, тогда конец активности означает переход управления к другому объекту в контексте одного потока исполнения; в контексте параллельных потоков будет неопределённость.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #10 : 05-06-2008 16:49 » 

Похоже, ты как-то разделяешь сам мастер и его шаги (состояния мастера). Это не разные сущности, состояния мастера это свойства сущности. Поэтому не совсем понятно, что значит "логичнее, чтобы следующий шаг выбирал визард, а не шаг"?
ну да разделяю - это два разных класса. Класс Wizard, а внутри него абстрактный класс Step и куча его наследников - реальных шагов. Класс визард имеет приватное свойство CurrentState (CurrentStep точнее), которое должно изменяться каждым шагом самостоятельно. Т.е. при нажатии на кнопку Next и вызове CompleteStep сам шаг решает, какой шаг будет следующим. Следовательно, при большом количестве шагов, избавляемся от громоздкой условной логики внутри Wizard'а (при линейной логике условностей вообще не будет).

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

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

Цитата: dimka
Гибкое решение с таким разделением потребует довольно сложного абстрактного мастера, для которого определён метаязык описания состояний и переходов между ними.
я скорее всего не буду пытаться это делать. для начала я спроектирую сам приказ (визард), а потом посмотрю - если будет возмоность как-то унифицировать приказы, чтобы они работали по метаданным, то сделаю, а если нет, то буду делать на каждый приказ библиотеку. Почти уверен, что выйдет по-второму варианту, поскольку (с учётом моего предыдущего вопроса) надо учитывать отмену уже изданных приказов.
На данный
Записан

Всю ночь не ем, весь день не сплю - устаю
neco
Участник

kz
Offline Offline

« Ответ #11 : 05-06-2008 16:52 » 

я хотел сказать:
На данный момент хочу прочувствовать весь мой визард-приказ, чтобы как можно больше вынести в абстрактные классы Order и Step, чтобы потом поменьше оставалось писанины и ответветсвенности в конечных классах-реализациях.
Записан

Всю ночь не ем, весь день не сплю - устаю
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 05-06-2008 18:02 » 

а как такой вариант?

* ex1.jpg (7.54 Кб - загружено 2573 раз.)
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
neco
Участник

kz
Offline Offline

« Ответ #13 : 05-06-2008 19:08 » 

Sla, да тоже самое

я не понимаю, что даёт диаграмма состояний для понимания как будет реализовываться внутренняя логика работы моего визарда.
всё-таки по-моему диаграмма состояний это не то... не для этого случая...
Шаблон State это да, но диаграмма тут нужна другая. Может сразу к диаграмме классов перейти?
Завтра с утра попробую...
Записан

Всю ночь не ем, весь день не сплю - устаю
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 05-06-2008 19:26 » 

neco, ты хочешь получить "нечто универсальное"
Имея граф переходов (состояний) достаточно легко строится wizard.
Достаточно только описать "реакцию" и точки перехода.

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

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

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 06-06-2008 09:20 » 

Цитата: neco
ну да разделяю - это два разных класса. Класс Wizard, а внутри него абстрактный класс Step и куча его наследников - реальных шагов. Класс визард имеет приватное свойство CurrentState (CurrentStep точнее), которое должно изменяться каждым шагом самостоятельно. Т.е. при нажатии на кнопку Next и вызове CompleteStep сам шаг решает, какой шаг будет следующим. Следовательно, при большом количестве шагов, избавляемся от громоздкой условной логики внутри Wizard'а (при линейной логике условностей вообще не будет).
Ты думаешь не о проекте, а о его реализации. То, что класс Step реализует состояние мастера в смысле шаблона проектирования "Состояние" (State), это понятно. Но это лишь способ программной реализации той основной идеи, что мастер меняет свои состояния, и что направление смены текущего состояния зависит как от входной информации, так и от текущего состояния.

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

И названия "Step 1", "Step 2", ... бессмысленны. Нужны конкретные названия, отражающие суть каждого экрана мастера. Если ты сумеешь в названиях состояний определить эту суть, ты даже сможешь при помощи этой диаграммы обсудить с пользователями порядок следования экранов и навигацию для того, чтобы пользователю было наиболее удобно решать свои задачи.

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

Т.е. на диаграмме состояний ты описываешь не факт того, что у тебя где-то есть состояния, а сами эти состояния, их смысл. Из смысла состояний вытекают и правила переходов между ними. Пока ты этого не сделаешь, нет смысла даже пытаться абстрагировать -- ты всегда получишь абстракцию типа шаблона проектирования "Состояние" (State) без всякой возможности включить туда что-то полезное для твоей предметной области.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #16 : 07-06-2008 21:57 » 

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

Накидал вот такую схему workflow (сам не знаю почему, но начал в Activity диаграмме - оказывается там всё тоже, что и в State):

честно говоря, очень доволен результатом, поскольку теперь реально вижу, что будет общим, а что будет лежать в отдельных приказах (фактически только ApplyChanges, RevertChanges и EditOrder - он же тот самый визард, о котором речь шла в начале). Таким образом, весь этот workflow отделился от внутренних Step'ов во время заполнения параметров и теперь уже не будет неопределённостью маячить в голове Улыбаюсь
Записан

Всю ночь не ем, весь день не сплю - устаю
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 08-06-2008 07:23 » 

neco, и эта диаграмма синтаксически некорректна.

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

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

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

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

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

Диаграммы не нужно слишком усложнять: 3-7 основных элементов, основные переходы; остальное детализируется в других диаграммах более мелкого масштаба.

Мне кажется, что ты попытался изобразить следующее.



Жизненный цикл приказа начинается, когда появляется соответствующая инициатива - это событие перехода из начального состояния (фиктивного, оно вне жизненного цикла приказа, приказа ещё нет) в состояние "Проект". На этапе проекта происходят все политические баталии, обсуждения, согласования, изменения, откладывания "под сукно" и возвращения к рассмотрению. Из этого состояния есть два пути: когда проект приказа согласован и принят (событие), приказ начинает действовать - переходит в состояние "Действует"; либо проект приказа окончательно отклоняется, и когда он отклонён (событие), он отправляется в мусорную корзину, на чём его жизненный цикл заканчивается. Со временем появляются новые приказы, отменяющие старые, поэтому, когда происходит отмена приказа (событие), он переходит из состояния "Действует" в некое другое состояние. Я назвал его "В архиве", ты назвал его "CancelledState" и свёл к нему как отменённые, так и отклонённые приказы, но, по-моему, более точно говорить об архивном хранении, для возможности посмотреть нормативную базу по старым делам. Возможно, в твоём случае и отклонённые проекты приказов тоже хранятся в архиве "в назидание потомкам" Улыбаюсь - тогда нужно проекты тоже переводит в архив. Этот период когда-нибудь заканчивается, поэтому я добавил условный переход по триггеру-таймеру к окончанию жизненного цикла приказа.

Сомневаюсь в целесообразности возврата из архива к состояниям "действует" или "проект". Обычно в таких случаях издают новые приказы. Зато может быть целесообразно ввести некое дополнительное состояние, в которое приказ переходит из состояния "Действует" по событию "Приостановлен", и из которого может вернуться в состояние "Действует" по событию "Возобновлён", либо перейти в состояние "В архиве" по событию "Отменён". Удачное название этого дополнительного состояния мне что-то на вскидку в голову не приходит... всё только слово "мораторий" крутится, но у него несколько другой смысл - похожий, но другой. Улыбаюсь

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

* p.jpg (10.95 Кб - загружено 2574 раз.)
« Последнее редактирование: 08-06-2008 07:36 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #18 : 08-06-2008 08:15 » new

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

Насчёт состояний и событий - я видимо реально всё напутал. наверное везде, где у меня небольшой прямоугольник сине-белого цвета, там должна быть просто надпись на стрелке.
А что делать с жёлто-синими прямоугольниками? Они у меня означают некое ключевое действие - в моём случае это применение или отмена действия приказа на сотрудника. Т.е. если приказ об увеличении зарплаты до 2000 баксов, то после шага ApplayChanges в БД значение поля должно будет измениться на 2000. А после шага RevertChanges, зарплата опять вернётся в предыдущему значению.
Как мне такое ключевое (важное для меня как разработчика) действие изобразить? в комментах только?

А с ромбиками что делать?

Может всё-таки это у меня диаграмма деятельности, а не диаграмма состояний получилась? Может если заменю все XXXXXState на Set to XXXXXState, то получится то, что нужно?
Записан

Всю ночь не ем, весь день не сплю - устаю
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 08-06-2008 10:03 » 

Цитата: neco
по-моему, не совсем корректная параллель - приказы и проекты.
Проект - это то, что у тебя названо черновиком ("DraftState"). Лучше, наверно, было назвать "В проекте", а не "Проект". Можно и "Черновик".

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

Но ничего вечного не бывает. Лучше так сказать: информация будет храниться в программном комплексе до окончания времени его эксплуатации, когда он из-за морального старения будет заменён более новой системой. Случится это, думаю, в ближайшие 20 лет. Концом может быть и ликвидация организации. Если реалистично взглянуть на вещи, то вечного не бывает Улыбаюсь Подумать о том, как из системы будет удаляться старая информация, нужно. С достаточно редкими приказами ещё терпимо, но в других системах свыше 99% архивных данных будут приводить к тому, что база данных будет бесполезно нагружать сервер, потом, возможно начнётся торможение работы вплоть до отказа.

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

Цитата: neco
и состояние Cancelled это не то же самое, что "в архиве", поскольку перед Cancelled происходит откат действия приказа - т.е. если приказ изменял позицию работника, то после отмены, сотрудник вернётся на старое место. А после архивации не должен. Если же выпустили новый приказ, то старый приказ тоже никак не должен изменять своё состояние. Состояние меняется у сотрудника.
потом в этой схеме я постарался максимально защититься от дурака. поэтому отменённый приказ можно пустить заново в обработку, не вводя заново данные по приказу (издавать новый приказ в этом случае не очень удобно). поэтому же из любого состояния можно перейти в любое состояние, ничего не боясь повредить.
Да, наверно событие "Отменить" не совсем удачно. Ты говоришь, что приказ не меняет своего содержания после выхода новых приказов - логично. Одним приказом Васю Пупкина перевели в отдел А, затем другим приказом того же Васю Пупкина перевели в отдел Б. Второй приказ перекрывает действие первого приказа в отношении Васи Пупкина. Это я и подразумевал под событием "Отменить". Но, наверно, один приказ может лишь отчасти затрагивать действие второго. В этом случае состояния "Действует" и "В архиве" становятся неразличимы. Даже явная отмена приказа есть новый более поздний приказ вида: "Считать приказ... недействительным." Например, так документы обрабатываются в SAP R\3...

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

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

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

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

Тут уж надо определиться.

Цитата: neco
Насчёт состояний и событий - я видимо реально всё напутал. наверное везде, где у меня небольшой прямоугольник сине-белого цвета, там должна быть просто надпись на стрелке.
А что делать с жёлто-синими прямоугольниками? Они у меня означают некое ключевое действие - в моём случае это применение или отмена действия приказа на сотрудника. Т.е. если приказ об увеличении зарплаты до 2000 баксов, то после шага ApplayChanges в БД значение поля должно будет измениться на 2000. А после шага RevertChanges, зарплата опять вернётся в предыдущему значению.
В какие моменты что меняется в БД, а что в ОЗУ - это пока ещё рано обсуждать. Если будет грамотно составлена диаграмма состояний приказа, то каждый переход из состояния в состояние будет означать запуск какого-либо действия: либо автоматического, либо мастера или диалогового окна, которые позволят пользователю ввести нужную информацию и вообще сообщить системе о том, что произошло событие. Например, посовещались и решили утвердить приказ: оператор запускает соответствующий мастер, поддерживающий процедуру перевода приказа из черновика в действующий со всеми сопутствующими операциями по организации исполнения приказа -- так система узнаёт о принятом решении и обеспечивает перевод приказа из одного состояния в другое.

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

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

Цитата: neco
Может всё-таки это у меня диаграмма деятельности, а не диаграмма состояний получилась? Может если заменю все XXXXXState на Set to XXXXXState, то получится то, что нужно?
У тебя тогда появятся деятельности вида "Начальник думает". Это деятельности, но начальника, а не системы. Ты же описываешь программную систему, а не всю работу твоей организации. Т.е. когда программа будет пытаться приказывать начальнику: "Думай и введи..." - это будет неудобная система, поскольку ты пытаешься начальника впихнуть в рамки алгоритма из-за того, что не совсем понимаешь, как разорвать поток управления. Это отчасти годится для армии, но в большинстве случаев не годится. Когда надо, начальник должен иметь возможность сам выбрать в программе тот вид дейятельности, который ему сейчас нужен, обратиться к тому приказу или проекту приказа, который его сейчас интересует, и этот приказ должен загрузиться в его текущем состоянии и предложить варианты дальнейших действий: "Отклонить", "Принять", "Согласовать", "Отказать в согласовании". При выборе каждого такого пункта для системы происходит событие, и система запускает соответствующую процедуру принятия, отклонения, согласования, исполнения и т.д., возможно, поддерживаемую мастером.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 08-06-2008 10:10 » 

Цитата: neco
поэтому отменённый приказ можно пустить заново в обработку, не вводя заново данные по приказу (издавать новый приказ в этом случае не очень удобно).
Здесь предлагаю рассмотреть вариант мастера по созданию нового приказа на основе (по шаблону) уже существующего - для упрощения ввода данных.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #21 : 08-06-2008 11:50 » 

Цитата: dimka
Но ничего вечного не бывает
разумеется.
и безграничных ресурсов тоже не бывает.
под "вечностью" подразумевается жизнь системы до следующего апгрейда.
меня вполне удовлетворит, если системы хватит на пять лет без обслуживания.
а вообще чистка данных, которые вводятся в ручную - это опасно, поскольку юзер часто говорит "ой" (старая версия программы работает уже почти год и со спецификой ведения дел на этом предприятии я уже более-менее знаком). поэтому в данном случае я против удаления чего-либо из базы - проще пометить как удалённое и потом в поиске фильтровать.
у меня на слуху есть опыт системы, в которой просто сделали каскадные constraint'ы и при удалении удалялось вообще Всё связанное с объектом. Потом столько возмущений было.
возможность отмены юзеры вообще видят только в виде "пусть в течении недели данный приказ можно будет отменить" и при этом ситуация "передумать через 7 дней" всем кажется реальной, а ситуация "передумать через 8 дней" - невозможной и означающей ручную правку БД или чего-нить в этом духе.
в этом плане мне нравится подход 1С бухгалтерии в отношении проводок - неважно когда была совершена проводка, её всегда можно отменить. Да, нерадивые бухгалтера отменяют старые операции и не перепроводят последующие, но это уже их личные проблемы, связанные с непониманием того, как работает система.

Цитата: dimka
какие ты предусмотрел для большей гибкости, как осуществлять откат изменений в объектах, попадающих под действие приказа в случае наложения влияний разных приказов разного периода на один объект
это и был мой первый в форуме вопрос - о реализации проводок.
я добавил ограничение на отмену - можно отменять только последний приказ. но после отмены последнего можно будет отменить предпоследний и так далее до самого первого. а затем исправить что-то в первом и повторить (перепровести) все последующие приказы (они ведь не удалены - просто в состоянии Cancelled, данные заново вводить не надо) и придти к текущему моменту.
иначе нельзя обойти ситуацию с наложением приказов на одни и те же атрибуты:
1. приказ №1 выставляет зарплату вместо 1000 в 1500.
2. приказ №2 выставляет зарплату вместо 1500 в 2000.
3. отмена приказа №1 возвращает значение 1000 для поля зарплаты и получается логическое нарушение.

кроме того, думаю, надо предусмотреть такую ситуацию:
1. приказ №1 выставляет (первый раз) зарплату в 1000.
2. приказ №2 выставляет вместо 1000 1500.
3. приказ №3 выставляет вместо 1500 2000.
теперь приказ №3 "помнит" старое значение 1500 и новое - 2000.
как-то надо сделать так, чтобы в случае последовательной отмены приказов №3 и №2 и повторного проведения приказа №3 в нём, в качестве старого значения сохранилось значение 1000 рублей.
получается, что сохранение старых значений надо делать в шаге CompleteOrder (раньше я думал, что в процессе редактирования буду записывать).

Цитата: dimka
Здесь предлагаю рассмотреть вариант мастера по созданию нового приказа на основе (по шаблону) уже существующего - для упрощения ввода данных.
в общем-то, это несложно сделать - копипастнуть xml со старого приказа и сохранить как драфт.
только это может увеличить количество ошибок (иначе пропущенные поля система не даст оставить) или придётся рядом кнопочку делать "значение проверено" и пока на него не кликнули, считать значение пропущенным, но это как-то сложно и мне написать и юзеру объяснить.
да и польза будет только при массовом вводе сотрудников на одну фирму - и выигрыш будет только в одном поле. остальные поля сплошь личная несовпадающая информация.
Записан

Всю ночь не ем, весь день не сплю - устаю
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #22 : 08-06-2008 14:23 » 

делопроизводство - вещь темная Улыбаюсь
Твой пример сродни применению правовых решений (законов, указов и пр.)
1. Закон
2. Добавления к закону,  или отменяющие действия пп NNN, или  внесение дополнительных, или переформулирующие некотрые пункты
3. Добавление (см. п. 2)
и т.д.
Самый последний Закон - об отмене Закона = архив.
Но это уже на уровне Приказов, уже принятых.
В твоем случае.
Wizard подразумевает действия на уровне принятия приказа - создание, редактирование, утверждение и т.д.
После окончания "начального" этапа - Вступление в силу.

Записан

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

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 08-06-2008 16:12 » 

Цитата: neco
я добавил ограничение на отмену - можно отменять только последний приказ. но после отмены последнего можно будет отменить предпоследний и так далее до самого первого. а затем исправить что-то в первом и повторить (перепровести) все последующие приказы (они ведь не удалены - просто в состоянии Cancelled, данные заново вводить не надо) и придти к текущему моменту.
иначе нельзя обойти ситуацию с наложением приказов на одни и те же атрибуты:
1. приказ №1 выставляет зарплату вместо 1000 в 1500.
2. приказ №2 выставляет зарплату вместо 1500 в 2000.
3. отмена приказа №1 возвращает значение 1000 для поля зарплаты и получается логическое нарушение.
А это реальная ситуация -- отменять первый приказ, сохраняя второй и последующие?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #24 : 08-07-2008 19:12 » 

извиняюсь за долгое отсутствие - сначала предложили ещё один проект, потом я им занялся, теперь хочу передать данный проект в субподряд, плюс квартал закончился - работы много, всё никак не успеваю.
но ваша помощь мне очень помогла и она не пропадёт напрасно - проект будет написан, заказчик на этом настаивает! Улыбаюсь
сейчас собираюсь на курсы по RUP'у, надеюсь после реальных примеров диаграмм, мои вопросы станут более правильными.
спасибо большое за помощь!
Записан

Всю ночь не ем, весь день не сплю - устаю
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 09-07-2008 10:25 » 

Цитата: neco
сейчас собираюсь на курсы по RUP'у, надеюсь после реальных примеров диаграмм, мои вопросы станут более правильными.
RUP и UML-диаграммы - вещи разные. RUP - это процесс разработки (кстати, весьма громоздкий и бюрократичный, имеющий смысл только для крупных и долгих проектов, хотя есть его адаптации для более мелких). Изучение этого процесса, хотя и полезно само по себе, но не поможет тебе лучше понять твою задачу (и задать здесь более точные вопросы - правильно заданный вопрос содержит половину ответа).
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
neco
Участник

kz
Offline Offline

« Ответ #26 : 15-01-2010 15:18 » 

Однако всё же этот проект загнулся. ))
Если кому интересно - на курсы по РУПу я всё же съездил и не могу сказать, что бесполезно. Да, не совсем всё понял, но ценным оказалось понимание того как бизнес диктует бизнес-модель, оттуда вытекают use case'ы, а из них требования, которые самым явным образом помогают разработке, тестированию и в конечном итоге успешному завершению проекта. Всего успешно завершённых пока три проекта за полтора года.
Однако, всё же испытываю сложности с проектами, в которых требований как таковых нет - т.е. программирование загодя. Не могу заложить достаточную гибкость в код. Но это уже тема для отдельного топика.
Записан

Всю ночь не ем, весь день не сплю - устаю
Dimka
Деятель
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 15-01-2010 19:47 » 

Цитата: neco
Однако, всё же испытываю сложности с проектами, в которых требований как таковых нет - т.е. программирование загодя. Не могу заложить достаточную гибкость в код. Но это уже тема для отдельного топика.
И, надо заметить, прелюбопытнейшая тема Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вахмурка
Помогающий

ru
Offline Offline
Пол: Мужской
Программист


WWW
« Ответ #28 : 16-01-2010 06:54 » 

Однако всё же этот проект загнулся. ))
Если кому интересно - на курсы по РУПу я всё же съездил и не могу сказать, что бесполезно. Да, не совсем всё понял, но ценным оказалось понимание того как бизнес диктует бизнес-модель, оттуда вытекают use case'ы, а из них требования, которые самым явным образом помогают разработке, тестированию и в конечном итоге успешному завершению проекта. Всего успешно завершённых пока три проекта за полтора года.

Use Case проще всего связывать с макетом пользовательского интерфейса, а интерфейс согласуется с заказчиком. Всему этому предшествует определённый этап, когда Use Case совсем "общие". Я пользуюсь таким подходом. Улыбаюсь
Записан

Программа – это мысли спрессованные в код.
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #29 : 17-01-2010 23:09 » 

Dimka, это
Цитата
RUP - это процесс разработки (кстати, весьма громоздкий и бюрократичный, имеющий смысл только для крупных и долгих проектов, хотя есть его адаптации для более мелких).
откуда следует? В самом рупе ничто на это не указывает, наоборот написано, что это методология подразумевает сильную адаптацию к среде, в которой идет разработка ПО (в том числе к размеру, сложности, новизне и т.д. и т.п. самого ПО), так что руп годится для любого проекта, а не только для крупных.

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

Вахмурка Вахмурка,
Цитата
Use Case проще всего связывать с макетом пользовательского интерфейса, а интерфейс согласуется с заказчиком
UI конечно же согласовывается с заказчиком, но этого мало, необходимо в первую очередь понять:
1. за что платят деньги
2. какой(~ие) БП или их части надо автоматизировать
3. какая должна быть функциональность ПО (т.е. что именно ПО должно делать, т.е. какие функции система должна предоставить "актерам")
4. какой должен быть UI
последовательность согласования именно такая.

neco,
Цитата
... проектами, в которых требований как таковых нет...
Если требований, как таковых нет, я бы даже за клавиатуру не сел. В данном случае, надо браться за лист бумаги и ручку и идти:
1. Человеку, который платит деньги (нужно, что бы вы поняли за что он платит деньги)
2. Человеку, который прекрасно знающий автоматизируемый БП (или знающий как надо изменить существующий БП). Выясняем БП (вот тут и должна быть выявлена и составлена диаграмма состояний приказов, которая к проектированию реализации /паттерны, классы, абстракции и т.д./ отношения не имеет). С этим человеком мы вникаем в БП и формируем UC (это сценарии использования системы)
2.1 Проверка на то, что результаты 2 коррелируют с 1
3. Человеку, который является/будет являться ключевым пользователем системы. Детализируем UC и выносим, рассматриваем и опять таки детализируем отдельно все функции системы (не забывая и про интеграцию их в единое целое, т.е. проверяя полноту покрытия и непротиворечивость)
3.1 Проверка на то, что результаты 3 коррелируют с 2 и как следствие с 1
4. На основе 3 проектируем UI формы с переходами и т.д.
4.1 Проверка того, что UI покрывает весь функционал
5. Составляем SRS и согласовываем

Архитектор берет в руки:
1. бумагу и карандаш на середине этапа 2 (выбирается платформа, среда, язык реализации, тулы и создается модульная архитектура)
2. клавиатуру в конце этапа 2 середине этапа 3 (определяется что пишем сами, а что закупаем, создается каркас приложения, т.е. тут как раз паттерны и т.д. и т.п. для критически важных частей и механизмов оповещения и диспетчеризации подсистем, также достаточно глубока проектируются сложные /новые, быстрые, чувствительные к пропускной способности, нагрузке и т.д. и т.п./ части системы)

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

Программист берет в руки клавиатуру
1. клавиатуру в середине пункта 4 (когда все функции достаточно точно выявлены и описаны, не вылизаны, но понятны так, что ПЕРЕделывать не придется, а вот ДОделывать - легко, а также разработан UI). Пишет (растит мышцу) реализацию для четко локализованных и продуманных структурных элементов (безусловно копаясь в своей песочнице реализации и имея право на шаг в право и шаг влево, но только в пределах утвержденных интерфейсов)  

К концу этапа 5 имеем прототип со всеми критичными для бизнеса UI формами, модулями (скелет, сосуды, нервные окончания и кожу, но почти без мышц, сердца и мозга).

После подтверждения заказчиком прототипа мы на верном пути, лабаем следующий прототип (реализуя в первую очередь самый важный/сложный функционал)

ЗЫ
тестирование и не функциональные требования опущены.
« Последнее редактирование: 17-01-2010 23:18 от lapulya » Записан

С уважением Lapulya
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines