I stumbled upon the artifact: <https://central.son...
# apollo-kotlin
s
I stumbled upon the artifact: https://central.sonatype.com/artifact/com.apollographql.apollo/apollo-runtime-android-debug , but where is this in the source code? I can't seem to find it here 😄 Am I looking at the wrong place?
b
I think it's just the android-debug version/variant of
apollo-runtime
?
1
s
Aha, interesting. I knew that it appends stuff for different targets, but I didn't know that debug in particular could be such a target. I got this because I was trying to use this and I wondered why I was even using that in the first place 😄
👍 1
m
Copy code
These transitive dependencies should be declared directly:
  androidTestImplementation("androidx.test:monitor:1.6.1")
  androidTestImplementation("junit:junit:4.13.2")
  debugImplementation("com.apollographql.apollo:apollo-runtime-android-debug:4.0.1")
I'd say it's an issue of DAGP not being too aware about KMP
apollo-runtime-android-debug
should be the same as
android-runtime
in terms of visibility
s
Yup, I will give it a try to just give it
android-runtime
and see if it's happy.
m
In the tutorial, I also have this:
Copy code
These transitive dependencies should be declared directly:
  [...]
  implementation("com.apollographql.apollo:apollo-api:4.0.1")
which is a bit surprising too.
Since
apollo-api
is an
api
dependency of
apollo-runtime
s
Yeah I am also just getting familiar with the tool right now, and it seems like it goes with a full explicit mode, where it wants you to define all dependencies that you use, despite even possibly getting them through your other dependencies exposing them with
api
. I am sure they got reasoning behind this. Reasoning that I am definitely not qualified to judge right now 😄
m
Same, still trying to wrap my mind around that. If you use
ApolloCall.execute(): ApolloResponse
in
apollo-runtime
and
ApolloResponse
is in
apollo-api
, surely you're going to use it anyways
So
apollo-runtime
adding
apollo-api
as
api
dependency should be enough IMO
But as you said, there might be reasoning behind this
s
https://dev.to/autonomousapps/the-proper-care-and-feeding-of-your-gradle-build-d8g > ...The problem with this anti-pattern is that the build maintainer or library author could change a dependency from
api
to
implementation
without changing the actual ABI (and therefore “safely”), but nevertheless break downstream builds who required those dependencies for compilation (in many cases without even realizing it). So we find that a simple upstream dependency change (supposedly transparent!) has broken the build. Must be due to this ^^ If there aren't even more reasons besides this
m
> library author could change a dependency from
api
to
implementation
without changing the actual ABI (and therefore “safely”)
In the specific case I mentioned, changing
apollo-api
to an
implementation
is pretty much not an option because
ApolloResponse
is part of the ABI
So we could do it but it'd be very wrong
I think this is only a problem if a lib exposes
api
dependencies that are not part of the ABI?
s
Yeah, its a way to protect from the scenario where a library is by mistake exposing something as
api
. Then notices the mitsake, fixes it. But the client was relying on that dependency, and then bumping a library results in red code and a lot of question marks are raised 😄 I can't say I've experienced this myself, but I can see how it's possible.
m
Yup
Copy code
That said, I must admit that this feature has always been the most controversial. If you fall into the camp of not caring, be of glad heart, for the plugin is highly configurable.
Copy code
dependencyAnalysis {
  issues {
    all {
      onUsedTransitiveDependencies {
        severity("ignore")
      }
    }
  }
}
That settles it I guess
Always a tradeoff 😄
s
haha yeap, tradeoffs tradeoffs 😄
😄 1
Hey interestingly enough, today that I got a bit further with this after your PR's help, I run the tool and I then did in fact have a bunch of red code because of this: • It noticed I am not using some classes coming from a specific dependency • It removed that dependency completely • I had done the
onUsedTransitiveDependencies { severity("ignore") }
trick • Now my build was failing since I was relying on those otherwise unused dependencies to bring in some transitive dependencies which I was really using One common case was that I was relying on some
androidx...-ktx
but I wasn't using it, so it removed it, but I was using the non
-ktx
version of it 😄 So that was fun, and I got my answer why by default it does not ignore such transitive dependencies 😄
👍 1
m
Nice!
Still, one could argue that
onUsedTransitiveDependencies { severity("ignore") }
is a good default because it did find the unused
androidx...-ktx
dependency, right?
s
Yeah but you do end up in a scenario where if you don't know what it is that you were transitively depending on, then you are a bit lost. You can remove this
onUsedTransitiveDependencies
, run it again, to see what it is that it would be bringing in, and then add it back and put it manually. In this case I knew I needed the one without the
-ktx
suffix just because it was a bit obvious. But it won't be like that every time. Overall I am a bit torn on this tool. I ran it and it detected quite a lot of unused dependencies, and more importantly it removed dependencies between my own modules which did not need to be there anymore, which means improved potential for parallelization. However it then removed some dependencies and when I let it pick itself it tried to bring in some deps which I am not sure are the right ones. For a jvm only module I have with compose (for molecule) it tried to bring in some
...compose-runtime-jvm-stubs
dependency or something like that for example, and I really don't think that's the right one. I suppose here I would have to explicitly bring in the Jetbrains compose dependency or something like that. It also turned a bunch of dependencies into
debugImplementation
or
runtimeImplementation
and at that point I don't even know if that would break anything, especially runtimeImplementation is not something I am truly familiar with. I feel like I might need to just run it manually once every few months, get the easy wins and ignore the rest or I need to go all-in and let it do everything and just trust it if all tests pass 😄
m
you do end up in a scenario where if you don’t know what it is that you were transitively depending on, then you are a bit lost.
Look at missing symbols in the compilation errors and google them? (we’re still missing a tool that gives you the maven coordinates from a class name, that’d be a cool hobby project)
Or worst case, look at transitive dependencies of the lib you just removed and in most cases, it should be relatively doable to find which ones you were using?
I feel like I might need to just run it manually once every few months, get the easy wins and ignore the rest or I need to go all-in and let it do everything and just trust it if all tests pass
Sounds like a very sensible approach 👍
I guess it’s hard to make it work in 100% of the cases
💯 1
s
Look at missing symbols in the compilation errors and google them?
it should be relatively doable to find which ones you were using?
Yes, you are right of course, you're not going to hit a complete roadblock. But at the same time, it's far from a "run this tool and get your fixes" 😄 Which of course I wish it was, but things are never that simple 😄
m
Right, the “error on transitive libs” gives you at least the name of the lib to add
1
But we need really this symbol <=> maven coordinate thing, would open the door to a lot of cool tooling...
Project number 592 😄
🤣 1