Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Evolving Ember's Major Version Process #830

Merged
merged 6 commits into from
Sep 6, 2022
Merged

Conversation

chriskrycho
Copy link
Contributor

@chriskrycho chriskrycho commented Jul 12, 2022

Rendered text


Introduce a standard release train for major releases, analogous to Ember's release train for minor releases:

  • After every M.12 minor release, Ember will ship a new major, (M+1).0, which removes any deprecated code targeted for that major release.
  • Deprecations targeting the next major cannot be introduced later than the M.10 release.

The result is a steady 18-month cadence between Ember major releases, complementing our steady 6-week cadence between Ember minor releases.

How this would work in practice for Ember's lifecycle from 4.8 to 7.0

Ember Release Release date LTS date
4.8 October 2022 November 2022
4.12 April 2023 May 2023
5.0 May 2023
5.4 October 2023 December 2023
5.8 April 2024 May 2024
5.12 September 2024 November 2024
6.0 November 2024
6.4 April 2025 May 2024
6.8 October 2025 November 2025
6.12 March 2026 May 2026
7.0 May 2026

@rtablada
Copy link
Contributor

I love this idea. Though I'll say we should be more wary of BCs in 1st party tooling along the way.

Many point back to 1.13, 2.4, etc but there's other hiccups like ember-babel and adoption of auto-import around the 3.21 release which feel like almost major BCs to teams.

Having a roughly annual major to target for paradigm shifts and what have been "minor" BCs actually surfaced to major releases.

@jelhan
Copy link
Contributor

jelhan commented Jul 12, 2022

Thanks a lot for writing this RFC. I think it's a good step forward.

A similar approach was discussed in #512 three years ago. The cadence picked in this RFC aligns very well what @runspired proposed at that time in #512 (comment). Adding here for context.

Not sure if intimate APIs are still a thing. If so, it might be good to call out explicitly if this RFC changes when they are removed after deprecation.

@mehulkar
Copy link
Contributor

What happens if there are no deprecations during the time period? Don’t know for sure, but I’m pretty sure minor releases have gone out without any new features for the sake of the schedule (which subverts ember’s commitment to SemVer, IMO).

My 2c: I think a scheduled cadence is more complicated and restrictive than it needs to be. This project has catered to apps that need the most stability for a long time, and I think it needs to swing in the other direction for some time!

That said, I know many people disagree with me on this, and I do think the proposed plan here has benefits. It is better than the alternative of doing nothing :)

@chriskrycho
Copy link
Contributor Author

chriskrycho commented Jul 12, 2022

@jelhan thanks for that link—I’d forgotten that cadences came up in that particular discussion!

Not sure if intimate APIs are still a thing. If so, it might be good to call out explicitly if this RFC changes when they are removed after deprecation.

They are indeed still a thing, though it rarely comes up. The reason I did not explicitly comment on it is that it does not change anything about that policy. In this design, they can still only be removed after an deprecation cycle that includes an LTS release between deprecation and removal. Given that, I'm going to let this comment stand as the record of that particular detail!


@mehulkar

What happens if there are no deprecations during the time period? Don’t know for sure, but I’m pretty sure minor releases have gone out without any new features for the sake of the schedule (which subverts ember’s commitment to SemVer, IMO).

This is a really interesting point. It's a fair point that we send a pretty weird signal when we cut a minor release with no features! In the early days of the framework, it was changing a lot, with new stuff all the time. That has naturally slowed down since then, but it might be worth revisiting… if it remains true!

To the thrust of the question, though: I think that's also fair… but I think we’re a long way from not having deprecations targeting a given major. On this proposed cycle, I expect it would likely be 7.0 before that could conceivably be the case, just thinking about what mown hopes are for deprecating Ember Classic and also thinking about the roadmap for e.g. a router replacement.

If we hit a point where we're no longer deprecating things and a major doesn't make sense, then we should revisit this in a similar way to how we should perhaps revisit the minors cadence!

I think a scheduled cadence is more complicated and restrictive than it needs to be.

While I definitely take your point, I think there are significant upsides to it when we are in periods of significant development—which we're headed into presently with the push toward Ember Polaris. The last couple years have been a lot quieter in no small part because of the impact of COVID on everyone's ability to ship things, plus a lot of community focus on Octane and then Embroider.

I think that it will also be particularly helpful for major releases and deprecations. Allowing us to target deprecations for later releases and know what that means is one of the big motivations for this proposal. As it is, "deprecate feature X targeting 6.0" likely implies to most Ember users that they can expect to use that feature through approximately 2028 (5½ years from now, given the average length of previous majors)—which is basically the same as not deprecating it, in practice. 😬

Had we had this policy in place during the 3.x era, we not only would have reached 4.0 much sooner (not itself valuable!) but would have been able to start rolling out targeted deprecations of classic features but aiming them for e.g. 5.0 or 6.0 knowing that that was a long-but-limited timeframe (which seems very valuable to me). As it was, even suggesting the deprecation of some features got a very strong negative response, because there hadn't yet been time to absorb the changes, and the community (rightly, I think!) has had no mental model for what it would mean to target a deprecation for a totally unknown amount of time but almost certainly 3–5 years out.

I think that gets at the sense you have of focusing on the maximal amount of stability. Putting a cadence in place lets us have a fairly controlled rate of change (assuming we use it wisely! 😅), while also providing good signal to the community to stop using something and start migrating to its replacement, and providing a known timeline on which they need to finish that work.

