Live data from Hacker News

Ruby 3.2’s YJIT is Production-Ready

shopify.engineering

271–280 of 304 posts

Re: Ruby 3.2’s YJIT is Production-Ready

#271
post #80

Earlier quoted context omitted.

As someone who spent a good chunk of their career teaching TDD, I agree and disagree. Yes, tests are crucial. However, which tests to write varies among other things by language. When I write Ruby, I benefit from testing even the simplest things. When I write Rust or even Type Script or Swift I'll focus much more on tests for complex logic and on integration and acceptance tests. Static typing eliminates an entire, l…

When I write Ruby, I test expected behaviours, and if there are type errors in there those tends to fall out from tests I needed anyway. If you need to test specifically for errors due types, then generally that suggests that either your application does not normally exercise those code paths at all and/or you fail to test behaviours of your application.

100% on testing behavior. That said, I still end up writing more and lower-level tests in Ruby to get fast feedback on silly errors, both in terms of locality of the failing test and in terms of not executing the entire stack to test variations of behavior somewhere deep inside.

Re: Ruby 3.2’s YJIT is Production-Ready

#272
post #138

Earlier quoted context omitted.

The problem, I think, is the restrictions that not having a compilation step places on what typing you can do without a big breaking change. Typescript didn't have this problem because everyone already used bundlers/minifiers/etc. Adding another compiler like step to that process was pretty natural. Ruby doesn't have that and adding it in poses problems for REPL development. They chose to go with a separate file for…

Speaking for sorbet - no compilation step is a feature, not a bug. Imagine adding some kind of build step to every ruby app out there! Sorbet annotations are just valid ruby code you add to your files (you don't need to write separate type files - the sorbet system might do this for you though). Sorbet also provides a gradual typing system where you can start adding types to a large code base and gradually make the c…

Couldn't you still have duck typing?

If a method expects to be passed an argument that it can call "quack" on, can't you define a type that has "quack"? The actual argument could be a Duck or a Goose but as long as it has a "quack" method the type will be OK

I haven't used types in Ruby (or much at all other than dabbling in Typescript), so I might be missing something

Re: Ruby 3.2’s YJIT is Production-Ready

#273
post #264
post #151

Earlier quoted context omitted.

Does this include writing libraries for use by third-parties?

To an extent. In libraries for third parties you do need to test contracts specified by your docs, but a well written Ruby library should intentionally avoid over-testing typing (both in separate tests and in code) and focus on testing behaviours. Sure, test for sane failure modes in line with the documented contract, and that may include the occasional test that is de facto a type test, but often testing for types,…

I have zero to no experience coding in Ruby, so I cannot comment in that case.

In Python or JavaScript/TypeScript, though, my experience is that failing to validate types at the borders (i.e. every single function/method/constructor/generator/... exposed in your API) is pretty much guaranteed to end up, months later, with developers attempting to sherlock out surprising breakages in production from logs that make no sense and traces that do not show anything remotely close to the actual culprit.

I have the scars to show it :) Of course, YMMV.

Re: Ruby 3.2’s YJIT is Production-Ready

#274
post #241

I've set this up in a staging environment of one of our apps to take a look. The staging environment we use for one-offs is on Heroku (can stand one up/down quickly), and the first issue is that a lot of the 'easy to deploy is a feature' PAAS platforms is that they bill by web/worker size restricted by memory rather than just pure virtual CPU power. Render etc all does this as well, and the memory headrooms are low.…

OT(ish) but a t3.medium on ec2 with 2v cores and ~4gb of mem is $33 a month ondemand. $20/mo on ri, and $10/mo spot. I'm mostly done with Heroku. With one kinda big app left, all other envs, and projects are now just on aws without the tax of heroku. And I was a big heroku fan, but their recent decisions made me shop around. I do miss the price $$ of metal in a dc, but not the price :clock: of metal.

Have you considered fly.io?

Re: Ruby 3.2’s YJIT is Production-Ready

#275

I start to have less love for technical pride languages and love business backed languages like Ruby more. It also means wide ranges of library, more jobs. Great or elegant niche languages put me in bad position so far. (Also sick of developer complex)

I understanding where you're coming at when I use Mastodon and see how RoR has enabled it but at the same time I cannot avoid thinking how much money the poor maintainers can save if it was written in Go or Rust.

Re: Ruby 3.2’s YJIT is Production-Ready

#276
post #108
post #51

Earlier quoted context omitted.

I've been coding for 10+ years and I would argue that ruby is not kind to the writer. Ruby requires you to be aware of much more "state" than any other language that I have coded in, because all assumptions about methods cannot be confirmed until the code is run. For example, a gem might modify the default_scope of a portion of active record models. You have to memorize all these tweaks and even then you don't know i…

That is a Rails issue, not a Ruby issue. Outside some Rails libraries this is not a thing. Virtually all non-Rails libraries try hard to avoid modifying global state.

