4 ms·
> My only counter argument here, is when those 4 things deploy independently. This brings us to the elephant in the room: monorepo strategies are just naive an
by chipdart 2y ago
> My only counter argument here, is when those 4 things deploy independently.
This brings us to the elephant in the room: monorepo strategies are just naive and futile attempts at fixing the problems created by an absolute lack of support for versioning.
If you support versioning, you don't care where and how you store your code. You just push the changes you need to push, and make sure you bump versions to reflect the nature of your changes. Consumers are left with the responsibility of picking which to consume, and when to consume it.
- dieortin 2y agoVersioning introduces a big maintenance cost, both on the side of the developer of a service and on the consumer side. On a monorepo you have a single version, and can be sure that everything works together on it. You are forced to address the costs of changing APIs continuously, but all components are always up to date. With multiple repos, versioning hell is real.
- chipdart 2y ago> Versioning introduces a big maintenance cost, both on the side of the developer of a service and on the consumer side. Not really. From the producer side it only requires that a) you do not break your contract, b) when you need to break a contract, you bump your version number, c) when no one uses older versions, remove the code. From the consumer, it's even easier: you just need to point to the version you're consuming. What exactly do you think is the problem?
- dezgeg 2y agoBugs can and will happen, eg. when A depends on B and some developer accidentally makes a change to B that will pass B's tests but only break in A's use case. In monorepo case such bug can be noticed before the broken code hits master. In versioned case it might take long time (until B releases, and A takes the release into use). Knowing when no one uses older versions is also hard (especially when you can no longer grep for them, unlike a monorepo) so some people get into defensive mode and never delete or fix any interfaces because "someone might still be using it".
- chipdart 2y ago> Bugs can and will happen, eg. when A depends on B and some developer accidentally makes a change to B that will pass B's tests but only break in A's use case. In monorepo case such bug can be noticed before the broken code hits master. I don't see what point you tried to make. So A breaks when someone breaks B. That's ok. You spot the error the moment you try to update A, well before you commit any code. You file a low-priority ticket and go on with your life because A is still good in production. > Knowing when no one uses older versions is also hard (...) Not really, it's the easiest part of the whole thing and a non-issue. If you manage a package this does not even register as a problem. If it's a service you have request metrics. What is the problem, really?
- dezgeg 2y ago> I don't see what point you tried to make. So A breaks when someone breaks B. That's ok. You spot the error the moment you try to update A, well before you commit any code. You file a low-priority ticket and go on with your life because A is still good in production. What inevitably happens is that A hasn't been updating their version of B in weeks/months, but some recently landed bug fix in B is now needed RightAway(tm). And now if something accidental breakage happened between now and weeks/months ago, it'll be much more annoying to triage. > Not really, it's the easiest part of the whole thing and a non-issue. If you manage a package this does not even register as a problem. Well, where I'm at we have semi-regularly teams we have never heard of using our libraries. How can I know what things such people are using?
- ggregoryarms 2y agoAt least you're in control of when to look at the updates in new versions. A monorepo gives you less control. If you're unable to enforce control through other means, sure use a monorepo. But it's limiting.
- wavemode 2y agoI guess I just don't see how this is any different from using external libraries. Yes, bumping a library from v3.2.4 to v3.2.5 can sometimes break your build. So, the solution is we stop using versioning? No, you just pin your app to v3.2.4 until a working update is made (either to the library or to your own app). I'm not sure why that suddenly becomes an impossible task once the creators of the app and the library work for the same parent company. > Knowing when no one uses older versions is also hard That's the thing though - you don't have to care. If you delete an interface, just bump the version number accordingly. People who still need the interface will stay on the old version. (And - bonus - they are now placed under implicit pressure to refactor their code away from using that old interface, now that they know it's deprecated and will no longer be maintained. By contrast, if you have a practice of keeping code around code just because people are still using it, that code tends to just stick around forever.)
- chrisandchris 2y ago> c) when no one uses older versions, remove the code. [...] So, like never?
- mewpmewp2 2y agoa) you do not break your contract That pretty much makes all internal APIs and code like Public APIs as a product, which adds a huge costs in terms of initial API designs, assumption validations, because you can't make any mistakes at all. And later down the road it fixes you into a place where if new requirements arise, and they will, you won't be able to pivot or refactor anything. Literally having this version setup and requirements changing I've seen estimates of what would be a week in a monorepo refactor either being estimated to take a year+ or simply impossible because of so many assumptions of those contracts. And there's such a nasty spaghetti of dependencies with different versions that no one can actually understand or hold in their head, and basically to build certain new features, they would have to start from scratch.
- chipdart 2y ago> That pretty much makes all internal APIs and code like Public APIs as a product (...) No. Different versions are not different products. They are the exact same product, provided in a way that delivers features in a way that won't break clients. > (...) adds a huge costs in terms of initial API designs (...) Obviously not. From the producer side, all it takes to support versioning is picking up your versioning strategy and sticking with it. This can mean providing an endpoint through a different path parameter, reading a request header, or even get the version through a query parameter. Does it take you much design work to add a "v1" in a URL path? How about reading a request header? Does passing a query parameter require meetings to review designs? Some frameworks even explicitly support versioning as a high-level concept and make it a part of their routing strategies. Copy the source file of a controller to another folder, change it's namespace to avoid conflicts, add a tag to the class, done. You just released a new version of your API. > (...) assumption validations, because you can't make any mistakes at all. You somehow managed to get it entirely backwards. With versioning, you can afford making all kinds of mistakes all the time. Breaking interfaces is no longer w concern. You release your changes to an upstream dependency/producer with zero use, downstream dependencies/consumers can gradually switch as their test plans allow, and if any problem is detected then this can be worked out before either consumers go live or producers receive production traffic. More importantly, you have your old stable versions ready to roll back.
- t43562 2y agoVersioning sometimes becomes a problem itself. You can't always allow support for V1 of some API to continue because it's just "wrong" in the light of your work. It can turn out that your "micro" architecture just didn't really work because factors X or Y tie certain groups of services together so much that a change to one forces changes to the others. So redesign right? Well, the contractors are all gone and your small team can barely manage the bugs and minor features, let alone redesigns which tend to force huge changes in the entire system because it wasn't thought out that well to start with. i.e. the mountain to climb to fix a little problem is as high as fixing all the problems. So you might have to update everything that references your changing API to use the new version....but your company has tons of repos and you don't know which ones reference your API, and they're owned by other teams and there's no central set of tests which have been run against the combination of the head of all these repos to ensure that they do in fact work together at exactly the state the combination is at when you are working. All deployments are a guess - which repos do you need to deploy for change X? Some other team deploys their repo without realising that it now depends on a new version of yours. Oh dear. We should have created a versioning mechanism of some kind and made their deployment depend on ours......but no time to do that kind of thing and could you get other people to agree to use it and how does it work with your CI system and.........well....you just muddle on, force yourself to remember the details, make mistakes etc etc. Busy work. IMO monorepos make a good place to put a set of whole-system end to end tests that everyone can run before they merge. That's going to sort out many conflicts before they turn into a bug hunt.
- chipdart 2y ago> So you might have to update everything that references your changing API to use the new version.... That's how versioning works. - You allow legacy applications to consume the legacy interface, - you provide a new interface to the world so that they have a path forward to migrate out of consuming the legacy service through the legacy interface, - the consumers migrate in a time frame that makes sense to them. - in the end you sunset the legacy API, and pull the plug. This scenario is not eliminated by monorepos. What monorepos do is force consumers to migrate to the new interface as an urgent task that's part of the critical path. If you have resources to do that migration, it does not matter how you store your code.
- globular-toast 2y agoYou actually have to do versioning properly, though. Most people I've worked with do not understand semantic versioning and basically don't understand how to ship new features in a non-breaking way. That or they're too lazy to do it. Either way, dependencies get broken constantly. That's the real point of a monorepo: you can treat the whole thing as internal, break it to your heart's content. You only need to make sure you don't break the user-facing part, for some subjective value of break.
- mewpmewp2 2y agoI've witnessed having those packages and versioning only lead down to unmanageable dependency hell.
- chipdart 2y ago> I've witnessed having those packages and versioning only lead down to unmanageable dependency hell. There is no dependency hell. Your consumers allocate work effort to migrate to the latest version. This is work you would still have to do with a monorepo.
- mewpmewp2 2y agoIn a monorepo it would be much easier to find out who the consumers are in the first place - how they use your APIs, and you could easily create a single PR that the consumers can review and approve. In my experience, with separate repositories, packages and teams, I think it's a huge challenge to get e.g. 8 different teams together and then to agree to migrate, since everyone's roadmaps are probably full for the following 4 quarters already.