software-challenge / software-challenge/backend
Unify listeners and add filters instead of multiple interfaces
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 13
- Forks
- 14
- PR merge metrics
- No merged PRs in 30d
Description
A long-standing issue: We have many listener interfaces, and if you want to listen to a specific event, you gotta find the right interface and still implement a bunch of extra no-op methods.
The worst issue however is the unwrapping of Protocol Messages: For many messages, there is a corresponding listener/notify method with the same signature as the Message, essentially duplicating it. With generic listening, these messages could instead simply be passed through - DRY!
A good example is the LobbyClient:
protected final void onObject(ProtocolMessage o) {
[...]
if (o instanceof RoomPacket) {
RoomPacket packet = (RoomPacket) o;
String roomId = packet.getRoomId();
ProtocolMessage data = packet.getData();
if (data instanceof MementoEvent) {
onNewState(roomId, ((MementoEvent) data).getState());
} else if (data instanceof GameResult) {
logger.info("Received game result");
onGameOver(roomId, (GameResult) data);
} else if (data instanceof GamePausedEvent) {
onGamePaused(roomId, ((GamePausedEvent) data).getNextPlayer());
} else if (data instanceof ProtocolErrorMessage) {
logger.debug("Received error packet");
onError(roomId, ((ProtocolErrorMessage) data));
} else {
onRoomMessage(roomId, data);
}
} else if (o instanceof GamePreparedResponse) {
onGamePrepared((GamePreparedResponse) o);
} else if (o instanceof JoinedRoomResponse) {
onGameJoined(((JoinedRoomResponse) o).getRoomId());
} else if (o instanceof RoomWasJoinedEvent) {
onGameJoined(((RoomWasJoinedEvent) o).getRoomId());
} else if (o instanceof LeftGameEvent) {
onGameLeft(((LeftGameEvent) o).getRoomId());
} else if (o instanceof ObservationResponse) {
onGameObserved(((ObservationResponse) o).getRoomId());
} else if (o instanceof TestModeResponse) {
boolean testMode = (((TestModeResponse) o).getTestMode());
logger.info("TestMode was set to {} ", testMode);
} else if (o instanceof ProtocolErrorMessage) {
ProtocolErrorMessage response = (ProtocolErrorMessage) o;
onError(response.getMessage(), response);
} else {
onCustomObject(o);
}
}
private void onGamePaused(String roomId, Player nextPlayer) {
for (IAdministrativeListener listener : this.administrativeListeners) {
listener.onGamePaused(roomId, nextPlayer);
}
for (ILobbyClientListener listener : this.listeners) {
listener.onGamePaused(roomId, nextPlayer);
}
}
private void onGameOver(String roomId, GameResult data) {
for (IHistoryListener listener : this.historyListeners) {
listener.onGameOver(roomId, data);
}
for (ILobbyClientListener listener : this.listeners) {
listener.onGameOver(roomId, data);
}
}
private void onGameLeft(String roomId) {
for (ILobbyClientListener listener : this.listeners) {
listener.onGameLeft(roomId);
}
}
[...]
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the LobbyClient listener dispatch shown in the issue and trace the existing listener interfaces and ProtocolMessage handling. Define the unified listener and filtering scope, then verify that messages reach the intended listeners without the duplicated notification methods or no-op interface implementations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, kotlin
- Domain
- backend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100