Earlier quoted context omitted.
Totally agree with you, but one point against doing what you mentioned is that you want to replicate your prod environment as much as possible in CI, to be able to catch bugs
From my experience this has been mostly painless, and yes, in CI you can obviously run against environments using the same stack as prod. It may help that I'm writing plain old boring ecommerces or internal tools (scrapers, chatbots, backoffices, warehouse management, delivery systems, etc) and not something more complex and low-level like databases or rendering engines.
One year after switching from Java to Go
121–130 of 503 posts
Re: One year after switching from Java to Go
#122Earlier quoted context omitted.
Even if your entire stack is TS, you still need validation because the submitted data from an external interface (API call) might not be valid. You can't just accept any JSON payload and expect it to be valid. In Java or .NET, it will fail at serialization when the runtime tries to map it to a static type (automatic). This is not the case at runtime with JS (because at runtime, it's no longer TS). Thus you need a Zod…
I think CharlieDigital's point is that a bad payload will fail right at the serialisation boundary in case of .NET. We know the problem right there. Now we only need to fix the bad payload. For TypeScript with only types and without validation, a bad payload gets through, and there is no telling where in the workflow it will explode. This could waste more time and developer resources in debugging.
Re: One year after switching from Java to Go
#123Earlier quoted context omitted.
What challenge did you run into with exception handling? I'm curious because I've never felt it being onerous nor felt like there was much friction. Perhaps because I've primarily built web applications and web APIs, it's very common to simply let the exception bubble up to global middleware and handle it at a single point (log, wrap/transform). Then most of the code doesn't really care about exceptions. The only cas…
Exceptions are fine if you never catch them. So is calling abort(). (Which is the Unix way to do what you described.) If you need to handle errors, you quickly get into extremely complicated control flow that you now have to test: // all functions can throw, return nil or not. // All require cleanup. try { a = f(); b = a.g(); } catch(e) { c = h(); } finally { if a cleanup_a() // can throw if b cleanup_b() // null che…
Re: One year after switching from Java to Go
#124> But there are obviously work around solutions in the Go ecosystem. It uses the Context ctx, which we pass around functions in order to juggle data around in the application. Man. This works. The context API allows/enables it. But I’d really recommend against passing data to functions via context. The biggest selling point of Go to me is that I can usually just look at anyone’s code and know what it’s doing, but thi…
I hit this point in tfa and had the same comment. Please don’t pass things around in a Comtext. Maybe stash a slog logger in there, but that’s about it. I made the switch to Go a few years ago. For those who are on a similar journey as the author, or the author himself, I suggest spending time with the Go standard library and tools written by Rob Pike and Russ Cox to get a handle on idiomatic Go. It’s clear the autho…
In Node, I remember wrapping Promisesromises into objects that had a stack for pushing messages onto them, so that the creator of a Promise could mark the calling site, and creating another Promise within that promise would pick up the chain of call site names and append to it, etc. Logging that chain when a Promise fails proved to be very useful.
Re: One year after switching from Java to Go
#125Earlier quoted context omitted.
I think CharlieDigital's point is that a bad payload will fail right at the serialisation boundary in case of .NET. We know the problem right there. Now we only need to fix the bad payload. For TypeScript with only types and without validation, a bad payload gets through, and there is no telling where in the workflow it will explode. This could waste more time and developer resources in debugging.
Again this isn’t an inherent property of .net, you have to add validation. There are plenty of ways to do this in node so the point is moot.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/{userId}", (int userId) => userId);
app.Run();
See `int userId`? If I call this API with `http://localhost:5123/asdf`, I will get an error because the types don't match. If I call this with `http://localhost:5123/1234` it will work fine. The same would be true if I required a class `User` here. The router is able to introspect the type at runtime to determine if the types match; both basic types like this as well as complex types using the built-in serializer. It is built in.I've put it into a short clip for you: https://imgur.com/a/WNbGUQD
Re: One year after switching from Java to Go
#126Earlier quoted context omitted.
Agreed, the spring framework is completely against the spirit of Java. Yeah, auto-wiring was a terrible idea - why do I have to guess what components are going to be pulled in? And why do I have to figure this out a runtime? The features of Spring Boot are nice, but Spring itself should probably be put out to pasture. Someone needs to write a good alternative to Spring and start promoting it like crazy (probably some…
went to springone conference in vegas in 2016. eight years later, there are still no good alternatives :)
Micronaut? Quarkus? Depends on what you need.
Re: One year after switching from Java to Go
#127Earlier quoted context omitted.
Again this isn’t an inherent property of .net, you have to add validation. There are plenty of ways to do this in node so the point is moot.
Here is a .NET web API var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/{userId}", (int userId) => userId); app.Run(); See `int userId`? If I call this API with ` http://localhost:5123/asdf `, I will get an error because the types don't match. If I call this with ` http://localhost:5123/1234 ` it will work fine. The same would be true if I required a class `User` here. The rou…
The fact that it’s built in is neat but not really important. Most people are not making thousands of toy apps. If the necessary they will integrate and move on.
There are more compelling reasons to use .net than this.
Re: One year after switching from Java to Go
#128I’ve been out of the Java scene for a really long time, but will be coming back to it soon. I’m curious - these performance issues described here, are they inherit to how Java itself? Is it baggage from Spring/Boot? Are there ways to get more bang for the buck with some careful choices in a system like this? The closest I’ve done to Java recently is C#, which I think may have similar challenges, but overall didn’t se…
Having done a lot of Java and Go, Go has much better mechanical sympathy between the language, libraries, and vm than Java does. The JIT GC in Java are marvels of engineering, but they have to be. As an example, in Java, everything is a pointer, so pointer chasing all the time, which is not good for cpu cache, etc. In Go, there is first class support for composition. The other main adjustment, if coming from Java, is…
Strictly speaking that's not true. It's everything is a pointer in theory to make it easier to reason with and JIT / JVM optimizing in the background.
There are primitive types and there are lots of tricks in the JVM e.g. escape analysis that places objects on the heap/stack etc.
Re: One year after switching from Java to Go
#129Going back to first principles, nominal typing is what I miss most with Go. I get the utility of structs + interfaces + structural typing, but most of the time there is more benefit in declaring that a type nominally implements an interface when that is the intention. Code is far easier to read and understand that way, both for developers and tooling. I suppose exclusively structural typing would be more acceptable i…
Are you aware of the trick of "var _ foo.RequiredInterface = myType{}" to make the compiler enforce that a struct implements a given interface? Is what you seek a nicer syntax for this or does what you speak of bring something more feature wise? At least IntelliJ IDEs will always make it clear what interfaces all your structs implement.
Yes, and while it uses the compiler to ensure a type implements an interface, it's still a trick that exposes a large hole in the language... and begs for it to be filled. Most importantly, it still doesn't make the code much easier to read and understand.
>At least IntelliJ IDEs will always make it clear (or less foggy)
Indeed. Go benefits hugely from IntelliJ, or to be specific the IJ plugin API.
Re: One year after switching from Java to Go
#130Earlier quoted context omitted.
https://github.com/codr7/tyred-java/tree/main/src/codr7/tyre... 24 of those files are under 100 lines - some of them are as small as three lines of code. and that's not a personal preference - that's mandated by Java that each type needs to be in its own file, ridiculous.
I don't see that as a problem at all, just like I don't see header files in C++ as a major problem, there are benefits as well and Java has the best IDEs of any language I've worked in except maybe SmallTalk.