Help with Mapping Dependencies in Stripe's Modularization System using Sorbet

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

Message originally sent by slack user U782CX14HG5

We don’t use Rails at Stripe, but we do have a modularization system. Something that makes Stripe unique is our use of Sorbet. We split our codebase into separate “packages,” and I think the biggest challenge being faced right now is mapping out dependencies between packages.

Message originally sent by slack user U782WI24OVK

Interesting. Funny I was just reading this from Shopify :slightly_smiling_face: https://engineering.shopify.com/blogs/engineering/writing-better-type-safe-code-with-sorbet

Message originally sent by slack user U782CX14HG5

Ah yeah nice, I remember seeing that Shopify is using Sorbet also

Message originally sent by slack user U7830DMKJNH

We’ve dipped our toes in too, but would like to spend more time with it :smile: We actually do runtime type-checks in our contracts too

Message originally sent by slack user U783MOJYF8Z

<@U782CX14HG5> that’s very interesting. We (Shopify) have built our own mechanism for packages and are also seeing straightening out the dependency graph as one of the hardest problems.

Message originally sent by slack user U783MOJYF8Z

We got some inspiration from Strip’e “prison guard” mechanism.

Message originally sent by slack user U783MOJYF8Z

I talked to Paul Tarjan about this two years ago, but he later told me that there hadn’t been much active work on it anymore.

I’d love to hear more on currently ongoing work - and can also share more about ours.

We’ve been aiming at open sourcing our packages implementation for a while, and it may actually happen this year :grin:

Message originally sent by slack user U783MOJYF8Z

Rails creates quite a few special challenges for acyclic dependency graphs.

Message originally sent by slack user U782CX14HG5

We’ve been aiming at open sourcing our packages implementation for a while, and it may actually happen this year

ah nice! that’d be great to see.

Message originally sent by slack user U782CX14HG5

I’d love to hear more on currently ongoing work - and can also share more about ours.
I think it’s picked up again recently. I’m actually not in-depth familiar with Stripe’s plans, I joined the company just a few months ago and am on a product team.

But right now, dependency boundaries are loosely enforced (via the prison-guard Rubocop stuff you mentioned). We’re working on stronger enforcement mechanisms.

Message originally sent by slack user U783MOJYF8Z

Seems similar to our situation. <@U782WV6188T> knows more about the current state of our packaging tooling (packwerk), but we’re currently weaning it off rubocop.

We’re also working on using selective code loading via gems and Rails engines for stronger boundary enforcement.

Message originally sent by slack user U782WI24OVK

Curious what’s the prison guard thing you mentioned. Is it part of Sorbet or Rubocop? Just Googled it but got no clue

Message originally sent by slack user U782CX14HG5

“Prison Guard” is what Stripe calls its custom Rubocop rules. I think it’s a tongue-in-cheek reference to a “cop” that “guards” Stripes (ie, prisoners)

Message originally sent by slack user U782CX14HG5

In the context of dependency management, Stripe’s packaging system requires that each package declare its dependencies on other packages. And by using “prison guards,” we enforce that you can’t (a) access the private components for other packages, nor (b) access packages that you haven’t declared a dependency on.

Message originally sent by slack user U782WI24OVK

Ah I see. So it’s something internal? That must be why when I Googled it only found statements like # rubocop:disable PrisonGuard/…

Message originally sent by slack user U782CX14HG5

That package declaration system is in turn used to drive the code loading process. Unlike Rails, Stripe doesn’t force a convention between file paths → class/module names. But with the packaging system, we can guarantee that dependencies are loaded before the code inside of a package runs.

Message originally sent by slack user U782WI24OVK

Ah, gotcha.

Message originally sent by slack user U783MOJYF8Z

We’re looking into Rails Engines as separate units of autoloading that can be switched on and off, as have other companies - there was even a talk at this year’s rails conf about it.

That mechanism can be used to enforce dependencies.

Message originally sent by slack user U783MOJYF8Z

Oops, I just realize I had already written that. Anyway, Ryan’s comment about dependent loading reminded me that we’re exploring a similar thing.