4 ms·
Microservices [0] > grug wonder why big brain take hardest problem, factoring system correctly, and introduce network call too > seem very confusing to grug
by jihadjihad 1y ago
Microservices [0]
> grug wonder why big brain take hardest problem, factoring system correctly, and introduce network call too
> seem very confusing to grug
0: https://grugbrain.dev/#grug-on-microservices https://grugbrain.dev/#grug-on-microservices
- jayd16 1y agoThe short answer is it adds monkey patching to languages that don't have it.
- actionfromafar 1y agoThis is true, but monkey patching is scary. If you can switch over a monolith, and keep a rollback in case of trouble, do that. Make small changes in the monolith a time, though.
- jayd16 1y agoBtw, do any good, modern CI tools support incremental rollout of multiple in-flight changes on monoliths? As in patch A is live, team B wants to rollout A+B and team C wants to rollout A+C. Ideally, A+B+C will eventually go live. Do cloud/paas providers deeply support this flow anymore? Every dashboard would need to compare across multiple live versions and I haven't tried that in a while.
- anonymars 1y agoWouldn't these just be different branches?
- jayd16 1y agoI'm referring to rolling out multiple merge downs (possibly from branches) from across the entire org into a monolithic deploy.
- bunderbunder 1y agoI'd say this is a job for feature flags. That way you always have exactly one live version of the code, but still retain the ability to hide WIP from users until it's ready. If you're instead doing this with feature branches or something like that, then by definition you don't have CI. You have NI: Never Integration. Because, to an approximation, there's never any point in time where all of the code you're working on is integrated together so that everyone has a chance to see how what they're doing interacts with what everyone else is doing. And yes, it is possible for a branch to successfully auto-merge and produce something that compiles and passes all automated tests, and still introduce a horrible regression defect because of an unanticipated interaction between two different changes on two different feature branches. I don't see it happen often, but when it does it usually creates such a big production SNAFU that even once every 5 years is still way too often for my taste.
- jayd16 1y agoI don't dispute that good CI is facilitated by committing early and often but difference do feature flags really make? You still need to roll out features whether you tie that to versions or not. If you're looking for performance regressions as you roll out feature flags, do you get any kind of support for that from built in dashboards? How do you get clean metrics if you only have one version and a bunch of teams turning knobs? SOA/Microservices have a lot of headaches but you do get the option for very tightly scoped deployments or feature rollouts.
- bunderbunder 1y agoMonkey patching is a great technique for hacking rudimentary testability into legacy software as part of your preparations for refactoring it for maintainability. But when I see a plan to use it that doesn't include a plan for how to stop using it again ASAP, I get very worried.
- cgannett 1y agogrug mention grug brain. grug also have grug brain. grug like grug. grugs together strong unless too many grugs then Overgrug think 9 grugs make baby grug in one month and grug not think it work like that
- BoardsOfCanada 1y agoBecause the network call turns the rule into a law.
- frollogaston 1y agoThis is also why app backends don't really need statically typed languages, no matter how big the company is. You have a well-defined API on the front, and you have a well-defined DB schema on the back, that's good enough. The static typing makes even less sense at finer code scopes, like I don't need to keep asserting that a for-loop counter is an int.
- roguecoder 1y ago"Need"? Probably not. But unlike microservices they don't really have downsides (at least not with modern IDEs and the automatic refactorings they support) and they do offer some benefits. Statically-types languages are a form of automatically-verified documentation, and an opportunity to name semantic properties different modules have in common. Both of those are great, but it is awkward that it is usually treated as an all-or-nothing matter. Almost no language offers what I actually want: duck typing plus the ability to specify named interfaces for function inputs. Probably the closest I've found is Ruby with a linter to enforce RDoc comments on any public methods.
- frollogaston 1y agoI'm fine with types in shared libs, just not in the app layer code, where the cost outweighs the benefit. I think you can do the in-between you describe with Typescript, but every time I've been on a team that says "oh you can use `any`," one day they disallow it. Especially in a big corp where someone turns it into a metric and a promo target.
- tauoverpi 1y agoStatically typed languages, when used correctly, save engineering time both as you extend your service and when thing go wrong as the compiler helps you check that the code you've written, to some degree, meets your specification of the problem domain. With a weak type system you can't specify much of the problem domain without increased labour but with a more expressive type system (and a team that understands how to use it) you can embed enough of the domain specification that implementing part of the business logic incorrectly or violating protocols turns into compile errors instantly rather than possibly leaking to production. As for your comment on `any`, the reason why one doesn't want to fall back on such is that you throw out most of the gains of using static types with such a construct when your function likely doesn't work with `any` type (I've never seen a function that works on absolutely anything other than `id :: a -> a` and I argue there isn't one even with RTTI). Instead you want to declare the subset of types valid for your function using some kind of discriminated union (in rust this is `enum`, zig `union(enum)`, haskell ADTs/GADTs, etc etc) where you set a static bound on the number of things it can be. You use the type system to model your actual problem instead of fighting against it or "lying" (by saying `any`) to the compiler. The same applies to services, APIs, protocols, and similar. The more work the compiler can help you with staying on spec the less work you have to do later when you've shipped a P1-Critical bug by mistake and none of your tests caught it.