170 похожих чатов

Вопрос о надёжности. У меня есть система запуска длительных заданий.

У задания есть тип, входные параметры и результат.

Тип это enum. Обработчик заданий берет десериализованное сообщение, в нем всегда есть поле с типом, и в большом switch доходит до ветки кода для этого конкретного типа сообщения, десериализует исходное сообщение ещё раз, уже в тип соответствующий типу задания и передаёт обработчику для этого типа заданий.

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

Затем я сделаю словарь с ключом по типам сообщений, т.е. enum, и значением для ключа - наследником того класса. И буду для каждого сообщения создавать экземпляр соответствующего класса и вызывать тот самый виртуальный метод, в котором будет уже написана десериализация сообщения в нужный тип и вся последующая логика.

Но вот вопрос. Для нового типа задания мне будет нужен новое значение в enum. В первом варианте обработчика, со switch, я могу повесить прагму, которая будет выдавать ошибку компиляции, если некое значение enum отсутствует в одном switch. А в варианте с со словарём, виртуальным методом и Фаулером у меня не будет способа заставить компилятор проверить корректность моего кода. Я могу конечно написать тест, только вот тест - это не проверка компилятора, а нечто иное.

Итак, можно ли заставить компилятор проверять вариант с виртуальным методом? Как бы вы сделали? Заранее попрошу не писать про MassTransit и около, он тут мало применим.

12 ответов

24 просмотра

Не понимаю, почему что то прописать в switch можно, а заполнение словаря нельзя. И не много не понятно, что именно хочешь ты от виртуального метода, что ты его проверяешь.

Слава- Автор вопроса
Сергей (F L )
Не понимаю, почему что то прописать в switch можно...

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

Слава
Хочу я вот чего: чтобы когда один человек пишет за...

не уверен что именно делать должно. Но для таких вариантов, мне кажется удобным система создания абстрактного класса который определяет 2 вещи. Как модель он несет сообщение - задание. И он же как инициатор задания определяет, как системе его обработать. Если это не большая логика, то в несколько делегатов можно запихнуть логику. Ну и наследоватся от абстрактного класса. Потом в одном месте ты их собираешь, и просто запускаешь. ничего искать по системе, где прописать, что забыл, не надо

Слава- Автор вопроса
Сергей (F L )
не уверен что именно делать должно. Но для таких в...

Как модель несёт задание. А как оное задание будет сериализоваться и десериализоваться? Ведь нам при первой десериализации, первичной, нужно понять, что это за сообщение, к какому классу оно принадлежит.

Слава
Как модель несёт задание. А как оное задание будет...

так же как и всегда. Сериализуются данные а не логика. Ты же это гоняешь не в рантайме так ? значит конкретные типы есть. В них можно пихнуть это. В какой то класс оно же десериализуется.

Слава- Автор вопроса
Сергей (F L )
так же как и всегда. Сериализуются данные а не лог...

Да, есть конкретные типы. И они должны быть помечены неким уникальным маркером, значением известного поля. А таким уникальным маркером обычно является энум, потому что он гарантирует уникальность имён. Ну можно отдельный набор констант завести, только вот зачем - непонятно. А коль скоро у нас имеется маркер, значит нужно выдумывать способ сопоставить маркер с конкретным классом, в том месте, где сообщение будет получено. А это либо большой switch, отсутствие значений в котором может быть проверено компилятором, либо таблица соответствия маркеров и классов. А в таблицу можно забыть добавить значение, и компилятор тут не поможет, в отличие от switch.

Слава
Да, есть конкретные типы. И они должны быть помече...

Делаешь абстрактный обработчик сообщения, реализуешь для каждого сообщения свою логику, скажем парсить сообщение по особому формату. Это думаю вполне в модель можно положить. Работаешь с абстрактным классом. Зачем тебе маркера Enum мне не понятно. Нужно уменьшать количество изменений в коде, при добавлении логики, а не увеличивать ее.

Слава- Автор вопроса
Сергей (F L )
Делаешь абстрактный обработчик сообщения, реализуе...

Вот у нас пришло сообщение. Пока что это строка, в ней json. У нас есть два типа сообщений: А и Б. Как я отличу А от Б в коде? Я полагаю, что для этого у всех сообщений должно быть некое обязательное поле, например MessageType. По его значению и можно будет понять, как десериализовать это сообщение правильно, что там лежит. Я ошибаюсь?

Слава
Вот у нас пришло сообщение. Пока что это строка, в...

Ты таким же успехом можешь сделать фабрику. Причем почти по той же логике. Ты определяешь классы А и Б, в них определяешь логику валидности данных. Где то в фабрике ты циклом можешь пройтись по скажем константным полям, или методам, если один класс признал формат, выбираешь его, сериализуешь в него. Дополнять список цикла можно через рефлексию наверно, не уверен конечно что так прокатит. НУ или на худой конец ручками. И в итоге. именно класс будет отвечать за наличие проверки валидности сообщения для него. А не внешний свич. Что несколько удобнее. Я почти уверен что можно автоматизировать поиск типов

Слава
Вот у нас пришло сообщение. Пока что это строка, в...

Можно схему json построить по классу, а потом валидацию входных данных делать, там где без ошибок, тот тип и будет

Если нужна конкретная реализация десереализации для каждого типа, то, теоретически, "вумный как вудка Фаулер" прав. Можно обойтись без энама, а сделать бстрактный хендлер с виртуальным методом десереализации и обработчик для каждого типа. Посмотри паттерн цепочка зависимостей.

Слава- Автор вопроса
Nikolay Shamshurin
Если нужна конкретная реализация десереализации дл...

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

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
Ребят в СИ можно реализовать ООП?
Николай
33
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта