Skip to content

Design Philosophy

Andy Boothe edited this page Jan 18, 2025 · 3 revisions

Here is the general, high-level design thinking around Rapier's design, in no particular order.

Let Dagger be Dagger

As a companion library to Dagger, Rapier's job is to work with Dagger as seamlessly as possible, not to offer critique or commentary. When there is a fork in the design road and Dagger goes left, then Rapier goes left, too.

Offload to Dagger

Dagger's dependency graph approach to code generation is very good, but also very complex. There is an enormous amount of detail involved in building, resolving, and validating the dependency graph, let alone generating the code.

Rapier is only concerned with injection sites. Therefore, out of a desire to maximize correctness and minimize maintenance burden, Rapier only models as much of Dagger's model as required to discover injection sites, and no more.

Everything else is offloaded to Dagger.

Trust Dagger, but Verify

Dagger is a complex library under active development, and it's important that Rapier keep up. Therefore, Rapier uses tests to verify every assumption that Rapier makes about how Dagger functions. That way, when Dagger zigs, Rapier zigs too.

Boilerplate is bad

Minimizing boilerplate code is Rapier's raison d'être.

If there is a fork in the design road and one path has less boilerplate than the other, in general, prefer the path with less boilerplate.

Simplicity is good

Since this library is intended to be used and understood by other people, simplicity is a virtue.

If there is a fork in the design road and one path is simpler than the other, in general, prefer the simpler path.