Hacker News new | past | comments | ask | show | jobs | submit login
Open-sourcing the Sorbet VS Code Extension (sorbet.org)
267 points by stanislavb on Jan 7, 2022 | hide | past | favorite | 83 comments



Happy to answer any questions about Sorbet, the VS Code extension, or anything else you're curious about!


Two questions (sorry if that's too much):

1. Sorbet isn't really great to use with Rails. I tried it out about a year ago - a few things might've changed but from scanning the relevant gems I think this broadly still applies. I used sorbet-rails but there were still a bunch of rough edges, eg. with using a class method on a model as a scope. The general theme was that Rails was doing quite a few things that make it super hard to type. ex - look at what it takes to do a type-safe pluck with sorbet-rails, and I don't think doing a typesafe select with association columns is even supported. Is there any acknowledgement of this from the Sorbet team itself, and will there be more to make the Sorbet with Rails experience better?

2. I'm really excited for the future of the Sorbet compiler. Like above, is there any work on making the AOT compiler work better with Rails?


Not OP, but hopefully this helps with your first point: we're happily using Sorbet with Rails (leveraging sorbet-rails). It's by no means perfect, but a gradual typing experience in Ruby never will be, unless you restrict the way you use the language. The benefits of having at least some level of type-checking outweigh the cons, IMHO. Sorbet picks up many of the little typos that only become apparent when you try out the code / run a test. I've been using an unofficial VS Code extension for ages, and I really like the increase in iteration speed.


Regarding Sorbet and Rails, I recommend Tapioca [1].

The Rails app that I worked on had a few edge cases Tapioca didn't cover so I wrote a simple script to load the Rails app and generate RBI files (e.g. generate RBI definitions for fixture methods in ApplicationTestCase). The Tapioca codebase helped provide a path for that [2]. Tapioca also continues to add to their DSL compilers. The work to integrate Sorbet paid off very quickly.

Also, T::Enum and T::Struct are handy in any Ruby codebase.

[1] https://github.com/Shopify/tapioca [2] https://github.com/Shopify/tapioca/tree/main/lib/tapioca/com...


1. I don’t know much about using Sorbet with Rails, but I do know that almost every major user of Sorbet that isn’t Stripe is using Sorbet with Rails! You might want to reach out in the #rails channel on our Sorbet Slack[1] for more?

2. Our focus for the Sorbet Compiler has always been more inward focused than Sorbet, so we focused pretty much exclusively on features that make the compiled code run fast on Stripe’s codebase. But you might be curious to read more about YJIT, the JIT compiler that was recently merged into Ruby 3.1—it’s being primarily developed by a team at Shopify where Rails performance is the highest priority.

[1] https://sorbet.org/slack


Is there official support for Sublime Text 3? I tried making it work a while ago and it wasn't easy to get it running.


We don't have anything custom on our end, but Sorbet implements the Language Server Protocol which it looks like Sublime Text 3 supports:

https://lsp.sublimetext.io/language_servers/#sorbet

These docs seem to even already have a snippet you should be able to add to your config to integrate Sorbet with Sublime Text 3.


I know Shopify are using it [1], Do you know if Github or Basecamp are using it too?

[1] https://twitter.com/rafaelfranca/status/1479259699694477312


I haven't heard anything from GitHub one way or another about whether they use Sorbet.

I'd be extremely surprised if Basecamp was using it, as DHH has always been particularly opposed to types, but again, I haven't heard anything one way or another from them.


Thanks for all the work! I've been wondering, are we to expect v1.0 at some point or we'll rely on daily/hourly new versions/updates?


Our goal with new Sorbet versions is to break things where it makes sense (fix bugs, improve types for the standard library) which sometimes introduces new type errors in projects using Sorbet. But wherever possible, we try to build autocorrects that allow for fixing or silencing those breakages.

One little known feature here that works mostly well right now but could definitely be better is the `--suggest-unsafe` [1] flag, which will attempt to insert `T.unsafe(...)` in places in the program where there was a type error.

Then in places where we improved Sorbet so that it no longer thought something was untyped, and started reporting errors downstream, you could run `bundle exec srb tc --autocorrect --suggest-unsafe` once after upgrading, and commit or delete the autocorrects as desired.

It isn't a goal to have some sort of v1.0 milestone where new releases will not introduce type errors to a codebase that doesn't have any, which is I think what you're asking about.

[1]: https://github.com/sorbet/sorbet/blob/master/main/options/op...

(edited to clarify phrasing in response to child comment)


Thanks for the info!

I don't use sorbet myself yet (although I am a ruby user), so this is not coming from any kind of educated basis, just an outside observer being curious, but I'm curious:

> We don't currently have a plan or a desire to get to a state where upgrading to a new Sorbet version will not introduce new errors on a codebase that previously type checked, which is what I think you might imply you want out of a v1.0 release.

That surprises me enough that I had to read it a couple times to make sure I was understanding how all the "not"s came out. I'd think that would be a thing you would straightforwardly want out of at type checker, the thing you said you don't have a plan or desire for. I'm interested in hearing more about why not, here or a link to somewhere else.


Here's an example PR from a few days ago where someone contributed an improvement to the type definitions Sorbet maintains for the standard library:

https://github.com/sorbet/sorbet/pull/5024

By adding those type definitions, any downstream projects using Sorbet that happened to use those definitions incorrectly will start to see new type errors.

Here's another example:

https://sorbet.run/#%23%20typed%3A%20true%0Aextend%20T%3A%3A...

This example shows a bug in how Sorbet handles shape types, that we definitely want to fix in the future but haven't had the time to yet. When we fix that, any project using shape types incorrectly will suddenly have new type errors.


The "not" is that they want freedom to make the type checker more strict, ie expand it to detect type errors it failed to detect previously


Any chance of this becoming supported in VSCodium?


I don't see why it wouldn't be supported! If the APIs are the same as VS Code's APIs, you should be able to build the VS Code extension from source and load it into VSCodium at your convenience.


Yeah, VSCodium is just a build of the open-source VSCode base, it just can't connect to Microsoft's extension store because that's reserved for Microsoft's proprietary build. It should have the same APIs. I just wondered if the maintainers would officially support this use case. I'm not a VSCode user, but I do not trust Microsoft to dominate the entire dev tool ecosystem, and a stronger alternative base built around VSCodium would be a good thing.


You can download the extension off of the official VSCode extension store in a web browser and install it manually in VSCodium.


This might be a dumb question but is there a chosen license for the this source ?


We open sourced it by merging it into the Sorbet repo, under which all code is Apache 2.0 licensed:

https://github.com/sorbet/sorbet/blob/master/LICENSE


I'm just wondering why this wasn't open-source to start with


when shall we expect RBS support?


Whenever I see "xyz VS Code", I still read "xyz versus code" and wonder for a moment: "What is xyz and why don't they like code?".


Thanks for this great project. It's amazing that: - It works both for static analysis and runtime checks (unlike Typescript); - Static analysis runs super fast even in a large codebase (unlike Erlang's /Elixir's dialyzer).

It's a shame that it didn't become the official Ruby type checker.


Yeah I'm sad about that too. I really dislike the official implementation because I can't easily see the function signature requirements.

Maybe w/ a VSCode extension but that means i can't read the signature a browser.


It's funny how we hear so much about Ruby's decline yet 3 of the highest-valued startups - Stripe, Shopify and AirBnB - are up there making fortunes with it whilst contributing to Ruby's vibrant ecosystem.


Stripe is actively moving away from Ruby to Java. All new services must be written in Java


Must be recent decision. I was at Stripe last year. They have a ton of Ruby. They were full throttle investing in Ruby.

And yes, Sorbet is magical. They’ve taken good ideas from typesystems such as Typescript including the tooling for code completion, inference and refactoring.

Sorbet truly brought joy to my lift.

Although Ruby is way too dynamic for my liking. Many ways you can shoot yourself with it.


I upvoted you only to get attention. You will need reference for this.

>But nearly all of Stripe’s codebase is implemented in Ruby running on the default Ruby VM (YARV). Not only did we not need Java VM-level interoperability, choosing either alternative Ruby implementation would have made for a difficult migration path.

https://sorbet.org/blog/2021/07/30/open-sourcing-sorbet-comp...


How/why did you land on Java for all new services?


Not at Stripe, but I guess it was picked as a compromise between efficiency and developer productivity. Dynamic languages like Ruby and Python don't perform well in the first area, native languages like C++ not much in the latter. Rust might be better, but it's still harder to learn than Java and there's less experienced developers to hire. That tradeoff usually leads companies to pick one of Java, C# or Go.


Why not Kotlin as it's arguably closer to Ruby?


Maybe Java includes the possibility to use Kotlin? At many teams I know its up to the team to write parts of Java libraries or services within Kotlin since it's mostly an implementation detail. But again - I'm not part of Stripe so I can't talk for them.


Yeah, I would be interested in the logic here. I'd assume Kotlin to be a far more productive language for ex-rubyists than Java.

Perhaps it's that they don't believe in the future of Kotlin outside of mobile?


In my experience it's usually JVM at these companies, not specifically Java, and certainly in recent years more and more teams use Kotlin for backend services.


Is there any source for that? Their public github profile shows that Go is their most preferred language these days.


Isn't this more of a reflection of when these companies originally developed their platforms? Similar to Facebook and their use of PHP.

It would be interesting to see in a few years what the next successful unicorns are building with today.


Anecdotally, TypeScript seems very popular among startups today. And for good reason - between Node.js servers, ReactNative mobile apps and React web apps, you can build everything in a single language. A language that’s naturally very productive while getting a product off the ground, pretty maintainable over time, with good enough performance (and concurrency support) for most use cases.

Agreed that PHP was the #1 startup language in the Facebook era, then Ruby in the GitHub era, and I think TypeScript now. But while they’re all very productive “early days” languages, TS stays much more productive over time.

Go, Java and Python are all popular startup choices too, but I think TS is the top startup choice right now, and a great choice at that.


Yeah, Typescript is a complete no-brainer as a pick - even if you're only picking a backend language. The type system is better than anything this side of Haskell, while still letting you write boring imperative code without getting in your way for every little thing if you just need to pipe some data around.

Performance is really not an issue unless you're doing very CPU-intensive work which you can't offload to a native library for some reason, or you need to scale vertically rather than horizontally (which is even rarer). Compute cost only really starts being a worthwhile optimization target at the "hundreds of billions of requests per day" level, and even then you're not gonna see much of an improvement from moving to Java unless you're actually very good at tuning threadpools (and it might still not be enough of a win compared to whatever else your developers could be doing with that time).


Rust's type system is also better than Typescript, and I would say Dart is slightly better too. But I agree Typescript is very very good, and you get access to such an enormous ecosystem it's worth it in most cases, and it's only a few times slower than C++/Rust. Not 50 times like Python or Ruby.


I'll grant that Rust could make a solid argument for itself with traits and such (though I haven't had a chance to use it myself). What's the five-second rundown on Dart's type system being better than Typescript's? I take a look every couple years and back in the day I remember thinking it was a solid alternative to C#/Java simply for its better null handling but Typescript solved that problem and many others besides.


