Shopify/packwerk

Transitive Dependencies

shioyama opened this issue · 0 comments

If you have three packages (based on the ones in the Packwerk intro video):

# app/models/building/package.yml
enforce_depencencies: true
dependencies:
- app/models/vehicle
# app/models/building/house.rb
module Building
  class House
    def initialize(blocks:, vehicle:)
      @blocks = blocks
      @vehicle = Vehicle::Truck.new(
        engine: Parts::TruckEngine.new
      )
    end
  end
end
# app/models/vehicle/package.yml
enforce_dependencies: true
dependencies:
- app/models/parts
# app/models/vehicle/truck.rb
module Vehicle
  class Truck
    def initialize(engine: Parts::Engine.new)
      @engine = engine
    end
  end
end
# app/models/parts/package.yml
enforce_dependencies: true
dependencies:
# app/models/parts/engine.rb
module Parts
  class Engine
  end
end

# app/models/parts/truck_engine.rb
module Parts
  class TruckEngine
  end
end

Based on the common understanding of "dependency", you would expect that referencing Parts::TruckEngine from inside Building::House would be allowed since building depends on vehicle, which depends on parts, which contains Parts::TruckEngine. But this would in fact fail since Packwerk does not consider dependencies transitively, so you would have to change the app/models/building package like so:

 # app/models/building/package.yml
 enforce_depencencies: true
 dependencies:
 - app/models/vehicle
+- app/models/parts

This is fine for three packages like this, but the problem scales badly with number of packages. We now have nearly 100 packages in our core monolith and the number of times dependencies are duplicated in package.yml files is getting out of hand.

I'd like to propose that Packwerk consider dependencies transitively, such that the change to app/models/building/package.yml would not be necessary. This seems like it shouldn't be hard to do.

Any thoughts?