Tool for Cleaning Up Dependency Trees: Is There One Available?

This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.

Message originally sent by slack user U71V6G2PDJS

Is there a tool for finding unnecessary dependency declarations / cleaning up dependency trees?

There is not … yet!

I believe that @AlexEvanczuk would be thrilled to see something like this added to one of the RubyAtScale gems

One thing to keep in mind: packwerk doesn’t do any analyses of dependencies within accepted dependencies. If it did that (memory prohibitive maybe)… or that could be activated, there are some other ideas as to what one could do:

• Generate a report showing how much two packages co-depend (count usages on one side and violations on the other) - might lead devs to flip dependency direction
• Use usage count + violation count as edge weights in a graph visualization
• Show a list of top 10 dependencies that could be removed via dep injection

Message originally sent by slack user U71V6G2PDJS

I would imagine Packwerk would already have a lot of the code required to build such a feature. It already does stale dependency checks at the class level, so a stale check at the package level seems obvious - at least from afar :wink:

yes, it does.

I suspect it might use a lot of memory in large apps

This has come up a couple of times in various forums… I can definitely see why we’d want it. It’s a bit tough architecturally in packwerk, because we only know what a package doesn’t need by doing a full scan, but packwerk checkers can only create violations/affect behavior for individual references.

It would be interesting if packwerk could call a method on each checker when the scan is finished, so checkers can spit out some warning/validation error of some kind.

In the meantime the simplest way to do this is:

  1. Collect existing dependencies (e.g. ParsePackwerk.all.map{|p| [p.name, p.dependencies.uniq ]}.to_h)
  2. Delete all dependencies from all packages (ParsePackwerk.all.each{|p| ParsePackwerk.write_package_yml!(p.with(dependencies: [], config: p.config.merge(dependencies: [])))})
  3. bin/packwerk update
  4. Get the dependency violations again, diff them to see what dependencies you need, rewrite them using similar command as in (2)

I can think of one way to automate this using existing tools.

  1. Create a custom Packwerk::Checker. It never registers a violation – all it ever does is modify a file tmp/packwerk/references.yml that lists out the unique pack A => pack B references.
  2. Create a custom Packwerk::Validator. It reads tmp/packwerk/references.yml and diffs pack A => pack B links with the stated dependencies. It raises a helpful error with what dependencies to remove when there is an unnecessary dependency listed.
  3. Then, bin/packwerk check and bin/packwerk validate in sequence could automate this process in CI for you.

Message originally sent by slack user U717FXJ8HWK

For now, there’s a script to do this: https://github.com/Shopify/packwerk/discussions/208#discussioncomment-3377131