Also applies to some microservice architectures I've seen. People completely disregard the complexity (and overhead!) of the interactions between microservices.
Also applies to some microservice architectures I've seen. People completely disregard the complexity (and overhead!) of the interactions between microservices.
They're so easy to set up and they immediately solve problems. But they also create many more, which aren't immediately obvious. And very few people are willing to say, "I was totally wrong to move to them, and let's spend some more precious time rolling them back."
It can make totally sense to break out certain parts into their own microservices if you thought long and hard about the interface and which data is going to be passed around – but if you break things out into their own microservices just for the heck of it, you will end up in a very messy mess quickly.
Using microservices to solve problems which don't demand them is similar to using OOP patterns in places where they are known to bring pain: you are holding a hammer and you think the world is made of nails.
That beeing said I am sure this has nothing to do with the real practicality of the underlying patterns, it just shows how easy people can lie to themselves.
RPCs and local method calls both need to be fault tolerant and race condition free. As you break up datastores, transactions become more complex but certainly you had a specific reason to do that so the complexity isn't a choice.
Sure the communication layer is added complexity but that too is should be abstracted into boilerplate such that you shouldn't have to think about it. Overall the added complexity requires more work but it shouldn't really make your business logic problems more complicated.
Firstly, the benefits they offer have often little to do with the architecture itself, but with the bigger picture (separating teams, CIs, allowing different stacks, managing costs, scaling, etc).
Secondly, unlike microkernels, not all microservices have to talk to every single other microservice. If you have a service to send emails, say, there'll be a few services that interact with it, but the majority won't. The same for an image resizing service.
So what you say doesn't necessarily hold
The structure looks something like this:
|-- third_party (third party libs)
`-- python
|-- libs (internally-written, common dependencies)
`-- application_name
|-- client (react app, connects to flask)
|-- server (flask app, connects to services)
`-- services (microservices)
We use a dependency-management + build tool (https://www.pantsbuild.org/index.html, we started before Bazel was public) to manage dependencies. Without pants, our repo would be a mess.Let me know if you have any questions, I'm happy to answer them! I'm super happy about our setup and eager to share it :)
Filed under sentences I never thought I'd hear.
In defense of pants, I meant that our repo would be a mess without a versioned dependency graph + reproducible builds. Of course other tools give you that too, and definitely do it better than pants does.
I guess I should have said “without some build tool”, our repo would be a mess.
Personally, I feel like the top-level directory ordering for a monorepo is somewhat arbitrary, in that you can argue for anything, but it probably doesn’t matter; especially if you have a decent build tool.