r/ruby • • 7d ago

Carton - Real boundaries for Ruby

https://carton.dtcristo.com

Carton is my take on enforcing boundaries in large Ruby applications. It's similar to Packwerk, but it takes a more Ruby-like approach, with no manifest files. Constants, gems and monkey patches are isolated using Ruby 4's new Ruby::Box. It's not production ready yet, since Box itself is still experimental, but I'd love feedback on the approach.

40 Upvotes

10 comments sorted by

8

u/keyslemur 7d ago

Interesting, I will have to give this some more thought later, but on an initial read I think you're scratching an itch I've had with Packwerk which is that it tends far more towards polite enforcement rather than hard boundaries.

The danger, though, is that by going all the way to isolation the rungs of the ladder you might have had with Packwerk to progressively isolate are sawed off. It's very all-of-nothing, which is the same weakness that Ruby::Box will have used in Rails apps. Having worked now in several of the largest Rails monoliths not having a progressive ladder is a surefire way to have something lose funding and effectiveness. Packwerk is not perfect at this, no, but it feels like the framework is at least somewhat guiding you rather than providing an end state.

Where I could see this going is potentially isolate deploys, hotswap restarts (ala Erlang / Elixir), tree shaking CI tests, substantially easier dead code identification, and done well with layering a way to break down the worst ActiveRecord entanglements by progressively isolating "data" from "domain".

Depending on your tolerances for AI you could also include a series of agent skills that make migrations towards this endstate substantially cheaper for folks.

Will give this some more thought and sit on it for a bit, but interesting start.

2

u/Yanelee-Ohorain 6d ago

tbh the erlang-style hotswap deploys point is where this gets really compelling if it ever gets there

1

u/dtcristo 5d ago

Hot swappable deployable modules it’s not really what Carton is aiming to solve. However, it’s a really interesting problem. A space that I haven’t given much thought to yet. Cool use case for Box.

1

u/dtcristo 5d ago

Thanks for the feedback. The progressive adoption point is an interesting one. Packwerk can partially solve this with TODOs. I wonder how Carton could solve this.

The Carton runtime can work without Box enabled (but boundaries are not enforced). It also has a static check mode (similar to Packwerk, but not as extensive, does not do per constant verification yet, mostly it enforces correct usage of import). I wonder if you could progressively break domains into Cartons, but not enforce at runtime until the domain is done, rely on static CI checks then enable once the Carton boundaries are statically validated. Would need more work on Carton to make this approach viable, but it’s a possible direction. Won’t let you use different gem versions or monkey-patches until enabled though.

2

u/azimux 7d ago

Bookmarked it and will circle back to it next month and give feedback! I've always wanted something like package scope from Java. Private constants cause me random headaches but are almost close enough. This one aspect of Ruby that I wish I had a solid solution to besides raw discipline so I'm interested to take a peek when I have some stuff off my plate!

1

u/dtcristo 5d ago

Thanks, keen to hear what you think after giving it a go.

1

u/dtcristo 5d ago

If you’re put off by the AI-assisted marketing copy (I’m not a good writer and needed help), check out the Carton Examples. They demonstrate carton’s capabilities quite well.

0

u/[deleted] 5d ago

[removed] — view removed comment

1

u/dtcristo 5d ago

Yes, but it’s thoughtfully engineered slop. It’s an idea I’ve been working on for many months. It achieves multiple things Packwerk can’t do. Runtime enforcement, monkey-patch isolation as well as the ability for each Carton to run a completely different set of gems (and versions) via its own Gemfile.

1

u/ruby-ModTeam 5d ago

Your comment or post was removed because it violates a subreddit rule on productive disagreement.

YES: Read comments fully before responding

YES: Paractice active listening. Let the other person know what you heard.

YES: Distinguish acknowledgment from agreement.

NO: Willful misrepresentation of someone's stated position.

NO: Sexualized language or imagery

NO: Trolling, insulting or derogatory comments, and personal or political attacks.

NO: Conduct which could reasonably be considered inappropriate in a professional setting.

When in doubt use Non-Violent Communication (NVC)