3 ms·
How? (honest question, I'm curious!)
by cjblomqvist 3y ago
How? (honest question, I'm curious!)
- Jach 3y agoIf you start with AService in module A, other modules need to depend on A to use it. You get into circular dependencies trouble when A needs to use a service from another module B that itself or through a dependency needs the AService. One solution is to split it into an AService interface you put in a new module, call it e.g. A-api, and leave the implementation in A which now depends on A-api. Do the same for B/B-api. It's a lot less likely that your -api modules will circularly depend on each other because they only contain interface definitions, so A can safely depend on both A-api and B-api and B can safely depend on both B-api and A-api. A more concrete example of an A and B that need to interact with each other might be a user account service and a (financial) transactions service. (Why not let them live in the same module? That can also be a solution, but as the scope of each grows and especially if separate teams end up owning each it can make sense to split them and enforce some boundaries via the interfaces.) Another example could be a notifications service and several of its clients, like whatever is handling user posts kicks off a notification event and asynchronously the notification service processes it and may need to reach around to call back into other services that could be part of the sender's module. (Passing simple lambdas may be an adequate alternate solution too.)
- jt2190 3y ago> One solution is to split it into an AService interface you put in a new module, call it e.g. A-api, and leave the implementation in A which now depends on A-api. This is what Fowler describes as “Separated Interface”. [1] Specifically he calls out the specific need for this special case: > “[Y]ou might need to invoke methods that contradict the general [module] dependency structure. If so, use Separated Interface to define an interface in one package but implement it in another.” It’s a special case because until you need to “contradict the general dependency structure”, you don’t need to do it. In particular, this is not the first tool one should reach for if you have a circular dependency between two modules. [1] https://www.martinfowler.com/eaaCatalog/separatedInterface.html https://www.martinfowler.com/eaaCatalog/separatedInterface.h...