rspec uses monkey patching for stubbing methods. Even rails libraries avoid modifying global state, but its still very much a thing.

Re: Ruby 3.2’s YJIT is Production-Ready

#277
post #107
post #49

Earlier quoted context omitted.

Even in dev, you have to basically code in irb in order to verify everything works.

Nonsense. I used to be a professional Ruby developer and that is nowhere close to the truth. While I prefer static typing it is not hard at all to code in Ruby once you have learned the basics and I almost never used IRB other than when I was a beginner.

How many different ruby projects did you code in? Once you have memorized the global state on a project, you can rely on your intuition and rely less on irb.

But anytime someone introduced a new gem (namely act_as_paranoid) or writes a new concern that modifies defaults, then you're back to need to do live code.

Re: Ruby 3.2’s YJIT is Production-Ready

#278
post #273
post #264

Earlier quoted context omitted.

To an extent. In libraries for third parties you do need to test contracts specified by your docs, but a well written Ruby library should intentionally avoid over-testing typing (both in separate tests and in code) and focus on testing behaviours. Sure, test for sane failure modes in line with the documented contract, and that may include the occasional test that is de facto a type test, but often testing for types,…

I have zero to no experience coding in Ruby, so I cannot comment in that case. In Python or JavaScript/TypeScript, though, my experience is that failing to validate types at the borders (i.e. every single function/method/constructor/generator/... exposed in your API) is pretty much guaranteed to end up, months later, with developers attempting to sherlock out surprising breakages in production from logs that make no…

The "Ruby way" in this respect tends to be to avoid being over-prescriptive. That doesn't mean "do no checks", but "do only the checks actually needed" with a very different expectation of "what is needed" than in many other languages.

Hence don't check for an IO object when what you care about is the presence of a "#read" method.

Or don't check if something is an Array if what matters is that it supports "#map". Instead, either somearg.respond_to?(:map), or if it needs more than map, somearg.respond_to?(Enumerable) (this seems broad, but supporting Enumerable only requires implementing "#each" and including the module, so a caller "worst case" can reopen a class or wrap their object), or call one of Array(somearg) (tries "#to_ary" then "#to_a" then falls back to returning [somearg]) or Array.try_convert(somearg) (tries "#to_ary" then falls back on nil).

Consistently picking the most generic applicable options when faced with choices like that still enforces the contract on the boundary, but also tends to lead to code with much less ceremony. E.g. far fewer [something]Adapter classes, or glue code to convert data before calling methods that are being overly prescriptive.

But for most statically typed languages, when people talk about static typing, they still talk about a class and a type as interchangeable (there are exceptions, and it's getting better, and with increased type inference coupled with increased support for type annotations and analysis of dynamic languages, I expect there to be an increasing convergence, though).

Re: Ruby 3.2’s YJIT is Production-Ready

#279
post #260

Earlier quoted context omitted.

> Most languages that pretend to be strongly + statically typed aren't, by a fairly large margin (I'm looking at you, C++, Objective C or Dart). What about Dart doesn't feel sufficiently typed for you?

Last time I tried Dart (2020?), it was pretty easy to confuse the type system and get it to just abandon all hope of typing a fairly simple expression. I remember the early Dart presentations in which the developers very clearly stated that they didn't even try to make the Dart type system sound, because they felt that it would complicate the life of users. Apparently, these days, Dart claims to be sound... except th…

Yes, sounds like you used it before Dart 2.0. As of Dart 2.0, the type system is sound in the same way that C#, Java, and Haskell have sound type systems, though a combination of mostly static checking with some runtime checks in a few places.

Re: Ruby 3.2’s YJIT is Production-Ready

#280
post #278
post #273

Earlier quoted context omitted.

I have zero to no experience coding in Ruby, so I cannot comment in that case. In Python or JavaScript/TypeScript, though, my experience is that failing to validate types at the borders (i.e. every single function/method/constructor/generator/... exposed in your API) is pretty much guaranteed to end up, months later, with developers attempting to sherlock out surprising breakages in production from logs that make no…

The "Ruby way" in this respect tends to be to avoid being over-prescriptive. That doesn't mean "do no checks", but "do only the checks actually needed" with a very different expectation of "what is needed" than in many other languages. Hence don't check for an IO object when what you care about is the presence of a "#read" method. Or don't check if something is an Array if what matters is that it supports "#map". Ins…

This makes sense, although there are downsides to not naming types, as these serve as documentation. Python documentation has a strong tendency to using descriptions to avoid giving names to types, which imho makes the documentation needlessly confusing.

Note that I'm writing "types" and not "classes". Interfaces do just as well, if not better!

For what it's worth, in the static realm, OCaml introduce features that let code check for presence of a method (instead of implementing an interface) ~25 years ago. Unfortunately, this proved rather unwieldy and, to the best of my knowledge, nobody uses that feature.

Post reply on HN