# Using Dependency inversion to avoid depending on volatile/heavy packages

**URL:** <https://discourse.julialang.org/t/using-dependency-inversion-to-avoid-depending-on-volatile-heavy-packages/74181>\
**Category:** General Usage\
**Tags:** package, dependencies\
**Created:** [January 7, 2022, 10:15am UTC](https://discourse.julialang.org/t/using-dependency-inversion-to-avoid-depending-on-volatile-heavy-packages/74181 "2022-01-07T10:15:56Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![bgctw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bgctw/32/22050_2.png) [@bgctw](https://discourse.julialang.org/u/bgctw)\
**Post date:** [January 7, 2022, 10:15am UTC](https://discourse.julialang.org/t/using-dependency-inversion-to-avoid-depending-on-volatile-heavy-packages/74181/1 "2022-01-07T10:15:57Z")

</div>

I want to use a simple optimization of an univariate function in my package [DistributionFits.jl](https://github.com/bgctw/DistributionFits.jl), but I want to avoid the package dependency on the heavy-weight package [Optim.jl](https://julianlsolvers.github.io/Optim.jl/stable/).

So far, I tried implementing Dependency inversion by considering function `optimize` to be an interface defined in `DistributionFits.jl`. The user of the package then needs to assign a concrete function to the binding `DistributionFits.optimize` by using exported function [`set_optimize(f_optimize)`](https://bgctw.github.io/DistributionFits.jl/dev/set_optimize/). Hence, I could remove Optim.jl from the package dependencies.  
In addition, [Requires.jl](https://github.com/JuliaPackaging/Requires.jl) allows to invoke set\_optimize(Optim.optimize) automatically when the module using DistributionFits is also using Optim.jl.

Is this a good Julian way to avoid hevay package dependencies?

Does this approach protect my package and further dependents from the need of being recompiled after changes in some other aspect of Optim.jl?

Related posts

- [Conditional package dependency to avoid build errors](https://discourse.julialang.org/t/conditional-package-dependency-to-avoid-build-errors/42742)
- [Dependency injection in Julia](https://discourse.julialang.org/t/dependency-injection-in-julia/12026)

---

<div class="post-metadata">

**Author:** ![bgctw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bgctw/32/22050_2.png) [@bgctw](https://discourse.julialang.org/u/bgctw)\
**Post date:** [January 24, 2022, 8:02am UTC](https://discourse.julialang.org/t/using-dependency-inversion-to-avoid-depending-on-volatile-heavy-packages/74181/2 "2022-01-24T08:02:45Z")

</div>

After reading this [mulitple implementations answer](https://discourse.julialang.org/t/best-practice-to-support-multiple-implementations/74240/11) by @stevengj, I implemented a slightly more complex strategy. Using a type hierarchy allows the “interface” to comprise more than a single method.

I now have a method `optimize(f, ::AbstractDistributionFitOptimizer, lower, upper)` that calls the actual optimization routine. By specializing this method, different implementations can be used.  
Method [`DistributionFits.set_optimizer(::AbstractDistributionFitOptimizer)`](https://bgctw.github.io/DistributionFits.jl/dev/set_optimize/) configures the Optimizer used by the package.  
Again, Requires.jl is used to automatically set the default, if the Optim.jl package is in scope.

I am happy about critical feedback and advice on a Julian way of managing project dependencies in a way that higher-level code does not depend on lower-level code.
