4 ms·
I see quite a few people defending microservices; the org is the problem, they must not have written the software correctly, etc. Most org structures are not gr
by ajsharp 6y ago
I see quite a few people defending microservices; the org is the problem, they must not have written the software correctly, etc. Most org structures are not great. Most software is not great. If you expect the exception to be the rule you're setting yourself up for a career full of disappointment.
Microservices are a modern re-branding of service-oriented architecture, but 'microservices' sounds cuter and less like it belongs in Java-land, and there's some theoretical idea that splitting your app into even smaller pieces will somehow make the whole thing better.
SOA/microservices solves a few problems and introduces a great many. The original SOA proponents were pretty explicit about this. Beware! There be dragons here! But one of the main pieces of prescriptive advice from domain driven design is helpful for splitting into distributed services: split along domain lines with minimum inter-service dependencies. Payments is an obvious one. Microservices seems to buck much of this advice in favor for a blissfully ignorant principle of "small" or "isolated". Good luck isolating something that is not meant to be isolated.
Scaling software is hard. Scaling teams is harder. Trying to scale teams by scaling/distributing software is an understandable goal but extremely hard to pull off because of additional complexities and costs you incur in doing so. Dev gets harder, deployment/ops becomes harder, testing becomes harder. Cross-team communication, documentation, API publishing and adherence goes from being very low impact within an org to suddenly being critically important.
To do SOA/microservices effectively you need complete organizational buy-in, and you have to commit completely to developing tooling and solving all the associated problems in moving to a services approach. Often, it's easier to just put it all back together, organize the code in such a way to minimize merge conflicts and wait for the ungodly slow test suite to run in CI. There are good reasons you rarely hear SOA/microservices success stories outside of enormous companies (Netflix, Facebook, Google, Amazing, etc). Doing this stuff takes an enormous investment and commitment from the entire organization, and there are just lower friction ways to skin this cat if you don't operate at mega web scale.
Growing a monolith is hard. Growing a microservices/SOA architecture is also very hard. Growing is hard.
- DrScientist 6y ago> split along domain lines with minimum inter-service dependencies. Exactly, and done right that quite often means big 'microservices'. All too often I see the 'functional programming disease' where the aim is to deconstruct to the smallest possible reusable functions ( 'micro' services right? ), often prematurely, creating high levels of compositional complexity and with zero tools to help you understand how the actual 'app' - say payment system works if it's distributed across 20 services. Yep each single microservice is simple - but the payment system might not be and that's what you need to understand - better if your payment system is one thing - with maybe one or two things separated out if you need to scale that part.
- capableweb 6y ago"Yep each single microservice is simple - ..." but the whole is not. I always find it more interesting what's _not_ in the single microservices, the stuff you do see. When you make a diagram with boxes and arrows, the interesting stuff would be the arrows, not the boxes themselves.
- crdrost 6y agoIndeed my loudest prescription to people doing service-oriented architectures of any kind is to simplify these arrows. The common mistakes that I see are for two services to share read access to a common database, or to discover each other and send RPCs to each other. Both really dangerous for exactly this reason! The common database obscures how the two communicate with each other, and invariably everything connected to a database becomes one service -- call it a "mini-lith" if the overlapping sets created by databases do not cover the whole architecture. The problem is the preponderance of implicit arrows; when I reason about what it means to make this datetime nullable so that I can store such-and-so, I need to consider whether everybody who can read that datetime will be prepared for its nullability. RPCs and APIs are the same way. I add a contract about what I am outputting and then everybody needs to know about my contracts and I must commit to them or else modify all of my consumers. So because the arrows are bi-directional everything just becomes one monolith again. Instead, I recommend message brokers -- all that pubsub stuff. A given service tells all the other services simultaneously "this happened," and it is their responsibility in their codebase to listen for that event and then say "okay, then this must happen." Publishing a new version of the event is done by just emitting both the old and the new version of the event and perhaps having a shared standard for deprecation across the codebase so that you get deprecation warnings in your prod logs. Every service has its own database and they generally only communicate to each other through these broadcasts, makes the arrows into the "stuff you do see".
- ajsharp 6y agoCompletely agree. The micro thing is rooted in a desire for simplicity, which is laudable from a theoretical perspective. Small is simple and simple is nice to work with. But in any production software it's usually a pipe dream. Kind of the whole point of software is to take a bunch of complexity and make it simpler for the end user. The fact that the software visually looks like shit or is difficult to work with because it's difficult to reason about is a rather unfortunate side-effect, but usually has no bearing on actual business success. There are lots of things we should try to do to reduce software complexity and make it easier and safer to work with and change. But trying to force simplicity by way of size usually has the opposite effect.
- breischl 6y ago>Cross-team communication, documentation, API publishing and adherence goes from being very low impact within an org to suddenly being critically important. Totally agree, but I think this is underappreciated by many. People tend to wave this away by just saying we'll just use Swagger/gRPC/whatever-doc-gen-tool, but that's not the main problem. The problem is that each service needs to have some coherent purpose, and must adhere to that purpose. Changes to that must be reflected through a proper API change and migration. But that requires thought, discipline, and (sometimes slow) work. When you inevitably run into a situation where you could instead throw a quick hack into the wrong service that will make things work now the temptation to do it very strong (bonus points if this is due to regulatory changes). But now you have an undocumented behavior dependency between those services - they're coupled in a subtle way. And eventually the accretion of those results in a distributed monolith instead of a plain-old monolith. >domain driven design is helpful for splitting into distributed services: split along domain lines with minimum inter-service dependencies Definitely, yes. But then when your business evolves in some way that causes all your domains to be inappropriate, you're up a creek again. I don't think there's really a solution to that, though.