Самое первое и самое главное: клиентский код должен оставаться чистым, состоять как можно больше из кода реализации алгоритма и как можно меньше из кода обслуживающего эту реализацию.
Клиентский код ничего не должен знать о том, как ты хочешь, например, оповещать пользователя об исключительных ситуациях. Ему просто незачем это знать, ему важно просто работать.
Поэтому,
from classes import MyTelegramm
- думаю, не стоит. Мне там и
try-catch
тоже не нравится. Пусть пользователь блоки
try-catch
пишет только для себя и только тогда, когда ему это надо. Когда он точно может словить исключение и выкрутиться из ситуации. Про такие исключения тебе, по-хорошему, и знать-то не стоит, т.к. они лишь меняют ветвь исполнения, но не обрывают его.
Клиентский код стоит выполнять в контролируемой среде, внутри специального защитного блока
try-catch
, в котором ты уже будешь ловить все доступные тебе исключения и производить их диспетчеризацию.
Скажем, doit все действия задачи выполняет внутри своего
защитного контура. При этом, таких защитных контуров у doit несколько, включая и самый
базовый, отвечающий за оповещение о критических сбоях работы. Что мне в doit малость не нравится, так это что обработка исключения делается по месту вместо того, чтобы организовать некоторый диспетчер, в котором это исключение уже и обрабатывать.
Свой защитный контур я бы связал с диспетчером (Dispatcher) исключений. Если контуров делать несколько, то и диспетчеров я тоже сделал бы несколько, разместив все диспетчеры в локаторе (Service locator).
Диспетчер начал бы свою работу с того, что завернул бы исключение в конверт (
Envelope, [
2], [
3]). Конверт просто легче читать, чем исключение непредсказуемого типа. Заворачивание я бы сделал с помощью абстрактной фабрики (
Abstract factory) конвертов, в которой исключение каждого типа и от каждого источника было бы завернуто в правильный конверт согласно конфигурации фабрики.
Получив конверт, диспетчер посетил(
Visitor) бы с этим конвертом почтовый ящик каждого адресата. Почтовый ящик адресата можно снабдить стратегией (
Strategy) приема конвертов, согласно которой почтовый ящик или перепишет конверт к себе, или оставит без внимания, в зависимости от написанных на конверте данных. Управлять почтовыми ящиками может локальный реестр (
Registry) диспетчера, в котором так же может быть реализована и функция обхода (Visit) для посещения почтовых ящиков.
Почтовый ящик обслуживает адресата. Адресат может подписаться (
Observer) на поступление письма, а может приходить к ящику за новыми письмами по расписанию и доставать только первые несколько писем, а не все. Как выгребать почтовый ящик - вопрос конфигурации адресата.
Когда адресат забирает письма, он раздает их в конечные точки, в роли которых уже и будут выступать все эти
MyTelegramm
или
MyLog
, но строго сконфигурированные и принимающие уже только копию письма.
Весь этот ворох шаблонов проектирования тянет на целый отдельный слой с набором подсистем, в каждой из которых будет твориться своя незабываемая чертовщина:
- Подсистема защитного контура и только диспетчера исключений (вместе с локатором, если он нужен).
- Подсистема обертывания исключения в конверт, фабрики конвертов и конфигуратора этой фабрики.
- Подсистема стратегии поведения клиента и, возможно, конфигуратора стратегии для конкретного клиента.
- Подсистема клиентов конверта, реестра клиентов, фабрики клиентов и конфигура этой фабрики.
Ну и, конечно же, любую часть всего этого безобразия можно отбросить и написать проще. :)
На начальных этапах можно заглушить стратегии и свести конфигураторы к виду линейной функции.
MVP тут, на мой взгляд, будет выглядеть как цельная система с гарантированной доставкой конверта с любым исключением во все созданные конечные точки, проводя их от защитного контура, через диспетчер и до адресата через почтовый ящик.