I don't know where to ask this... it's not a suppo...
# community-support
r
I don't know where to ask this... it's not a support request (I don't think). I'm trying to write a nicely decoupled, ports-and-adapters, JVM (Kotlin) app. I'm using gradle subprojects along with the
autonomousapps.build-health
to help me with this and it works very well; I look very hard at any change to dependencies in
build.gradle.kts
in each subproject and that, and the compiler, then force me to maintain architectural boundaries. However, I'm ending up with a volume of subprojects containing very few source files that my fellow developers think is insane. Currently 19 gradle subprojects for 58 production source files. I'm being pressed to switch to a single project and use ArchUnit to enforce the architectural boundaries, but I'm unenthusiastic because then you only find out about breakages when you run your tests. I want the compiler, and hence the IDE, to be telling me what I can and can't do. Another option is to use multiple source sets in a single project, but I think this will still be viewed as overkill by my fellow devs. I know it doesn't, but I'm wondering if Gradle could theoretically support multiple
module-info.java
files in a single source set? Then I could collapse a lot of the projects into a single
src/main/kotlin
directory, with
module-info.java
files in each of the
app
,
core
,
portN
,
adapterN
packages that would control visibility?
I basically want to turn this:
Copy code
my-project/
├─ app/
│  ├─ build.gradle.kts
│  ├─ src
│    ├─ main
│      ├─ kotlin
│  ├─ src
│    ├─ test
│      ├─ kotlin
├─ core/
│  ├─ build.gradle.kts
│  ├─ src
│    ├─ main
│      ├─ kotlin
│  ├─ src
│    ├─ test
│      ├─ kotlin
├─ dependency1/
│  ├─ api
│    ├─ build.gradle.kts
│    ├─ src
│      ├─ main
│        ├─ kotlin
│    ├─ src
│      ├─ test
│        ├─ kotlin
│  ├─ tech-specific-implementation
│    ├─ build.gradle.kts
│    ├─ src
│      ├─ main
│        ├─ kotlin
│    ├─ src
│      ├─ test
│        ├─ kotlin
├─ dependency2/
│  ├─ api
│    ├─ build.gradle.kts
│    ├─ src
│      ├─ main
│        ├─ kotlin
│    ├─ src
│      ├─ test
│        ├─ kotlin
│  ├─ tech-specific-implementation
│    ├─ build.gradle.kts
│    ├─ src
│      ├─ main
│        ├─ kotlin
│    ├─ src
│      ├─ test
│        ├─ kotlin
Into this:
Copy code
my-project/
├─ the-app/
│  ├─ build.gradle.kts
│  ├─ src
│    ├─ main
│      ├─ kotlin
│        ├─ app/
│          ├─ module-info.java
│        ├─ core/
│          ├─ module-info.java
│        ├─ dependency1/
│          ├─ api/
│            ├─ module-info.java
│          ├─ tech-specific-implementation/
│            ├─ module-info.java
│        ├─ dependency2/
│          ├─ api/
│            ├─ module-info.java
│          ├─ tech-specific-implementation/
│            ├─ module-info.java
│  ├─ src
│    ├─ test
│      ├─ kotlin
│        ├─ app/
│          ├─ module-info.java
│        ├─ core/
│          ├─ module-info.java
│        ├─ dependency1/
│          ├─ api/
│            ├─ module-info.java
│          ├─ tech-specific-implementation/
│            ├─ module-info.java
│        ├─ dependency2/
│          ├─ api/
│            ├─ module-info.java
│          ├─ tech-specific-implementation/
│            ├─ module-info.java
v
I don't think it is possible as the compiler cannot do that. I mean, you could probably have multiple source sets where the source sets each only contain a subset of
src/main/kotlin
, but I doubt your fellow devs would be any happier about it, and it would make the situation much less clear imho. I would probably agree, that you should use different projects (or at least different source sets that are clearly separated).
r
It probably breaks every model gradle has, but I was wondering if you could theoretically write a plugin that setup multiple Java modules within a single Gradle source set dir. Though getting an IDE (IntelliJ) to understand that would probably also be a colossal pain.
I wonder if the JPMS team ever considered allowing multiple
module-info.java
in a single compilation unit...
v
Hmm, now that you mention it, it might be that "Module Source Hierarchy" is what you are after, which is supported by JPMS / Java compiler, but not built-into Gradle yet, though with some PITA doable. Here the directory hierarchies are documented: https://docs.oracle.com/en/java/javase/20/docs/specs/man/javac.html#directory-hierarchies Here the Gradle issue is, though it seems the Gradle folks might not want to support module source hierarchy eventually according to latest comment from @Sterling: https://github.com/gradle/gradle/issues/25974 And here a blog entry about the PITA and how to get it working eventually: https://geomatys.github.io/draft/Modularization.html
r
Oh wow, that's a treasure trove, thanks - looks very like what I was envisaging. It's so sad that JPMS has had so little takeup and love, I think it has a lot to offer...
1