12/11/2025 at 4:24:31 PM
Please do the opposite. Let all deprecation warnings last at least a decade, just include in the warning that it is not maintained.But more to the point, go out of your way to avoid breaking backwards compatibility. If it's possible to achieve the same functionality a different way, just modify the deprecated function to use the new function in the background.
My biggest problem with the whole static typing trend is that it makes developers feel empowered to break backwards compatibility when it would be trivial to keep things working.
edit: Not that it is always trivial to avoid breaking backwards compatibility, but there are so many times that it would be.
by dec0dedab0de
12/11/2025 at 4:45:40 PM
> just include in the warning that it is not maintained.I'm convinced this isn't possible in practice. It doesn't matter how often you declare that something isn't maintained, the second it causes an issue with a [bigger|more important|business critical] team it suddenly needs become maintained again.
by jkubicek
12/11/2025 at 4:53:09 PM
And here's where your business can contact me to talk about a support contract.If it's important, they'll pay. Often you find out it wasn't that important, and they're happy to figure it out.
by tux3
12/11/2025 at 5:26:26 PM
It sounds like you're imagining open source whereas the comment you're replying to is imagining more intra-company dependencies.by nisegami
12/11/2025 at 8:05:42 PM
I think deprecation in intra-company code is a completely different beast. You either have a business case for the code or not. And if something is deprecated and a downstream project needs it, it should probably have the budget to support it (or code around the deprecation).In many ways, the decision is easier because it should be based on a business use case or budget reason.
by mbreese
12/11/2025 at 8:32:31 PM
The business case is the easy part, the quagmire is in getting the different teams to agree who should support the business case, why it's more important than the business cases they wanted to spend cycles on instead, and how much of the pie supporting it takes on the budget side. Less so when the place is small enough everyone knows everyone's name, more so when it's large enough they really don't care what your business case is much even though it'd be 10x easier to support from their side instead of another.by zamadatix
12/11/2025 at 9:48:07 PM
Oh. But that is a solved problem. The users of the library just copy the code from before the deprecation and then stick it in their codebase not to be maintained anymore. Problem solved. /sby spockz
12/12/2025 at 7:50:37 AM
> I'm convinced this isn't possible in practice.I don't agree. Some programming languages started supporting a deprecated/obsolete tagging mechanism that is designed to trigger warnings in downstream dependencies featuring a custom message. These are one-liners that change nothing in the code. Anyone who cares about deprecating something has the low-level mechanisms to do so.
by locknitpicker
12/12/2025 at 4:48:55 PM
For sure, but for this to work you need someone downstream to notice those messages and prioritize the work to migrate off the deprecated code paths. Some teams will respond, but many won't. No matter how loudly you declare that the code is deprecated, you'll still have people using it up to the point it stops working.It's far better to plan the removal of the code (and the inevitable breaking of downstream users systems) on your own schedule than to let entropy surprise you at some random point in the future.
by jkubicek
12/13/2025 at 4:45:16 PM
> For sure, but for this to work you need someone downstream to notice those messages and prioritize the work to migrate off the deprecated code paths.Deprecation messages show up as compiler warnings. As a package maintainer, your job does not include taking over project management work in projects that depend on your package.
by locknitpicker
12/11/2025 at 5:00:15 PM
I don't know that I see why/how this is a problem? You would do the same with any other thing in your life?More, in many things, we have actively decided not to do something anymore, and also highly suggest people not mess with older things that did use it. See asbestos. Removing it from a building is not cheap and can be very dangerous.
by taeric
12/11/2025 at 5:39:40 PM
It also keeps slowing down development as getting a green global compile will make you still update "deprecated" functions that face breaking API changes.by dietr1ch
12/11/2025 at 8:15:24 PM
> My biggest problem with the whole static typing trend is that it makes developers feel empowered to break backwards compatibility when it would be trivial to keep things working.I don't see the connection you're drawing here.
by zahlman
12/11/2025 at 8:59:04 PM
Disclaimer: I’m a strong advocate for static typing.I absolutely see the connection. One of the advantages of static typing is that it makes a lot of refactoring trivial (or much more than it would be otherwise). One of the side effects of making anything more trivial is that people will be more inclined to do it, without thinking as much about the consequences. It shouldn’t be a surprise that, absent other safeguards to discourage it, people will translate trivial refactoring into unexpected breaking changes.
Moreover, they may do this consciously, on the basis that “it was trivial for me to refactor, it should be trivial to adapt downstream.” I’ll even admit to making exactly that judgment call, in exactly those terms. Granted I’m much less cavalier about it when the breaking changes affect people I don’t interface with on a regular basis. But I’m much less cavalier about that sort of impact across the board than I’ve observed in many of my peers.
by eyelidlessness
12/11/2025 at 8:32:50 PM
Rather, static typing empowers backwards compatibility, right?Because it lays out the contract you have to meet on the interface. No contract? No enforced compatibility.
by ljm
12/11/2025 at 8:57:55 PM
It is a way to signal to other developers that your code changed, which is better than not saying anything.But it seems to make library developers more comfortable with making breaking changes. It's like they're thinking 'well it's documented, they can just change their code when they update and get errors in their type checker/linter.' When I think they should be thinking, 'I wonder what I could do to make this update as silent and easy as possible.'
Of course, we all have different goals, and I'm grateful to have access to so many quality libraries for free. It's just annoying to have to spend time making changes to accommodate the aesthetic value of someone else's code.
by dec0dedab0de
12/11/2025 at 10:17:10 PM
But it also makes it easier for library developers to identify that a change is breaking. Without static types you can easily make a change you think is fine, but it ends up breaking user code because they depended on something you didn't expect. Granted, static typing doesn't completely solve that problem, there can still be changes in behavior that break things, but it is a useful tool in identifying certain classes of breaking changes.by thayne
12/13/2025 at 3:22:35 AM
yes, that is my point.by dec0dedab0de
12/11/2025 at 10:12:55 PM
I think the only time I’ve ever seen this is in a JS library, where each major version bump is practically a different library altogether because it’s a complete rewrite, and these days is a wrapper around some Rust thing.Not even JS alone. I blame the enforcement of semantic versioning, as if a version of code simply had to be a sequence of meaningful numbers.
by ljm
12/12/2025 at 8:40:20 AM
If you are using a language with a complete type system, sure. But who uses those?When using the languages people actually use in the real world, not really. Consider a simple example where the contract is that you return an integer value from 1 to 10. In most languages people actually use, you're going to be limited to using an integer type that is only constrained by how many bits it is defined to hold, which can be exploited later to return 11, unbeknownst to the caller's expectations. There are a small number of actually-used languages that do support constraining numeric types to a limited set of values, but even they fall apart as soon as you need something slightly more complex.
This is what tests are for. They lay out the contract with validation of it being met, while also handily providing examples for the user of your API to best understand how it is intended to be used.
by 9rx
12/12/2025 at 9:48:14 AM
More than anything, this reveals your lack of understanding of modern languages and type systems.TypeScript, for example, is one of the most widely used languages in the world. It has an incredibly powerful type system which you can use to model a lot of your invariants. By leaning on patterns such as correct-by-construction and branding, you can carry around type-level evidence that e.g. a number is within a certain range, or that the string you are carrying around is in fact a `UserId` and not just any other random string.
Can you intentionally break these guarantees if you go out of your way? Of course. But that's irrelevant, in the same way it is irrelevant that `any` can be used to break the type system guarantees. In practice, types are validated at the boundaries and everything inside can lean on those guarantees. The fact that someone can reach in and destroy those guarantees intentionally doesn't matter in practice.
by IceDane
12/12/2025 at 9:55:33 AM
Typescript is one of the actually-used languages that supports constraining the integer, albeit in a pretty awkward way. type Decade = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
But now try defining a type that enforces a RFC-compliant email address...There are languages with proper type systems that can define full contracts, but Typescript is not among them. Without that, you haven't really defined a usable contract as it pertains to the discussion here. You have to rely on testing to define the contract (e.g. assert the result of the 'generate email' function is RFC-complaint).
And Typescript most definitely does. Testing is central to a Typescript application. It may have one of the most advanced type systems found in languages actually used, but that type system is still much too incomplete to serve as the contract. Hence why the ecosystem is full of testing frameworks to help with defining the contract in tests.
by 9rx
12/12/2025 at 4:05:38 PM
You clearly don't understand the patterns I described. Look up branding and try reading e.g. "parse, don't validate".by IceDane
12/12/2025 at 4:33:43 PM
"Parse, don't validate", while familiar to all HN users (it feels like it gets posted here every week), is orthogonal and does not address what we are talking about. To extrapolate, let's stay with the email address type example.In Typescript, you can define an EmailAddress type as:
type EmailAddress = string & { __brand: "EmailAddress" }
If you are feeling saucy, you can even define it as: type EmailAddress = `${string}@${string}` & { __brand: "EmailAddress" }
But nether of these prove to me, the user of your API, that an EmailAddress value is actually a RFC-compliant email address. Your "parse" function, if you want to think in those terms, is quite free to slip in noncompliant characters (even if only by accident) that I, the consumer, am not expecting. The only way for me to have confidence in your promise that EmailAddress is RFC-compliant is to lean on your tests written around EmailAddress production.That isn't true for languages with better type systems. In those you can define EmailAddress such that it is impossible for you to produce anything that isn't RFC-compliant. But Typescript does not fit into the category of those languages. It has to rely on testing to define the contract.
by 9rx
12/13/2025 at 10:31:43 AM
Let's imagine we are working with some hypothetical language in which what you describe is possible.At some point, you will have to write a function where you validate/parse some arbitrary string, and it then returns some sort of `Email` type as a result. That function will probably return something like `Option<Email>` because you could feed it an invalid email.
The implementation for that function can also be wrong, in exactly the same way the implementation for the typescript equivalent could be wrong. You would have to test it just the same. The guarantees provided by the typescript function are exactly equivalent, except for the fact that you do technically have an escape hatch where you can "force" the creation of a branded `Email` without using the provided safe constructor, where the other language might completely prevent this - but I've already addressed this. In practice, it doesn't matter. You only make the safe constructor available to the user, so they would have to explicitly go out of their way to construct an invalid branded `Email`, and if they do, well, that's not really your problem.
by IceDane
12/14/2025 at 1:59:43 PM
> Let's imagine we are working with some hypothetical language in which what you describe is possible.Or even a real one. The hypothetical part is that you'd be able to understand it. The languages with complex type systems are complete bears to work with, as I am sure you can image. It isn't just some historical curiosity as to why we prefer to use testing over types to define the contract. It is way more practical. But, no matter how you feel about that, it remains that we do define the contract in tests in the languages people actually use.
> The implementation for that function can also be wrong, in exactly the same way the implementation for the typescript equivalent could be wrong.
The compiler would give you an error if you got the syntax wrong, and in isolation it's fair that you could, say, get the domain name wrong as long as it is syntactically valid. I suppose what I failed to convey, making some assumptions about your understanding of type systems, is that the types would not just specify RFC-compliance. You would also spec out other dependencies such that you also couldn't even provide the wrong domain name without a compiler error. So, no, the implementation of the function couldn't be wrong.
You could mis-spec the contract, of course. Then the function could be "wrong". Maybe this is the intent behind what you are trying to say here. But the idea has always been here that I would also read and accept the contract, so it wouldn't actually be "wrong". It would be exactly what we both expect. My side will be written to what the contact specifies. If you try to deviate from the contract later, you'll face the wrath of the compiler.
As you point out, that's not the case in Typescript. If you try to change the contract (even if by accident) the compiler/typechecker will never say a word. I won't know until my code starts breaking. Your tests are the only thing you have to keep you in line with what we agreed upon. Tests define the contract in its case.
by 9rx
12/14/2025 at 4:14:38 PM
> Or even a real one. The hypothetical part is that you'd be able to understand it. The languages with complex type systems are complete bears to work with, as I am sure you can image.I have written Haskell professionally for several years and worked with Idris and other similar languages. I'm perfectly aware of what is possible.
> The compiler would give you an error if you got the syntax wrong, and in isolation it's fair that you could, say, get the domain name wrong as long as it is syntactically valid. I suppose what I failed to convey, making some assumptions about your understanding of type systems, is that the types would not just specify RFC-compliance. You would also spec out other dependencies such that you also couldn't even provide the wrong domain name without a compiler error. So, no, the implementation of the function couldn't be wrong.
Wow, wouldn't that be something. This is hilariously wrong. You can build tiny functions and then compose those into larger functions and then the larger functions are all correct but only as long as their components are correct. It would be lovely if there was some magic construct that prevented you from writing incorrect code. Maybe it could be extended to hacker news comments, and then we could have just skipped this entire discussion.
> You could mis-spec the contract, of course. Then the function could be "wrong". Maybe this is the intent behind what you are trying to say here. But the idea has always been here that I would also read and accept the contract, so it wouldn't actually be "wrong". It would be exactly what we both expect. My side will be written to what the contact specifies. If you try to deviate from the contract later, you'll face the wrath of the compiler.
A truly baffling take. Bravo! Even on Hacker News, that was truly something. I don't even know where to begin. I guess I don't really have to, since when it comes to explaining the ease with which you transfer words straight from your ass to hacker news comments, it does a better job than I could possibly hope to do.
> As you point out, that's not the case in Typescript. If you try to change the contract (even if by accident) the compiler/typechecker will never say a word. I won't know until my code starts breaking. Your tests are the only thing you have to keep you in line with what we agreed upon. Tests define the contract in its case.
At this point, it's fairly clear that you are just thoroughly confused about how any of this works and what is actually possible. If you disagree, I'd love to hear how you would implement some sort of construct that allows you to write a function of the type `String -> Email` that doesn't throw if the email is invalid, can process arbitrary user input (not just string literals in your code), and somehow makes it a compiler error if your code is ever incorrect at all. PS: Explicitly returning and carrying around proof of validity doesn't count.
by IceDane
12/14/2025 at 4:52:57 PM
> that doesn't throw if the email is invalidWhy can't it 'throw' if the email is invalid? You can — and would — encode that into the contract, detailing exactly what that means, so no problem for the user. They will write their code expecting that condition and everything will be fine. There is nothing special about failure cases. It is only a state, just like every other state.
> At this point, it's fairly clear that you are just thoroughly confused about how any of this works and what is actually possible.
Ad hominem is a logical fallacy. It is surprising that a comment that claims to understand programming language types in great detail would also commit an obvious logical error, given how important logic is in that context. But, stranger things have happened, I suppose. Unfortunately, there is nothing we can take from a logical error. Assuming it was trying to be written in good faith and free of errors, no doubt we'll get a meaningful explanation of what was actually trying to be expressed with code examples to follow. Looking forward to it.
by 9rx
12/14/2025 at 5:34:18 PM
Thank you for (once again) making it clear to any reader that you are not to be taken seriously. If only we could edit older comments so that the reader didn't have to suffer through all your nonsense to find out.by IceDane
12/14/2025 at 9:08:19 PM
The reader has no idea who the author is. Nor do they need to as the words on the page already provide sufficient information to determine if the words are worthy of being taken seriously or not. Trying to assign meaning from the author onto the message is not logically sound. Words stand on their own.Turning to logical fallacies in an attempt to steer the reader away from understanding that Typescript relies on testing to downplay the original misunderstanding that you mention realizing cannot be edited now isn't going to work, I'm afraid. The reader is able to see through such a thin veneer. They could be convinced by a technical exchange directed at the topic at hand, but it is telling that we never saw anything of the sort.
by 9rx
12/11/2025 at 9:03:04 PM
I could see some maintainers being encouraged by static typing to introduce breaking changes, as long as the changes ensure compile-time breakage. However, that’s only an option in languages without dynamic linking. So it’s the combination of static typing and static linking that would encourage that.by layer8
12/12/2025 at 12:07:00 AM
Indeed. C# is statically typed. Python is not. Which is the one with a notorious backwards-incompatibility story?by anonymars
12/12/2025 at 2:31:05 AM
Both.https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/br...
by shakna
12/12/2025 at 7:09:27 AM
Come on, those are very rare and minor things that are very easy to fix.by mrsmrtss
12/12/2025 at 7:10:56 AM
Port me something from DotNet 9.0 and say that again.https://learn.microsoft.com/en-us/dotnet/core/compatibility/...
by shakna
12/12/2025 at 7:35:38 AM
We have already ported many projects from .NET8 and .NET9 to .NET10 with close to zero issues.by mrsmrtss
12/12/2025 at 1:06:37 PM
Guessing you never used OpenAPI or Razor then. Which were core features in 9 and no longer existed in 10.by shakna
12/12/2025 at 2:27:01 PM
What are you talking about?? OpenAPI and Razor are both still present in .NET10.by mrsmrtss
12/12/2025 at 3:06:33 PM
Yeah, I'm confused at these examples, along with the implicit idea that the existence of breaking changes means C# had equivalent compatibility challenges to, say, python3..NET Framework -> Core was more persuasive, but I stand by the overall point that compatibility is more about project philosophy than "static vs dynamic typing" and indeed I think Framework/Core illustrates just that: Framework more heavily favored preserving compatibility compared to Core
edit: I assume this was a superficial grasp onto "Deprecation of WithOpenApi extension method" ("WithOpenApi duplicated functionality now provided by the built-in OpenAPI document generation pipeline") and "Razor runtime compilation is obsolete" ("Razor runtime compilation has been replaced by Hot Reload, which has been the recommended approach for a few years now.")
by anonymars
12/13/2025 at 1:01:16 AM
Of course, its an entirely trivial process to completely replace serialisation everywhere in your product and swap out your own custom hot reloading compilation pipeline you created before the language created its own one incompatible with your API...by shakna
12/13/2025 at 3:12:43 PM
Which breaking changes required you to completely replace serialisation everywhere in your product?I guess it's true that a dynamic language wouldn't have lent itself to creating a custom hot reloading compilation pipeline so, yeah, checkmate I guess
by anonymars
12/12/2025 at 11:02:20 AM
The .NET framework to .Net Core migration broke a bunch. Similarly java 6 to 8, and when they introduced the new module system in Java 11 broke a bunch in another case. You’d still need to fixed that they swapped the string types, renamed a bunch of core APIs etc. in a statically typed pythonby Macha
12/12/2025 at 1:14:15 PM
Those are good examples. But python is dynamically typed -- indeed, python 3 is what I was alluding toThat being said, I think backwards compatibility comes down to project philosophy and foresight (e.g. https://learn.microsoft.com/en-us/dotnet/standard/design-gui...), not static versus dynamic typing
by anonymars
12/11/2025 at 7:18:32 PM
As with all things, this can be pushed too far. Microsoft was suffering a maintainability crisis before the transition to Windows XP; their years of bending the API to support customers (which, in the short run, did keep customers to their benefit) was making for a fairly unmaintainable mess of an API surface that then screamed under the strain when the Internet era hit and all those open, under-observed APIs became potential worm attack vectors.by shadowgovt
12/11/2025 at 9:24:19 PM
Actually, I think backwards compatibility is the reason Windows still dominates. It isn't the best OS at anything and it's actively user hostile, but if you want to run Windows apps... there are decades of Windows apps and they basically all work.by Wowfunhappy
12/11/2025 at 9:18:06 PM
I was hoping to spin it as an environmental concern. You change something "for reasons". If you're doing this in a popular tool/library you probably just burnt down a small forest of trees worth of energy from all of the work people will have to put in deal with it. 100s of thousands of users missed dinner with a kid or loved one because of the extra work you created. A product that would of shipped on time didn't. Things you wanted to exist didn't because 100k people were distracted dealing with your breakage.by socalgal2
12/11/2025 at 5:31:06 PM
> Not that it is always trivial to avoid breaking backwards compatibility, but there are so many times that it would be.In this case it was 2 functions with 1 line of code each. https://github.com/urllib3/urllib3/pull/3732/files
by mxey
12/11/2025 at 7:30:46 PM
Wow. Why even remove it? It's just the thinnest wrapper around the dict and since the dict is now part of the public API these methods will work forever unmodified.by Spivak
12/11/2025 at 11:54:00 PM
Static Typing != Strongly Maintained Relationships.While I am happy to see types in Python and Javascript (as in Typescript) I see far more issues how people use these.
In 99% of the time, people just define things as "string" or if doesn't cover, "any". (or Map/Object etc)
Meanwhile most of these are Enum keys/values, or constants from dependencies. Whenever I see a `region: string` or a `stage: string`; a part of me dies. Because these need to be declared as `region: Region` or `stage: Stage`. Where the "Region" and "Stage" are proper enums or interfaces with clear values/variables/options. This helps with compile (or build) time validation and checking, preventing issues from propagating to the production (or to the runtime at all)...
by pvtmert
12/11/2025 at 11:51:09 PM
Stripe do this in a cool way. Their REST API is version based on date, and each time they change it they add a stackable compatibility layer. So your decade old code will still work.by keeperofdakeys
12/12/2025 at 2:37:54 AM
Isn't that arguing for keeping the maintenance cost high and also stagnating the design?by bmitc
12/12/2025 at 9:51:36 PM
this is the answer.No matter what others say, the pipelines are long.
The delays for release, getting into a distribution, then living out its lifetime... they are significant.
by m463
12/11/2025 at 5:23:01 PM
One thing I've always hated was this idea of "bitrot." That software just spontaneously stops working after time and loses backwards compatibility. Like it's some force of nature.It's not a force of nature. Bitrot is: many software developers deliberately choosing to break backward compatibility in very small ways over and over. Software written in 1995 should still work today. It's digital. It doesn't rot or fall apart. It doesn't degrade. The reason it doesn't work today is decisions that platforms and library maintainers deliberately made. Like OP. Deprecate like you mean it. That's a choice!
If we want to solve bitrot, we need to stop making that choice.
by ryandrake
12/11/2025 at 5:33:43 PM
Progress is often only possible by breaking things. It's not a choice, it's the only way forward. We have to optimize for the future being better, even if it makes the present a little worse occasionally.This is a huge reason why open source projects are often so much more successful than corporate clones: they actually iterate and innovate, something corporate america has forgotten how to do.
by jcalvinowens
12/15/2025 at 4:07:38 AM
>Progress is often only possible by breaking things. It's not a choice, it's the only way forward.See you think it's Progress, but it's actually Regress. It's not a moving forward, but backward.
Do not break contract. Do not break API. Do not break muscle memory. Everytime you do, kittens die horribly. Just Say No!
by rustcleaner
12/11/2025 at 8:43:43 PM
Some deprecations are required to make progress. Many others aren't, and those are the most frustrating.For example, ruby deprecated the `File.exists?`, and changed it to `File.exist?`, because enough people felt that the version with the `s` didn't make sense grammatically (which I disagree with, but that is not germane to my point).
For a long time, you would get warning that `exists?` was deprecated and should be replaced by `exist?`.... but why? Why couldn't they just leave `exists?` as an alias to `exist?`? There was not cost, the functions are literally identical except for one letter. While the change was trivial to fix, it added annoyance for no reason.
Although, luckily for me, with Ruby I can just make exists? an alias myself, but why make me do that?!? What is the point of removing the method that has been there forever just because you think the s is wrong?
by cortesoft
12/11/2025 at 10:32:02 PM
Imagine I am new to Ruby. I go looking to figure out if a file exists. Or I get a list of available methods from the file object. Now I have to research both `exist?` and `exists?` to figure out if I should be choosing one or the other.Now multiply that by.... every past history of every API and it makes adopting something really difficult as a newcomer.
aka Common Lisp.
by coryrc
12/11/2025 at 11:40:36 PM
It doesn’t matter which one you do, the methods are literally identical other than the extra s. You can’t pick the wrong one.This sort of choice is very common in Ruby, you can have different style choices for the same functionality. You can have blocks made with {} or do and end. You can do conditionals in the form of “a if b” or “if b then a”. You can call methods with or without parentheses.
These are all Ruby style choices, and we already have a way to enforce a particular style for a particular project with formatters like rubocop.
by cortesoft
12/11/2025 at 10:53:38 PM
I'm not defending the Ruby decision, I literally said I wouldn't have done it. It reminds me of the disttools removal from python, which was also not something I'd have done nearly so aggressively if it were up to me. Multiple distros have patched it back in.But it wasn't up to me. It's not my project. I'm using somebody else's project, and at the end of the day it's their decision, because they own it. Unless it's impossible to work around, I feel like I have to either respect that, or switch to an alternative.
You're free to maintain a patch on top of Ruby to add the alias and run that on your machines, btw. It would probably be very simple, although certainly not as simple as aforementioned sed command...
by jcalvinowens
12/12/2025 at 1:38:50 PM
> You're free to maintain a patch on top of Ruby to add the alias and run that on your machines, btw.Comments like this are honestly just asshole-ish.
by kelipso
12/12/2025 at 1:53:34 PM
Why? It's true. It's not even really that hard. My point is nobody is forcing them to accept it.by jcalvinowens
12/12/2025 at 2:06:36 PM
Because Ruby is nothing without the community around it. If they wanted to make Ruby and don’t care about the people using it, they should go private, shut down the project, or have someone else take over.It’s wrong to shut down discussion like this with comments like “it’s their code”, “make your own fork”, etc. because Ruby is supposed to be part of the open source community, which implies collaboration, give and take, discussion of pros and cons, etc.
What you are doing is ignoring this major aspect of a programming language and taking this weird anti social stance on it.
by kelipso
12/12/2025 at 3:36:44 PM
I'm not shutting down any discussion, I'm simply stating my opinion. You're free to disagree.I didn't say to fork it. Do you really not appreciate the difference between rebasing a trivial patch forever, and maintaining a wholesale fork forever?
by jcalvinowens
12/12/2025 at 3:57:51 PM
Crowing on saying “it’s not your code, they can do what they want” is an attempt to do that.Fork, patch, maintaining your private whatever, that’s not the point, and is a digression.
by kelipso
12/12/2025 at 4:14:36 PM
It's a perfectly valid point, you just disagree. I'm not the one shutting down discussion here.by jcalvinowens
12/11/2025 at 11:43:19 PM
Of course it is their decision, and they don’t OWE me an explanation.But this is a discussion forum, and I am asking for people who agree with the decision to explain why they agree. Again, they don’t have to answer me if they don’t want to. I am just saying, “if anyone knows an argument for this type of change, I would love to hear it”
Saying they don’t have to explain their reasoning is true but not really relevant to our conversation. I am not asking THEM, I am asking HN readers.
by cortesoft
12/11/2025 at 9:04:43 PM
Your example could be fixed in your entire codebase with a single sed invocation. While yes, if it were up to me I'd probably just have left the alias, the annoyance for the end user does seem quite minimal...You get to use open source projects for free, and a lot of people do ongoing maintenance on them which you benefit from for free. In return, sometimes you are expected to modify your code which depends on those projects because it makes their maintainer's life easier.
Personally, I see that as a very reasonable trade-off.
by jcalvinowens
12/11/2025 at 9:35:36 PM
The third option is to use things that don't break themselves. One of the many joys of Go is that I can leave personal projects untouched for years and then go back and everything is still workingby Ferret7446
12/11/2025 at 9:59:59 PM
> Your example could be fixed in your entire codebase with a single sed invocationI also have to hope all the dependencies I use did that, too.
But my real question is why? Why make me do it at all?
by cortesoft
12/11/2025 at 10:10:40 PM
Because they wanted to, and it's their project. Part of being an adult is accepting you won't agree with every decision that affects you.You were free to show up and argue against it, as was anyone else. Did you?
by jcalvinowens
12/11/2025 at 11:29:16 PM
Ok, I think you are arguing against something I am not saying.I am not arguing that they don’t have the RIGHT to make the change, or that they owe me personally anything. I am not even THAT mad. I still love Ruby the most of any language, and generally think they make the right decisions.
I am simply annoyed by this decision.
And yes, I argued against this change when it was first proposed (as did many others). They obviously were not convinced.
Again, I am not arguing that they should be FORCED to do what I want, or that they did something shady or nefarious by making this change. I am not asking for any remedy.
I am simply saying I disagree with this type of change (changing a method name because some people feel the new name makes more grammatical sense, but not changing the method itself at all). The reason I commented was because this is not a “we have to deprecate things for progress” situation. They aren’t limited in any way by the current method, the syntax isn’t cumbersome (and isn’t changing), there is no other capability that is held back by having to maintain this method. It is literally just “I read it as asking ‘Does this file exist?’ rather than asking ‘This file exists?’”
Again, they are obviously free to disagree with me, which they do. I am simply arguing that we shouldn’t break syntax just because you like the way it reads better without an s. And I am asking for someone who disagrees with me (you) to explain why it is worth making this type of change.
by cortesoft
12/12/2025 at 4:28:15 PM
It's important for code to be clean and free of old cruft, even if that means old code has to change. Readibility is one of the most important aspects of maintainable code. Arguably more important than testing, IMHO. This is another reason open source solutions so consistently win over corporate ones, the open source world understands this.Are there changes I disagree with? Of course. But I'd rather live in a world that moves forward and occasionally breaks me, than one where I have perfect compatibility but am stuck on code lacking the new innovations my competitors benefit from.
The whole idea behind deprecating things is to give people time to make the changes before they become breaking.
I went and looked: exists? was marked as deprecated in 2013 and removed in 2022. That's enormously generous, my previous comparison with the disttools debacle in python was inaccurate. You had a decade!
by jcalvinowens
12/11/2025 at 9:49:51 PM
You've moved the goal posts quite a bit from your previous post to this one. Originally, you said that "progress is often only possible by breaking things... it's the only way forward". But the Ruby example that cortesoft provided isn't necessary to make progress. The language would get by just fine without that deprecation (or even without making the change at all). Saying "but it's a trivial change" in response is irrelevant, because you weren't originally trying to justify changes on the basis that they were easy, but that they were necessary.by bigstrat2003
12/11/2025 at 10:12:10 PM
> Saying "but it's a trivial change" in response is irrelevantOf course it's relevant. It's a laughably trivial example compared to the other one in this thread.
by jcalvinowens
12/11/2025 at 5:45:13 PM
It's absolutely a choice. All software can progress while preserving backward compatibility for existing users. It's not always easy, but it's never impossible.by ryandrake
12/11/2025 at 5:49:18 PM
> All software can progress while preserving backward compatibility for existing usersThat's an incredibly ignorant claim. Just run "git log" in glibc, it won't take you very long to prove yourself wrong.
by jcalvinowens
12/11/2025 at 5:50:50 PM
glibc, which has had ABI compatibility for decades?by mxey
12/11/2025 at 5:52:47 PM
There have been plenty of build breaking changes over the past couple decades, generally they happen for very good reasons and only affect niche usecases.by jcalvinowens
12/11/2025 at 5:56:48 PM
So existing binaries will keep working?by mxey
12/11/2025 at 6:08:00 PM
Not necessarily if you go back far enough to have nss problems :)by jcalvinowens
12/12/2025 at 9:24:12 AM
Not always without a performance cost which is a no go in projects with very expensive hardware (ahem Cisco).by lan321
12/11/2025 at 5:37:28 PM
Actually this is the reason why Win32 is the stable ABI for Linux.by mxey
12/11/2025 at 7:37:57 PM
While I certainly empathize with the author of that article and respect the work they put into debugging it, this is a better explanation of that whole thing: https://maskray.me/blog/2022-08-21-glibc-and-dt-gnu-hashby jcalvinowens
12/11/2025 at 7:20:18 PM
God, would I hate to be programming now the way I had to program in 1995.Granted, modern coroutines do bring up some nostalgic feel for the days I had to support cooperative multitasking...
by shadowgovt