Шаблоны проектирования для динамического наследования - PullRequest
2 голосов
/ 09 апреля 2011

Вот что я пытаюсь сделать, я не уверен, что искать или как правильно спроектировать это:

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

try:
    mightThrowAnException()
except RecoverableException:
    handleThisException()

И тогда у меня будет что-то вроде:

class MyException(...):
    ...

Где MyException может принимать FatalException или RecoverableException в качестве базового класса, в зависимости от того, что происходит в конструкторе.

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

Итак, пара вопросов:

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

Ответы [ 2 ]

6 голосов
/ 09 апреля 2011

Я рекомендую отделить содержание исключения от его значения.Одно и то же исключение может иметь разные значения в разных местах!

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

1 голос
/ 09 апреля 2011

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

class MyBaseException(Exception):
    def __init__(self, ..., fatal=True):
        self.fatal = fatal

class MyException(MyBaseException):
    ...

try:
    do_something_that_raises()
except MyBaseException, e:
    if e.fatal:
        logging.error(e)
        raise
    else:
        recover_somehow(e)

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

...