This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.
Message originally sent by slack user U717FXJ8HWK
How have you approached cyclic dependencies? For our monolith, we’re currently at around 150 packages, and for a while we’ve been ignoring circular dependencies. Now we’re at a point where the dependency graph is very messy because for the most part we’ve been accepting dependencies to resolve existing dependency violations. So I’m thinking of removing some subset of dependencies that cause cycles, accepting those violations as TODO (into package_todo.yml), and then no longer allowing dependency cycles in CI. Anyone with similar or relevant experience here?
We do what you’re proposing here, and it works ok. It’s better than ignoring them altogether, but hopefully it drives the conversation about if the dependency is the correct one or not. We don’t allow declaring circular dependencies, but do allow them via Todo, and use packwerk check / packwerk validate in CI to verify it.
In practice, I think it can become a task of “fixing the build” instead of thinking about the proper dependency tree. Some devs, especially more junior become accustomed to just regenerating Todo to fix the build - I’ve even noticed it instead of declaring a 1-way dependency. So, I’d recommend adding some guardrails/training about the overall goal/philosophy of packs.
How big are your packs? Perhaps they’re bigger than ours - we went for lots of relatively small packs, and we’re currently at 500 000 LOC total, so it’s around 3 300 LOC/pack. With this number of packs, the dependency cycles are very long and it’s hard to untangle them.
Our monolith has over 80 KLOC and right now we have ~40 packs. But we just started moving files into packs a couple months ago and it’s an effort we’ve been having to do in small bursts of efforts.
For now, we’re focusing on architecture violations. We defined a few layers, defined a few packs for each and started moving files to them.
We’re measuring progress with (this depends on my PR here to be merged so it supports architecture):