The Changelog: Software Development, Open Source - Types will win in the end (Interview)
Episode Date: July 13, 2023This week we're talking about type checking with Jake Zimmerman. Jake is one of the leads at Stripe working on Sorbet — an open source project that does Type checking in Ruby and runs over Stripe's ...entire Ruby codebase. As of May of 2022 Stripe's codebase was over 15 million lines of code spread across 150,000 files. If you think you have a bigger Ruby codebase, Jake is down to go byte-for-byte to see who wins. Jake shares tons of wisdom and more importantly he shares why he thinks types will win in the end.
Transcript
Discussion (0)
What's up friends? Welcome back this week on The Change Lab. We're talking to Jake Zimmerman.
Jake is one of the leads at Stripe working on Sorbet. Sorbet is an open source project that
does type checking in Ruby and runs over Stripe's entire Ruby code base. As of last May, that code
base was over 15 million lines of code spread across 150,000 files. If you think you have a
bigger Ruby code base, Jake is down to go bite for bite to see who
wins.
Stick around because Jake shares tons of wisdom and he also shares why he thinks types will
win in the end.
A massive thank you to our friends and our partners at Fastly and Fly.
This podcast got you fast because Fastly is super fast all over the world.
Learn more at Fastly.com.
And our friends at Fly help us put our app in our database close to our users with no ops.
Check them out at Fly.io.
So I'm here with Ian Withrow, VP of Product Management at Sentry.
So Ian, you've got a developer-first application monitoring platform.
It shows you what's slowed down to the line of code.
That's very developer-friendly and is making performance monitoring actionable.
What are you all doing that's new?
What's novel there?
Traditionally in errors, what's the strength of Sentry is we've taken not a stream of errors and
said, hey, go look at this, like all these error codes are flowing into SES. We actually look at
them, we try and fingerprint them and say, hey, we've actually grouped all these things. And then
we give you everything you need within Sentry to go and solve that error and
close that out. And that's, I think, driven tons of value for our users. And traditionally, if you
look at performance, it's not that thing. It's looking at certain golden signals, setting up
lots of alerts, maintaining those alerts, grooming those alerts, and then detecting them. And then
maybe you have a war room and you try and look at traces, or maybe you realize,
oh, it's this engineering team that owns it.
Maybe they'll look at logs,
whatever they have available.
Performance is very rotated on detection
and then isolating to where the problem may exist.
And root causing is often an exercise left to the user.
Good performance products provide a lot of context and details
that an experienced engineer or DevOps professional
can kind of parse and make sense of
and try and get to a hypothesis of what went wrong.
But it's not like that century error experience
where it's like, here's the stack trace, here's all the tags.
Oh, we see it's like this particular segment of code,
and Ian did the commit that changed that code,
and do you want to fire your issue and assign it to Ian?
It's not that crisp, kind of tight workflow that we have here.
This is breadcrumbs.
Right.
And we said, hey, maybe there's no reason why we couldn't do this for performance.
Let's try.
Okay.
So you took a swing.
You tried.
Describe to me how that trial works.
If I go to my dashboard now and I enable APM on my application,
what are the steps?
Largely because we kind of encourage you to go and set up
transaction information when you set up Sentry.
You probably, as a user, probably don't need to do much.
But if you skip that step, you do need to configure to send that data in your SDK. And what happens is we start now looking at
that information. And then when we see a, what we call a performance issue, we fingerprint that,
and we put that into your issues feed, which is already where you're looking for error issues.
Right. It's not a separate inbox. This is the same inbox.
The same inbox. Yeah. Now we obviously give logical filters. And if you just want to look at those, we do that.
And for newer users, sometimes we detect, hey, you've probably never seen this before. We can
kind of, we do things because we know we build for mass market that bring your attention to it,
but it's the same workflow you have for errors today. So you don't have to learn something new
to take advantage of these things.
So you asked the experience.
So last fall, we did the experiment,
the first one, which we called M plus one.
And we didn't know how it was go, honestly.
But people liked it.
Like we kind of know people like it
when they start tweeting and saying nice things about it.
And so, yeah, it got traction.
Very cool.
So if your team is looking for a
developer first APM tool to use, check out Sentry. Use our code to get six months of the team plan
for free. Use the code changelogmedia. Yes, changelogmedia, six months free of the team plan. Check them out at Sentry.io. Again, Sentry.io. That's S-E-N-T-R-Y.I-O. All right, we are here with Jake Zimmerman.
What's up, Jake?
Not much. How are you guys?
Doing good. Doing good. Happy to have you here.
This is a requested episode.
Always happy when we get to do a show that's...
Requested.
We know it's 100% on point for at least one person in our listening audience.
This one was requested by Max Veldink,
who says type checking has been a white whale in Ruby for a long time and very
divisive. There's even a built-in attempt in Ruby 3 called RBS that hasn't gained much traction.
Sorbet, on the other hand, is being adopted by many organizations, including Stripe, Shopify,
Instacart. His company just works. And he says, I think it's telling that many large Ruby shops
are switching to some sort of type safety on larger Ruby code bases. It would be cool to hear from Jake, who works on
Sorbet at Stripe around the origin story, what problems it solves there, and how it was like
trying to convince pretty curmudgeonly Ruby devs to add type checking into their code bases. So
Max, thanks for writing that to us.
I agreed.
I thought that would be cool.
So I reached out and you're here now, Jake.
That's true.
Yeah.
Yeah.
I think all of those things he commented on are kind of what I've lived and breathed for
the past five years of working on Sorbet and type checking Ruby.
And it's been a wild ride.
Yeah.
That's the first thing that I noticed was I had heard of Sorbet, but it was somewhat
recently.
And I went back to check a little bit on the history.
And like you guys were doing presentations in 2018.
Yep.
And I think it goes back to 2017.
Is that right?
Like you've been working on it for a long time.
The project itself started, yeah, in fall of 2017 at Stripe.
And that's kind of, yeah, one of the things that's kind of set this project apart from a lot of other larger attempts to type JavaScript or type Python.
We've kind of just focused on just doing what we need to do and not really going out and trying to sell other people on this vision of what typing in Ruby could be.
It's more just been kind of like, here's what we have.
If you want it, that's great.
If you don't, you can still keep using Ruby.
What about inside Stripe, though? Is it more evangelical inside of stripe in terms of like
well that's the other weird thing is uh max that in his comment had said like i'm curious to hear
like how you know it must have been hard convincing these camaraderie ruby developers but it was the
complete opposite inside of stripe it was the sort of thing where like for years prior to starting
this type checker project people were like i, I love working at Stripe. You know, our
product is great, but every day I come in here and I have to use Ruby and our code base is too big.
I don't understand how anything works. Really just wish there was a type checker. And so we
didn't have to convince most of the company. We just kind of had to build the product.
That's interesting. Do you think that TypeScript and
that move paved the way
to some degree that it could be done successfully?
Oh yeah, absolutely.
I think a huge part of it was people
would switch back and forth between
writing TypeScript in the front end or Flow
in the front end and then Ruby in the back end
and know what could have been the case,
what they were
missing out on, basically.
So they just asked for it, and they kept asking for it.
The lack of types in Ruby is really keen to the prototyping,
and I think Stripe is kind of baked.
Obviously, you're innovating.
Do you think that that's maybe less needed now?
You know where Stripe is going.
It's a big code base, lots of Ruby.
Do you think that's why types in that environment
is welcomed versus,
hey, we're proving new ground here.
We need to be, at compile time, flexible.
We need that flexibility.
Yeah, I think people will sometimes say
that in the prototyping phase,
you care less about types,
and in the iteration, long term,
maybe you need more types.
I mean, there's a class of people
that will break that mold and say, I actually prefer the type checking you know, long term, maybe you need more, more types. I mean, there's a class of people that
will break that mold and say, like, actually prefer, you know, the type checking, even when
I'm in my prototyping phase, just because it means that you can, if you do want to, like,
completely switch out one half of your system, you know that you've, you know, switched it out
correctly, because the type checker will catch you. But I think that the biggest motivating
factor for us was just at the time, you know, we were getting up to the place where we had hundreds of developers. And even if we were
building new code, it was hard to make sense of it all. We really just wanted to jump to definition
to be able to like follow paths of, you know, control flow through the code base and connect
things together. So it was more about understanding the code, I would say.
It's interesting hearing that because I guess being around long enough, I remember
when people would be so excited
to be able to work in Ruby
on their day job because
it was just hobbies for so long and it was
slowly becoming adopted.
Obviously Rails really
helped that adoption come in when you could
actually make money doing Ruby.
But we're so far past that point, plus we're
at a point where people switch jobs and orgs so much.
I've talked to multiple people on the front end side through JS party who have
come to a Ruby,
a shop like Shopify or Stripe from something else.
Maybe they grew up in JavaScript land doing node apps and stuff.
And they're like,
yeah,
the job's cool,
but I have to use Ruby.
I don't know Ruby and it's weird.
I don't like it.
And I'm like,
that's it. That's the drawback don't like it. And I'm like, that's it?
That's the drawback is the programming language?
And I understand it.
But it's just a weird place to be when it's like,
that's the part of the job they're not excited about
because it used to be that that was so exciting for people
to be able to use the programming language they love
and make money.
Yeah, it's probably just a relative popularity thing.
I think that people's primary programming language tends to be just such a large fraction of how they think and how they approach problems. And if you're used to something, you want to switch that thing is so, you know, different wanted it so apparently there was a desire yeah inside of stripe for something like this but how
come you and how you've been working on it for a long time before the show you said you eat drink
and dream i love that you said something along the lines of sorbet is all you think about so
here you are five years later still just thinking about that all day why you and uh tell the origin
yeah yeah uh so i mentioned it started in kind of the fall of 2017.
It started with two people who had been working at Stripe
for a number of years
and one person that we had hired from
just finishing his PhD working on the Scala compiler.
So it was a very small team,
a very experienced set of people.
They spent about a year building it from scratch.
So by the end of that year,
they had gotten it to the point where it was able to type
check most of the code at Stripe.
It was still kind of maybe only 75% of the code base was opted into the type checker
and the other 25% still hadn't gotten around to enabling it.
But I started at Stripe actually basically the same time that this project started.
So I got to kind of follow the project from my team, just, you know, outside looking in for that whole year. And yeah, when I was in school,
I was always just super interested in types and programming languages. I didn't really realize
this until basically my last year of being in university. If I had realized it maybe a year
or so sooner, it's possible I wouldn't have even joined Stripe and I would have tried to do some
sort of research and maybe go into higher education but it didn't work out that way and so I was just kind of like
I knew that I had this passion for types and programming languages but I didn't quite
understand like whether there was a way to go from just being excited about it to being able
to actually do it professionally but I knew for this whole first year that I was working full
time at Stripe that that we did have this team and so I eventually got whole first year that I was working full time at Stripe that we did have this team.
And so I eventually got to the point where I was just like, I'm going to regret it for the rest of my life if I never even asked to join the team.
So one day I just, yeah, I asked and said, hey, you guys have an opening.
Can I come help out? team had been staffed by like these super experienced people that they actually really
wanted somebody who had zero experience so that they, the people on the team could have the chance
to, you know, flex their like mentorship muscles and kind of learn what it takes to teach younger
developers. And so I was one year out of school. I was working with three really experienced people
who had this, basically this mandate to like your whole job now is to
train this other person so it was a great environment and again yeah because i already
knew that i was kind of interested in it i just kind of dove right in and that's kind of been it
we've worked on a handful of different things over the five years whether it's been making the type
system better whether it's making the experience of using the type system in your editor better.
We even spent a couple of years working on an ahead of time compiler using Sorbet to
actually compile Ruby code to native code.
And now we're kind of back focusing on how we can basically just improve the type system,
improve the editor, improve the type checking experience.
Was that ahead of time compiler?
Was that work that ended up being not super fruitful
so you went back to it?
Or what was the story when you went down that path?
Yeah, the compiler project, it was kind of interesting.
It was at a point in time when latency was the primary concern
for pretty much every team at Stripe.
This was during the height of the pandemic
when suddenly everyone across the internet
who was running a software
company was seeing increased volumes and increased loads on the system. So we had basically just
every team working on different ways to achieve latency. And we were just going to take whichever
long-term bet panned out the quickest. So some of those people working on latency were just
profiling Ruby code, seeing where they could get latency when some people were
focusing on making the database faster.
Some people were taking really longer-term sorts of changes,
like should we rewrite the core architecture
to use a different language?
All sorts of different bets across the company.
So one of these was the ahead-of-time compiler for Ruby.
And we actually got to the point
where it was completely working in production,
and it really was just a matter of
whether we wanted to continue working on it.
And because of all the great work of other teams at Stripe
making the Stripe API faster,
we got to the point where we didn't quite need the latency
from the Sorbet compiler,
and it would have come with its own set of trade-offs.
So given all that, we wanted to focus then again
on the developer productivity side of having a type checker
where we can actually make people writing Ruby code
more productive.
That's cool.
So inside of Stripe then,
if you could come up with a percentage
of how much code is sorbeted across the code base,
do you have those numbers?
Do you know how much?
Yeah, I have.
It's less than 1% is not using Sorbet.
Oh, wow.
Yeah. There's kind of various strictness levels to what it means to have Sorbet turned on.
So the very bottom level is what we call typed false. And even still, even though it says typed false, it's still doing some kind of sanity checking, which it'll make sure that all of the
classes and modules and constant references in the codebase resolve, and it will obviously like
check that your syntax is valid. But then up from that there's typed true, and that's the point
where Sorbet will start doing actual type inference on method bodies and tell you if you have any like
classical type errors like expected integer found string sort of type errors. And then one level up from that is typed strict. And at type strict, not only will it do the type inference,
but it'll require that you put explicit type annotations on every method in your file.
And I think we even have that type strict level. So it's like 99% at typed true or higher,
but at type strict, I think we're somewhere close to like 80% or something like that.
It's the sort of thing where over time people encounter the file
that doesn't have type annotations and encounter the files that do have type annotations
and they find that it's a lot easier to edit and understand
and refactor the code that has the type annotations.
And so they've self-selected to opt their files into these stricter checking levels.
That's interesting. Network effects, in a sense, right?
Exactly. Like, hey, this file doesn't have this. I want to bring it in there. It's interesting. Network effects, in a sense, right? Exactly.
This file doesn't have this. I want to
bring it in there. It's good stuff.
It's crazy to have such a project
take over, too.
In one of the posts, I think it's
a 2018 posting, where Sorbet is at
now, this is State of Sorbet Spring
2019. It actually says
100% of our production Ruby files
are Sorbet-ed according to this. Every CI build in the main
repository is checked by sorbade. You kind of lay that out there, but
to put such a percentage there, this is a big deal. You're making
developers productive. How does the type checking, how does this really
equate to being more productive? What are some of the ways that this
comes into play?
Yeah, so there's all sorts of different things. I think that really equate to being more productive? What are some of the ways that this comes into play?
Yeah, so there's all sorts of different things. I think that the quote that I like bringing up here is the first time that we, so we had built this type checker and it was really just kind of
like this policeman just kind of like enforcing that you're not doing the wrong thing. In the
beginning, that's all there was. It was like either your CI check would fail with a big red
scary message or it would pass.
And that's fine.
Like you can get a lot of value out of that.
But the first time that we took this type checker and we started building editor functionality
and like, you know, kind of typical IDE sorts of features
and exposing that to users,
that was when people really started to have their eyes light up.
So the first time that we sent an email to the company saying,
you can now use Sorbet to get accurate jump to definition.
People were telling us like,
this is the best Christmas present you could have ever given me.
It's July, I don't even care.
I think that people really identify with being able to understand their code
and use the information that the type checker has to,
yeah, just dive into an unfamiliar part of the code base
and have confidence that they're going to be able to figure out what it's doing.
Sounds a lot like what Sourcegraph markets do.
They call it code spelunking.
I've heard Byung-Loo talk about that.
Being able to jump to definition and explore code base.
Especially if you're moving teams, like Jared mentioned before,
if you're moving from one shop to another, you've got to relearn,
if not just domain knowledge, but also this built-up code knowledge of how the code base works.
In an untyped world, it's got to be challenging if you can't do that.
Yeah, and it might be a problem that you only realize is a problem at a certain code base size.
For example, even inside the Sorbet code base itself,
it's only ever been worked on by two or three people full-time.
The codebase itself is only maybe 100,000 lines of code.
But when you get into these codebases where it's hundreds of people over millions of lines of code,
and the ownership of which parts of the codebase are owned by which teams is fluid over time,
you're very rarely working with the same lines of code
for an extended period of time.
And so you're kind of always doing that code spelunking
where you're jumping from one place to another.
Yeah, that's the part in my mind
where type checking gets to be super, super valuable.
When I think about programming languages
that lend themselves towards type checking and enforcement,
Ruby is like on the bottom of that list, isn't it?
I mean, this had to be a monumental task
because it's so malleable.
It's so self-referential.
It has reflection.
It has metaprogramming.
You can just monkey patch and redefine
and change stuff all the time.
And despite the warnings of use with care,
we tend to do that when it's convenient.
Sometimes we do it just because we can.
I know I used to be a young Rubyist
who liked to shut off different things that he could do,
even if just to myself.
Oh, look what I can do.
Was this very difficult to build?
I mean, are there still ways you could poke a hole through it?
What's the situation with all of the,
just the weirdness of Ruby as a language?
Yeah, I will definitely agree with you
that the kind of dynamism of Ruby
is both a huge strength
in that it's been what's let communities
like the Rails community succeed,
but also a big challenge
just because those sorts of,
like when you can only understand
what the code is doing at runtime,
obviously that stands in the way of static analysis.
So it's definitely a big problem. And it's And I wouldn't say it's a fully solved problem in Sorbet by any means. That's probably still one of the biggest reasons why you might evaluate
whether your company or your code base should switch to using Sorbet and you decide against it.
Your team really gets a ton of value out of the super dynamic metaprogrammy sorts of features of Ruby.
And Sorbet would, in many cases, ask you to give that up.
It's interesting because Stripe actually started, Stripe has never used Rails,
but it has used a lot of metaprogramming in especially its early history.
And as people have started to adopt Sorbet at Stripe,
it's kind of been this incremental rejection of
the metaprogramming parts of Ruby. Part of this is because people see the value, again, that they
get all these features, all these, you know, safety guards that they get when people are using
type checking in their files. So people will, you know, say, here's my trade-off, I'm willing to
put down the metaprogramming and pick up the static
analysis. To dive into some specifics, you can just basically read a network request that the
static analysis tool is never going to be able to see. And using the contents of that network
request, you're going to be able to define methods in Ruby. You could ask the user for the name of
a method to define and define it. And there's nothing that the type system is going to be ever able to do
to know that that method name is going to be available to be called.
So yeah, stuff like that has its place.
And Sorbet basically just gives you escape patches to be able to use that stuff.
So again, we were talking about the typed false levels.
If you have a certain file that's using a lot of metaprogramming,
you can just opt to turn checking off in that file
where it's maybe super metaprogramming heavy
and turn it on in the other files.
You can also silence the type errors at a specific call site
and say like, okay, even if I do have typed true enabled in a given file,
this one call site where we're doing a lot of metaprogramming,
I'm just going to ask the type checker to ignore that line
so you can kind of weave it into your system
where you want the type checking to happen
and where you want to be able to use the metaprogramming
and each code base or team or individual
will kind of make those trade-offs
knowing what they're giving up and what they're gaining
Are there any facilities in there to outlaw
like hey, no method missing, for example?
We're not going to have method missing.
Maybe that's not really a Sorbet thing.
Maybe that's like a linter.
I don't know.
I guess Sorbet is kind of a linter on steroids, isn't it?
How do you picture these tools fitting together?
I think that linters and type checkers
are very complementary.
The thing about linters is they're way more heuristic based
and so you kind of want the ability to say like i know better than the heuristic in this particular
case in sorbet there's the rules kind of apply universally so we are kind of more conservative
with what we reject in sorbet like sorbet will not reject method missing because if sorbet rejected
method missing anyone who everbet rejected method missing,
anyone who ever wanted to use it would not be able to use Sorbet.
So in our code base, we do have a bunch of linters.
I don't know if we ban method missing or not.
There's probably some method missing in there somewhere.
We should explain method missing for those who aren't regular Ruby programmers. So briefly, in Ruby, if you call a method on a module or on a class, and that class or that object of that class doesn't have the method that you just called, there's a method called method missing that you can define, which will then run other code that you have decided that will run in order to do whatever you like. So you can use it to dynamically define a new method. You can use it to run a switch statement
and do a bunch of different stuff.
You could raise an error.
It's just basically a hook
for you to write some code
in case the method that you called
doesn't exist.
And people have used that
to do all kinds of things.
One of the nice things
is to write really nice DSLs
and provide like top level keywords
that are kind of arbitrary
or quasi arbitrary
and use method missing
in order to call them.
But as you can imagine, you can also do some gnarly stuff in there and it's difficult to
analyze because it's not defined until runtime.
Yep.
So method missing is definitely one of those kind of tricky parts for Sorbet to analyze,
but it's far from the only one.
We do have plenty of lint rules that we turn on to basically say, this is okay, this is not okay.
And yeah, kind of guide people into having the most success when using survey. This episode is brought to you by our friends at Drada.
Automate and accelerate your SOC 2 compliance, your ISO 27001 compliance, and many, many more compliance frameworks.
With a suite of more than 75 integrations, Drada easily integrates with your tech stack through applications such as AWS, Azure, GitHub, Okta, and Cloudflare.
And countless security professionals from companies including Lemonade, Notion, and Fivetran
have shared how crucial it has been to have Drada as a trusted partner in the compliance process. They have deep native integrations that
provide instant visibility into a security program and continuous monitoring to ensure compliance is
always met. Drada allows companies to see all their controls, easily map them to SOC 2, ISO 27001,
and many other frameworks to gain immediate insight into framework overlap.
They are the only player in the industry to build on a private database architecture from day one,
meaning your data can never be accessed by anyone outside your organization.
It is time to say goodbye to manual evidence collection
and hello to automated compliance by visiting drada.com
slash partner slash changelog.
That's drada.com slash partner slash changelog.
They are bringing automation to compliance at Drada speed. so one thing that max brought up is like a first party i I guess, Ruby official types,
which he says in the works.
I don't know much about this.
I'm sure you probably know a lot about this, Jake,
just from being in the community.
Tell us about that, how it relates to Sorbet.
Are they wildly different?
Are they similar?
Could they adopt Sorbet if they wanted to?
He says it's divisive,
so I'm sure there's lots of opinions as well
about this topic.
Yeah, I think it's mostly divisive just because typing in general is divisive so i'm sure there's lots of opinions as well about this topic yeah i think it's mostly
divisive just because typing in general is divisive in the ruby community mostly right
not like a specific implementation that's going on in the elixir community right now as well
is they're talking about types for elixir and that's divisive because same exact reasoning
yeah and so obviously as someone who works on a type checker and who's been interested in types
for a very long time i'm super biased biased in favor of the typing side of this.
And, you know, I hold the view that types will always win in the long term.
But so you're going to get the biased view here on the state of typing in Ruby.
I don't even think Sorbet was the first attempt at building a type checker for Ruby.
There were a number of research projects specifically.
I remember a couple by the kind of like research projects out of the University of Maryland. I think there was also one other type checker that was built by a person by the name of Sotaru
Matsumoto out of Japan and it was called Steep. And so then there was one other that was kind of
like a very hobby project built by someone at GitHub in their personal time.
So Sorbet kind of started as this just one more type checker sort of thing.
So it's always been the case that people have noticed that Ruby didn't have types built into it and kind of decided on various ways to add their own. Eventually, I think that the popularity of Sorbet and the kind of backing of
having such a large company like Stripe and Shopify behind it meant that the Ruby core team
was more willing to consider what a first party typing support would look like. So we actually
have met multiple times with the Ruby core team. For a period of time, we were meeting with them
monthly to kind of talk about what the state of typing in Ruby would look like. And over time,
it became apparent that the design constraints that we were going to be working under would be
no syntax changes to Ruby itself.
Partly this is because Ruby is already syntactically very complex.
Parsing Ruby is already hard.
Adding more syntax in service of type annotations
would have been just challenging on its own.
But also, Mats's the person who created
Ruby and still has a very significant, you know, influence in what features get added and what
don't was pretty partial to keeping type annotations out of the core syntax. So that meant that we were
kind of focusing on having annotation files that lived alongside the Ruby source code. So you kind
of have this split between like header files and source files that you might have Ruby source code. So you kind of have this split
between like header files and source files that you might have in C and C++. So that comes with
its own trade-offs. Some people will say that that is already a non-starter for them, that no matter
what syntax you choose for these like definition header files, that it's already too divisive,
like it's already going to not work for them and cause a division in the community.
That's, I think, a valid concern, but let's just press forward and say that we're fine with having
these annotation files. The next thing that you're going to run up against is, do you use the same
syntax as Ruby in these annotation files, or do you invent some completely new syntax? So Sorbet
had one of its design goals was to be backwards compatible
with the syntax of Ruby. And so all of the Sorbet type annotations are actually just a Ruby DSL.
So there's no transpilation step that you need to be able to use Sorbet in your codebase.
It's just kind of the magic of, again, the Ruby metaprogramming. One of the benefits that you
can get is you can define these ad hoc syntaxes, and they're backwards compatible.
So Sorbet already had this type annotation syntax that was valid Ruby code.
And to make these kind of header files, these definition files, it repurposed that existing
syntax.
So you only had to learn one way to declare the type of an array.
You only had to learn one way to declare a signature for a method, to declare an interface, to declare abstract methods, all these sorts of things.
The fact that they lived in the source code of a Ruby file or in some file alongside was just a
preference for where you want types to live in your code base. But I think that the problem
with that is that by defining types in this DSL syntax that we had
invented ourselves, it was kind of clunky. Like we had to go to kind of great lengths to be able
to choose syntax that was backwards compatible with this, you know, what we could build a DSL
out of. So at the same time that we were working on defining these separate files, we came to the
realization that we don't have to be backwards compatible with Ruby in these new files, we could just throw everything out the window and design
type annotation syntax that would be a little bit more elegant, but not necessarily fully
compatible with existing Ruby code. So that was the approach that we ended up taking that
eventually standardized as what they call RBS files, Ruby signature files. And yeah, they just have a completely different syntax,
but they're a lot less verbose than Sorbet annotations.
So at the end of the day, though,
they are just annotations,
and Sorbet could one day just parse them
and understand the annotations that are in them.
I think that that's mostly just been,
we haven't quite gotten the feedback
that people would really absolutely
love to use Sorbet. But also like the one thing holding them back is whether it parses these
RBS files versus the annotation files that Sorbet supports. So we've been focusing on building
features for the people who are using Sorbet. And those people are asking again for things like
better editor tools or better type system features. So that's where we end up spending our time.
So it's kind of more just like not a fundamental separation,
but rather just like it would be work that we have to do.
And we haven't yet found that it bumps up to the top of the list.
Okay, good explainer of the state of things,
at least from specifically on the Sorbet side.
What about on like the Ruby Lang side with these RBS?
Is it going to happen?
Oh, it's already happened.
They shipped these annotations
in this format in Ruby
3.0.
It's shipped in public and you can
just use Ruby 3.0
plus and annotate
your Ruby with
these RBS files
and there's just a built-in type checker into the language?
So it's still, you have to pick and choose your
third-party type checker. The annotation format is just
Okay, so it's not like built-in then. It's just spec.
Exactly.
So probably the most popular type checker that uses these
annotations is the Steep type checker, which I mentioned earlier.
There's also a handful of other tools that consume them.
It's just that Sorbet kind of doesn't,
and maybe that's the biggest point of division,
is that we haven't gone to the work to parse these files.
Is that just the nature that it's open source
and you've got other things that are more important?
Obviously, it's not that you don't want to
it's like eventually you might.
Yeah, exactly. So for example the sorts of
things that we would have to stop working on right now are
we've made a number
of improvements to just the core
type system for like what you can
actually express in the type system. We've made
improvements to how fast Sorbet is
all sorts of things like this. And so
we regularly go and ask people whether that's in the open source community or
people using Sorbet at Stripe, hey, what's the thing that you wish existed
the most? And it's always something else.
I guess, why wouldn't it just get built in? That's what I don't understand.
I guess maybe you could say, well, RubyGems wasn't built in either
for a really long time and eventually gem
became shipped with Ruby and
so this would be a similar circumstance
maybe like they want
a bunch of tools to be able
to do this and it just seems like if
they were if they being Ruby core team
was like super committed to the types
that they would maybe this is
just step one and they're going to do it eventually
they would do this and they'd say and download Ruby 3 and it's type checked.
Yeah, I guess one of the benefits of having it be this third party gem is you can iterate on it
and release new versions independently of Ruby versions. So Ruby kind of famously releases a
new version only once a year on Christmas. But if you wanted to add a new revision to the RBS spec
or standard or parsing libraries for it,
having that be in this extra gem that you'd have to opt into
makes the release process a lot easier.
Good point.
You've obviously thought about this more than I have, Jake.
And of course, there's lots of different parties involved
in these kinds of decisions.
It's got the wrong name though, Jared.
What's that?
That's why it's not being adopted by the core team.
It needs to be called Type Ruby or something like that.
Oh, Sorbet?
Yeah.
What do you think?
Sorbet is a cool name, man.
It is a cool name,
but I just wonder if it needs to be TypeScript-like.
Take a page from the TypeScript book
and it's got to be Type Ruby or something.
I don't know.
I'm not saying it's a wrong name.
I'm just making a joke.
Again, I think one of the other things that has set apart Sorbet and TypeScript is just the amount of evangelism that has been put into each project.
I think that Microsoft in general is just really good at building products
for developers and evangelizing them.
And Stripe as a company does that as well.
Obviously Stripe is an API company and evangelizes their API,
but it's never been the case that Stripe really evangelized Sorbet.
Just having popularity and community enthusiasm
behind a project would be the tipping point
behind maybe more first-party integration with Sorbet.
We're kind of fine with the way things work now.
We build the thing and we ship the thing.
And people who want to use what we've built are completely able to do so.
And people who would prefer, we'd prefer to ignore it can.
So let's talk about Sorbet itself, like the implementation, the design.
I was reading some of the docs and some of the guides,
just trying to see what it was like to use.
I did notice pretty decent, pure Ruby DSL.
You're writing Ruby inside of your Ruby in order to specify
a method signature and that kind of stuff.
There were a few phrases on the website that I was like,
this sounds fancy because I don't know what it is.
Now I'm not a type guy, so maybe people who are all about type checkers
know these kind of things. But I read gradual type checking, I read control
flow sensitive typing, some stuff that sound like Sorbet features
that I'm sure you had a large part in that might be interesting to our listener
to learn about Sorbet.
Yeah, absolutely. So gradual type checking is just this idea that you don't have to type check 100% of your code base
from day one, that you can opt in
at various levels of granularity.
That's basically table stakes
if you're trying to add a type system
to a language that didn't start with the type system.
I don't necessarily,
there will definitely be people out there
who tell you that this is actually a completely desirable property, even if you're designing
a language from scratch today. Again, you're getting the biased type system nerds view.
And I think that it's more just like a trade-off that you have to accept if you're
adding types to a language that didn't start with them. Because it means that you have these gaps,
you'll always have these gaps in the type system where it won't be
able to tell you when you've messed up. And so the biggest problem then is actually figuring out and
identifying where the gaps are, if that's the state of your code base. Control flow sensitive
typing is really interesting. And I actually think that even more traditional languages that don't
have backwards compatibility with untyped programming language could benefit from. And that's just this idea that if you have something that is either nil or,
you know, some real type, like maybe an integer or some struct, some class that you've written,
that the type of the variable will be aware of all of the conditional branches that you've taken
through the code base. So if you start out with something that's either nil or integer, and then you say,
is this thing nil? Well, if you use that variable inside of that branch,
Sorbet will be able to say, you've already checked that this thing is not nil. So
here it's an integer. So TypeScript does this. Most languages that are gradual type systems for
existing untyped languages end up building this feature just because there's so much Ruby code out there that's written this way, or so much, you know, existing untyped code out
there written this way, that you get a lot of, like, ease of adoption by building this feature.
You don't force people to go change their code base to, you know, be, I don't know, maybe a
little bit easier to type check. So it's this advanced type system feature for sure, but it's
one that models Ruby code as it exists in the real world
and makes it easier to start using the type checker.
Okay.
What's an example of when that might be useful
or some code that might typically hit up against this,
just not knowing necessarily the value being returned?
Yeah, so for example, let's say that you are interacting with the database
and you try and load some object with a specific ID.
You're going to either get back nil if that object doesn't exist, or your ORM is going
to give you the model class back.
And if you are writing kind of good defensive code, the first thing that you do when you
try and load this thing is you're going to ask whether it existed or not, and then you're
going to handle that exception case.
Maybe you report an error to the user. maybe you try looking for the object in a different
place, maybe you do something else.
But in the case where you definitely know that you have it, now you can start calling
the methods on your model.
You can ask for the user's name or the user's email or whatever fields are on this model
class that you got back.
So if Sorbet thought throughout the entire method body that this variable that you got back from your ORM
was either a nil or a user model,
then it's going to say,
I can't claim for sure
that you calling these methods on this model exist or not.
Gotcha.
Yeah, I can definitely see a lot of Ruby code out there like that.
Because there's so many like that nil case is just always the edge.
That's just like.
Exactly.
Causes us to want types in the first place.
It's like, ah.
But.
And so like, for example, this was, you know, kind of famously the Java's, you know, billion
dollar mistake was conflating that every type could be null.
I think that it's obviously very hard to to
make changes to a language as widely used as java is now but it's the sort of thing where like if
you could solve this problem um and yeah build control flow sensitive type checking for for
specifically whether a value is null or not i think it would go a long way to making it easier
to reason about yeah in java even, whether a value is null or not.
So you bring up an ORM, which makes me think about active record,
which makes me think about active record base,
as it used to be called, like base classes.
It makes me think about existing Ruby libraries.
One of the huge advantages of TypeScript
being so widely evangelized and adopted.
It's like darn near every library ships with type definitions for TypeScript
to just work out of the box.
And I'm wondering if Sorbet has that kind of momentum,
or is there a place where you can go out and say,
I'm going to use this Ruby gem, and the gem's already typed by somebody.
Yep, I definitely noticed that in TypeScript, it's like most libraries that you pull off of,
you know, NPM are already going to work with TypeScript just out of the box. And
there's kind of nowhere near that level of support for typing in Ruby gems that you'll
encounter most commonly. Part of that, there's a number of reasons for this. So part of it is like,
as a project, we've almost always focused on making it easier for application developers and library developers. We've always taken less steps to making the process easier for them.
That's definitely something that would need to change. And partly it's just kind of,
we've never gotten around to it. I think that despite the low investment,
people have still done it and still publish gems
that have type annotations for them.
The biggest ones like Rails though don't.
And so if you want to be able to use a, you know,
Sorbet in a project that's using like, yeah,
ActiveRecordBase or something like that,
you're going to need a different approach
to be able to type these sorts of things.
And so some, the way that that is typically handled
in Sorbet is with third-party gems. And so the way that that is typically handled in Sorbet
is with third-party gems that will analyze
the way that you are using these gems
and generate those annotation files
that we were talking about earlier.
And so instead of annotating the source of ActiveRecord itself,
you would look how ActiveRecord is being used in your code base
and generate some annotation files
and rely on those annotation files
to figure out what the gem is doing that seems somewhat fraught is that pretty reliable
at the end of the day or is my spidey sense accurate it's somewhat fraught for sure it's
kind of a question of like how much you're going to push it if you're using the very common cases
it'll be fine but if you're trying to do something more complicated especially if you
combine this with heavy use of metaprogramming, then it's going to be a little bit trickier. So I think that recently one person in the community,
it's actually someone who has been on this podcast before, Justin Sears or Searles.
Searles, yeah.
He's actually maintaining this mocktail library for kind of a testing library for Ruby. And he has been posting quite a lot in the survey
Slack, just about what it takes to get typing added to a gem. And it's been really interesting
just because it's exposed all of these, you know, places that we could make the experience better,
just about like decisions for if you want to have type annotations in this gem, should you start
with having annotations that live inside
the source code and then strip those out before you publish? Or should you put them inside your
source code and also have files that live alongside? Should you make it easier for people
to just generate the RBIs on their own? Anyways, it's like his experience has been neat because
every time he ran into a challenge, he posted about it and asked questions. And it's been
kind of eye-opening to just have that experience.
Justin, thank you for all of the comments that you've given us.
That's one of Justin's skills is communicating.
You know, he's always willing to post those comments and whether they're more or less salty, depending on his mood.
Justin likes to...
Yeah, he's been quite polite.
So I'm sure that maybe that's gone through a filter. But it's been great seeing what he's been quite polite so um i'm sure that maybe that's gone through a filter but
um it's been it's been great seeing what he's been working on he's usually pretty unfiltered
but he's also a kind person so when you say rbi now is that the same thing as rbs on the other
side but it's like yeah sorry that's the name that sorbet uses for these annotation files that
uses a different syntax but for the same goal and then rbi just stands for ruby interface
okay so if i was going to provide type annotations for something i would i would produce an rbi or i
guess this is what justin's trying to figure out with mocktail is like what do we actually
what's our output as a library author yeah so as a library author like you would either have to
have sorbet read the sources of your gem files and use that to understand what's defined,
but typically people will not ask the source of the gem be type checked
because obviously then it's also going to do things like
actually read the method bodies and make sure that all the method bodies type check
and that's going to be particularly slow.
So having just the interface files will speed things up a bit.
Gotcha.
Why go RBI and not RBS?
Why would you create a whole new world in a way?
Well, so it kind of harkens back to the conversation we were having earlier about
what syntax do you want in these files?
Do you want the contents of these annotation files to be the same syntax as Ruby code?
Or do you want them to start from this blank slate where you can design the syntax that you want?
So the syntax of RBI files is literally just Ruby files
with no method bodies.
So if you wanted to annotate a method,
it's the same syntax in a Ruby source file
as it would be in a Ruby interface file.
Whereas RBS is this streamlined syntax
that you plus the Ruby team kind of collaborated on.
Is that correct?
Exactly.
In defense of the RBI syntax,
I think that one of the things that's a lot easier about it
is you don't have to kind of switch
between two type systems in the docs.
So if you see a type annotation anywhere in Sorbet's docs,
it's completely valid to put that both in the Ruby file
or in the RBI file
versus having to learn two type syntaxes if you're trying to
use Sorbet with RBS files.
Does Sorbet run faster with RBIs than it would just in the source code?
Or does it not matter?
It's really just a function of how many bytes Sorbet is reading.
If your source files are really long, then it might slow down a little bit
just to parse
through and get the actual annotations out.
The crazy thing, though, is just how fast Sorbet actually is.
I have gone on record many times and claimed that Stripe's Ruby codebase is the largest.
Obviously, I haven't seen every Ruby codebase in the world, and no one has contested me
on this point.
So I'm going to go forward and continue saying this until someone corrects me that Stripe's
Ruby codebase is the largest Ruby code base in the world.
Bigger than GitHub.
Oh, by a long shot. And the nice thing about this, if you are a user of Sorbet, is Sorbet will,
like, the amount of time that it takes to type check your code base will never be longer than
like the slowest code base to type check. So you kind of like benefit from, someone will always
encounter performance problems before you will. And that someone will be Stri like benefit from someone will always encounter performance
problems before you will. And that someone will be Stripe. That someone will be Jake Zimmerman.
Yeah. So that's kind of why a large part of the work that we end up doing is just
optimizing and optimizing. One of the fun projects that I got to work on
last year was making Sorbet more incremental. So the entire history of Sorbet,
if you needed to run Sorbet in your editor,
it would basically just retype check the entire code base.
And it was fast enough.
Like it would be a little bit slow.
You would be able to see when it's doing this retype check operation,
but it would only maybe last a couple seconds.
And that's fine.
That's actually like most of the time fast enough.
Eventually the code base got to the point where that wasn't fast enough, which meant that we had to do some work to make it faster.
And the way that we did this was just being smarter about not doing work. Basically we would
figure out the contents of any given edit and say like, okay, well we can actually tell that
in this edit, only these definitions have changed and then do some really clever things to not have
to retype check the entire code base.
So it's those sorts of optimizations
that personally I find really fun
and also people benefit from
that the code base will never get to the point
where it's super slow to type check
because we've found the problem,
fixed it before it ever becomes a problem for anyone else.
Stripe is bigger than Shopify.
Yep, Shopify, I think.
He's saying this like so unequivocally.
He's like, yep.
I know Shopify's codebase is one of the codebases
where I have actually very exact numbers
on how large that codebase is.
Because they're using Sorbet.
Yeah.
They're also one of our closest partners
that we collaborate with on improving Sorbet.
They've made a number of contributions themselves
and we meet regularly with them
to figure out how we could be making Sorbet better. So that's kind of like one of the things that I'm
always worried about is like, well, what if, you know, the performance is getting out of hands on
other people's code base and I'm not able to even see what the problems are because I can go profile
our code base and see what the problems are. Is Twitter still Ruby or is it still a real shop or
what? I don't think Twitter is Ruby anymore.
I think they use Scala, a lot of Scala.
Scala and maybe some other languages at this point.
They all got them too much, I guess.
Is Stripe bigger than Basecamp?
Probably is.
That's one of the ones I don't know of,
but again, no one has reached out and told me otherwise.
All right, listener out there,
if you have a code base larger than Stripe
or you think it's larger,
then you need to let us know so we can prove Jake wrong. How many lines of code roughly?
Yes, I wrote a blog post on the Stripe engineering blog in May of 2022, I believe. And the code base
size at that time was 15 million lines. And that was a year ago, roughly.
That was a year ago. If you think you can beat 15 million lines, I'd be very, very curious to hear.
Now, I also want to express my condolences
for having to work in a 15 million line code base.
Is lines of code the best way to quantify it,
though?
Wouldn't bytes be better?
Yeah, bytes would be better, for sure.
I mean, you could have a long or a short line, right?
Yeah.
If you have millions of short lines,
then I have half a million really long lines.
Maybe I win.
Yep. No, absolutely. Bytes, like, if I have half a million really long lines. Maybe I win. No, absolutely.
If I've sniped you enough,
you dear listener, into
let's compare our codebase sizes,
I will try and ask if you can find the number of bytes.
It's usually the tools
that report codebase sizes are easier
to measure lines of code for whatever reason.
So that's usually the kind of like...
That also makes for nicer headlines in blog posts.
Right.
Survey has this many bytes,
or Stripes code base has this many bytes,
doesn't quite have the ring to it that lines of code does.
Right, LLCs are better in that case, yeah.
But if it's going to come down to it,
we'll go byte for byte.
That's what you're saying.
We'll definitely do that.
Okay.
If you're comparative on lines of code,
let's go byte to byte.
Yeah, exactly.
Okay.
Cool, man.
So I guess the only thing that I'm left thinking is,
what is the user experience?
Like, let's just say I have a 12 million line Rails app out there,
or maybe even a 16 million line Rails app out there,
and I'm thinking Sorbet might be for me.
Like, how do we opt in or incrementally adopt?
What does it look like day to day to adopt it and use it?
Yeah, so the steps to adopt it, you can just go to sorbet.org
and there'll be instructions there.
The instructions will basically ask you to install a gem.
There's actually two gems.
One of them is going to be the static type checker
that'll report all the type errors in your code.
And one of them is going to be that runtime library
that lets you use the DSL for annotating
type syntax.
So you add these two gems to your code base.
You don't even need to write any annotations out of the box if you don't want to.
And you can start type checking it.
It'll probably report a bunch of errors on your code base.
You can either fix those errors or you can turn off the type checker in those files.
And that's that.
The thing that you're going to want to do is as quickly as possible, get it to the point where
every file is at least typed false. So if you have any files that don't have valid syntax or that
have constant names that Sorbet doesn't know about, there's various ways to fix those errors.
But that's kind of the baseline. It's getting every file to be able to type check at typed false. And from there, you can now start using Sorbet in CI
and making sure that it continues to type check.
You can start using Sorbet in your editor
and take advantage of all these jump to definition features.
And then gradually, again, opt individual files into stricter levels,
start adding type syntax to the methods that you care the most about.
And that's kind of
it. Yeah. What does the editor support look like? So there's a VS Code extension that you can
install and it'll automatically figure out where Sorbet is installed in your code base and how to
run it. And it'll show you the errors and, you know, all of the fancy VS Code features will be
wired up. If you don't use VS Code,
the editor support is powered by a language server protocol server,
and it'll work with any editor client
that supports language server protocol,
which is most of them at this point.
I thought that might be coming,
because I read that you're a Vim guy,
and I thought there's no way Jake's not going to have support
for his favorite editor through some sort of fashion.
Yep, no, it works completely fine in Vim over LSP.
What about tracking adoption? I see there's two documents here
in your docs, adopting Sorbet, which is outlined as you mentioned,
then you also have tracking. How important is it to track adoption when you begin
to incrementally bring it in? Who's tracking the adoption?
I'd say that the tracking adoption, the metrics one, is more focused for larger
companies that are going to be staffing the effort to add types as a proper
project. The nice thing is you want to give other stakeholders at your
company visibility into the progress that you're making. And there's various ways to
ask Sorbet to report how much coverage there is in a codebase
so that you can keep people involved and in the loop.
The first thing you asked me was,
how many files does Sorbet have type-checked in Stripe's codebase?
And yeah, it'll print those out so that you never have to be in the dark
about how much progress you're making.
I also see TypeScript versus, I guess versus,
or comparative to Sorbet as a document.
I'd imagine since you all use TypeScript on the front end
and then on the back in Ruby obviously this
Sorbet type checker, you're
wanting to keep the
mental gymnastics to a low
so what is this document outlining?
If you're familiar with TypeScript you should be
somewhat familiar with the way Sorbet is doing
are you trying to mirror a lot of what they've done well?
I think that doc is one big table that kind of like,
if you know this type system feature
and the name for it in TypeScript has this name,
here's the corresponding name in Sorbet's type system.
Because again, people are way more familiar.
Like for a lot of people,
TypeScript is people's only experience
with the typed language, especially these days.
So kind of anything that we can do to make it easier for people to onboard,
to survey and understand what names we've chosen for various pieces of the type system
is what that doc is trying to provide.
Earlier in the show, you said, I'm going to paraphrase something to the fact that
types will win in the end or it's a type world.
But restate that and give us the synopsis of why you think
that's true i just uh yeah part of it is just a fanatical belief and part of it is i just live
and breathe the benefits of type checkers every day and especially yeah once you get to the point
where you can't you can no longer hold the code base in one person's head where you have to start
collaborating on a code base with more than one person which is almost all code bases that do anything interesting these days having a type
checker to offload the burden of understanding the code and keeping track of relationships between
various files and data structures and all these sorts of things is you know super valuable so
just uh again we kind of talked about this at the beginning where the language that you use changes the way that you think and changes the way that you approach problems.
And languages with type systems, I think, give you such strong vocabulary for how you can structure your thoughts.
Did you say types will win in the end?
What was the exact phrasing?
Give me, lay it down hard.
We're trying to name this episode.
We're trying to get your mail down so we can name it that yeah let's uh i mean now that i know i'm on
the on the book for figuring out what it is i i will say like yeah types will win in the end just
because they're so much more yep this kind of harkens back to my schooling days where i had
professors who were super fanatical about types and they kind of
instilled in in this kind of like going to church and hearing your preacher preach about whatever
gospel just kind of preaching about the values of types so yeah types will win in the end sure
there you go all right last question for me you are a type fanatic working in a dynamic language
which you seem to have much respect for at least on display
and you have a cool job so
surely you want to keep it but if you were to not
have to use Ruby like if you were just like
Jake Zimmerman start from scratch
surely there's a programming language you like better
because of the type
side of things like what would you be working in
would it be something
so when I was in school almost all of our classes
were either in C which is just everyone should learn C at some point, or they were in
this language called standard ML. Standard ML is a very not very widely known language, but it was
kind of one of the first languages to really pioneer algebraic data types and pattern matching
and type inference and all these other type system features that have started to gain rapid popularity in other languages.
So I think that using standard ML as a language
to actually write code in is almost impossible.
There's no libraries for it.
There's no build system for it.
There's no way to really collaborate with other people.
But a lot of languages have gone to great lengths
to copy
their features. So I think that the most popular language that has copied the most from standard
ML is probably Rust. So I'd probably try and use Rust if it were possible.
Very cool. I'm looking at the Wikipedia. Influenced Elm, Fsharp, Fstar, Haskell,
OCaml, Python, Rust, and Scala. So a lot of influence, like you said, on other languages.
I guess at the end of the day, Rust will win. Any other questions on your end before we let him go? I'm clear. I almost brought back in cold ice cream and hot kisses because sorbet, but whatever.
Don't do it.
Jake probably hasn't.
Don't do it.
Jake probably hasn't heard that episode yet.
He's like, what are you talking about?
The funny part about the naming of sorbet is I'm not even a huge fan of sorbet.
I really like ice cream better. What exactly is sorbet is i'm not even a huge fan of sorbet i really like ice cream better
what exactly is sorbet i think it's more of like a dairy-free alternative to
yeah it's like frozen desserts yeah like strawberry usually or it's like uh
a snow cone of sorts right similar to that sort that's the other funny part is i don't think it's
typically served in a cone but our logo definitely has it with the cone yeah it does now we know what's
what's holding back adoption it's just this cognitive overload
what is this sorbet thing i think it's a cool name just because it's different and uh
memorable it is well that's the that's the half the battle is, I mean, Go, for example, is a challenging language to operate around when it comes to finding information.
Because it's just a good name, but poorly named in reference to the fact that everything goes somewhere.
Overloaded.
You have to say Golang, which is basically frowned upon by anybody who writes Go daily.
Like Golang is not part of
their lexicon at all they have like weird rules around they do like just social norms like you
can type go lang but you shouldn't say go lang i'm like i don't know all these rules people
there's a definitely a similar problem with sorbet where if you try and search like
sorbet thing that i need to search for half the time it'll just show you like recipe sites you're gonna get some frozen
sherbert or whatever it is well you do you'd land sorbet.org which is a sweet website considering
you know 2017 most websites are were taken by then but just one single word got the.org so i
mean that's good yeah yeah it was definitely uh i was excited to get that one just a lot of there's
actually like quite a few good domain names out there.
It's just kind of a question of how much you have to pay for them.
But luckily it wasn't a personal project.
It was a Stripe project.
So what looks expensive for me looks a lot cheaper for Stripe.
Good point.
Adam, we should start some Stripe projects.
Get some good domain names.
All right.
We're bike shedding the name.
I think that means we're officially done here. Don't you think, Adam? Let's do it. We're done. All right. We're bike shedding the name. I think that means we're officially done here.
Don't you think, Adam?
Let's do it.
We're done.
All right.
Thanks, Jake.
Jake, thanks so much for coming on, man.
Yeah, thank you for having me.
So there is a bonus after today's show.
So if you're a Plus Plus subscriber, stick around because we asked Jake what it's like to be in such a privileged
position, to be employed
by Stripe, working on
open source, and having
such a significant impact.
Living the dream, the
open source dream. But if you're not a
Plus Plus subscriber, it's too easy.
changelog.com slash plus plus
$10 a month,
$100 a year.
Directly support us.
Drop the ads and get a little closer to the metal.
Again, changelog.com slash plus plus.
Also want to mention a big show coming out on Friday here on The Changelog, an episode of Changelog and Friends.
Our new friend, Jeff Geerling, goes deep with us on the state of
enterprise Linux, what's happening with RHEL, Oracle Linux, Rocky Linux, Alma Linux, all
the Linuxes.
Will Red Hat Enterprise Linux remain the open source enterprise Linux standard, or have
they made a move that makes that change in the near
future? Time will tell. Tune into that show on Friday. Of course, a big thank you to our friends
and partners at Fastly, Fly, and also our friends at TypeSense. Those beats from Breakmaster get
better and better with age. It's like a fine wine or a fine cheese,
just in audio form.
Those beats, they're banging.
But hey, that's it.
This show is done.
Thank you for tuning in.
I appreciate having you here and we'll see you on Friday. Outro Music