10 ms·
It is possible to build balls of mud either with microservices or larger-sized services. There are pros and cons to both. But when "easier testing" (from OP)
by dagss 8y ago
It is possible to build balls of mud either with microservices or larger-sized services.
There are pros and cons to both.
But when "easier testing" (from OP) is said to be an advantage of microservices specifically...I am not sure what to say.
I mean it is not like every test has to test the entire monolith. And it is not like testing each microservice in isolation is always going to be sufficient.
It is entirely orthogonal. Of course a well-designed microservice is easier to test than a monolithic ball of mud, but a well designed monolith is also easier to test than a poorly designed spaghetti of microservices.
It is as if some people think "good code" and "microservices" are synonyms. No. They are orthogonal.
Industry is always going in circles. Fads come and go.
In many ways, Cloud Functions are very similar to a horizontally scalable stateless monolith backend. When you break up services small enough, the "monolith" arises again as simply the sum of what you deploy in an organization.
- colonelpopcorn 8y agoIt just goes to show how few folks truly test in isolation.
- stingraycharles 8y agoCould you elaborate on what you mean with this? It seems like you are hinting at something which I apparently did not pick up.
- quickthrower2 8y agoI don’t always, but I’ve never had the luxury of working on a greenfield project. With legacy code it’s a mammoth task to pull apart the spaghetti (more like a drawer of tangled headphones) to get the ideal test.
- jimmy1 8y agoA better way of stating it, "It goes to show how few folks truly value testing in isolation" that is, having good tests in isolation is seen as a nice ideal to pursue, but delivering working code first trumps all. "How do you know it works?" is a common reply to this line of reasoning, obviously we all have an idea of what "working" looks like, it's just whether or not we have gone the extra step of formalizing it in the form of tests.
- danmaz74 8y agoTesting components in isolation is useful to ensure that your components work as expected. But it will never ensure that your whole system works as expected, unless the interaction between your components is so simple as to be obviously correct (which, in my experience, is almost never the case).
- jrockway 8y ago> when "easier testing" (from OP) is said to be an advantage of microservices specifically...I am not sure what to say. I think the service boundary ends up being a very good place to inject "fakes", because that boundary is not artificial like it is when you fake out parts of a monolith. The RPC service has two methods and that is the only way _anything_ can interact with the real service, so faking out those two RPC calls let you write focused tests easily. Obviously you can have service boundaries in monolithic applications, but they are easy to ignore "just this once". By having an API boundary enforced in production, you avoid these problems (or the workarounds become more creative, but that's easier to say no to). The average monolithic app sitting in production is quite difficult to test because no thought is given to internal APIs. Things rendering HTML make literal database queries, and so the only way to test things it so just run the whole monolith against a local database. That ends up being slow and flaky. Basically, microservices forces code to do less. When code does less, it's easier to test. When any HTML page can write to your database, you have a mess on your hands. That is totally orthogonal to microservices, but microservices enforce your API contract in production, which I find valuable.
- dagss 8y agoIMO if you are writing backend code where it is difficult to insert fakes at any point where you need to test, then all bets are off anyway. Doesn't matter if you use monoliths or microservices. If you can't abstract out some dependency and insert a fake without actually hitting the network layer then you shouldn't be writing backend code. It is more about test-driven development than anything else. You need a policy to do micro-services in the first place. You can also have policies (enforced by peer review) to have well-tested code and internal API boundaries. It doesn't come by itself, but neither does microservices. At the end of the day you need development processes driven primarily by automated tests and good coders. Bad coders will make a total spaghetti mess of microservices too, in fact the consequences of microservices can be catastrophic and crippling if the developers don't properly understand how to write distributed systems etc. (trust me I've seen it happen). Difference is, when you have that micro-service spaghetti mess, refactoring it to something with clean nice boundaries can be harder than with a monolith -- since the position of the boundaries tend to be less malleable. (This varies depending on how the microservices are tested & deployed, and also, how "malleable" and how "hard" a boundary is is really orthogonal.) If micro-services does anything, it is to raise the bar for what developers can succeed in working with it. Put those same developers at work on a monolith though, and I think the results are the same. It's a filter for good developers, more than the things you say, IMO.
- mlthoughts2018 8y ago> “It is as if some people think "good code" and "microservices" are synonyms. No. They are orthogonal.” I disagree very strongly, and it is also part of why I believe monorepos are generally a mistake. Microservices are a natural extension of things like decoupling and Single Responsibility Principle. Just because you superficially could achieve similar effects with gargantuan amounts of tooling and imposed conventions in a monolith class or something is absolutely no type of refutation of the fact that modularity and separated boundaries between encapsulations of units of behavior represent a better way to organize and structure the design. It is no different and there is no leakiness to the same abstraction when you move to discuss services instead of classes or source code units, or polyrepos v monorepos. The abstraction definitely can become leaky if taken too far in other domains, it just happens that the abstraction is depicting precisely the same organizational complexity properties in the case of source code -> service boundaries -> repository boundaries.
- dagss 8y agoWell, but some services composed of microservices turn into a distributed spaghetti monolith though. They only "naturally decouple" if you draw the lines between units correctly in the first place. And if you are able to do that well, that's the most important step in making any code turn out well regardless of the size of the services and how much of the boundaries are in the same class/repo/process/service. It also correlates with the "tendency to cheat" within a single service. There ARE real advantages to micro-services, sure. But you trade them against an ability to quickly refactor if it turns out you drew the lines completely wrong initially. Or perhaps you end up with something that becomes very complex that could in fact have been short-circuited and replaced by 5% as much code by looking at the problem from an entirely different angle -- which you never do because of the pattern that has settled in how the micro-services were divided. (At the end of the day, the code that is simplest to maintain is the one you don't need to run..) So I maintain that it's a trade-off. This seems relevant: https://xkcd.com/2044/ https://xkcd.com/2044/
- mlthoughts2018 8y agoWhat you propose ends up sounding like this from my point of view: Salad is generally better for your health than red meat. However, some people eat so much salad, with so much dressing, that it ends up being worse than red meat. Meanwhile, with great care about meal planning and moderation, some people stay pretty healthy eating red meat. Therefore red meat is actually healthier than salad.
- danmaz74 8y ago> It is entirely orthogonal. Of course a well-designed microservice is easier to test than a monolithic ball of mud, but a well designed monolith is also easier to test than a poorly designed spaghetti of microservices. I would also add that a well-designed monolith is inherently easier to test than a functionally equivalent well-designed microservices architecture.