I have a dilemma here about what is and what is not a circular reference... and how to get rid of it in affirmative case.
Let's say I have a Main
class that instantiates two different classes where each of these classes need to execute a method in the other:
MyMain {
AlarmManager alarmManager;
DatabaseManager databaseManager;
MyMain() {
alarmManager = new AlarmManager(dataBaseManager);
databaseManager = new DatabaseManager (alarmManager);
}
AlarmManager getAlarmManager() {
return alarmManager;
}
DatabaseManager getDatabasetManager() {
return databaseManager;
}
}
And the classes:
AlarmManager {
DatabaseManager dataBaseManager;
onAlarm(alarm) {
dataBaseManager.saveInHistorical(alarm);
sendAlarm(alarm);
}
sendAlarm(alarm) {
socketWriter(alarm);
}
}
DatabaseManager{
AlarmManager alarmManager;
onDatabaseConnectionError() {
saveInHistorical(databaseAlarm);
alarmManager.sendAlarm(databaseAlarm);
}
saveInHistorical(historical) {
connection.store(historical);
}
}
I suppose you get the idea by looking at the code. If there's an alarm we receive it in the AlarmManager, but it needs to save it in the historical database. However, if we have a connection error with the historical database, we need to also send an alarm.
Is this really a circular reference, where main has alarm but alarm also has main and the same for database/main? How would you solve it?
I had a similar problem when did a CAD development. In every Electronic CAD you have some component ports and signal lines that represent connections between the ports. The lines and ports are many-to-many connections: every line must maintain a list of ports that it binds together as well as the ports must beware of the lines, attached to them. So, every time user wants to connect two ports, he creates a line and attaches the line to each port by
line.add(port)
port.add(line)
These two operations must always be executed together. This means they must be abstracted as a procedure: calling line.add(port)
would automatically call port.add(line)
and, by symmetry, port.add(line)
should call line.add(port)
. Well, we are in the vicious circle, exactly the one you have in your question!
I bothered me for years but I did nothing better than giving up the symmetry. I have exposed only line.add
to the user, hiding the port.add
, that it calls, behind my netlist manipulation API. This way, port.add
does not need to call the line.add
back since we know that we are in port.add
only because line.add
is already happening.
I could restore the symmetry by introducing public port.add
and line.add
, which would call API-private line.onAdd(port)
and port.onAdd(line)
callbacks. This also seems trivial. Yet, you are right asking this question. I encourage you to upvote my response but not accept it. I would like to know the correct (OOP) answer myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With