DEV Community

Discussion on: Exploring the Typescript Monorepo (a practical, hands-on adventure)

Collapse
 
andreidascalu profile image
Andrei Dascalu

"And what if we then find the change to the library wasn't quite right for our product?" - a little bit on the "why" thingie.

A library isn't used by the product. The whole point of a monorepo is to package a "product" in a way still allows separation between different applications, their common dependencies but keep them in a single repository.

But that's kindof the thing, even monorepo comes at a cost. It's great (like you said) when you want to make quick changes to the shared codebase but without the overhead of updating packages in each consume.

But the bit above isn't true. A change to a library serves its consumer. The procut is the whole of the applications of the monorepo, but still a shared component serves a subset of that. If a change to the shared codebase isn't right ... you do the same thing you do regardless of organisational pattern: you revert.

Thing is, once your application becomes production-worthy, the monorepo's cost becomes obvious when you start needing to be able to version components properly and maintain hard dependencies through the packet manager. The whole advantage of having independent applications (whether in a single repo or not) is to be able to deploy and version them individually and if you're indeed focused on the product that's pretty invaluable to be able to maintain integrity once in production.

When considering monorepo (as in, different apps in a single repo) it's often better to first consider a properly DDD'ed monolith.

Collapse
 
jonlauridsen profile image
Jon Lauridsen • Edited

I think I largely agree. What I write is from a practical point of view: I change the library to improve the product, but when I then use that change in the app I now see I didn't quite get the requirements right… So I go back to the library to do better. Maybe that means reverting and re-doing the change, or I can extend the original change further, but either way it's a problem for me when that back-and-forth takes too long or imposes too many restrictions.

The details differ depending on your workflow:
1) Change the library, version it, release it, realize it wasn't quite right. In this scenario it takes too long to go through changes.
2) Link the two together in a local development. Changes go fast now, but it is a hard requirement that the library has tests for all the app's use-cases (otherwise it doesn't make sense as a library). So landing changes becomes more strict.

I want a solution that separates the code, but doesn't introduce the hard requirements of versioning/releasing or tests.

At this point you're not wrong to suggest a monolith, that is definitely a solution here. If there's such a delicate coupling between the systems then separating them is probably too early. I buy your argument on this.

But for me it becomes problematic when that direction pushes me into the "code jungle" corner. I seek the practical option of being able to separate that code, even when the code is not conceptually well separated yet. I find by putting a box around it (making the library) I can start the process of separation. Suddenly the code sits there naked in its own project, making its points of coupling scream out.

I hope that clarifies the point you quoted and disagreed with.

I like your points on the drawbacks of monorepos, they're quite true. I see a lifecycle of a library or app beyond what this article describes. where a library may be individually versioned and deployed inside the monorepo, and even a further matured lifecycle where it escapes the monorepo entirely to become its own repository. I don't explore any of that in this article-series but the monorepo pattern will support all that quite smoothly.

Anyway, thanks for your feedback!