luuio
Where our conversation is at, it's not about RDBMS vs. NoSQL.
On the Redis INCR operation example (or an equivalent operation in any database, even in an RDBMS). In short, you don't always have the guarantee to know the result of the operation. This is part of what the 99.9% means when services advertise their reliability. 99.9% of the time you'll get an acknowledgement back, but not 100%.
The question comes to, what happens if I miss an INCR, or if I accidentally double INCR when I retry? For some use cases, it's acceptable: like counting the number of views on a Youtube video. For others, say a financial system counting money or making a payment, that's not OK. That's where idempotency really matters (btw this is why many redis operations have the NX option).
Let's go completely off track for a little bit, say you're Strava. You let devices and users upload workouts to your service. What happens when a phone sent you the workout, then disconnected due to bad receptions? In this case, the phone doesn't know if the operation succeeded so it's forced to retry. How do we make sure the workout isn't created and counted twice on Strava? Well, each workout has a unique UUID generated by the device. Strava uses this UUID to dedup when it receives an upload. The UUID is the idempotency "checkpoint".
In this case, it doesn't matter what kind of database Strava is using. The idempotency problem is the same.
Imagine this: you issued a write, a few things can happen: 1. The callsite crashed, maybe due to an out of memory issue or whatever. You don't know if it succeeded
2. The database returned an acknowledgement, but then the callsite crashed before storing the acknowlwedgement for the next step.
when you retry and load the object, you get {count: 10, etag: 3}. how do you know if your previous attempt had successfully persisted or not?
you can imagine this:
```
var thing = KVStore.Get<MyThing>(...);
if (things.Checkpoints.Contains(myUuid) == false) {
thing.Counter += 1;
}KVStore.Update(thing); ```
having an etag doesn't help you with retries, where we expect that `thing` could be mutated by another flow between your retries.
i have found this to be true throughout my career. not that things cannot improve, they can always improve. but assuming the original work wasn't grossly incompetent, anything "new" tend to make the same [undocumented] mistakes
2. Having the business logic (not just loading the data) inside the stored procs meant that a change in business logic that would normally only need to update application code, now invalidates the stored procedure's cached execution plan.
Storing the checkpoints along with the mutation was for idempotency. If the checkpoint was in the document, that meant the mutation had succeeded and a retry should be no-op
- Simple solid modern colors, no halo/vignette effect like the Vista/7 logos
- Multiple colors, not just one single boring blue color like the newer logos
- The S-curve lines are just soft enough, yet not overly complicated, but also not boring straight lines
- Go (the language) is missing the ability to declare something immutable. I don't mean making fields in a struct private then exposing getters. I mean the equivalent of an immutable reference in Rust or `const ref` in C++.
- Go mod and go workspace still can't get a cohesive story together [1]: - - If my module wants to depend on another module in a workspace, `go mod tidy` would freak out. - - If I use replace in my go mod file to point to the other modules in the same workspace, `go mod vendor` will copy these workspace modules to the vendor folder as well.
- Go (the language) is missing the ability to declare something immutable. I don't mean making fields in a struct private then exposing getters. I mean the equivalent of an immutable reference in Rust or `const ref` in C++.
- Go mod and go workspace still can't get a cohesive story together [1]: - - If my module wants to depend on another module in a workspace, `go mod tidy` would freak out. - - If I use replace in my go mod file to point to the other modules in the same workspace, `go mod vendor` will copy these workspace modules to the vendor folder as well.
It's not what C++ can or cannot do, it's not what Rust can or cannot do. It's what the Rust language and compiler opinionatedly encourage you to do and not to do. This is what's lacking in C++.
As others have responded, there are definitely trade offs with different models. The way I've seen (B) worked well is:
* Given a project, separate out the "level" of different axes. A project could have level N technical scope, but level N+1 collaboration scope, etc.
* Let the level-N engineer handle one level N+1 axis at a time, with supervision on other axes.
* And if they ace one axis, then back off and give them more responsibilities on the other axes, for the same project or subsequent projects.
Of course there are also scenarios where someone is just thrown into the deep end. They will either sink or swim :)
One common behavior seen in “mature” software engineers
> As for being intuitive, the default experience is to use the Web SDK. I didn't even get into SDKs but it does more than default the framework reference. It also exposes capabilities that tooling use to light up behaviors in the build and in the IDE.
It is these "does more than default framework reference" are precisely the things in discussion here. All of these hidden functionalities and dependencies are like a black box. What's the difference between what James shared here and the default Sdk=...Web, then? It's the lack of uniformity, where "ASP.NET is a first class citizen" rather than just another piece of the ecosystem that is a turn off.
Compared to other ecosystems, for example: Go, Rust, even Java for example, where everything is just code that one can pull in, and the customization is in the code, not the runtime/JVM.
The answer the asp.net team shared below, was instead of using the SDK attribute, use a completely different thing called FrameworkReference. Which can completely replace this SDK attribute, it seems.
Hence my question to them below was, why is framework reference not the default? Especially since it does lead to better searchability, and the template shows that one could have multiple of these per project, intuitively.
Look through the rest of this comment thread and see how many failed attempts at solving this problem there were before two high profile members of the ASP.NET team came in (JamesNK and davidfowl).
It's not about looking up or not looking up. The criticism here is that the way the framework is laid out is not intuitive enough. It's very "different" from the rest of the industry (in this case, there are 3 potential ways of pulling in dependencies for ASP.NET). This requires a lot of time investment for its users to solve these slight one-off issues.
My question to them below was why isn't what they shared here the default. If they had done that, it would be intuitive to know that one can add other "FrameworkReferences" in a project, or know what to search for. Instead, the default is "each project can only target one SDK".
From Python: have one way of doing things
From Go: explicit is bette than implicit.
Is Sdk=... is just a short cut to pull in a handful of framework references? Or are there actually more things happening under the hood?
The other question is, why isn't what you posted the default, but defaulting to this <Project Sdk=...>? To me, it's a lot more intuitive, signaling that each project can have multiple framework references, vs. just one SDK attribute.
This still begs the question, or my original point still stands—why framework reference vs. nuget reference? I'm sure there's a perfectly rationale explanation, but this in itself, having at least two "official" ways of managing dependencies (framework reference vs. package reference on nuget), it's kind of a "code smell" imo.
That's what I have been calling out. I have not had much luck in pulling in the right dependencies needed. Could not find any documentation on it. Everything relies on that Sdk=...Web thing on the official documentation.
When I said console app, I literally meant using the project that you would create if you do `dotnet new console`.
To copy from my other comment:
That is exactly the thing. I do not want to have the Sdk=...Web/Worker. Imagine this scenario, you started a new project with the Sdk targeting Worker. Then you need that binary to also target web. What do you do?
- If you switch the project to Sdk=...Web, you won't have the dependencies to build the worker services.
- If you keep it as Sdk=...Worker, you won't have the dependencies to build asp.net
- If you switch the project to Sdk=...Web, you won't have the dependencies to build the worker services.
- If you keep it as Sdk=...Worker, you won't have the dependencies to build asp.net