NOTE: this post was written a few days after the first public Sorbet release (on 2019-06-20). If you're reading this months after that happened, mo...
For further actions, you may consider blocking this person and/or reporting abuse
Is debugging with
binding.pry
still an issue if runtime checks are disabled? I don't see how sorbet could mitigate this cleanly without digging deeper into one specific Ruby implementation.BTW: Do the runtime checks work with Rubies other than MRI? Looks like a pure Ruby gem but that's not a guarantee for compatibility.
I haven't tried it, but I'd expect not. Presumably they implement it with
TracePoint
, which can register and unregister for events (ie I would expect it is implemented without changing the actual structure of the code)As far as I can see, there is no TracePoint usage. They use method_added instead to redefine the method and wrap it with the signature validation.
So, it doesn't seem to have anything MRI specific.
Hi Vladimir, thanks for your article. In the current state I don't think I'd adopt it either. To be honest I'm not sure it's going to scale easily considering how most Rails apps load tons of gems full of metaprogramming and DSLs.
Stripe AFAIK does not use Rails, Sorbet should be easier in a Ruby-only project.
A few comments:
2 Megabytes for a small library... It's probably a fixed increase of size though, I don't think it's directly proportional to how many signatures or definition files.
I think this is the same problem the Javascript community had when trying TypeScript. The type checker needs to evolve with the language and AFAIK there's no formal spec of Ruby so you have to track each change manually anyway.
BTW I didn't know Sorbet is written in C++
You did a lot of wrangling there. It's the thing that annoys me from these checkers, the time spent to make the tool happy
Can I say that this signature looks ridiculous? I'm thinking of the cognitive complexity that adds for devs at all levels.
I agree when you say that the tool should move the signatures away from the code, or at least have a switch that can do that.
Code is read much more than it's written.
7% of CPU overhead is a lot for an already slow language. Stripe has a ton of VC money, they can just scale up the machines :D
:((((
Thanks for the comment!
Yep. But we also have Shopify, an early adopter/beta user of Sorbet. We haven't heard a lot about this adoption yet though.
And there are already some tools to make it easier to integrate with Rails: github.com/chanzuckerberg/sorbet-r....
So everyone is now shopify or [insert random company xyz]?
I mean there is a reason why this abomination has been created by a COMPANY. At the least they finally open sourced it - it was ludicrous that they promoted it while it was closed source.
Nice article. It seems like a really ambitious project. If I were working on it I would target a strict subset of Ruby and try to creep forward from there (I wonder if this is what Stripe have been doing internally).
Nice idea, although I think it kind of beats the purpose of types annotations, because every time you need to consult or adapt two files, instead of one.
I've been thinking too whether libraries should adopt Sorbet or not. As library maintainer, I don't want to force users to install Sorbet. I wish there would be a ways to enable those typechecks only if Sorbet is already present (because parent project decided to use that, or because I'm just developing my own library).
Probably it's a matter of time before some
sorbet-dummy
lib comes out, which would defined methods used by Sorbet (such assig
), but does nothing and steps off when it detects that "real" Sorbet is available.The examples make it look like you can noop it with a simple
def sig(*) end
. Is that not why you defined it in the block form?Honestly, I still can't see why type checking is ever necessary in Ruby?
What does it add to your codebase or workflow?
I think, type checking could bring value at a large scale: huge codebases, bigger teams (this post shares some thoughts on this topic).
For example, when you work on a large application you might not know all the internal APIs; type checking could help you to avoid
Undefined method foo for NilClass
kind of errors when writing code using these unknown APIs. Documentation could also help but it could easily get out of sync.Refactoring with type system is also much easier and faster even if you have a decent test coverage: when test fails you have to spend time to figure out why; when type checking fails you know the exact place in code. That becomes useful when you have hundreds of such places to change.
If type checking fixed this we would never have seen
NullPointerException
in Java/.NET static typed worlds.Totally disagree that type checking helps with refactoring. My experience with Java and C# is exactly the opposite. It becomes a large pain to either a) need to change the param of a method to a different type or b) add a parameter to an existing method. Yes tools like resharper help, but most of the time you play compiler jujutsu trying to find just the right generic or whatever type necessary to satisfy all your existing code.
These changes become more cumbersome to implement. Duck typing allows these kind of changes with ease, and ruby method signatures are usually pretty flexible with keyword args, option splats etc being common.
I think we’ll tested systems mean type checking is totally superfluous. I moved to ruby from a C# /Java background and I have not missed types/generics one iota in Ruby. Keep ruby ducky :)
Thanks for the great post! Your findings are extremely valueable for anyone trying to adopt the Sorbet.
Why exactly?
It does not really address the type annotation situation from an objective point of view. To be fair it is also not that subjectively biased either; but even then he makes huge claims such as:
"this is a huge leap forward for Ruby itself (especially, compared to other evolutionary features like pipeline operator)."
He does not explain why it would be a "huge" leap forward. I don't see what is leaping here.
And he contrasts it to the pipeline syntax sugar. Well, I don't like the pipeline syntax either; don't hate it but just don't see a point. But this is still so totally different to the SCOPE of sprinkling type annotations all over a code base with the deliberate attempt to make it uglier and less readable than it was before, for the promised gain in return that certain errors will be caught (which real ruby hackers don't run into - you only have this problem IN BIG COMPANIES where the worker drones have to churn out code for a living).
Keep ruby clean - that should be the main motto.