I think the main issue with TypeScript’s type system is that most of the time, there’s no runtime types. You know something matches an interface, but if you have some untyped object (like say a thrown error from some lib that you caught), and you need to check if it’s a X, often it’s pretty awkward and hacky to do so. Obviously this issue is inherited from JS, but it’s still an issue.

Great type system and language otherwise, though.


That's not an issue if you code properly. Most statically typed languages only have run-time type information as a sort of "ok fine if you're desperate you can use it, but please don't" feature.

Exceptions are a special exception in Typescript because they can come from pretty much anywhere so it can't realistically know the type at compile time.

For everything else you are probably want discrimination unions.


Yeah, for your own code it’s not really an issue, as long as you’ve got decent team-wide discipline. But when integrating with external libraries, especially JS ones with type definitions tacked on later, it can be an annoyance.


Yeah, the story for handling thrown errors is much worse than it is in Java, and arguably worse than e.g. C#. But it's not a total loss:

1) 99.9%+ of the time, it'll be an instance of `Error` or some child class.

2) There's a recent compiler flag that's been added which defaults caught errors to `unknown` rather than `any`.

3) You still have access to the same tools to inspect unknown errors as you do everything else - `instanceof`, checking the presence/absence of properties, etc.

It's not great but it's something.

I would actually say the propensity of libraries to use exceptions as control flow and then _fail to document anything about those totally expected outcomes_ is a much bigger headache; that truly is an artifact of its JS inheritance.


