In such a language, any change on framework update would cause compiler errors if the framework's type constraints didn't match what your code expected.
As a result, upgrading in a dependently typed language is simply a matter of fixing compiler errors, and then it's upgraded.
For non-dependently-typed languages that take advantage of the type system, it's still significantly easier, though you probably will have to do a little more than just make sure it compiles.
> As a result, upgrading in a dependently typed
> language is simply a matter of fixing compiler
> errors, and then it's upgraded.
This is very naive, and is probably hilarious to a lot of people who've been through upgrade hell in a dependently typed language. A few (and then some) major reasons:1. It's really the subtle runtime behavior changes that bite you. The ones that a compiler doesn't help you with. (This is not a Rails-specific thing; ask Unity or OpenGL etc. devs)
2. A lot of the pain of upgrading a project (Rails or otherwise) is dependency hell. You upgrade the framework, but some of your dependencies haven't been updated and don't work with the newer framework version. This is true whether it's a dynamic or compiled app.
3. It's certainly true that in a strongly typed language, these sorts of trivial problems would be caught at compile time and that's certainly an advantage. However it's not exactly rocket science to catch these in a Rails app. Assuming your test suite is anywhere near adequate, it's going to spit out a comprehensive list of these problems just like a compiler would, albiet not as instantly.
3a. Rails is pretty good about documenting these breaking identifier changes between versions. They don't exactly sneak up on you, unless you get drunk one night and decide to upgrade your enterprise Rails app without looking at the release notes.
3c. Rails is also quite conscientious at loudly announcing to you, via log messages, when you use functionality that is deprecated and targeted for removal. Assuming you're not willfully ignoring these (ie, drunken late-night upgrade bender?) they don't typically catch one by surprise.
I agree that dependency hell and getting the versions to line up right is equally hard.
However, I disagree that 3 is a good argument.
> these sorts of trivial problems would be caught at compile time and that's certainly an advantage. However it's not exactly rocket science to catch these in a Rails app
Actually, it kinda is. To model the constraints you create in a dependently typed language, you have to create a set of tests and checks in your dynamically typed language which are basically the equivilant of a full dependent-type-system. Creating an ad-hoc human-enforced type-system and test suite is incredibly hard and I can't think of a single large project written in a dynamically typed language that adequately does this.
Regardless of how good the documentation and testing and warnings in rails are, it's not a replacement for a full type system, and the only way to get those benefits is to implement a poor ad-hoc type system in your methods and tests.
Yeah, big upgrades are always hard. Good type systems make them less scary and have less chance of breaking stuff, which honestly is the most important thing... But after you've finished getting through the stuff that all languages share (hardware sucks, dependencies suck, etc), a dependently typed language will be a matter of fixing compiler errors, not watching percentages of 500s in prod and crossing your fingers.
> But after you've finished getting through the stuff
> that all languages share (hardware sucks, dependencies
> suck, etc), a dependently typed language will be a
> matter of fixing compiler errors, not watching
> percentages of 500s in prod and crossing your fingers.
I am speaking from very direct experience here.I was involved in a Rails 3.x --> Rails 5.x upgrade of one of the larger Rails monoliths in the world and the trivial sorts of things a compiler can catch were... well, also pretty trivial in our upgrade path. Just not quite as trivial as they'd be with a compiled language (nobody's denying they have the edge here)
> To model the constraints you create in a dependently typed
> language, you have to create a set of tests and checks in
> your dynamically typed language which are basically the
> equivilant of a full dependent-type-system.
No, that's not how you do it.You don't "model the constraints" explicitly. You write integration tests, same as you'd do in any sort of language. If MethodA from Class1 is passing the wrong stuff to Class 2 from MethodB, your integration tests will fail. At least, assuming you've got proper coverage.
But even in a staticly typed, compiled language you have to write that test anyway, right? Because you need make sure that code path actually works anyway and MethodA is getting the correct response from MethodB there.
There are definitely advantages to strongly typed, compiled languages! To be honest, after a few years in Ruby land, I'm ready to GTFO and go back to something a little more static. But Ruby's not the nightmare you describe it as.