K
K
Kirill Gorelov2020-01-09 11:11:41
Software design
Kirill Gorelov, 2020-01-09 11:11:41

Application design and architecture?

Guys, hello everyone.
I'm a little confused and have a mess in my head after reading McConnell, Gang of Four and Robert Martin. I plan to read Fowler and about DDD.
Separately, I understand how everything works, but how to put it together, my eyes widen from the choice of different possibilities that OOP provides me.
Now for example.
I take a specific situation that I need to solve - this is logging in the program.
I want to trace a log of how the program algorithm is executed, write to a file. Catch exceptions and send them to mail and telegrams.
What I did for this, I will give a conditional code. (python)

from classes import Logger

def example_code():
  Logger.log('старт скрипта')

  try:
    r = 1+1
    Logger.log('Нормально все прошло идем дальше')
  except Exception as e:
    Logger.log('Исключение')

  Logger.log('конец работы скрипта')

Since this is a case study, I would leave everything. But in a real application, I would not do this, I finalized it, especially the except block.
Because by condition, I want to catch exceptions and write to a file, as well as send myself notifications to mail and telegrams.
I see two options here.
First:
Just add another class MyTelegramm and MyException, and call them in the except block. The MyException class will write more exceptions separately.
from classes import Logger
from classes import MyEmail
from classes import MyTelegramm
from classes import MyException

def example_code():
  Logger.log('старт скрипта')

  try:
    к = 1+1
    Logger.log('Нормально все прошло идем дальше')
  except MyException as e:
    Logger.log('Исключение')
    MyEmail.send()
    MyTelegramm.send()

  Logger.log('конец работы скрипта')

Option two.
And shove all the exception handling logic into the MyException class.
And already in the MyException class, inherit three classes and there already record and send logs to me by mail. I understand that this is far from the limit, and you can leave both the first and second options, and even come up with something else. I also understand that I'm looking for the perfect option, but why not?).
class MyExeption(Logger, MyEmail, MyTelegramm):

Answer the question

In order to leave comments, you need to log in

2 answer(s)
E
Evgeny Shatunov, 2020-01-10
@Kirill-Gorelov

First and foremost, the client code should remain clean, consisting as much as possible of the implementation code of the algorithm and as little as possible of the code that maintains this implementation.
The client code should not know anything about how you want to, for example, notify the user about exceptions. He simply does not need to know this, it is important for him to just work.
So from classes import MyTelegrammI don't think it's worth it. I try-catchdon't like it there either. Let the user write blocks try-catchonly for himself and only when he needs it. When he can definitely catch an exception and get out of the situation. About such exceptions, in a good way, you don’t need to know, because. they only change the execution branch, but do not break it.
The client code should be executed in a controlled environment, inside a special protective block try-catch, in which you will already catch all the exceptions available to you and dispatch them.
Let's say doit performs all the actions of the task inside its protective circuit . At the same time, doit has several such protective circuits, including the most basic one, which is responsible for notifying about critical malfunctions. What I don't like a little about doit is that exception handling is done in place instead of organizing some dispatcher in which this exception is already handled.
I would connect my protection circuit to the exception dispatcher. If there are several contours, then I would also make several dispatchers, placing all the dispatchers in the locator (Service locator).
The dispatcher would start by wrapping the exception in an envelope ( Envelope , [ 2 ], [ 3 ]). The envelope is simply easier to read than an unpredictable type exception. Wrapping I would do with the help of an Abstract factory of envelopes, in which the exception of each type and from each source would be wrapped in the correct envelope according to the factory configuration.
Having received the envelope, the dispatcher visited ( Visitor) with this envelope the mailbox of each addressee. The recipient's mailbox can be equipped with a strategy ( Strategy ) for receiving envelopes, according to which the mailbox will either rewrite the envelope to itself or leave it unattended, depending on the data written on the envelope. Mailboxes can be managed by the dispatcher's local registry ( Registry ), which can also implement a bypass function (Visit) to visit mailboxes.
The mailbox serves the addressee. The recipient can subscribe ( Observer ) to receive a letter, or can come to the mailbox for new letters on a schedule and get only the first few letters, and not all. How to rake out a mailbox is a matter of configuration of the addressee.
When the addressee picks up the letters, he distributes them to the endpoints, in the role of which all these MyTelegrammor will already act MyLog, but strictly configured and accepting only a copy of the letter.
This whole heap of design patterns draws on a whole separate layer with a set of subsystems, each of which will have its own unforgettable devilry:
- A protective loop subsystem and only an exception manager (along with a locator, if needed).
- A subsystem for wrapping an exception in an envelope, an envelope factory and a configurator for this factory.
- A client behavior strategy subsystem and, possibly, a strategy configurator for a specific client.
- Envelope client subsystem, client registry, client factory and configuration of this factory.
And, of course, any part of all this disgrace can be discarded and written easier. :)
At the initial stages, you can mute the strategies and reduce the configurators to the form of a linear function.
MVP here, in my opinion, will look like a complete system with guaranteed delivery of an envelope with any exception to all created endpoints, passing them from the protective loop, through the dispatcher and to the addressee through the mailbox.

D
dmitriy, 2020-01-09
@dmitriylanets

And shove all the exception handling logic into the MyException class.
- not true, the exception handling logic should be in the code that uses your functionality and catches these exceptions,
so the first option

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question