The same argument can be made of PHP, COBOL, or even FORTRAN.

None of this is changing the fact that Ruby has been on a sharp decline for a decade now and it's probably never coming back.

My personal interpretation: Ruby is extremely slow, dynamically typed, and RoR hasn't kept up with the web innovations of the past decade.


I'm not sure how this applies to those languages. Ruby has an actual ecosystem via gems, and has a pretty nice syntax and language features so it's not hard to pick up. Pretty modern feeling even on older language versions. I think most of why it lost popularity is because faster ergonomic solutions have appeared, and python is a more popular competitor for dynamic backend langs (mainly due to ecosystem size).

COBOL, PHP, and FORTRAN all lack modern ecosystems (package managers, etc) which hinder them significantly.

COBOL is dead for new development because it has horrible ergonomics compared to modern languages. There's a reason why companies will pay big bucks if you're willing to maintain old COBOL with nearly no qualifications.

PHP is still widely used, but it's also got some language quirks and was mainly aimed at backend work. Since most web dev tries to offload onto the user instead of the server now, it's disappearing for both reasons.

FORTRAN is still widely used in academic research and the modern language version (f90+) is actually pretty nice to work in imo. It's a decent competitor to C/C++ and the compilers are nuts for scaling which is why it sticks around for scientific work. It's practically free to move from single node to a full cluster workload using only compiler flags.


