I have a bit of code duplication and trying to figure a better way to reduce it. I'm looking for any suggestions. If this was in Java I could easily use reflection.
The code posted is a basic sample but hopefully, gives the idea of the duplication problem I'm having. The application is made up of "events" that get serialised to and from json. An event is never changing so all the fields are const.
I have a method that creates a child instance of the event class by just passing the enum like so:
std::shared_ptr<Event> Event::createInstance(const EventType eventType) {
switch (eventType) {
case EVENT_TYPE_SET_MATCH_TYPE:
return std::make_shared<Event::SetMatchType>();
case EVENT_TYPE_SET_MATCH_TEAM_PLAYER:
return std::make_shared<Event::SetPlayer>();
case EVENT_TYPE_SET_MATCH_TEAM:
return std::make_shared<Event::SetTeam>();
case EVENT_TYPE_START_INNINGS:
return std::make_shared<Event::StartInnings>();
case EVENT_TYPE_END_INNINGS:
return std::make_shared<Event::EndInnings>();
case EVENT_TYPE_START_MATCH:
return std::make_shared<Event::StartMatch>();
case EVENT_TYPE_START_OVER:
return std::make_shared<Event::StartOver>();
case EVENT_TYPE_END_OVER:
return std::make_shared<Event::EndOver>();
case EVENT_TYPE_BALL:
return std::make_shared<Event::Ball>();
case EVENT_TYPE_EXTRA_BALL:
return std::make_shared<Event::ExtraBall>();
case EVENT_TYPE_PENALTY:
return std::make_shared<Event::Penalty>();
case EVENT_TYPE_RETIRE:
return std::make_shared<Event::Retire>();
case EVENT_TYPE_RESUME_MATCH:
return std::make_shared<Event::ResumeMatch>();
case EVENT_TYPE_END_MATCH:
return std::make_shared<Event::EndMatch>();
case EVENT_TYPE_SWAP_BATSMAN:
return std::make_shared<Event::SwapBatsman>();
case EVENT_TYPE_NEW_BATSMAN:
return std::make_shared<Event::NewBatsman>();
case EVENT_TYPE_NEW_BOWLER:
return std::make_shared<Event::NewBowler>();
case EVENT_TYPE_NEW_WICKET_KEEPER:
return std::make_shared<Event::NewWicketKeeper>();
case EVENT_TYPE_WICKET:
return std::make_shared<Event::Wicket>();
case EVENT_TYPE_UNDO:
return std::make_shared<Event::Undo>();
case EVENT_TYPE_AUDIT_ADD:
return std::make_shared<Event::AuditAddBall>();
case EVENT_TYPE_AUDIT_REMOVE:
return std::make_shared<Event::AuditRemove>();
case EVENT_TYPE_AUDIT_MODIFY:
return std::make_shared<Event::AuditModify>();
case EVENT_TYPE_AUDIT_RETIRE_MODIFY:
return std::make_shared<Event::AuditModifyRetirement>();
case EVENT_TYPE_ADD_NOTE:
return std::make_shared<Event::AddNote>();
case EVENT_TYPE_REMOVE_NOTE:
return std::make_shared<Event::RemoveNote>();
case EVENT_TYPE_NEW_CAPTAIN:
return std::make_shared<Event::SetCaptain>();
default: break;
}
return nullptr;
}
I have another method that creates a child instance of the event class by json:
std::shared_ptr<Event> Event::createInstanceFromJson(const Value &serializedJson) {
auto member = serializedJson.FindMember("Event.eventType");
if (member == serializedJson.MemberEnd()) {
throw std::invalid_argument{"Error..."};
}
auto eventType = static_cast<EventType>(member->value.GetInt());
switch (eventType) {
case EVENT_TYPE_SET_MATCH_TYPE:
return std::make_shared<Event::SetMatchType>(serializedJson);
case EVENT_TYPE_SET_MATCH_TEAM_PLAYER:
return std::make_shared<Event::SetPlayer>(serializedJson);
case EVENT_TYPE_SET_MATCH_TEAM:
return std::make_shared<Event::SetTeam>(serializedJson);
case EVENT_TYPE_START_INNINGS:
return std::make_shared<Event::StartInnings>(serializedJson);
case EVENT_TYPE_END_INNINGS:
return std::make_shared<Event::EndInnings>(serializedJson);
case EVENT_TYPE_START_MATCH:
return std::make_shared<Event::StartMatch>(serializedJson);
case EVENT_TYPE_START_OVER:
return std::make_shared<Event::StartOver>(serializedJson);
case EVENT_TYPE_END_OVER:
return std::make_shared<Event::EndOver>(serializedJson);
case EVENT_TYPE_BALL:
return std::make_shared<Event::Ball>(serializedJson);
case EVENT_TYPE_EXTRA_BALL:
return std::make_shared<Event::ExtraBall>(serializedJson);
case EVENT_TYPE_PENALTY:
return std::make_shared<Event::Penalty>(serializedJson);
case EVENT_TYPE_RETIRE:
return std::make_shared<Event::Retire>(serializedJson);
case EVENT_TYPE_RESUME_MATCH:
return std::make_shared<Event::ResumeMatch>(serializedJson);
case EVENT_TYPE_END_MATCH:
return std::make_shared<Event::EndMatch>(serializedJson);
case EVENT_TYPE_SWAP_BATSMAN:
return std::make_shared<Event::SwapBatsman>(serializedJson);
case EVENT_TYPE_NEW_BATSMAN:
return std::make_shared<Event::NewBatsman>(serializedJson);
case EVENT_TYPE_NEW_BOWLER:
return std::make_shared<Event::NewBowler>(serializedJson);
case EVENT_TYPE_NEW_WICKET_KEEPER:
return std::make_shared<Event::NewWicketKeeper>(serializedJson);
case EVENT_TYPE_WICKET:
return std::make_shared<Event::Wicket>(serializedJson);
case EVENT_TYPE_UNDO:
return std::make_shared<Event::Undo>(serializedJson);
case EVENT_TYPE_AUDIT_ADD:
return std::make_shared<Event::AuditAddBall>(serializedJson);
case EVENT_TYPE_AUDIT_REMOVE:
return std::make_shared<Event::AuditRemove>(serializedJson);
case EVENT_TYPE_AUDIT_MODIFY:
return std::make_shared<Event::AuditModify>(serializedJson);
case EVENT_TYPE_AUDIT_RETIRE_MODIFY:
return std::make_shared<Event::AuditModifyRetirement>(serializedJson);
case EVENT_TYPE_ADD_NOTE:
return std::make_shared<Event::AddNote>(serializedJson);
case EVENT_TYPE_REMOVE_NOTE:
return std::make_shared<Event::RemoveNote>(serializedJson);
case EVENT_TYPE_NEW_CAPTAIN:
return std::make_shared<Event::SetCaptain>(serializedJson);
default: break;
}
return nullptr;
}
I also have a map that stores a static method to each event:
static const auto EVENT_TYPE_TO_PRE_CHECK = std::map<EventType, std::function<void()>> {
{EVENT_TYPE_SET_MATCH_TYPE, Event::SetMatchType::preCheck},
{EVENT_TYPE_SET_MATCH_TEAM_PLAYER, Event::SetPlayer::preCheck},
{EVENT_TYPE_SET_MATCH_TEAM, Event::SetTeam::preCheck},
{EVENT_TYPE_START_INNINGS, Event::StartInnings::preCheck},
{EVENT_TYPE_END_INNINGS, Event::EndInnings::preCheck},
{EVENT_TYPE_START_MATCH, Event::StartMatch::preCheck},
{EVENT_TYPE_START_OVER, Event::StartOver::preCheck},
{EVENT_TYPE_END_OVER, Event::EndOver::preCheck},
{EVENT_TYPE_BALL, Event::Ball::preCheck},
{EVENT_TYPE_EXTRA_BALL, Event::ExtraBall::preCheck},
{EVENT_TYPE_PENALTY, Event::Penalty::preCheck},
{EVENT_TYPE_RETIRE, Event::Retire::preCheck},
{EVENT_TYPE_RESUME_MATCH, Event::ResumeMatch::preCheck},
{EVENT_TYPE_END_MATCH, Event::EndMatch::preCheck},
{EVENT_TYPE_SWAP_BATSMAN, Event::SwapBatsman::preCheck},
{EVENT_TYPE_NEW_BATSMAN, Event::NewBatsman::preCheck},
{EVENT_TYPE_NEW_BOWLER, Event::NewBowler::preCheck},
{EVENT_TYPE_NEW_WICKET_KEEPER, Event::NewWicketKeeper::preCheck},
{EVENT_TYPE_WICKET, Event::Wicket::preCheck},
{EVENT_TYPE_UNDO, Event::Undo::preCheck},
{EVENT_TYPE_AUDIT_ADD, Event::AuditAddBall::preCheck},
{EVENT_TYPE_AUDIT_REMOVE, Event::AuditRemove::preCheck},
{EVENT_TYPE_AUDIT_MODIFY, Event::AuditModify::preCheck},
{EVENT_TYPE_AUDIT_RETIRE_MODIFY, Event::AuditModifyRetirement::preCheck},
{EVENT_TYPE_ADD_NOTE, Event::AddNote::preCheck},
{EVENT_TYPE_REMOVE_NOTE, Event::RemoveNote::preCheck},
{EVENT_TYPE_NEW_CAPTAIN, Event::SetCaptain::preCheck}
};
I am happy to supply more information around this problem if needed.