It is better than the alternative of doing nothing

💙

@simonihmig
Copy link
Contributor

simonihmig commented Jul 13, 2022

I am strongly in favor of this! I always wondered when a new major is going to come, and why it would take so long. I specifically agree with the RFC that this means that less upgrade work is piling up per major, i.e. it is not a renouncement of Ember's stability philosophy. In fact a little number of majors is in no way a proof of stability (I am not saying this is a message Ember has promoted), as each major could be very hard to overcome. Instead having easy upgrade paths for every major is what counts (e.g. good documentation, codemods etc.).

Somewhat related, but actually orthogonal to this RFC and probably requiring one of its own, I wonder if Ember's node support policy deserves to be revisited should this RFC be accepted? It was IMHO always a bit strange, as it allowed dropping support for node version without a major (which was not what any other Ember or non-Ember library or addon was doing). I guess the motivation was to not have to support node versions significantly beyond their EOL, with majors coming only so rarely. But with this RFC we would have to keep supporting them only for a maximum of 60 weeks, so maybe this doesn't justify this special SemVer rule anymore? 🤔

It would also wipe out the concern raised above that we could have no deprecation in a scheduled major (very very theoretical for the foreseeable time indeed).

@chriskrycho
Copy link
Contributor Author

I wonder if Ember's node support policy deserves to be revisited should this RFC be accepted? It was IMHO always a bit strange, as it allowed dropping support for node version without a major (which was not what any other Ember or non-Ember library or addon was doing). I guess the motivation was to not have to support node versions significantly beyond their EOL, with majors coming only so rarely. But with this RFC we would have to keep supporting them only for a maximum of 60 weeks, so maybe this doesn't justify this special SemVer rule anymore? 🤔

