Resources for packwerk and Rails engine interaction?

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

Message originally sent by slack user U71N3KA8TMX

Hello, can anybody point me towards any resources or discussions about how packwerk interacts (or doesn’t) with Rails engines? My sense is that perhaps the consensus has moved away a bit from engines as the primary mechanism for modularity, but I wanted to test that sense. Thanks!

Message originally sent by slack user U717GMJTWHJ

Packs kind of are engines? They have pretty much the same directory structure as a “baby” rails app.

Message excluded from import.

Message originally sent by slack user U783ZNM0KD4

Some helpful tools: https://github.com/rubyatscale
Stephan’s book: https://leanpub.com/package-based-rails-applications

Hey Mark. Are you considering a refactor or for future development?

Packwerk is a dev environment tool that offers insight into the app’s modularity. In contrast, engines are for production, and they create hard boundaries and are much more than a tool for modularity.

When strictly considering modularity, I favor packwerk. It allows the team to work toward modularity in small steps and is a valuable tool that encourages and guides the team to respect boundaries.

By the way, every engine can be made a packwerk package.

By the way, every engine can be made a packwerk package.
Thanks for the plug, David! :smile:

And I have to echo your sentiment. Packages are superior for modularity work: Mainly it is because of the reduced overhead and the ability to act at the same strictness as engines (and more) but also to allow for more intermediate states.

For a while (after packages) I recommended using (unbuilt) engines if you think you’ll extract them as separate gems. While I don’t think that’s become untrue, there just aren’t a lot of situations people run into where they do this. If your real destination for such an engine is a separate Rails application…

Stick with packages, crank up all the protections over time, move it to a separate DB connection and then extract straight from package to app.

Message excluded from import.

That’s an awesome approach that I expect to work well if you can keep the consistency and start like this. I should add as context to my comment: This is what I would say to folks who currently work in an existing largely non-design, ball-of-mud Rails app

All of our Rails apps are engines first

This is cool. I’ve bootstrapped a couple of apps following this approach, and I really liked it.

Speaking of Packwerk and Engines, they work great together. Here is the demo app we’ve built for a quick demonstration some time ago:

https://github.com/bibendi/modular-rails

Message originally sent by slack user U71N3KA8TMX

Thanks for all your thoughts, and hi Aaron!! :tada:

I’m currently working mostly on a small Rails app, and occasionally on a medium/large Rails app. Neither app was greenfield when I joined the team. Both teams had read Stephan’s previous book (CBRA), and over break I read his new book as well, and that kind of forms the context for my question.

Both apps are currently segmented into engines and neither currently uses Packwerk. I know the small app better, and my sense after working with it for a while is that the engine boundaries may have been drawn somewhat prematurely, and this causes us development friction without providing a lot of benefits in terms of modularity. (This is my sense for the large app as well, for what it’s worth, but I don’t work in that codebase as often, so it’s more likely I am wrong in that case!)

Anyway, I’ve been toying with the idea of moving the smaller apps’ code out of engines and back into the root app, and then setting up Packwerk and looking to re-draw the package boundaries in a way that makes more sense for the current team and state of the application.

For the smaller application, I think it is very unlikely that any of the enginified-code will ever be extracted into a gem or a standalone application. The smaller application is itself already kind of an extracted specialist app.

Message excluded from import.

Message originally sent by slack user U71N3KA8TMX

I think the tricky part for us is that, for our large app, the codebase is big and mature enough that many changes are confined to one or at most two engines/gems, and so there is not a dev process cost to the modularity, even if the boundaries are not perfect

Message originally sent by slack user U71N3KA8TMX

for the smaller app, virtually every change crosses engine boundaries and sometimes reaches into a couple of unbuilt gems as well

Message originally sent by slack user U71N3KA8TMX

and I am reluctant to just tear that all out, for the reasons you mention, it is harder to put it back in once you have the big ball of mud

Message originally sent by slack user U71N3KA8TMX

but it is also a real cost, now, because the existing boundaries are in the wrong places (IMO)

Message originally sent by slack user U783ZNM0KD4

around how many engines are in the large app?

Message originally sent by slack user U71N3KA8TMX

10

Message originally sent by slack user U71N3KA8TMX

Aaron I am curious about this:

It is only in development and when we deploy it that it is an application (when it’s deployed, it is typically the only engine mounted, when it’s in development, we may mount additional engines that assist in development that would otherwise be “too” isolated).

Does this mean all communication between engines is over some non-Ruby mechanism (like http or redis or similar)? Even in development? One of the things I find odd about working with engines in these codebases is that I feel they are “mostly” just namespaces, and it feels like there are frequent cross-engine dependencies (although I have not felt like circular dependencies are a major problem)

Message excluded from import.

Message excluded from import.

Message excluded from import.