I have a simple StopWatchController
that creates and controls multiple StopWatch
objects (the dependencies).
When an event triggers inside each StopWatch
(their clock reaches a certain date), the StopWatch
needs to notify the StopWatchController
. Then the controller needs to get some value from all the StopWatch
(their getState()
output) and print it. (in a realife scenario, this happen on the server side, when an event happens inside each worker, the controller needs to notify the client)
My first attempt:
My first attempt involves Circular dependencie. More specifically, the controllers depends on the stopwatches but I am also passing the controller to each instance of the StopWatch
. (in their constructor, I pass this
-> referring to the StopWatchController
)
class StopWatch {
private eventDate: number;
private master: StopWatchController;
private currentTime = 0;
private trigger = false;
constructor(eventDate: number, master: StopWatchController) {
this.eventDate = eventDate;
this.master = master;
}
start() {
setInterval(() => {
if (this.currentTime === this.eventDate) {
this.trigger = true;
this.emitEvent();
}
this.currentTime++;
}, 1000);
}
private emitEvent() {
this.master.onTrigger();
}
getState() {
return [this.currentTime, this.trigger];
}
}
class StopWatchController {
private stopWatches: StopWatch[] = [];
createSlaves(count: number) {
for (let i = 0; i < count; i++) {
const slave = new StopWatch(this.getRandomDate(), this);
this.stopWatches.push(slave);
}
}
start() {
this.stopWatches.forEach((s => s.start()));
}
private getRandomDate() {
return Math.floor(Math.random() * 10) + 1;
}
onTrigger() {
console.log('One of the stopwatch has triggered!');
console.log('Summary is:', this.getAllStopWatchState());
}
private getAllStopWatchState() {
return this.stopWatches.map(s => s.getState());
}
}
function main() {
const master = new StopWatchController();
master.createSlaves(10);
master.start();
}
main();
My Second attempt:
My second attempt prevents circular dependency issue by passing an event handler instead of the whole class to each instance of the StopWatch
. In my case, the event handler is a callback function. ( instead of this
, I pass this.onTrigger.bind(this)
class StopWatch {
private eventDate: number;
private currentTime = 0;
private onTrigger: () => void;
private trigger = false;
constructor(eventDate: number, onTrigger: () => void) {
this.eventDate = eventDate;
this.onTrigger = onTrigger;
}
start() {
setInterval(() => {
if (this.currentTime === this.eventDate) {
this.trigger = true
this.emitEvent();
}
this.currentTime++;
}, 1000);
}
private emitEvent() {
this.onTrigger();
}
getState() {
return [this.currentTime, this.trigger];
}
}
class StopWatchController {
private stopWatches: StopWatch[] = [];
createSlaves(count: number) {
for (let i = 0; i < count; i++) {
const slave = new StopWatch(this.getRandomDate(), this.onTrigger.bind(this));
this.stopWatches.push(slave);
}
}
start() {
this.stopWatches.forEach((s => s.start()));
}
private getRandomDate() {
return Math.floor(Math.random() * 10) + 1;
}
onTrigger() {
console.log('One of the stopwatch has triggered!');
console.log('Summary is:', this.getAllStopWatchState());
}
private getAllStopWatchState() {
return this.stopWatches.map(s => s.getState());
}
}
function main() {
const master = new StopWatchController();
master.createSlaves(10);
master.start();
}
main();
My question
I have read several posts on StackOverFlow and most people highly recommend preventing Circular dependencies as much as possible.
Is there a way to pass the event better than my second attempt?
I am looking for a solution that is at the same time Easy to unit-test, more maintainable` and more scalable.
Aucun commentaire:
Enregistrer un commentaire