This is an interesting one. I think we could revise how we approach not only Node but also browsers and TS versions (which are currently specced, though we haven't shipped TS natively yet, to use a "rolling windows" policy exactly like our Node and browser policies) if we had a predictable major cadence. I wouldn't couple it to this change, but I think it'd be worth revisiting if we decide to go ahead with this proposal (or a variant of it).

@robbytx
Copy link

robbytx commented Jul 17, 2022

As a long-time (since 1.5) Ember user and fan, maintaining three production apps, one of which is still running successfully pre-Octane (3.12), I must say that this proposal concerns me that we should expect a new round of breaking changes roughly once per year.

I also must say I’ve greatly appreciated Ember’s “stability without stagnation” mantra, and I’m certainly not one to stand in the way of legitimate progress, as I’ve enjoyed the benefits of Octane, and I’m excited about the arrival of Embroider and TypeScript, and I understand that realizing those benefits ultimately require incurring the costs of breaking changes.

Still with more than two decades under my belt as a developer, I’m no longer one to live on the bleeding edge, and it’s often difficult to rationalize the cost of dependency upgrades for upgrade’s sake, when only a fraction of my development time is spent on front-end development. Therefore I foresee in this proposal that I am likely to fall behind the vanguard by multiple rounds of breaking changes, further complicating the complexity of catching up after the rest of the community has since moved on.

What’s more I fear the universe of community addons we depend on may suffer a similar fate from this proposal, as there becomes an annual tax on compatibility that our graciously moonlighting maintainers may choose to stop paying, leaving users of those addons in the lurch. Breaking changes can be hard enough to deal with on their own, but when there are suddenly three different major versions in as many years, then it can easily become impossible to find the right combination of Ember and addon versions that will actually play nice together, while you work or wait to get the lagging addons upgraded.

In many ways, this proposal seems to fit the mold of the day, where every piece of software we use and every library we develop against is forever introducing breaking changes that expect to keep their users on a constant upgrade treadmill for fear of getting stuck in the past. From my perspective, Ember has been different in this regard and a breath of fresh air - Yehuda’s keynotes emphasized the purpose of editions is to introduce and land new concepts gradually, and then enable the community to migrate all at once together so that no one is at risk of being left behind. It’s difficult for me to square that philosophy and intent with a fixed cadence of breaking changes, as the work to accomplish that intent takes time that we all know cannot be predicted consistently in advance, even if we have a dedicated full-time team working on it.

The tweet introducing this RFC said the goal is to “decrease the pressure on majors”, but to part-time users like me who “just want to keep shipping working software” that is exactly the opposite goal I want to see in one of my dependencies. My first and foremost goal is stability, so I can know that the software I’m dependent upon won’t leave me in a lurch down the road, when I inevitably need to upgrade on a short timeline to fix a security vulnerability. To that end, breaking changes should ideally be introduced and released purposefully only after enough effort has been expended to ease the transition for users.

Perhaps there are other plans unstated here that will alleviate my concerns about the annual cost of these major versions, but I doubt it will be possible to avoid the situation where various addons and apps stagnate on particular major versions. Within as little as 14 months, every Ember app and addon will find themselves two major versions behind, and having to deal with the perception that they are obsolete and that the cost of upgrading may be too great to undertake, especially when the same situation will certainly arise in another 14 months, and another 14 months after that, so long as this cadence continues. It’s not so much the actual cost of the breaking changes that is painful here, as the perceived futility of upgrading because you will never reach a state where you can rest in the satisfaction that there are no breaking changes in the foreseeable future.

I’ll close by recognizing that I am but one part-time user in the Ember community, certainly not one that has played any sort of active role in its development, yet benefiting from the work of those who have. You don’t owe me anything, and if those closest to the community feel this is a solid proposal, then I have no right to and will not stand in its way. I merely wanted to voice my concerns and perspective as a user on the periphery, who is simultaneously concerned that Ember will continue to lose mindshare and ultimately momentum in the greater JavaScript community. I firmly continue to believe that Ember is an incredibly powerful solution for building web applications in 2022, and I want to see it and the community succeed without losing people along the way.

@webark
Copy link

webark commented Jul 17, 2022

I agree @robbytx ! And thanks for your voice and viewpoint.

One caveat that I would say is, Ember tends to have "hidden" majors in its minors though, that have been historically challenging for addon developers, where they have to be pegged at minor versions. So I'd say some of those could have been better served as major upgrades, which would have brought us closer to the proposed cadence.

@DingoEatingFuzz
Copy link

This is neat! Hopefully it'll help core/addon maintainers shed gnarly conditionals and composite types more frequently.

At first glance I was concerned about how this would impact LTS releases, since it looked like they would almost always be a major version behind, but after color-coding the proposal it actually looks like an even split!

Spreadsheet of timeline

image

@simonihmig
Copy link
Contributor

Thanks for sharing your view here, @robbytx! But I'll try to counter your arguments here... 😅

I must say that this proposal concerns me that we should expect a new round of breaking changes roughly once per year

The RFC does not state anything about the rate of introducing breaking changes, or the severity of them. It just says that there will be a predictable cadence, with yes a shorter time frame, but this also means the chunk of required upgrade work is smaller, as I said earlier:

this means that less upgrade work is piling up per major,

So what makes tackling let's say 5 deprecations once a year any worse than tackling 15(!) deprecations every 3 years?

Yes, we shouldn't make users have to spent maintenance cycles at an unreasonable frequency. My team and me have been maintaining apps that were basically in some maintenance mode, with little new features added over time, and our team was not dedicated to just one or two apps, so we had to be efficient with how we spend our time on these kind of apps. Probably not much unlike the situation you are in. But I think spending time to upgrade once a year is very reasonable. I would actually recommend a more frequent schedule, like from LTS to LTS. Again, the upgrade work just piles up if you do it less frequently.

And if there are deprecations of really hard to refactor features (let's say the Ember object model is getting deprecated), as stated in the RFC there is now a way to say "hey, this thing is going to be removed not in the next major, but the one after it, so please stop using it for new code, but you still have time enough to refactor existing code as it won't be removed for quite some time". This wasn't really possible before.

when I inevitably need to upgrade on a short timeline to fix a security vulnerability

You seem to suggest that you can address problems quickly by jumping from the (older) version you are on (mentioned 3.12) to the latest minor version that includes some fix (that would now be 3.28 LTS). This is true in a perfect world, where SemVer works fully as intended, but I don't think that's the world we live in. There are addons using private APIs, "hidden" majors have been mentioned above (remember that double re-render assertion?), or you just run into some wild dependency hell. So I think it could be just as painful or even more so to upgrade from 3.0 to 3.28 as compared to a potential upgrade from e.g. 5.0 to 6.0 (under the new cadence).

Again, my recommendation is to do it regularly, in smaller, manageable chunks.

What’s more I fear the universe of community addons we depend on may suffer a similar fate from this proposal, as there becomes an annual tax on compatibility that our graciously moonlighting maintainers may choose to stop paying

As a maintainer of a good dozen or more addons, I can say that yes, maintenance does cost quite some time. Often you wonder where all that time went into, as you haven't really added any new features. This can come from a variety of sources, like updates to other dependencies and whatnot, but of course also from new deprecations. But either your tests are set up to fail on deprecations anyway, or users report them as if they were actual bugs. And so either you do maintenance regularly, to fix them way before a new major will actually drop them, or you don't, in which case your addon is likely to fall behind anyways. So I don't really see much extra burden coming from this RFC.

Final point: I think there is a balance to strike here between maintenance burden of app developers on the one side, and framework/library/addon authors on the other side. While keeping deprecated features alive for a long period of time makes it easy for app developers to delay their maintenance work, it also makes the author's (and new contributors!) work harder, as you have to still support that legacy code. So there is a sweet spot to find, and I think a period of >3y is just too much burden on the framework's side IMHO.

@chriskrycho
Copy link
Contributor Author

@robbytx thanks for this write-up. I think you probably speak for a lot of people in the Ember community with it, and I think you summarized the possible downsides well (and without dramatizing it over-much!). I think there are a couple pieces of it that are worth digging into, and I hope this response will help set your mind at ease about what I intend—but in any case I think your response will be a key part of our discussions as we dig into this as a team!

Rather than go point-by-point, I’m going to try to respond to what I take to be the major themes of your comment. (Please feel free to let me know if I’m wide of the mark on this!) The key concerns I read in your comment are:

  • that this will make for more churn and decrease stability
  • whether this will make getting security upgrades harder
  • how this affects ecosystem coordination and stability
  • the way it feels to have major changes come every 13–14 months

I think @simonihmig covered a lot of this really well already (esp. on security updates!), so I want to focus in on just two things: churn and how it feels.

Bonus notes on having an app on 3.12 and impact to security upgrades

To your point about having an app on 3.12 and pre-Octane: there is literally no difference between where that app is today and where it would be if we had the policy suggested here—

  • It is not on a supported version of Ember: it’s been out of even long term support for years now. What’s more, it is not even on the same major release as the current LTS!

  • There is a rather large list of deprecations you’ll need to fix to get to the current version (4.4 LTS or 4.5).

  • The addon ecosystem has already crossed at least one (and in many cases several) breaking change releases since 3.12—for Node compatibility, Ember Data compatibility, and Octane support—so you already have coordination challenges in your upgrades.

There is one significant difference: with this proposal, there would be two major releases instead of one for you get to get caught up. (You’d already have done one to make it to what was 3.12 from 3.8: it would have been 4.4 instead.) That’s a real difference… but it’s also not a huge difference.

Churn

We will not make more breaking changes with this proposal. Nor will we compromise on our commitment to only remove a feature once a replacement and migration path exist. Nor will we change how we think about Editions as the primary mechanic allowing us to land features when they are ready and to enable smooth migrations.

When I wrote “decrease the pressure on majors,” one possible reading is “Make it easier to make breaking changes.” That is not the intent. What I was actually thinking of was an analogy to our minor releases:

  • If you do one big feature release every few years, there’s always pressure to rush your feature in at the last minute—even if it’s not really ready yet—because the next opportunity won’t come for a long time. Having a predictable minor release train decreases the pressure for features: they can land when they’re ready.

  • If you do one big breaking change release every few years, there’s always pressure to rush your deprecation in at the last minute—even if that causes churn or is rushed—because the next opportunity won’t come for a long time. Having a predictable major release train decreases the pressure for deprecations: they can land when they’re ready.

Making that cadence be relatively short means there’s no sense that the framework is stuck maintaining something for an unpredictably long time just because someone missed a major release!

The actual intent here is to make just two (meaningful!) tweaks:

  1. Make it possible to know ahead of time when the changes will come. Right now, no one knows (even the Framework team) when the next major will be. That makes planning hard for everyone. Shifting to a cadence gets rid of that ambiguity, which is helpful for both maintainers and users of Ember.

  2. Decrease the number of breaking changes in any given major release. The question of how often we do a major release is totally orthogonal to the question of how many breaking changes happen in a given period of time. This way, the total amount of work over time is the same—but it’s spread out more evenly instead of coming all in one big chunk.

What’s more, having a cadence makes it easier to intentionally target deprecations for longer periods of time.

For example, imagine an RFC to deprecate Ember Classic. With this RFC in place, we would not target Ember v5.0 for most of those deprecations! We would mostly target v6.0 and in the case of a few APIs maybe even v7.0—giving the community a long, but finite and known, amount of time to migrate.1

How it feels

A big part of your comment seemed to me to be not just about the facts of the situation, but about how the situation feels:

It’s not so much the actual cost of the breaking changes that is painful here, as the perceived futility of upgrading because you will never reach a state where you can rest in the satisfaction that there are no breaking changes in the foreseeable future.

This gets at a very real experience people have—not only in the Ember community, not only in the JS community, but in software in general. Churn sucks. Having more major releases can contribute significantly to the feeling of churn, even if it doesn’t really change how much actual churn there is. So: that emotional response is valid and understandable!

Once we’ve acknowledged that emotion, though, I think it’s worth setting it aside—because, in the end, it’s not the whole story. This proposal represents a change, but one that I think will actually make for less churn rather than more, by improving how we use major versions as tools for communication and coordination.

In many ways, this is what the whole history of Ember’s approach to versioning has been about! We ship features when they’re ready in regular minor releases, on a predictable cadence. We have LTS releases so that people who need even more predictability and support can get that. We use Editions to bring those minor features all together coherently. We don’t do big splashy major releases; instead we reserve them for removing deprecated features. And with this proposal, we put those major releases on a predictable cadence, with fewer breaking changes in any given major.

Footnotes

  1. Spoilers: I’m working on exactly this, to be published in the next month or two. 😉

@joukevandermaas
Copy link

First, I think the Ember project deprecates things far too frequently for this to be a good idea. Just scrolling through the 3.x deprecations many of them are just removing some old code-path that is no longer idiomatic. A perfect example is the removal of application controller router properties. Why did this need to be deprecated? It just generates churn with no benefit.

Secondly the ecosystem clearly cannot keep up with the churn in the framework. Many addons are unmaintained or on autopilot. More frequent removals of APIs will just make this problem even worse. I know the community has taken over some of these but problem is still very real. This is a very big reason we are still on 3.x.

Third, the idea that churn is inevitable is simply not true, there are many platforms where churn is minimal and old code keeps working even over multiple decades (as an example, idiomatic code written in C# 1.0 in 2002 will still compile today). It is simply a matter of priority and resource allocation. Ember has promised over the years to be "stable", but this is not my experience.

I am really starting to doubt if we are the target audience for Ember. The framework seems to cater to either small apps that are easily kept up-to-date or massive apps that have an entire team dedicated to infrastructure. We are a small company with a mid-size (~50K LOC) app and don't have a dedicated team for front-end. Many on the team don't really understand front-end deeply and just want to occasionally contribute a feature. It feels like we are always 3 steps behind keeping up, while our much bigger (~1.5M LOC) C# codebase is very easy to keep up-to-date.

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Jul 19, 2022

@joukevandermaas I deeply feel your concerns, and experience them as well, I'm on a fairly large team where most folks don't know how to maintain apps. however every point you bring up is ubiquitous amongst all of frontend. It's way worse in other ecosystems as well (not all, but React is a fair bit worse of a ecosystem as far as togetherness (when comparing projects of similar size) -- libraries rarely even have test matricies) -- other ecosystems are too new (Svelte), and don't have complete stories around everything we take for granted (testing, being the main one right now)

C#, and every compiled lanugage really, doesn't have the burden of "payload" in browsers or "framework design". C# is much more focused as it's a language, whereas .net (and .net core), Do have frequent breaking changes that consumers do have to deal with.

@chriskrycho
Copy link
Contributor Author

chriskrycho commented Jul 19, 2022

@joukevandermaas I have a few thoughts, but first I want to reiterate something I've said over and over in this thread (as well as in the RFC itself): this proposal will not increase the number of deprecations made! 😅

Now, to some of the things you raised—

First, Ember absolutely wants to support teams like yours. I was on one for years, where we had two or three front-end developers total with a >100KLOC app, and we stayed up to date for years (and I know that that team, while a little larger now, has recently hit the point where that app is fully on Embroider with route splitting, and fully on TS including Glint!). I sympathize with people's desire not to have to change, but I also don't believe it's unrealistic for small teams with small apps to keep up. I can also say that in my current role, having an infra team doesn't make the effort disappear—to the contrary, migrating the whole Flagship app at LinkedIn to Octane was an enormous effort that involved hundreds of developers across a 2-year period. (But it was worth it!)

Second, the analogy to C♯ is misleading. Yes, C♯ 1.0 code still compiles. And JS code written in 2002 still runs, too! But .NET is a different story: even Microsoft no longer supports the frameworks from back then—not for security patches, and not for anything else. And while it definitely does have a longer support policy than Ember has had, it isn't forever, and it has definitely been the case that taking advantage of the latest and greatest features of .NET has required upgrading your code!

Third, Microsoft is famously (infamously?) on the far end of "never break backwards compatibility ever" side of things. They also employ dozens (hundreds?) of engineers to make that happen. We don't. The current count of people working full time on Ember is zero! Nor, when we compare to other web frameworks, do we have a particularly high rate of breaking changes—go look at React, Angular, Vue, etc., and you'll find that we are comparable or better on that front.

That means that we necessarily have to make different tradeoffs than they do. There are lots of things we want to do (and which the community wants us to do!):

  • We want to modernize Ember in ways that make it easier for new users to come onboard. That means introducing new ways of doing things sometimes, but there's a teaching cost to having multiple ways to doing things.

  • We want to make it easy (and indeed: easier!) for existing users to upgrade to new versions of the framework with the features it brings along. The easiest way would seem to be to never remove things, but maintaining multiple paths and interop between old and new is actually one of the biggest sources of bugs between releases, so having more to carry around can make the upgrade paths harder at times.

  • We want to make sure the framework has great performance characteristics so people can use it and indeed want to compared to the alternatives.

    • That includes updates to the rendering engine (Glimmer, Octane, etc.), which has an interop cost as well with legacy code.

    • It also means making the bundle smaller if we can… which involves shipping fewer features to end users; but to date we have not identified a path where we can have both clean interop with the legacy system and make it so users who don't use the legacy system don't pay for it. (It may be possible, but no one has had time to figure out whether it's doable, much less to get it done!)

    That second part is really important here when comparing to .NET and similar, too: by and large, you don't really care how big the runtime is for your server-side code. That is not true for web frameworks. Performance is very sensitive to bundle size!

  • We want to remain competitive with the rapidly evolving landscape around us. Ember is over a decade old. People have started frameworks in the last few years which have gotten to learn from multiple generations of iterations of frameworks, including Ember, and are doing remarkable new things. For us to remain compelling, we need to be able to deliver new capabilities as well… and that is harder to do when every new feature has to integrate with every old feature!

We cannot satisfy all of those perfectly. We're just aiming for a good spot in the tradeoff space which serves our existing users and new users. This very thread has a bunch of evidence now of people in the community who want both more change and less change! 😆

Myself, I think we should move somewhat faster than we do. Other folks on Framework think our pace of change is about right. Still others have indicated they think we’ve moved too fast. And there is variation across which parts of the framework are moving too fast/too slow/etc. Net, there isn't an obvious right pace or right approach here. Any point we pick on the curve will be dissatisfying to some group or another.


I think it would be much more helpful here to talk about how this proposal will make things better or worse on this front for your team, and in specific and concrete ways.

@chriskrycho
Copy link
Contributor Author

chriskrycho commented Jul 19, 2022

Ah, one other point: when you say that any given deprecation "generates churn with no benefit," I disagree very strongly.

I think what you're saying is: it generates churn with no apparent benefit to you as a developer. And that's a fair thing to feel! However, every deprecation we do has to have a justification—it has to have a benefit. That benefit might be in in a way that will take some time to pay off: the one you offer, for example, is part of a long, slow process of changing how we routing so that hopefully we will someday be able to fully finish revising it.

What's more, there is a cost that even you would pay for our keeping around that old code: it's extra maintenance work for Ember's maintainers, which means less feature or performance work from them, and more opportunities for bugs.

It's totally fair to disagree with a given deprecation. That's why we have RFCs for them, and your input is not only welcome but desired for those! But it's not accurate to say that there's no benefit there. 😄

@joukevandermaas
Copy link

@chriskrycho Thank you for the response. Let me first emphasize that I think the Ember core team has done a great job over the years. We've been using Ember since 1.12 and we're on 3.28 now so certainly a lot of versions have passed by 😄 I realize I sound a bit disgruntled but that's probably because I'm knee-deep in trying to get from 3.x to 4.x right now.. and it's a lot of work.

I have 4 main points:

  1. Fundamentally, the goal of the framework (IMO) should be to never deprecate anything. The goal should be that the APIs added are good and don't need to be changed. That's not reality of course, but it feels weird to expect enough deprecations to make a major version worth it every n versions. Personally I think the current pace of majors is fine. Each one has felt manageable (ish) yet worth doing.

  2. As written, the proposal does not say anything about the nr of deprecations. IMO it should at least say that the rate should be evaluated. As it stands, you can go 18 months or so without looking at deprecations if you must. That will no longer be true when this is merged. So although that is not the direct topic, it is certainly related and cannot be left out of the discussion.

  3. To be concrete about what this means for us: we'll have to be more diligent about keeping up. Totally reasonable to expect this, but it means fewer resources for feature work. Keep in mind that from the framework perspective, each major is a "reset" of sorts. Old stuff is removed, and we can move forward. But from our app team perspective, it's very much not. If you can't get onto one major for one reason or another, you are left behind forever. We are having this problem now with the 3.x series, where we heavily used some addons that are not making the transition (prime example is Ember Paper, which is too big for us to maintain it ourselves, and the community has more or less abandoned it).

    In practice it may not actually be a problem for the community at large, but it certainly feels like a struggle to keep up. Personally I am especially scared that Ember.Object and Ember.Component will be deprecated at some point, that will really be something 😄

  4. Ultimately I trust the core team on this, I have been a happy Ember user and I am still glad we chose it back in 2015. I sometimes feel that the RFC process encourages "big" changes (to make the hassle worth it) over small improvements, but ultimately I have always felt that feedback is taken seriously and the project has always moved in the right direction.

@chriskrycho
Copy link
Contributor Author

@joukevandermaas thanks for elaborating there! A couple more thoughts in response.

  • I'm knee-deep in trying to get from 3.x to 4.x right now.. and it's a lot of work.

  • Each one has felt manageable (ish) yet worth doing.

  • …we'll have to be more diligent about keeping up.

Here, I just want to reiterate that this proposal is designed to make those more manageable: to make the hump you have to get over smaller. My own team at work is also working on getting from 3.x to 4.x, so I sympathize. But it’s so big in part because we have years and years of deprecations piled up! It would have been much easier if we had had this proposal in place (just for Ember, not even including Ember Data):

  • 10 deprecations to tackle for a 4.0 which came after 3.8.
  • 14 deprecations to tackle for a 5.0 which came after what was actually 3.16 (in practice, a few of these would have been scheduled for a 6.0 or even a 7.0 release on this proposal!).
  • 2 deprecations to tackle for a 6.0 which came after what was actually 3.24.
  • 32 deprecations to tackle for a 7.0 which would have just landed instead of what was actually 4.4—around half of which were added after 3.24. Again, though, in practice a lot of those likely would have targeted an 8.0 release to give the community more transition time instead of "squeezing in" before the minor.

Even given how very many deprecations landed just before 4.0—32 deprecations! 😱—it would have been a much smaller lift if we had had this policy in place. Almost half the deprecations would have been taken care of years and years sooner, meaning it would have been easier for everyone to keep up.

I also think it extremely unlikely that we would have had 32 deprecations landing in the equivalent of the 3.25–3.27 period if we had had this policy in place. This is what I mean when I talk about the rush to get in a bunch of deprecations at the end of a cycle—it’s totally understandable, but it’s actually a huge pain for the community, and I want to diminish that!

As written, the proposal does not say anything about the nr of deprecations. IMO it should at least say that the rate should be evaluated.

I understand the sentiment, but we do not have a policy about the number of deprecations today. See previous section. 😉 Part of the trick here is that the number of deprecations is less important than what they are. We could have a hundred deprecations for features barely anybody uses, and it wouldn’t be a big deal… or we could deprecate Ember Component, and it would be a very big deal even though it's only a single deprecation! So figuring out what such a policy would look like or mean deserves tackling separately.

…it means fewer resources for feature work.

Your response here is totally understandable—“Ack! More majors means more work!”—but this is actually just not true of this proposal. It's the same amount of work, it's just distributed more smoothly over time instead of being incredibly spiky, and because it comes on a known cadence you can actually plan for it.

Fundamentally, the goal of the framework (IMO) should be to never deprecate anything. The goal should be that the APIs added are good and don't need to be changed.

I don’t quite agree with this. The goal should be to add APIs which don’t need to be changed, and indeed Ember generally aims for exactly that! We aren’t interested in change for change’s sake. We don’t want to deprecate things “just because” or even just because we can see a better way of doing things given our experience. That’s why we emphasize so strongly that deprecations must come with migration paths, and why we generally try to provide long migration timelines.

But what that misses is that there are at least three factors which undercut that:

  1. We learn things over time based on implementing and using the APIs we design.
  2. The environment in which we operate changes over time. The language changes, browser get new APIs, and other frameworks come up with good ideas.
  3. There are actual costs (teaching, maintenance and interop, bundle size) to keeping around old things.

You mentioned EmberObject, and I think that’s a perfect example of something we expect to deprecate, motivated entirely by concerns (2) and (3) there. It was a good design, and it was absolutely necessary for its time… but all the capabilities it gave us are now things provided natively by JavaScript itself.1 We aren’t going to deprecate it because it’s a bad design, or because we’re bored with it. We will deprecate it because it no longer pays its weight in terms of teaching, maintenance, and straight-up bundle size… and has a language-native alternative which is better in every single way along with a well-paved migration path.

Net, we all try to design APIs that won’t need deprecation, but there are reasons besides “we designed it wrong” to deprecate things… and sometimes we did design it wrong (or at least: found a way to design it much better).

The key is finding a balance where we don’t overwhelm our users with churn, always provide good migration paths, and make sure that the result is a substantial net positive.

Footnotes

  1. Now that Decorators are finally stage 3! 😅

@wagenet
Copy link
Member

wagenet commented Jul 25, 2022

I think one concern that hasn't been fully addressed is the fear that addons might be more aggressive about dropping support for any Ember majors other than the most recent. I believe this a potential risk, but my hope is that addons would only drop majors when it's necessary for them. With this policy, I suspect we'll find addons not rushing to drop majors as quickly because the deltas between majors will be smaller.

@NullVoxPopuli
Copy link
Contributor

that's fair, but I don't think that's too different from addons only supporting the last 4 or fewer LTSes today (which is commonish)

@wagenet
Copy link
Member

wagenet commented Jul 25, 2022

To be clear, I'm not actually that concerned about addons dropping majors too quickly, but in the interest of alleviating fears we may want to specifically address it.

@simonihmig
Copy link
Contributor

With regards to addons, I think there is indeed one thing that is important: that addons should not only support one major version, or at least there is a version of the addon that supports the previous and the next major. So an app that is say on 4.8 can first upgrade all addons - which now hopefully support both 4.8 and 5.0 - and then upgrade Ember from 4.8 to 5.0, in two separate and independent steps. If addons would support only either 4.x or 5.x (i.e. they fix things for 5.0 and at the same time are too eager to drop 4.x support), then users would be forced to upgrade both Ember and addons in one big step, which is bad IMO.

@runspired
Copy link
Contributor

runspired commented Jul 25, 2022

@simonihmig I'd disagree on that and would go the other direction. My experience with ember-data has taught me that even supporting just the last two LTS releases is often a huge burden. Enough of one we've become stuck, and our path forward is to cut our own major that drops support for all but latest ember with a narrowed subset of ember APIs supported (e.g. we're going stricter on what you can use than even Ember does). If addons are going to have a uniform policy (and I do encourage them to have a policy) then I think they should support current LTS + current release at time of addon version being released. One could make the argument it's a major each time the LTS changes and I wouldn't be opposed to it, I'm probably going to head that direction with the data team.

edit I think I missed the main point which is that addons shouldn't be dropping support for one major while adding support for another all in one release. I agree with that, and the ideas I presented above would also largely ensure that.

@wagenet
Copy link
Member

wagenet commented Jul 30, 2022

It’s also important to note that #832 is likely to spread deprecations across multiple major releases.

@webark
Copy link

webark commented Jul 30, 2022

Second, there was strong agreement that we need to make sure we do keep the pace of breaking changes manageable.

So it hasn't been stated whether or not "Ember Classic" would be deprecated in 4 or 5, but if it is in 4, that leaves a MUCH shorter timeframe for anyone who was maybe hasn't migrated to 4 yet, you are basically at that point almost going to have to do a complete rewrite.

I understand the value of both these RFCs, they just make statements like the one above "feel" disingenuous, even though I know that is not the case.

This might just be me, but wanted to highlight what these two in parallel could feel to some in the community. Maybe as more details on the timeline of #832 emerge it will make more sense.

@webark
Copy link

webark commented Jul 30, 2022

It’s also important to note that #832 is likely to spread deprecations across multiple major releases.

That is good to hear. Thank you for stating that. If they are split up and staggered this new cadence will prove valuable churning though that change. 👍

@wagenet
Copy link
Member

wagenet commented Jul 30, 2022

@webark keeping things manageable is very much a key goal for the core team. Obviously, we can’t say there will be no work, but as @NullVoxPopuli pointed out, Octane Classic is going to have to be deprecated at some point. @chriskrycho and myself are both acutely aware of the pain here since we work on large Ember apps that are still working on getting to 4.0, much less entirely to Octane conventions!

i also think the Octane changes were an especially difficult bunch since they involved aligning Ember with newer JavaScript features. I can’t promise no future challenging changes, but I am hopeful we won’t see anything quite as tough as the Octane conversion can be. (I should be clear that I think the Octane changes were definitely the right way to go, but they can be tough changes to make!)

@chriskrycho
Copy link
Contributor Author

I think you mean #832? Here’s the thing: I’m writing that RFC no matter what. The key is knowing when it comes and how the deprecations are distributed. Also worth noting (as I’ll cover in much more detail in that RFC) that the transition period for features there has already been almost three years in most cases and will ultimately probably be 5+ when all is said and done. 😊

@chriskrycho
Copy link
Contributor Author

Heh, that comment came through on a delay and the others came in between. The Classic deprecations will almost certainly be targeting a mix of 6.0 and 7.0, though (with possibly a very short list of exceptions, but we won’t rush anything in).

@webark
Copy link

webark commented Jul 30, 2022

Yea. I think that the marring of the two, (set predictive cadence) and the goal to move through a large body of legacy conventions pairs very nicely together. With that plan laid out it will allow teams to target that smaller subset, but know the next subset is going to come a year or so ahead, and be able to plan accordingly. So i'm all on board.

I just initially read that as "we are wanting to get this list of deprecations in before we hit 5 so we can remove them for 6 and Polaris" and responded too quickly. Thank you for the clarification and all the hard work you do.

@chriskrycho
Copy link
Contributor Author

Glad we could clarify. And yeah, it’s actually the opposite of wanting to rush it in before a relatively soon v5! I’m waiting to have this one locked down so we can target later versions and have people know what that actually means!

- drop the extra long upgrade cycle
- set final introduction of deprecations to M.10
- use `M.` instead of `X.` for 'Major'
@chriskrycho
Copy link
Contributor Author

Thanks everyone for continued contributions. After a few more rounds of discussion in Framework Core, we've decided to make two tweaks to the proposal here:

  1. We will do 12 minor releases, not 8.
  2. We will target the M.10 release as the final release including deprecations targeting the next major.

The result is an 18-month cycle, with major releases expected in May and November. We may revisit this in the future after seeing how it goes, but this is the path that gave the broadest group the highest confidence. I expect we'll probably move this to FCP at this next week's Framework Core team meeting.

For comparison, the timeline in the original proposal:

Ember Release Release date LTS date
4.8 October 2022 November 2022
5.0 January 2023
5.4 June 2023 August 2023
5.8 December 2023 January 2024
6.0 March 2024
6.4 August 2024 September 2024
6.8 February 2025 March 2025
7.0 April 2025

And the timeline with this update:

Ember Release Release date LTS date
4.8 October 2022 November 2022
4.12 April 2023 May 2023
5.0 May 2023
5.4 October 2023 December 2023
5.8 April 2024 May 2024
5.12 September 2024 November 2024
6.0 November 2024
6.4 April 2025 May 2024
6.8 October 2025 November 2025
6.12 March 2026 May 2026
7.0 May 2026

@chriskrycho chriskrycho force-pushed the evolving-majors branch 2 times, most recently from af714cc to 8fa22f9 Compare August 15, 2022 15:59
@jenweber
Copy link
Contributor

The Learning Team has reviewed these changes to identify any additional work that comes from changing the release cadence, and request the addition of one requirement to the RFC. The main concern we have is that writing more blog posts a lot of additional effort, if nothing else changed about our process besides release cadence. For success, we need commitment from all teams (and individual implementers/subject matter experts) to put all necessary user-facing details for releases into changelogs. Subject matter experts can provide context and motivation information that our users will benefit greatly from. They help translate from code to user-facing features.

The learning team has historically helped draft and ship the blog post, however it is a joint responsibility of all teams. It's not sustainable for volunteers to do investigative research into all bugs, deprecations, and features at a faster cadence, added to the fixed overhead of running a new release. Writing the blog post is the most time consuming step.

@chriskrycho
Copy link
Contributor Author

chriskrycho commented Aug 15, 2022

@jenweber very much noted, but: as it stands this will not require any change in cadence to increase the number of blog posts. Only major version releases will happen more often.

@jenweber
Copy link
Contributor

Understood, thank you!

@robbytx
Copy link

robbytx commented Aug 16, 2022

@chriskrycho thank you (and others) for listening and responding to feedback. This was my first comment on an Ember RFC, and even though there were strong opinions expressed, I found it to be a very positive experience, and I'm comfortable with the outcome.

@chriskrycho
Copy link
Contributor Author

@robbytx thanks for that comment—getting serious feedback is why we do this process, so I’m really glad that (a) you felt heard and (b) you feel comfortable with the outcome. That’s extremely validating for us!


@kategengler reminded me that we have discussed some changes to the mechanics of how we ship a major version that will make it easier to do on a cadence. See this newly added section which discusses that. It’s intentionally “non-normative” in the sense that we are not required to use exactly these mechanics to accomplish the goals, but we currently think this is the best way to make it easy to ship majors on a schedule.

TL;DR: make deprecations become hard errors automatically (and make sure our test infrastructure and the process of adding deprecations works correctly with this!) so that the cleanup can happen more or less “whenever” rather than having to happen in a rush before the release.

@chriskrycho
Copy link
Contributor Author

The Framework team talked about this last Friday and everyone is on board, so it is now going into Final Comment Period to merge!

@chriskrycho
Copy link
Contributor Author

This RFC has been in FCP for over a week now and we all agreed that it's ready to go at the most recent Framework Core team meetings, so: merging it! 🎉

@NullVoxPopuli
Copy link
Contributor

do typescript types have a schedule? how do those versions align with ember's major version?
if I'm reading #730 correctly, an ember-source major cannot drop a minor version of TS without declaring a major version change (which means TS versions may not be dropped outside of major version schedule described in this PR?)

@chriskrycho
Copy link
Contributor Author

I’m on vacation so will keep this super brief but will also try to provide some more detail in a few weeks when I’m back:

No. Per #800, Ember proper is using the Rolling Windows policy for TS, basically treating it the same as it does Node and browser support. The key is that LTS versions must always have overlapping TS version support. (I covered this in detail in my EmberConf 2022 talk, FWIW.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.