Шаблон проектирования, который может заменить цепной переключатель / переход? - PullRequest
27 голосов
/ 27 октября 2010

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

int version = 1002;   // current app version

switch(version)
{
   case 1001:
      updateTo1002();
      goto case 1002;

   case 1002:
      updateTo1003();
      goto case 1003;

   case 1003:
      updateTo1004();
      goto case 1004;
      break;

   case 1004:
      updateTo1005();
      break;
}

Здесь у нас есть каскадный метод, вызываемый путем перехода к указанному блоку case. Интересно - это хорошая практика, которую следует использовать (в данном случае это часто считается плохой практикой!)? Я не хочу вызывать метод один за другим - вот так:

updateTo1002()
{
   // do the job
   updateTo1003();
}
updateTo1003()
{
   // do the job
   updateTo1004();
}

Есть ли какой-нибудь шаблон проектирования, описывающий такую ​​проблему?

Ответы [ 13 ]

0 голосов
/ 28 октября 2010

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

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

У вас должна быть просто коллекция объектов, каждый с кодом обновления и номером версии.

Вы просто перебираете эту коллекцию, пока номер версии <вашей целевой версии, и вызываете обновлениекод этого объекта для каждого.Таким образом, чтобы создать новый уровень обновления, вы просто создаете один объект «Обновление» и помещаете его в коллекцию. </p>

Ваша цепочка объектов обновления может быть перемещена как назад, так и вперед с добавлениемотмена и очень тривиальное добавление кода к контроллеру - то, что станет кошмаром для использования с примером кода.

0 голосов
/ 28 октября 2010

Мне приходилось сталкиваться с такой проблемой (получить файл в этом формате, чтобы его можно было перевести в этот другой формат и т. Д.), И мне не нравится выражение switch. Версия с тестами 'if' может быть хорошей или рекурсивной может иметь что-то вроде:

/* Upgrade to at least version 106, if possible.  If the code
   can't do the upgrade, leave things alone and let outside code
   observe unchanged version number */

void upgrade_to_106(void)
{
  if (version < 105)
    upgrade_to_105();
  if (version == 105)
  {
    ...
    version = 106;
  }
}

Если у вас нет тысяч версий, глубина стека не должна быть проблемой. Я думаю, что версия if-test, тестируемая специально для версий, с которыми может справиться каждая процедура обновления, читается лучше; если номер версии в конце не тот, который может обрабатывать основной код, сообщите об ошибке. Или же вы можете потерять операторы if в основном коде и включить их в подпрограммы. Мне не нравится выражение 'case', потому что оно не учитывает возможность того, что подпрограмма обновления версии может не работать или обновлять более одного уровня за раз.

0 голосов
/ 27 октября 2010

Я думаю, что все в порядке, хотя я сомневаюсь, что это ваш настоящий код. Вы уверены, что вам не нужно инкапсулировать метод Update внутри класса AppUpdate или что-то еще? Тот факт, что у вас есть методы с именами XXX001, XXX002 и т. Д., Не очень хороший знак, ИМО.

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

var updates = new Action[] 
                 {updateTo1002, updateTo1003, updateTo1004, updateTo1005};

if(version < 1001 || version > 1004)
   throw new InvalidOperationException("...");    

foreach(var update in updates.Skip(version - 1001))
   update();

Было бы трудно порекомендовать наиболее подходящий шаблон без более подробной информации.

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