Live data from Hacker News

The costs of microservices (2020)

robertovitillo.com

281–290 of 410 posts

Re: The costs of microservices (2020)

#281
post #205

Earlier quoted context omitted.

> God forbid you find yourself with a need to rewrite one of these shitpiles. Actually, this is much easier with micro services as you have a clear interface you need to support and the code is not woven into the rest of the monolith like a French plat. The best code is the easiest to throw away and rewrite, because let's face it, the older the code is, the more hands it's been through, the worse it is, but more impo…

If the monolithic application is written in a language with sufficient encapsulation and good tooling around multi-module projects, then you can indeed have well known and encapsulated interfaces within the monolith. Within the monolith itself you can create a DAG of enforced interfaces and dependencies that is logically identical to a set of services from different codebases. There are well known design issues in mo…

> If the monolithic application is written in a language with sufficient encapsulation and good tooling around multi-module projects, then you can indeed have well known and encapsulated interfaces within the monolith. Within the monolith itself you can create a DAG of enforced interfaces and dependencies that is logically identical to a set of services from different codebases.

So then, not Rails apps

Re: The costs of microservices (2020)

#282
Having an API gateway sounds nice, but that’s not how I’ve seen it. Usually the FE has to query and synchronize multiple API endpoints (eg auth, product, billing).

In this case microservices really just means "let the front-end handle the complexity of synchronizing multiple API endpoints."

And then we wonder why the FE is so complex: https://bower.sh/front-end-complexity

Re: The costs of microservices (2020)

#283
post #205

Earlier quoted context omitted.

> God forbid you find yourself with a need to rewrite one of these shitpiles. Actually, this is much easier with micro services as you have a clear interface you need to support and the code is not woven into the rest of the monolith like a French plat. The best code is the easiest to throw away and rewrite, because let's face it, the older the code is, the more hands it's been through, the worse it is, but more impo…

I disagree. The older the code is, the more hands it's been through, which generally means it's stronger, hardened code. Each `if` statement added to the method is an if statement to catch a specific bug or esoteric business requirement. If a rewrite happens, all that context is lost and the software is generally worse for it. That being said, I agree that maintaining legacy systems is far from fun.

> If a rewrite happens, all that context is lost and the software is generally worse for it.

Unless you have a strong test suite which tests the absence of those bugs. OFC you can never prove the absence of an issue just the continued functionality of your codebase, but re-writes are often prompted by weird "in-between" functionality becoming the norm (or slow/buggy behavior).

Of course a lot of test suites are of dubious quality/many devs have no idea what a good test suite looks like (usually unit tests are some combination of throw-away/waste-of-time, acceptance tests are mostly happy-path and due to recent trends integration tests are all but non-existent).

But in theory, re-writes are fine when you do have a test-suite. Even with a bad one, you learn what areas of the application were never properly tested and have opportunities to write good tests.

Re: The costs of microservices (2020)

#284

Similarly with frontend devs thinking a "modern web-app" can only be built with frontend frameworks/libs like React/Vue/Svelte, etc, lately I feel there's an idea floating around that "monolith" equals running that scary big black ball of tar as a single instance and therefore "it doesn't scale", which is insane. Another observation is the overall amount of code is much bigger and most of these services are ~20% busi…

> Similarly with frontend devs thinking a "modern web-app" can only be built with frontend frameworks/libs like React/Vue/Svelte

Those aren’t frameworks, they are view libraries and I’ll die on that hill.

Further, front end complexity is all in your head: https://bower.sh/front-end-complexity

Re: The costs of microservices (2020)

#285

Earlier quoted context omitted.

If the monolithic application is written in a language with sufficient encapsulation and good tooling around multi-module projects, then you can indeed have well known and encapsulated interfaces within the monolith. Within the monolith itself you can create a DAG of enforced interfaces and dependencies that is logically identical to a set of services from different codebases. There are well known design issues in mo…

"composition over inheritance, because that's how encapsulation can be most easily broken as messages flow across a single-application interfaces, but then I'd also throw in enforced immutability, and separating data from logic" Could you elaborate on this? I see how "separating data from logic" is a problem but what about the other two?

Well now that you mention it I think it does all come down to 'separating data from logic'. I was working backwards from the premise of: "what if we want a monolithic in-process application to have the same cognitive simplicity as an API-based client-server model?"

If you want to enforce a clean interface between an in-process client and server (i.e. a piece of code calling a library interface), then the best model is to think of it as a message passing system, where once a payload is passed from the client to the server and vice versa, the other side should not be able to witness changes to the payload. An immutable payload in this context is the same as the json that goes over the wire between a client and server.

If you really wanted an in-process application to look like a microservice you could take the added step of forcing a serialization / deserialization step on both client and server. I've seen frameworks that do this. But I think immutability, if it can be enforced, is a practical way of solving this problem and far less complex.

