Делая завершенную работу, откат в случае ошибки


У меня есть следующие строительные программы:

  while(true) {
    <...>
    try {
        JobManager.markJobCompleted(unitOfWork.getSqlFactory(), jobId, dataOut);
    } catch (DbLogicException e) {
        logger.error(JobManager.CANNOT_MARK_JOB_COMPLETED + jobId, e);
        try {
            unitOfWork.rollback();
        } catch (DbLogicException e1) {
            logger.error(UnitOfWork.CANNOT_ROLLBACK_TRANSACTION, e1);
            unitOfWork.closeSilently();
            return;
        }
        continue;
    }
    <...>
  }

Итак, логика заключается в следующем:

  1. Пытаюсь отметить работу завершено
  2. Если мы потерпим неудачу, попробовать откатить сделку и перейти к следующему пункту задания
  3. Если откат транзакции не удалось, что-то серьезно не так, прекращаем все

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



Комментарии
3 ответа

Да.


  1. Бросить специализированные исключения, как CannotMarkJobCompletedException и CannotRollbackTransactionException...

  2. Сделайте ваш метод toString() метод исключения, чтобы вернуть то, что вы хотите, что ваш регистратор для входа

  3. Вместо того, чтобы делать: ...CAN_..._COMPLETED + ид_задания, вы можете сделать: исключение уже знает эту ид_задания

  4. Храните исключение в переменную и вызвать после того, как ваш регистратор

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

6
ответ дан 27 апреля 2011 в 06:04 Источник Поделиться

Я сделал быстрый рефакторинг, чтобы извлечь новый метод UnitOfWork::rollbackOrCloseSilently(), но я не уверен, что это действительно помогает.

public boolean rollbackOrCloseSilently() {
try {
rollback();
return true;
}
catch (DbLogicException e) {
logger.error(CANNOT_ROLLBACK_TRANSACTION, e);
closeSilently();
return false;
}
}

В то время как он просто скрывает сложность в другой способ, это очистить ваш оригинальный кольцо:

while(true) {
<...>
try {
JobManager.markJobCompleted(unitOfWork.getSqlFactory(), jobId, dataOut);
} catch (DbLogicException e) {
logger.error(JobManager.CANNOT_MARK_JOB_COMPLETED + jobId, e);
if (!unitOfWork.rollbackOrCloseSilently()) {
return;
}
continue;
}
<...>
}

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

Начинаю заново, еще один простой, лучше будет извлечь весь код между парами <...> в новый метод того же класса. Раз у вас есть три возможных выхода: продолжить обычную обработку, если работа будет отмечена как завершенная ладно, продолжаем цикл рано, если он не отмечен, но откатывает, или выйти из метода, если он не может быть откат. Вот где конкретные исключения, как Inanç поставляет рекомендуемые могли бы помочь:

while (true) {
<...>
try {
markJobCompletedOrRollback(unitOfWork, jobId, dataOut);
}
catch (MarkCompletedException e) {
continue;
}
catch (RollbackException e) {
return;
}
<...>
}

...

private markJobCompletedOrRollback(UnitOfWork unitOfWork, ? jobId, ? dataOut) {
try {
JobManager.markJobCompleted(unitOfWork.getSqlFactory(), jobId, dataOut);
}
catch (DbLogicException e) {
logger.error(JobManager.CANNOT_MARK_JOB_COMPLETED + jobId, e);
try {
unitOfWork.rollback();
}
catch (DbLogicException e1) {
logger.error(UnitOfWork.CANNOT_ROLLBACK_TRANSACTION, e1);
unitOfWork.closeSilently();
throw new RollbackException();
}
throw new MarkCompletedException();
}
}

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

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

2
ответ дан 28 апреля 2011 в 02:04 Источник Поделиться

Как насчет этого:

while(true) {
<...>
try {
JobResult const result = JobManager.markJobCompleted(unitOfWork.getSqlFactory(), jobId, dataOut);
if (JobResult::Fail == result && unitOfWork.rollback())
{
unitOfWork.closeSilently();
}
}
catch (DbLogicException1 e) {
logger.error(JobManager.CANNOT_MARK_JOB_COMPLETED + jobId, e);
continue;
}
catch (DbLogicException2 e) {
logger.error(UnitOfWork.CANNOT_ROLLBACK_TRANSACTION, e1);
return;
}
}

1
ответ дан 27 апреля 2011 в 08:04 Источник Поделиться