Я бы попробовал что-то вроде этого:
class Mailer():
def send_message(self):
exception = None
for method in [self.connect,
self.authenticate,
self.send,
self.quit]:
try:
if not method(): break
except Exception, ex:
exception = ex
break
if method == quit and exception == None:
return True
if exception:
self.handle_exception(method, exception)
else:
self.handle_failure(method)
def connect(self):
return True
def authenticate(self):
return True
def send(self):
return True
def quit(self):
return True
def handle_exception(self, method, exception):
print "{name} ({msg}) in {method}.".format(
name=exception.__class__.__name__,
msg=exception,
method=method.__name__)
def handle_failure(self, method):
print "Failure in {0}.".format(method.__name__)
Все методы (включая send_message
, на самом деле) следуют одному и тому же протоколу: они возвращают True, если им это удалось, и если они на самом деле не обработают исключение, они его не перехватывают. Этот протокол также позволяет обрабатывать случай, когда метод должен указать, что он потерпел неудачу, не вызывая исключения. (Если единственным способом сбоя ваших методов является создание исключения, это упрощает протокол. Если вам приходится иметь дело со многими состояниями сбоя неисключения вне метода, который не удался, вы, вероятно, столкнулись с проблемой проектирования, которая еще не сработало.)
Недостатком этого подхода является то, что все методы должны использовать одни и те же аргументы. Я выбрал ни одного, ожидая, что методы, которые я заглушил, в конечном итоге будут манипулировать членами класса.
Преимущества этого подхода значительны, однако. Во-первых, вы можете добавить к процессу десятки методов, не усложняя send_message
.
Вы также можете сходить с ума и делать что-то вроде этого:
def handle_exception(self, method, exception):
custom_handler_name = "handle_{0}_in_{1}".format(\
exception.__class__.__name__,
method.__name__)
try:
custom_handler = self.__dict__[custom_handler_name]
except KeyError:
print "{name} ({msg}) in {method}.".format(
name=exception.__class__.__name__,
msg=exception,
method=method.__name__)
return
custom_handler()
def handle_AuthenticationError_in_authenticate(self):
print "Your login credentials are questionable."
... хотя в этот момент я мог бы сказать себе: «Сам, ты довольно тяжело работаешь с шаблоном Command, не создавая класс Command. Возможно, сейчас самое время».