Current best practises on dealing with optional dependencies

Say I’ve written up a package to compute Foo and now I’d like to add support to write and read Foo to HDF5 or to plot Foo. May be I’d like to plug a DifferentialEquations.jl solution into Foo. What is the current recommended way to do deal with integration with large packages?

Should I just live with having giant dependencies in my package to add functionality only some users will sometimes need?

Or do I make little glue packages like FooHDF5.jl, FooDiffEq.jl and FooPlots.jl which glue my package and these large dependencies together? This doesn’t force large dependencies on the package but still allows for full functionality. It comes at the cost of a proliferation of glue packages though.

Or do I use Requires in my package? If so don’t I still need to have the dependency in my Project.toml even if the code doesn’t get loaded, right? And I still have the increased CI workload of having to test the integration with these large packages everytime I make any change to my code, even if it doesn’t affect integration.


@ChrisRackauckas would you mind sharing your thoughts on this?

Most of these have small Base packages you’re supposed to hook into so you avoid the dependencies. RecipesBase.jl, SciMLBase.jl, etc.


So it seems the recommendation would be to split up large packages so that the basic interface can be extended without loading the whole thing. So, once a package gets large enough with enough dependencies it should probably split up into a BaseFoo.jl and SpecificFoo.jl for specific features.

Small package developers then shouldn’t need to worry about dealing with requires and such since extending the basic interface of large packages shouldn’t incur much of a cost.