>COBOL, PHP, and FORTRAN all lack modern ecosystems (package managers, etc) which hinder them significantly.

I think your PHP info is wrong, PHP has a package manager named composer. So if you need to connect to amazon S3 amazon published a package (that does't depend on 100 leftpads) https://packagist.org/packages/aws/aws-sdk-php

Maybe is not modern enoug in your opinion? Then what is missing except lefpad and color-red ?


> COBOL, PHP, and FORTRAN all lack modern ecosystems (package managers, etc) which hinder them significantly.

Its unfortunate that PHP has been clubbed with COBOL :-).

You may not be aware but PHP has a great package manager called composer. It is intensively used in the PHP community for a long time now. The packages are available at https://packagist.org/ .

Packagist houses 300,000+ packages and has received 50 Billion package downloads since 2012 (See https://packagist.org/statistics ). PHP's Packagist would actually would easily rank amongst the biggest package management ecosystems among programming languages.

PHP is certainly not disappearing. While it is no longer as dominant as it used to be and there is a slow, long term decline, it continues to be very active. Ruby's decline actually is sharper than PHP. Here is an interesting resource https://redmonk.com/rstephens/2021/08/05/top-20-june-2021/ . All statistics need to be taken into perspective but if you look at other proxy activity like GitHub PRs, projects, jobs etc. for PHP, it continues to be very strong. Using the word "disappearing" feels wrong to me. Trends are not irreversible. Over the years, languages have gone down, only to come back up.

P.S. Fortran is still going strong also. It is still used extensively in the Scientific Computing community. While, I'm not familiar with the ecosystem there are package managers in Fortran too. I'm not familiar with how good or popular they are though.


Of course it will come back, you just need to wait until dynamic typing becomes fashionable again. Development time is still more important than operational speed.


I very much doubt dynamic typing will ever come back, it's a thing of the past now. No sane new project will ever start in a dynamically typed language.

Modern statically typed languages do everything that dynamic languages do and a lot more.


I’d bet against this. Ruby has a great community and Rails 7 is looking amazing. Dynamic typing is very much alive and well.


The new hotness seems to be html over web sockets, which Rails does.


Oh wow. they still use Ruby at Airbnb? For some Reason I thought they'd moved to Go or the JVM.



I don't know about go (some cursory googling reveals a few open source projects, but nothing concrete) but you might be mistaking their work on Android libs for moving their backends to the JVM. For reference, their style guides are for JS and Ruby only so far.


the post mentions "At Airbnb, backend services are mostly written in Java "


Will Sorbet and this extension allow for autocomplete of non-Sorbet signed methods? Or does it only expose methods with a signature?


If Sorbet knows the type of the receiver of the method call, it will suggest completion results, regardless of whether any of the suggestions themselves have sigs, or whether you're inside a method with a signature.

But without any sigs, there aren't going to necessarily be as many opportunities for Sorbet to know the type of the receiver as there would be with sigs.

Here's an example

https://sorbet.run/#%23%20typed%3A%20true%0A%0Aclass%20A%0A%...


Even if I dont have signatures in my code, can I use it to get stdlib/gems signatures?


stdlib rbis are shipped with Sorbet. A limited selection of gem RBIs are available at https://github.com/sorbet/sorbet-typed.


Can someone explain how this fits into .rbs files? Would sorbet support adding/reading types as part of .rbs files in the future.

I personally find adding types inside ruby files to be unreadable. Well, this is just my personal opinion.


This article might help clear some things up:

https://sorbet.org/blog/2020/07/30/ruby-3-rbs-sorbet

tl;dr:

- RBS files are what Ruby 3 uses to describe types in separate files

- RBI files are what Sorbet uses to describe types in separate files

- Sorbet invented its RBI file syntax before RBS files existed. RBI files use the same syntax for types and signatures as in type annotations that live inside `*.rb` source code with Sorbet.

- We've been meaning to add support to Sorbet to consume both RBI files and RBS files, but we haven't had a chance to get around to it.

If someone beat us to it and implemented support for RBS files in Sorbet that would be amazing! Shopify took an early stab at implementing an RBS parser in C++ for performance[1], but I'm not sure what the status of it is today.

[1] https://github.com/Shopify/rbs_parser


Thank you - Great looking release! Other Ruby extensions seemed like afterthoughts or incomplete efforts.

Does Stripe use Ruby enough internally to "bootstrap" this from the ground up?


Stripe has a huge existing Ruby codebase that powers a lot of the dashboard and more. But there’s also a push towards Java for new services.

Notably, Stripe does not use Ruby on Rails: instead there’s a few homegrown frameworks used for routing, storing data in a database, etc.


Why the push towards Java for new services?


A robust performant multithreaded runtime with a big set of enterprise libraries for the big boys.


That explains the JVM, but why Java, specifically? JRuby offers everything you mention.


Jruby is anything but performant when compared to Java, there's overhead.


Speculating but aside from the enterprise ecosystem advantages it's hard as hell to hire senior ruby devs.


Really? The Ruby ecosystem has been around a long time (Rails itself has been around for over 17 years!), so I'm surprised to hear there is any difficulty hiring highly experienced Ruby professionals.


It just isn't the language that people learn as their first language (via college or bootcamps). Plus it's not a gaming, data or machine learning language so it's not the kind of language that people come to from some other motivation. So I would say it hasn't had great organic growth for 5-7 years. That's practically a generation of programmers at this point.

I think all the big shops have most senior ruby devs locked up. If one has any meaningful rails and ruby experience under their belt they can stick their thumb out and land a job immediately.


If you look at all the job postings for Stripe, you'll notice that none of them require you to know ruby and expect you to be able to learn it on the job.


Right, which would indicate that they have more or less given up on appealing to ruby devs specifically. I work at a ruby only shop and we are the same way. I would say only about 30% of the candidates I interview have any ruby experience and of those, maybe 50% have recent experience.

We would prefer to hire talented ruby devs, but they just aren't there.


what does talented even mean? If anyone is a not a shitter they should be able to be productive with ruby in the order of weeks


Yeah, duh, that's why we hire devs with any talent -- like I said. I'm not sure what you are pushing back against?

The contributions of a senior ruby engineer in a large, complex rails codebase will be immediate and will have a long tail over someone that has no experience in rails or ruby. This seems self-evident to me. It's just that there aren't enough of them.


I'm pushing back because I've had the opposite experience. I've started in a new team with exceptionally talented people, all of whom who have never written a line of ruby, all providing incredible contributions and hitting all our (pretty crazy) dates. All in a large highly complex ruby monolith.

It takes like 1 month to ramp on ruby, maybe even less. The cost of one month of ramp is highly justifiable given the fact that it's hard to find anyone who knows ruby (for real knows ruby) & most of the ramp is on system specifics anyways


Not sure what you mean by "bootstrap" in this context! Stripe uses Ruby extensively.


I just meant to create it with internal resources and release it - meaning Ruby is enough of Stripe's culture to allow it to happen. Kudos!


Congrats on this milestone!


Thanks!


Awesome to see and looking forward to trying it out. Thanks team!


tryeuyrdutyititFJVKVGKSAdbgbK CVKTFLYIUHGLGUJ GHKFGKMGK KHLB VKJ VKB,B




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: