This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.
Message originally sent by slack user U721PQJPN3K
Has anyone merge separate rails apis into one using this pack idea? What was the process like?
In my head it could be something like just making a pack for each of the apps and then transitioning over time from there but what are the gotchas?
For more context, we have 3 large monolith APIs that all have duplicated code due to poorly defined domains. They’ve grown to the point that being separate is far more of a pain than being together
Based on your description, the trickiest bit will be divergent app setup and the fact that the duplicated code likely means naming collisions when you merge.
My attempts at merging 3 services into 1 is failing . Due to the overlapping domains, there are hundreds of classes that are named the same which is making refactoring this difficult. My thought was to just move everything for each one into a module to avoid the issue but struggling with that. Anyone have any tips/ideas?
At this point, also just debating moving the 3 services into a mono repo and starting to extract gems that can be shared between them. Goal still being eventually to merge them into one app since the domain boundaries are really poor. I dunno how to feel about that tho
I moved all my projects/websites into the same project since they are using the same Ruby on Rails template repository and are mostly the same.
I thought long and hard about being super productive and kept it simple: modules for namespaces and done with it. I will be strict about keeping things isolated and might add Packwerk later.
So far, the feeling is phenomenal. For example, some of my other projects need subscriptions and messaging. Now I can sort it all out with one PR instead of 4-5 different ones touching similar things.
Keep going, move things into modules first, change table names etc. Below is the module definition for one of the “engines” or websites.
module Energy
def self.table_name_prefix
"energy_"
end
def self.use_relative_model_naming?
true
end
end
Are those naming collisions in fact collisions?
Yea they are. These 3 apps have things like a model Retailer.
In one, that is a regular active record, in another it makes an api call to to populate the model, the other uses elastic search to build the model. Each one has slightly different methods in them beyond just the property names as well which is where just deleting 2 of them is difficult. Multiply this by literally hundreds. These services were somewhat separated to solve an authorization problem (which wow) so there is literal duplication with small differences to address different authorization behaviors.
I was hoping to merge them and start refactoring to shared code and better patterns over time but starting to think that’s not going to be feasible
modules for namespaces and done with it. I will be strict about keeping things isolated and might add Packwerk later.
Yea honestly I like the module namespace regardless and think I would do it with packs or not. Ruby’s global namespace has always been somewhat of a dislike for me (when it comes to application code rather than library code)
Yea I guess to further highlight the example.
In one service, you’ll see a method like Retailer.is_canadian?. In the other, the service will just say Retailer.country==“CA” everywhere. They really are the same domain in different services.
Oh that makes total sense and I agree. It’s just in this case, they aren’t separate domains. They are the same ones duplicated across 3 applications. I would expect in the longer term refactor the data models may be somewhat shared across different domains for sure
These were the original attempted “domains” based on nouns/the data model so I use that term. In the sense of actual DDD, none of that has been done with the 3 applications
So yea, with all that said, that was my goal with mashing them together. To make it easier to refactor in to proper domains. But feels like there isn’t going to be a good shortcut.
Putting them in a monorepo and shared gems has been my backup plan but I feel like I want to avoid that. My thought is with the extracted shared code, eventually a single monolith would be able to emerge. But, somehow I just get a sense that won’t happen lol