Hi Tim,
On 12/21/2015 08:09 AM, Tim Graham wrote:
> I'd like to ask for opinions about whether or not deprecations are more
> useful than making small backwards incompatible changes when they move
> Django in a direction toward unhiding probable developer error.
>
> An example from a past release is the validation of fields in
> select_related() [1]. This was done as a backwards-incompatible change
> in 1.8: invalid fields immediately raised an error. Would you rather a
> change like that go through the normal deprecation cycle (pending
> deprecation, deprecation, error)? My reasoning against it is that it
> continues to hide probable errors in new and old code (especially in the
> first release since PendingDeprecationWarning isn't loud by default) and
> the cost for users of fixing existing code is likely low compared to the
> overhead of a deprecation cycle in Django. Did anyone find this was not
> the case in their own projects?
>
> The question came up again with the behavior of the default error views
> silencing TemplateDoesNotExist when a custom template name is specified [2].
Obviously the first question is whether the behavior in question is
documented. If it is, then a deprecation path is definitely required. On
the other hand, if the current behavior contradicts the documentation,
then it's a bug and can just be fixed.
But the two examples you cite have an edge case with behavior that is
unspecified in the documentation. The next question I would ask in those
cases is "Can I imagine a scenario in which someone is intentionally
taking advantage of the current behavior - it's not just hiding an error
in their code? How likely is that scenario? How reasonable is their use
case? And if we conclude that there may be people out there with a
reasonable use case for the current behavior, how hard would it be for
them to change their code to continue working as-is, if Django's
behavior is changed?"
So to take the TemplateDoesNotExist case with the built-in error views:
The one scenario I can imagine is that someone has written their own set
of reusable error views wrapping the default ones with a different
default template naming convention, but they still want to use their
custom reusable error views in projects that may or may not choose to
actually provide the custom error templates.
I think this use case is reasonable and the scenario is possible, but
I'll concede that it may be unlikely. But if someone were doing this, I
would consider it a perfectly reasonable use of the existing API
contract ("nonexistent templates fall back to the default error view
content"), not abuse of a bug.
To adapt their code to the new behavior, they would need to add a
try/except for TemplateDoesNotExist in their wrappers. Not totally
trivial (and might require them to write some new tests), but not
unreasonable.
So for me, this case falls in a murky area. I tend to think it's better
for us to err on the side of being more backwards-compatible when the
current behavior isn't clearly a bug, and someone might be reasonably
relying on it. But I concede that it's in a grey area, and wouldn't
stand in the way of a decision to just treat it as a bugfix.
In cases where we really can't construct any realistic scenario for
intentional use of the current behavior, then I think we just make the
change right away and call it a bug fix. I don't think it's a bad thing
to cause code that was previously silently broken to start breaking loudly.
I think `select_related` with invalid field names is closer to this end
of the spectrum. I _can_ construct a scenario for intentional use of
that, but it's very unlikely and feels much more like abuse of a buggy
API. So if I did earlier suggest that the select_related change should
have gone through a deprecation path, I hereby retract that suggestion :-)
Carl