This also applies to dependency injection. While it has significant benefits, it hurts clarity of the code. It becomes more difficult to see where each object is coming from.
Plain old putting-dependencies-in-the-constructor-instead-of-newing-them is great.
If you 'wire' it yourself, you see the top-level structure of the project in main, e.g.
cache <- createCache "./cache"
workQueue <- createWorkQueue parallelism
projectFinder <- createProjectFinder basePath
gradleBuilder <- createGradleBuilder cache
normaliser <- createNormaliser
gradleParser <- createGradleParser normaliser
relationFinder <- createRelationFinder cache normaliser
At a glance I can see what uses normaliser, and what is used by normaliser.