Assume we have a single large JVM project (the example is in Kotlin), containing code. As part of a refactoring effort, we are decoupling pieces of the code by splitting the code into multiple modules, and using a build tool such as Gradle/Maven to build deploy applications with only a small set of the modules.
Some more details:
class SomeService(
private val SomeCallable: callable, // implemented by OtherService during runtime
) {
fun doSomething() {
callable.call()
}
}
interface SomeCallable {
fun call()
}
class OtherService: SomeCallable {
fun call() {}
}
We want to split this code into two modules:
// Module A
class SomeService(
private val OtherService: callable,
) {
fun doSomething() {
callable.call()
}
}
// Module B
class OtherService: SomeCallable {
fun call() {}
}
// Module ???
interface SomeCallable {
fun call()
}
The question is in which module the interface belongs. If it would be part of module A, then the implementation in module B cannot compile. If it would be part of module B, then the calling service cannot compile. It seems we need a third module C containing just the interface SomeCallable
, and that both modules A and B depend on.
A compilation dependency diagram:
A B
\ /
C
A runtime dependency diagram:
A
| \
B |
| /
C
Is this the best way to achieve the decoupling of code/modules, or are there better ways?