This hasn't been a serious problem in a decade.
> We also had no typing then, so every bug was a runtime bug. Hopefully it's improved in the years since...
The ecosystem has been introducing gradual typing, but even at high scale, types were not remotely the most common type of problem I ever ran into, and certainly not "every" bug.
(ex-Braintree engineer, we processed billions of requests on Rails)
If you took that away from what I wrote, I apologize. I meant that without a compiler and type-checker, you would only find bugs at runtime. In my experience, the vast majority of these would be easily discovered by a compiler. Presumably that experience is shared by Ruby devs since they're now adding type-checking.
> This hasn't been a serious problem in a decade.
That may be true. I haven't had any need to revisit Ruby or Rails since I moved to Go. But it was a serious problem with no workaround, and I've never encountered any scenario like that since switching to Go.
Giving up frameworks with 10+ years of hardening and documentation and libraries and support etc just because of coroutines or static types or nice syntax or because that's what google does then I should do it too makes absolute no sense to me.
Active storage and variants make life so easy.
It's not too bad now, set up a Node environment and there's first class support for using vanilla esbuild or if you want to go without Node entirely there's import maps and lots of goodies at the Rails level to help you manage your JS dependencies. Technically Webpack is still supported too but it's vanilla Webpack instead of Webpacker, that's all part of the new https://github.com/rails/jsbundling-rails abstraction for using a number of different JS bundling tools with their stock set ups.
Personally I went with the esbuild + tailwind combo and it's been smooth sailing. I have an example app here https://github.com/nickjj/docker-rails-example.
It might have improved somewhat, but I find myself pretty comfortable with a much more pared-down test suite that focuses on correctness tests at logical module boundaries in TypeScript, rather than verifying things the computer can just do. I do look forward to seeing Ruby's gradual typing become more entrenched in the ecosystem, though, because I like the language--I just don't like using the language professionally because of the additional manual work I find myself doing.
I would argue that if your unit test is only testing things which would have been shown by the type system of another language, you are testing at too low of a level. In addition to being tedious, such tests are often very brittle.
Having them not be necessary is nice.
Having also used Go a fair amount, I very much prefer the real type system which both documents and enforces.
I enjoy both languages though.
Languages with better type systems do exist (Rust, Swift, Kotlin, from what I hear even typescript?, and all ML type languages including Haskell, ...). They are much better at preventing bugs. My life became better when I had to stop worrying about NPEs, for example.
That's a typical response from dynamic typing advocates, but the response is that in a language with a good type system, many more things can be type errors than would be in a dynamically typed one.
For example, from my time writing Ruby, trying to call methods on `nil` was an incredibly common error, but this is simply a type error in some more modern statically typed languages (including Kotlin and Swift).
For example, if you have a method A that gets a foo from the method B and then does something to that foo, you might get a runtime error if B returns nil. If this happens over dozens of method calls, it can start to become very hard to see where the error was introduced.
But if you know that B is always supposed to return foo and never nil, then the compiler can show you where the error in your definition of B is ahead of time.
The value of null-safety is not in making everything nullable and then just proceed with unwrapping etc., the value is that we can make a lot of types explicitly non-nullable.
I don't think it's controversial that a good type system allows to verify more soundness guarantees at compile time. The only controversy is whether it's worth the effort.
Any static analysis tool you can use to catch bugs before runtime in production is something we want.
Nothing is perfect. In my book restarting a server because of memory leaks is an acceptable trade off versus all the crazynes of having to decide and maintain on how to tie together a database, error validation, background jobs, translations, react, redux, an API to interface with the backend, logging, etc, etc, etc. Also, Go is just part of your system, I'm pretty sure you also have a frontend stack, and complexity increases a lot as I explained here. Compare that to Laravel+Livewire or Rails+ Hotwire. Night and day. I'm pretty sure any serious business will take the restarts any day vs the increased complexity and developer time.
> I've been happily running Go backends for the past 7 years now, and they're stable and fast and easy to refactor.
Yes, and I bet something built in 7 years with Go would have taken 7 months with Rails or Laravel.
On the static typing stuff, I'm with you on that. PHP (and Laravel) are a bit closer to that, but nothing is perfect. And for Web Development using Laravel or Rails is a good trade off.
On larger projects (100k LOC+) I use chi for my router in combination with codegen via sqlc and moq, and I wrote a small program to generate the routes for me automatically with a config file.
Golang encourages libraries and frameworks with much smaller surface, so there is indeed a boilerplate issue, but that's also an issue with golang as a whole.
Curious - were these actual memory leaks or Rails memory bloat due to how ruby allocates memory and holds on to them?
I ran Rails in production years back and swore it off then. We had constant memory leaks that seemingly came from Rails itself, and the only solution we had was "just restart the server." We also had no typing then, so every bug was a runtime bug. Hopefully it's improved in the years since...
I've been happily running Go backends for the past 7 years now, and they're stable and fast and easy to refactor.