| ▲ | mrkeen 2 hours ago |
| > Inside a monolith it's easy to answer questions like "Which dependencies are we shipping?"; or "Is this piece of code still used?" Static analysis can often tell you. Once the code is spread across dozens of independent services, those answers become much harder to obtain. I draw the opposite conclusion here. In monoliths, someone else might want the code to stay in the codebase. I don't want to ask everyone about it. Everyone's responsibility is no-one's responsibility, and the code stays as is. In a microservice, I publish an interface, and I'm free to tear up all the carpet behind it as long as it keeps doing its job as advertised. Knowing whether public routes are still in use is still a problem, so you need a minimum level of metrics or logging before you can retire an endpoint. |
|
| ▲ | inigyou an hour ago | parent | next [-] |
| Microservices still have global concerns. Is someone actually using that endpoint or can you remove it? How will you know? Ask everyone? How many HTTP calls are made during one user request and how long does it take? (This concern brought down one of the early microservice projects with a 10-minute page load time) What are the race conditions? User removes billing info at the same moment as making a payment - what happens? Is the payment marked as successful but not actually billed? |
| |
| ▲ | mrkeen an hour ago | parent [-] | | At least read to the end > Knowing whether public routes are still in use is still a problem, so you need a minimum level of metrics or logging before you can retire an endpoint. > What are the race conditions? Everywhere. Just fucking everywhere. I ran a workshop for my team (4-5 backenders) with a simple, pared down example with reads and writes within a 'transaction'. I then demonstrated that LINQ breaks its transactionality, and running in READ-COMMITTED (which everyone does) also breaks transactionality. Either of these conditions is enough. My team walked away understanding this. But we left the idea there to die, because you cannot change these things politically. No monolith owner is going to even pretend to demonstrate thread safety. The lines of defence are: * He will assume it's thread safe * He will argue against change "for code consistency" * He will argue that it makes the code simpler and easier to understand * He will introduce a change which he assumes will fix it, but clearly only makes the race condition harder to diagnose * He will argue that it doesn't matter because race conditions are rare anyway. It's all academic anyway - in a monolith you won't get past the first line of defence anyway. |
|
|
| ▲ | sdfdfsfsdsdf an hour ago | parent | prev | next [-] |
| It's called programming to an interface. type ThingDoer interface {
DoTheThingIDontCareHow() (result, error)
} func NewAmazingThingIMade(theThingINeedButIDontCareHowItDoesIt ThingDoer) {
// You receive the superduper thing and dont care about it in any other way
} func (a *Amazing) DoSomeThing() (result, error) {
return a.DoTheThingIDontCareHow()
} Nothing about "monoliths" prevents or hampers this development style. Once someone decides to do the Thing in another fashion, they are free to do so and you wouldn't have to change a thing. All problems you experience are organizational, not technical. It's psychology we should be studying, not computer science. Edit: In fact you introduced a network boundary which can fundamentally only complicate matters, not make them simpler. |
|
| ▲ | nlitened 2 hours ago | parent | prev | next [-] |
| I think you described not monolith vs microservices, but single person working on a project and making decisions vs multiple. “Everyone’s responsibility is no-one’s responsibility” works the same way if multiple people work on the same microservice. Also a monolith may (actually, must) have internal public interfaces through which components must communicate, and those contracts are more enforceable, amenable to static checks, and much higher performance that microservices’ network interfaces. |
| |
| ▲ | reactordev 2 hours ago | parent [-] | | monoliths can be anything under the boundaries. That's why people get this so wrong. There is no rule that says you must have internal public interfaces (misnomer? how can it be public, but internal, at the same time?). Microservices were entirely designed to split work across teams. |
|
|
| ▲ | VulgarExigency 2 hours ago | parent | prev | next [-] |
| > I draw the opposite conclusion here. In monoliths, someone else might want the code to stay in the codebase. I don't want to ask everyone about it. Everyone's responsibility is no-one's responsibility, and the code stays as is. Then they can retrieve it from source control? Leaving dead code in the codebase because "someone else might want it" sounds like nonsense. |
| |
| ▲ | inigyou an hour ago | parent | next [-] | | It seems usual to leave code in the codebase (possibly commented out) if you think it may be used again in the near future. It's easier than digging through source control. If you know you won't need it any more, then you delete it | |
| ▲ | mrkeen an hour ago | parent | prev [-] | | Then substitute 'dead code' for 'buggy code that someone else likes' |
|
|
| ▲ | danbruc 2 hours ago | parent | prev | next [-] |
| You do exactly the same in a monolith, functionality is broken into modules with a public API and you can switch out the implementation at any time if you want or have to. |
|
| ▲ | reactordev 2 hours ago | parent | prev [-] |
| This is complete lack of experience on the authors part. No tracing, no observability, no knowledge of distributed systems design to allow them to see what they can clearly measure. Your take is the correct one. Microservices break up the monolith so that multiple teams can work on pieces of the solution/platform without stepping on each others toes. The rest of it is documentation/discovery. |
| |
| ▲ | jbreckmckye an hour ago | parent | next [-] | | Tracing and o11y are a poor sibling to static analysis. > This is complete lack of experience on the authors part Actually I'm going to turn the accusation back on yourself: if you think reasoning about a system's entire graph of behaviours from runtime traces is trivial, I don't believe you've worked on a truly complex system The range of what a program can do is much larger than what a program does do in your two week Datadog aggregation window | | |
| ▲ | reactordev an hour ago | parent | next [-] | | It is trivial when properly configured and used. I get why you think I might not have worked on large systems but to the contrary, I've built systems for Fortune 500s. All of them had this baked in and all of them had a place to go when things went wrong. Self-service, observable, documented, and supported by the very folks who wrote it. | | |
| ▲ | jbreckmckye an hour ago | parent [-] | | Observability and operability are just not the same thing as being able to reason about the software. You need both You can't capture the full range of behaviours and edge cases unless you are willing to ingest billions of events without lossiness Metrics have limitations of cardinality. Logs need to be reduced or else you are in archive rehydration hell There will be code paths that have never been triggered that you still need to reason about as part of analysing a system, eg in threat modelling > I get why you think I might not have worked on large systems I didn't, necessarily. But it looked like an excessively strong claim, combined with a challenge to the author's competence. I wanted to call that out. |
| |
| ▲ | mrkeen an hour ago | parent | prev [-] | | Missing the point. Static analysis doesn't go away. Metrics just covers the gap of "is this used by external callers", and nothing more than that. You need that to identify dead routes in a monolith anyway. If you like static analysis, you should be able to spin up new code in a language more amenable to it than the incumbent code. Not doable in a monolith. |
| |
| ▲ | inigyou an hour ago | parent | prev [-] | | Why do you think different people can't work on different parts of a single deployment unit (which is what we mean by "monolith")? | | |
| ▲ | mrkeen an hour ago | parent [-] | | * My last monolith job had 4 hour release windows. * You can't change anything of substance. The more people touching the same codebase as you statistically puts you way lower in the pecking order. Changes become political, not technical. Sometimes the forces of stupidity cancel each other out. It was a 10+ year-old C# monolith, and the top dog wanted to switch to Python because "AI works better with it". I didn't have to waste any time worrying or arguing, since him keeping the system as a monolith made this change impossible. |
|
|