Inheritance is a hazier point I was making, in hindsight, because you could use inheritance for data modeling, which is quite fine in some situations... so I think it's effectively subsumed under the "separating data from logic" argument: which is that if you're passing behavioral inheritance from a "server" to a "client", then it gets harder and harder to predict how that client is going to use it and thus it's harder to reason about the functional boundary between two pieces of code. But it's a hazy point because I think the larger and more important point to make, as you point out, is that you simply shouldn't (in most cases) pass any kind of behavior between client and server--just data.

Another approach to look at (besides taking inspiration from Smalltalk) is the actor model, where it's incredibly clear that any communication between modules in an ecosystem is immutable messages. In fact a side effect of the actor model is that it gets pretty easy to move things from in-process to cross-process because most activity in the system is already performed through message passing, so you can just start channeling messages from Actor A to Actor B through a serialization/networking layer rather than in-process if you want to deploy them separately for reasons of convenience or computational needs.

Re: The costs of microservices (2020)

#286

Earlier quoted context omitted.

Your 'senior' engineer is likely right: they are trying to get some kind of process going and you are actively sabotaging that. This could come back to haunt you later on when you by your lonesome decide to merge a 'small PR' with massive downtime as a result of not having your code reviewed. Ok, you say, I'm perfect. And I believe you. But now you have another problem: the other junior devs on your team who see vros…

> Your 'senior' engineer is likely right: they are trying to get some kind of process going and you are actively sabotaging that Why? Because it's a "good practice"? They have 12 people and no customers, they can almost certainly adopt a very aggressive developer cycle that optimizes almost exclusively for happy-path velocity. You'd never do that at 50+ engineers with customers but for 12 engineers who have no custom…

No, because you're not infallible, you'll merge some crap, some things that are outright wrong, that your reviewer might have caught and that slight delay is less painful than dealing with that commited mistake - whether it be an incident in production or 'just' confusion when the next person in that area has to work out if your bug was for some reason intentional and what might break if they fix it.

Re: The costs of microservices (2020)

#288
post #281

Earlier quoted context omitted.

If the monolithic application is written in a language with sufficient encapsulation and good tooling around multi-module projects, then you can indeed have well known and encapsulated interfaces within the monolith. Within the monolith itself you can create a DAG of enforced interfaces and dependencies that is logically identical to a set of services from different codebases. There are well known design issues in mo…

> If the monolithic application is written in a language with sufficient encapsulation and good tooling around multi-module projects, then you can indeed have well known and encapsulated interfaces within the monolith. Within the monolith itself you can create a DAG of enforced interfaces and dependencies that is logically identical to a set of services from different codebases. So then, not Rails apps

Yes, a good point, I think the more dynamic the language, the more one gravitates towards microservices as a problem solving tool, because you'd give up a lot of the value of the dynamic environment by enforcing strict rules.

Though I'm seeing a lot of convergence between environments over time, which makes me think we're all headed towards a nicer future.

For example in Scala, which does a lot of type inferencing, it's typical to tell the linter to require that public methods have explicit types, even though the compiler will reify them at compile time anyhow, because that makes the interface much more robust to refactoring. Meanwhile in a more dynamic environment, in Python it's getting more typical to use type annotations, and, similarly, to especially use them on functions that define a reusable interface.

I figure that the ideal languages in the future have module-level systems where they can define strict interfaces across modules, but then get as crazy and dynamic as they want inside of the modules.

Re: The costs of microservices (2020)

#289
post #76

Earlier quoted context omitted.

Because of dependency issues like he mentioned. If I am using Library A which depends on version 1 of Library C and I need to start using Library B which depends on version 2 of Library C then I have a clear problem because most popular programming languages don't support referencing multiple different versions of the same library.

OSGi and Java Modules would like a word. Too few developers use the facilities available for that kind of in-process isolation, even when it is possible. (Don't tell me Java isn't popular... It may be the new COBOL, but it's still mainstream.)

Good show for mentioning that. If it becomes commonplace for popular runtimes and languages to be able to load modules and their dependencies at that level, then a lot of arguments for service encapsulation go away.

I think in these discussions, a lot of times people are taking past one another. If I start putting a JRE-targeted application together, I know I can eventually reach for isolated modules if I follow good internal practices, whereas if I'm in Python land it's pretty unattainable.

Re: The costs of microservices (2020)

#290
post #284

Similarly with frontend devs thinking a "modern web-app" can only be built with frontend frameworks/libs like React/Vue/Svelte, etc, lately I feel there's an idea floating around that "monolith" equals running that scary big black ball of tar as a single instance and therefore "it doesn't scale", which is insane. Another observation is the overall amount of code is much bigger and most of these services are ~20% busi…

> Similarly with frontend devs thinking a "modern web-app" can only be built with frontend frameworks/libs like React/Vue/Svelte Those aren’t frameworks, they are view libraries and I’ll die on that hill. Further, front end complexity is all in your head: https://bower.sh/front-end-complexity

That's why I included "/libs", for people like you :)

To be clear, for me they are libraries, but realistically people use them as frameworks, as in "standard" ways to think, "frame" and implement something.

But because I'm not dying on any hill specially front-end ones, I'll take a right then a left and go on my way.

Post reply on HN