Добрый день.
Пытаюсь тут упороться. Если кратко -> есть множество FSM, которые общаются между собой эвентами. Так же есть большой проект с кучей легаси.
В проекте эвенты делятся на запросы/ответы (упрощёно). Сейчас генерация ответа на запрос происходит рандомно + совсем нет никакого контроля о том был ли послан ответ на запрос или нет + нет защиты от повторного ответа.
Что я хочу сделать:
- добавить проверки ответа (просто в деструкторе)
- добавить проверку на то что ответ посылается только один раз
- ОБЯЗАТЬ запросы иметь 2 метода: ResponseSuccess(), ResponseError().
Если пункты 1 и 2 реализовать просто то возникает вопрос как адекватно сделать 3й пункт? Есть возможность допилить проект, чтобы реализовать хотя бы эти 3 пункта.
Подскажите, пожалуйста, в какую сторону смотреть? Ничего адекватного в голову не приходит.
Использовать можно 17й стандарт. Желательно чтобы это всё дело работало быстро.
Ниже прилагаю псевдокод, может быть это внесёт больше ясности в моё упоротое описание задачи, код не рабочий, просто попытался саму суть показать что хочу запилить. В реальности задача сложнее, дела обстоят сложнее, но этой задачи в вакууме будет достаточно чтобы сильно продвинуться дальше, код в чистом виде в проект не пойдёт, просто хочется понять принцип как это дело можно сделать красиво.
#include <iostream>
enum EventId
{
REQUEST_A
, ERROR_A
, SUCCESS_A
, REQUEST_B
, ERROR_B
, SUCCESS_B
};
class EventReceiver;
class RequestA;
class ErrorA;
class SuccessA;
class RequestB;
class ErrorB;
class SuccessB;
class Event
{
public:
using Id = uint64_t;
explicit Event(EventReceiver* receiver = nullptr) : _receiver{receiver} {}
virtual void ResponseError() const = 0;
virtual void ResponseSuccess() const = 0;
[[nodiscard]] virtual Id GetId() const = 0;
protected:
EventReceiver* _receiver = nullptr;
};
class RequestA : public Event
{
public:
explicit RequestA(std::string message) : _message{message} {};
[[nodiscard]] Id GetId() const override { return REQUEST_A; }
void ResponseError(std::string message) const {_receiver->Send(new ErrorA{message});};
void ResponseSuccess(int value, std::string message) const {_receiver->Send(new SuccessA{value, message});};
std::string _message;
};
class ErrorA : public Event
{
public:
ErrorA(std::string message) : _message{message} { }
[[nodiscard]] Id GetId() const override { return ERROR_A; }
std::string _message;
};
class SuccessA : public Event
{
public:
SuccessA(int value, std::string message) : _value{value}, _message{message} { }
[[nodiscard]] Id GetId() const override { return SUCCESS_A; }
int _value = 0;
std::string _message;
};
// ещё N таких же запросов/ответов с разными конструкторами //
class EventReceiver
{
public:
void Send(Event* rawEvent);
void Receive(Event* rawEvent)
{
switch (rawEvent->GetId())
{
case REQUEST_A:
{
auto* event = dynamic_cast<RequestA*>(rawEvent);
if (rand()%2)
{
event->ResponseError("Unlucky");
}
else
{
event->ResponseSuccess(42, "Lucky");
}
break;
}
case REQUEST_B:
{
auto* event = dynamic_cast<RequestB*>(rawEvent);
if (rand()%3)
{
event->ResponseError("Unlucky", "Try again later", false, 42);
}
else
{
event->ResponseSuccess();
}
break;
}
case ERROR_A:
case SUCCESS_A:
case ERROR_B:
case SUCCESS_B:
{
std::cout << "Received: " << rawEvent->GetId() << std::endl;
break;
}
}
}
};