Our application now has some clear structure. We have main for logic, and we have some driver functions for effects. This part down here is neither logic nor effects. What it does is tie together the main with the drivers. Essentially, it is meant to make our app just run.
We could put that in a function called run, and that takes as argument the main function. Then here, we just call that main function like this to get the sinks, and then pass those to the drivers.
Now, this works after we pass our actual main function, that one up there, to run. Then it would work just like before. One problem is that here, we have the drivers hard-coded into this run so it's not so generic.
One of the problems is that if you just don't have the log anymore, then sinks.log would be undefined. Then once we try to pass undefined to this log driver, it would try to subscribe to something undefined, and it would crash.
It's not nice that we're hard-coding it here. Instead, what we can do is pass those drivers here as an argument. We're basically saying run this application and use these drivers to execute those effects. For instance, this would be an object, and here we would have the DOM driver and the log driver.
Under the key DOM, we can put the DOM driver, and under the key log, we can put the log driver so that this key will match the key there, and this key here in the drivers object will match the key there in the sinks object.
Now that this is an object, we can iterate over each key by doing object.keys. For each key, we can run a piece of code. First, we want to actually check does sinks under that actually exist? Here for log, it won't exist, so sinks.log will be undefined, and we don't want to run the log driver in that case.
We only want to run it if it's not undefined, so if it's a normal situation. In that case, we are going to say drivers key. Let's say in the case of log, that would be drivers.log, and we're going to pass the corresponding sink.
Then we don't need this anymore. Once we run this function, it's going to check under each of these properties, does it have a sink corresponding to it? If it does, it's going to pass it to this function and so forth.
This should still work like before, except now we don't have the console effect, because we have turned that off here in main. We can put that back, and then run our application again. Now, we see both of the effects happening as it should.
This is how run can become very generic, and we don't need to hard-code anything inside it anymore. Its only role is to plug together the main function with the drivers.