The Context Passing Problem

I think there's an important part of this discussion being missed that I want to highlight, because I feel like it's not being heard clearly. When @mordil says that he's concerned about adding a parameter to 200+ methods, and when I say that a sufficient case has not yet been made for API stability breakage on AHC, your response so far has been of the form:

I think you have not meaningfully tackled the objection being raised. So let me try to clarify it a bit in the hope that you'll more clearly address it.

Firstly, the common ground: I agree with you that optional context is not a good design. I agree that it's too easy to fail to propagate the context in the case where the parameter is defaulted. Users should be encouraged to make choices in order to improve the ability of developers to audit the code and understand the context passing requirements. I personally am convinced that the right design is to add context, non-defaulted, to all relevant invocation methods.

Where we disagree is that I don't think anything I just said in the above paragraph is sufficient to justify the addition of "and therefore we must break the API". Let me bring in another principle of mine: as a general rule, the less frequently you can break your APIs, the better. API breaks are occasionally necessary to clear away cruft and to embrace new features more fully, but the more users you have the more painful each break gets. The result of this is that there is positive value in preserving your major version number where you can, and cost in revving it. This doesn't mean we shouldn't break API, but it does mean that a strong, affirmative case has to be made that doing so is important and right.

For AHC, I am extremely confident that such a case hasn't been made. This is because for AHC we can much more effectively do a "deprecate-and-replace" dance. In this case, we'd keep the old code around, but deprecate it in favour of the new one that passes a concrete context type. These warnings will discourage new code from using the old API, and will also positively encourage newer users to adopt the preferred API, but will continue to allow users to have access to those older APIs. This opens the door to those users remaining supported, getting security fixes and performance improvements, and whatever else, without forcing them into a churn cycle or causing dependency hell in the dependency graph.

For RediStack, things are a bit trickier. As @mordil has noted, RediStack requires substantial work to add new parameters. I still think on balance that RediStack should consider adopting a deprecate-and-replace dance for this change, but it may be worth considering whether an alternative approach for RediStack is worth it to avoid revving to 2.0.

All of this context work is really important, and I'm glad the community is tackling it. I just want to be counselling caution on revving major version numbers where we don't have to.

2 Likes