Separating Web-Agnostic Code: Advice Needed on Evolving Packs and Access to External Resources

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

Hi everyone. I understand eventually it could be great to separate web-agnostic code (like modes, jobs, services) to separate packs and have specific packs for web-related code (like controllers, views, serializers). But we didn’t start this way. Currently we have business domain-based packs including controllers, views, models, and everything related to a specific domain. I thought this was OK as a first step and then we could “evolve” into further separating packs. Now I’m having 2nd thoughts, but I don’t want to end up almost doubling the number of packs.

I’m finding that the web-related code tends to need access to more stuff outside their own pack (or arch layer) compared to models.

Any advice on this? What has been your experience?

I guess this is related to the issues <@U70VYN8QFSQ> wrote about in the blog post mentioned last Friday.

Message originally sent by slack user U712YWCKK8T

We have a shared web pack with all our common UI code and then domain packs that have web code depend on that

Message originally sent by slack user U70TIGAX94P

My opinion as informed by doing this stuff for a few years at Shopify and consulting at other companies:

Layers shouldn’t be a problem for the web stuff since it would probably be your top layer, and each layer should have access to all layers below.

As for dependencies on other domains from your web layer - this kind of depends what your web layer looks like and what your goals are.

In general, I would go with the „what changes together, lives together“ principle if you’re optimizing for developer productivity. If you have separate frontend teams, a cross-domain web package may make sense.

Otherwise, it‘s likely that there are parts of the web layer that are maintained closely together with domains, in which case it makes sense to draw a vertical boundary and have web and domain layer for a single domain in the same package. That way you reduce friction and indirection in things that often change together.

If you‘re optimizing for something else, like scaling hardware separately or deploying separately, you may come to different conclusions.

There‘s also a consideration about the order of things. If you think your web layer is very entangled and you just don’t want to tackle it yet, you may want to cut packages differently.

Message originally sent by slack user U70TIGAX94P

As for how to disentangle the web layer - there are two commonly helpful patterns in my experience:

• make sure there‘s little to no logic in your web layer that is not directly concerned with adapting to the outside world (presentation, coercion, input validation are what belongs there).
• dependency injection. If one page or endpoint exposes information from other domains (my favourite example is a dashboard), you may want to create extension points that allow other domains to hook their stuff in.

Thanks for your replies, guys. Really appreciated.

We have a small team and we’re wanting to leverage packs to better separate code ownership by verticals. We do have both frontend and backend devs but that division is not strict. Our goal is for backend devs to own vertical slices by domain, with the UI code mostly using components (ViewComponent) defined and coded by the frontend devs. Some of them defined in more generic, lower layer packs, and some more specific components defined on the same packs they’re used.

Message originally sent by slack user U73HGJ7DOU2

Hy guys, thanks for sharing, the discussion is very interesting. <@U70TIGAX94P> I’m not sur I understand what you mean by create extension points that allow other domains to hook their stuff in

Could you please elaborate?