4 ms·
Is there anything you can think to say to convince the old you? I have a few friends who haven’t yet seen the typing light. I also think Stripe’s API (external
by hardwaresofton 5y ago
Is there anything you can think to say to convince the old you? I have a few friends who haven’t yet seen the typing light.
I also think Stripe’s API (external) should not be moving ids and objects. Given some payload in which ‘account_id’ is always present and ‘account’ may be the object (using ‘expand’ IIRC?) or not makes a lot more sense to me.
- jez 5y agoMy experience has been that the people opposed to types won't be convinced to start liking them by anything you can tell them or have them read. In all of the cases where I've seen Sorbet be adopted, the process looked like this: 1. Ambitious team who wants types does work to get the initial version passing in CI. Importantly, it's only checking at `# typed: false`, which basically only checks for missing constants and syntax errors. 2. That initial version sits silently in the codebase over a period of days or weeks. If new errors are introduced, it pings the enthusiastic Sorbet adoption team; they figure out whether it caught a real bug or whether the tooling could be improved. It does not ping the unsuspecting user yet. 3. Repeat until the pings are only high-signal pings 4. Turn Sorbet on in enforcing mode in CI. It's still only checking at `# typed: false` everywhere, but now individual teams can start to put `# typed: true` or higher in the files they care about. 5. Double check that at this point it's easy to configure whatever editor(s) your team uses to have Sorbet in the editor. Sorbet exposes an LSP server behind the `--lsp` flag, and publishes a VS Code extension for people who want a one-click solution. 6. Now the important part: show them how good Sorbet is, don't tell them. Fire up Sorbet on your codebase, delete something, and watch as the error list populates instantly. Jump to definition on a constant. Try autocompleting something. In my experience trying to bring static types to Ruby users, seeing is really believing, and I've seen the same story play out in just about every case. One final note: be supportive. Advertise one place for people to ask questions and get quick responses. Admit that you will likely be overworked for a bit until it takes off. But in the long run as it spreads, other teammates will start to help out with the evangelism as the benefits spread outward.
- hardwaresofton 5y agoThanks for this thoroughly practical advice -- evangelizing types inside Stripe must have been quite the journey! Been following since Dmytro and Paul's talk @ strangeloop.
- jez 5y agoInterestingly enough, I don't recall there ever being much pushback against static types at Stripe. The "evangelizing" work was more organizational: convincing people that yes, it is possible to build a production-ready type checker in 6-9 months[1], and then staff a team long term to continue improving it. I was at Stripe during that time, but on a different team, so I can't speak too much to the process. Luckily I think Stripe is a well-functioning org with smart and reasonable leaders—much easier to present that case than e.g., trying to win debates on static vs dynamic typing on the internet! [1] https://sorbet.run/talks/StrangeLoop2018/#/28 https://sorbet.run/talks/StrangeLoop2018/#/28
- girvo 5y agoThis process is near identical to the ones I went through to introduce Flow (initially) then Typescript (later on) for a number of projects I've worked on over the past few years. Nowadays, its extremely rare for me to come across projects that don't use Typescript already!
- sodapopcan 5y agoWhat are some examples of where types have saved you? I mean, I can imagine some, but are there any good blog posts or have an example yourself? I've moved on from Ruby to Elixir and we use typespecs at my current job, but I still never do in any of my own code. Elixir does have a way to do type hinting which I do use and appreciate when appropriate. So I'm not "against" types and like the idea in theory, but I've never really felt the pain. The most tangible argument I've bought is that types help out in a huge codebase. I can definitely see this. This is really solving a social problem, of course, because on smaller teams, it's much easier to enforce coding standards, especially if you follow XP and pair all the time. For example, in large dynamic codebases I've worked on, calling something `object` when it really means `object_id` would never fly. Variables and functions always have to be full words describing exactly what they do. Functions are only ever allowed to return one type. And of course everything is thoroughly tested. Of course I understand that not all these things are practiced everywhere and nor do they need to be. But for me that has always made for incredibly readable code. I'm writing this just to give the perspective of a dynamic weenie and maybe looking to be convinced a little more? I also know three incredibly good programmers with 20-50 years experience each who all wrote in typed languages for years and then couldn't be happier not to have types when they moved to Ruby. So ya, I dunno what I'm expecting here, but mostly offering my perspective. But the TL;DR: if I join your team and you want me to use types, I'll do it! But I really feel there are ways around it but those ways may not be for everyone (and sometimes perhaps impractical). hmmm, I dunno, this was longer than I meant it to be, haha.
- brightball 5y agoYour experience mirrors mine. I have become a dialyzer evangelist though.
- sodapopcan 5y agoWhat won you over? The thing I left out was that it's only been four month of being forced to write typespecs (I actually secretly resent it when I am forced to add them to private functions) so maybe I'll come around?
- 5y ago
- KwisaksHaderach 5y agoRemember, this are devs that worked on codebases that have millions lines of Ruby code (Stripe) and most probably have to handle loads of state in the application layer, so their context/anecdata might be different for your friends. I prefer dynamically typed languages for most stuff but at the scale of Stripe I would also like to have a type checker.
- drusepth 5y agoI haven't yet seen the typing light, so maybe my perspective might spawn some replies that could help. I understand that types are helpful, especially within the context of learning new code (both as a new dev, and more easily understanding new code written by your team), but my hesitation to "jump ship" to them comes from weighing all the "boilerplate" code necessary to get them working versus the tangible benefits I feel they'd give. To that end, maybe enumerating over the benefits for your friends (ideally more specifically than just "fewer bugs" or "easier to read/write") might tilt the scale more towards using them. The article shows some good examples of problems that types solve, but many of them could also be "fixed" with better naming schemes, standardizations, and/or refactors -- and then wouldn't also be littered with type annotations (which take up 50% of the code in their example, [1], where I've also added a couple other easy-to-understand "solutions" with less cruft. IMO, most of the typing syntax in their examples is distracting from the actual code -- especially when just writing better or more standardized code (which you still need to do with types) would make the typing syntax, again IMO, less necessary. [1] https://sorbet.run/#%23%20typed%3A%20true%0Aextend%20T%3A%3ASig%0A%0Aclass%20Invoice%0A%20%20%23%20...%0Aend%0A%0Asig%20%7Bparams%28invoice%3A%20Invoice%2C%20paid%3A%20T%3A%3ABoolean%29.void%7D%0Adef%20update_invoice%28invoice%2C%20paid%29%0A%20%20%23%20...%0Aend%0A%0A%23%20error%3A%20Expected%20%60Invoice%60%20but%20found%20%60String%60%20for%20argument%20%60invoice%60%0Aupdate_invoice%28'in_1KZ7eP2eZvKYlo2C3B98SLc9'%2C%20true%29%0A%0A%0A%0A%0A%0A%0A%0Aclass%20Invoice%0A%20%20%23%20...%0Aend%0A%0Adef%20update_invoice_paid%28invoice_id%2C%20paid%29%0A%20%20%23%20...%0Aend%0A%0Aupdate_invoice_paid%28'in_1KZ7eP2eZvKYlo2C3B98SLc9'%2C%20true%29%0A%0A%0A%0A%0A%0A%0A%0Aclass%20Invoice%0A%20%20%23%20...%0Aend%0A%0Adef%20update_invoice%28invoice_id%3A%2C%20paid%3A%29%0A%20%20%23%20...%0Aend%0A%0Aupdate_invoice%28invoice_id%3A%20'in_1KZ7eP2eZvKYlo2C3B98SLc9'%2C%20paid%3A%20true%29 https://sorbet.run/#%23%20typed%3A%20true%0Aextend%20T%3A%3A...
- hardwaresofton 5y agoYeah unfortunately this is one of the problems, bolting on the types rarely works as well as it does for Typescript (looks quite natural to me). In Haskell for example, writing signatures is actually both unnecessary (they will be inferrable, most of the time so it's basically only for humans to read) and a net positive (they fit well prose wise and you can use them as documentation) but that's a harder hill to climb. I do want to note that one big advantage of specifying signatures is that now your IDE can help you when using the functions and detect when something is going wrong. Maybe "no more trying to figure out what the input/output of a function that you didn't write is supposed to be" would be a draw?