Нарушение разделения командного запроса - PullRequest
1 голос
/ 14 апреля 2011

Что вы думаете о

 if(!DoSomething()) return;

В чистом коде это рассматривается как нарушение разделения командных запросов. Но как понять, что в команде DoSomething () что-то пошло не так? А как насчет команды sql (например, void Delete (Table))? Как мы можем узнать, существовала ли эта таблица?

Спасибо.

Ответы [ 4 ]

1 голос
/ 12 февраля 2012

Я напишу этот пример на Eiffel, чтобы его было проще понять.

my_code
      -- Calls the `do_something' routine
   do
      set_table ("my_table")
      do_something
   end

do_something
      -- Something to do
   require
      valid_table: is_valid_table (table_name)
   do
      sql_list := execute_sql_on_table (table_name)
   ensure
      has_result: sql_list.count > 0
   end

sql_list: ARRAYED_LIST [STUFF]

table_name: STRING

set_table (a_name: STRING)
       -- Set `table_name' to `a_name'
   require
      has_name: not a_name.is_empty
      valid_table: is_valid_table (a_name)
   do
      table_name := a_name
   ensure
      table_name_set: table_name.same_string (a_name)
   end

delete_table (a_name: STRING)
      -- Delete `a_name' from the database.
   require
       valid_table: is_valid_table (a_name)
   do
      execute_sql ("DROP TABLE " + a_name)
   ensure
       table_gone: not is_valid_table (a_name)
   end
  1. Функция `do_something '- это команда, в которой массив sql_list должен быть загружен с помощью STUFF из таблицы" my_table ".
  2. Предварительное условие для do_something' makes it the responsibility of the client my_code 'для предоставления table_name' before making the call to do_something'.
  3. В свою очередь, договор о пост-условии обеспечения возлагает на него ответственность поставщика do_something' fill the array sql_list 'с экземплярами STUFF.
  4. Функция sql_list представляет собой запрос, возвращающий ссылочный указатель на массив STUFF.
  5. Аналогично, функция table_name' is a query returning a reference pointer to a STRING, which is set with a "setter" command called set_table '.

В этом случае «контракты» «Разработка по контракту» обеспечивают надлежащее разделение интересов и кто за что отвечает в этом небольшом фрагменте кода выше. Обратите внимание на явное отсутствие конструкций TRY-CATCH в коде. В этом случае ожидается, что источник данных будет иметь «my_table». Наличие контрактов означает, что программное обеспечение вызовет исключение, если контракт не будет выполнен. Сбой по требованию говорит о том, что вызывающий абонент неисправен, а сбой в проверке после условия указывает на функцию поставщика.

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

«Но как мы можем понять, что что-то в команде DoSomething () пошло не так? Как насчет команды sql (например, void Delete (Table))?

Хотя это может быть правдой, что вызов delete_table ("my_table") может быть внедрен в какого-то предка или может произойти в другом потоке, для этого и нужны контракты в do_something'. As long as those contracts stand guard over calls to do_something ', процесс будет соответствующим образом обрабатываются. Внедренный вызов delete_table просто приведет к сбою контракта.

Все это предполагает, что НЕЛЬЗЯ БРОСАТЬ ТАБЛИЦУ на "my_table", и это трагически случайно. Тем не менее, если для «my_table» станет ОК для DROP TABLE, то для управления этим вариантом использования потребуется механизм повтора или другой «обработчик», и приведенный выше код работать не будет.

1 голос
/ 14 июля 2011

Если что-то пошло не так, DoSomething(), вероятно, должно выдать исключение, если вы, как вызывающая сторона, должны это обработать.
Например:

try  
{  
  DoSomething();  
  // .. do more after success  
}  
catch(SomeException ex) // maybe focus on a special error
{
  // maybe do something special or just clean up!  
}  
1 голос
/ 24 июля 2011

Я согласен с комментариями от rObiwahn, что вы должны проверить CanDoSomething перед выдачей команды DoSomething.В чистой среде CQRS DoSomething не будет ничего возвращать, и если что-то помешает Что-то произойти (не из-за исключения, а из-за состояния гонки или чего-то другого, изменяющегося между CanDoSomething и DoSomething), ваш домен выдастDoSomethingWasInvalid событие (или что-то в этом роде), которое позволит вашему приложению в конечном итоге стать согласованным.

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

В группе DDD / CQRS в группах Google есть много хороших ресурсов.Вопрос типа ' Как сообщить отправителю, что команда не выполнена? ' немного похож на ваш вопрос.Такие люди, как Уди Дахан, Грег Янг, Ринат Абдуллин и другие, следят за этой группой и дают действительно отличные ответы.Я бы рекомендовал проверять это время от времени тоже.

Надеюсь, это поможет!

0 голосов
/ 14 апреля 2011

Мне действительно пришла в голову эта вещь сейчас [почему мы не думаем о «проблемах разделения», а не «разделения интересов»!] Я знаю, что это не по теме, но слишком сильный толчок для стандартов приведет кНЕТ ГДЕ.Из истории человечества легко увидеть, как много практик / стандартов оказались неверными со временем!все зависит от вашей перспективы совершенства.

, поэтому в таком случае я всегда стараюсь думать об обратном, чтобы оставаться РЕАЛЬНЫМ.Я хочу сказать больше, но я думаю, что этого достаточно с моей точки зрения ответа;)

удачи!

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