www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Improving deprecation management

reply "Dicebot" <public dicebot.lv> writes:
There is one thing that seems really inconvenient to me but I'd 
like to see community opinion before writing a DIP :) It is all 
about current semantics of "deprecated" attribute.

Right now using deprecated symbols is a warning. And if you use 
"-w" switch (like most pedantic projects do) it is an error that 
halts the compilation. It is possible to use "-d" to avoid 
breaking stuff but then it will just work silently, with no 
message at all.

In practice, I tend to always apply the following deprecation 
path:

1) Modify the code to print message about upcoming deprecation 
(via pragma(msg))
2) On previously defined date mark symbol as deprecated and 
define expected removal date
3) Remove it completely

It is very inconvenient to do manually but necessary to make 
deprecation process smooth - initially I just want to make users 
aware that some time should be scheduled to adjust their code in 
future, without any interfering with normal compilation. Then do 
actual deprecation that will result in an error but still provide 
meaningful message about changes that need to be made. And only 
after that removal is viable.

I'd really love to be able to provide date/time parameter in some 
way to deprecate attribute and let compiler do all this routine 
for me automatically - just print message (not a warning) if 
compiled before the date, act as it does now after.

So far I have not found see any way to define a good deprecation 
path with an existing toolset.

Opinions / recommendations?
Nov 13 2013
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, November 13, 2013 18:19:49 Dicebot wrote:
 There is one thing that seems really inconvenient to me but I'd
 like to see community opinion before writing a DIP :) It is all
 about current semantics of "deprecated" attribute.
 
 Right now using deprecated symbols is a warning. And if you use
 "-w" switch (like most pedantic projects do) it is an error that
 halts the compilation. It is possible to use "-d" to avoid
 breaking stuff but then it will just work silently, with no
 message at all.
 
 In practice, I tend to always apply the following deprecation
 path:
 
 1) Modify the code to print message about upcoming deprecation
 (via pragma(msg))
 2) On previously defined date mark symbol as deprecated and
 define expected removal date
 3) Remove it completely
 
 It is very inconvenient to do manually but necessary to make
 deprecation process smooth - initially I just want to make users
 aware that some time should be scheduled to adjust their code in
 future, without any interfering with normal compilation. Then do
 actual deprecation that will result in an error but still provide
 meaningful message about changes that need to be made. And only
 after that removal is viable.
 
 I'd really love to be able to provide date/time parameter in some
 way to deprecate attribute and let compiler do all this routine
 for me automatically - just print message (not a warning) if
 compiled before the date, act as it does now after.
That would actually be a _big_ problem for code maintainability. The same compiler binary _must_ be able to compile exactly the same set of programs no matter when it's used. I should be able to compile exactly the same set of programs with a particular compiler binary ten years from now as I can today. Anything else will be a huge problem for real world environments that use the same compiler for years at a time. It's not always an option to update the code or the compiler, and even if it is and even if you do update the code and the compiler, you need to be able to reproduce old builds, and that won't work if deprecated symbols suddenly stop working just because the date changed. I can understand why such a feature would be desirable from the perspective of the one who has to put the symbol through the various stages of the deprecation process, but it's ultimately a bad idea (and this is coming from the fellow who is generally the one to make sure that deprecated stuff goes through the full deprecation process in Phobos once it's been deprecated).
 So far I have not found see any way to define a good deprecation
 path with an existing toolset.
 
 Opinions / recommendations?
We ended up with what we have, because it's simple and works, and Walter doesn't like the idea of having deprecated become complicated. Lots of ways to improve it have been discussed in the past, and it was agreed to make it to so that you could add a message to deprecated. Anything more complicated was rejeceted. The only other big change was to make it so that deprecation warnings were warnings rather than errors, which makes it possible to deprecate stuff without breaking code, whereas before, it was guranteed to break code. And -w does _not_ turn deprecation warnings into errors (and I just confirmed that with a simple test program). So, while I'm actually inclined to think that -w should be gotten rid of anyway (since it changes the behavior of code), it doesn't actually cause any problems with deprecated symbols. I very much doubt that you will get Walter to agree to anything more complicated than what we currently have. And while more complicated deprecation features might be nice, I really don't think that we need them. At this point I'm inclined to think that the deprecation process should be as simple as 1. Mark symbol as deprecated with a message indicating what the programmer should use instead (preferrably with the documentation giving some indication as to when the symbol will be fully removed). e.g. deprecated("Use bar insead.") void foo() {} 2. Remove the symbol. Nothing else is really required. If you're being more paranoid (as we tend to be with the standard library), then the process can be made slightly longer to give people more time to change their code without leaving the deprecated symbol in the documentation for people to continue to try and write new code with. 1. Mark symbol as deprecated. 2. Remove the symbol's documentation. 3. Remove the symbol. Regardless, I don't think that we really need to add any more features to deprecated at this point. It works fine as-is. - Jonathan M Davis
Nov 13 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 13 November 2013 at 19:02:22 UTC, Jonathan M Davis 
wrote:
 That would actually be a _big_ problem for code 
 maintainability. The same
 compiler binary _must_ be able to compile exactly the same set 
 of programs no
 matter when it's used. I should be able to compile exactly the 
 same set of
 programs with a particular compiler binary ten years from now 
 as I can today.
 Anything else will be a huge problem for real world 
 environments that use the
 same compiler for years at a time. It's not always an option to 
 update the
 code or the compiler, and even if it is and even if you do 
 update the code and
 the compiler, you need to be able to reproduce old builds, and 
 that won't work
 if deprecated symbols suddenly stop working just because the 
 date changed.
What about connecting it to date of compiler release? That will fix the issue and does not change much for the original proposal.
 And -w does _not_ turn deprecation warnings into errors (and I
just confirmed that with a simple test program). I did not know that. That helps process a bit but makes existing situation even more of a mess then. One shouldn't call a warning what is not a warning. My problem with existing feature set is that it has created a whole damn zoo of compiler flags (which is bad on its own) without addressing one of key deprecation properties - in the very same application using one stuff may be an error and other just an informational message. It is not something that can be decided application-wise.
Nov 13 2013
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, November 13, 2013 20:13:43 Dicebot wrote:
 On Wednesday, 13 November 2013 at 19:02:22 UTC, Jonathan M Davis
 
 wrote:
 That would actually be a _big_ problem for code
 maintainability. The same
 compiler binary _must_ be able to compile exactly the same set
 of programs no
 matter when it's used. I should be able to compile exactly the
 same set of
 programs with a particular compiler binary ten years from now
 as I can today.
 Anything else will be a huge problem for real world
 environments that use the
 same compiler for years at a time. It's not always an option to
 update the
 code or the compiler, and even if it is and even if you do
 update the code and
 the compiler, you need to be able to reproduce old builds, and
 that won't work
 if deprecated symbols suddenly stop working just because the
 date changed.
What about connecting it to date of compiler release? That will fix the issue and does not change much for the original proposal.
Not necessarily a bad idea, but again, Walter isn't going to go for complicating deprecated any further (we're arguably lucky to have what we've got), and given that you need to take the time to go and remove the deprecated symbol manually anyway, I don't think that it would really save you anything. With the current scheme, you can simply mark the symbol as deprecated and then remove it manually at some later date without having to do any other manual steps in between (unless you want to have the symbol undocumented but still there for some period of time, which adds one manual step). And since you really shouldn't be deprecating stuff all that frequently anyway, I don't think that a little extra work matters all that much.
 And -w does _not_ turn deprecation warnings into errors (and I
just confirmed that with a simple test program). I did not know that. That helps process a bit but makes existing situation even more of a mess then. One shouldn't call a warning what is not a warning.
You can consider it a "deprecation warning" rather than a "warning." It's not like we have extra terms to throw around that we can use for these things, and having deprecation warnings affected by -w would essentially defeat the purpose of making them warnings instead of errors in the first place. And without that, deprecating anything breaks code immediately, which for something like the standard library tends to mean that you can't deprecate anything.
 My problem with existing feature set is that it has created a
 whole damn zoo of compiler flags (which is bad on its own)
 without addressing one of key deprecation properties - in the
 very same application using one stuff may be an error and other
 just an informational message. It is not something that can be
 decided application-wise.
As compilers go, dmd has _very_ few flags. So, we're actually pretty well off in that regard. If it were up to folks like Bearophile, we'd probably have blizzard of flags for controlling what the compiler does and doesn't warn about. Walter tends to insist on flags being truly useful. It's just a shame that he gave in and added warnings to the compiler. With regards to warnings and deprecation, we only have -wi, -w, and -d, so it's not like there are very many you have to worry about. Now, -wi should arguably be the default (which would remove a flag), and -w should definitely die IMHO, because it changes what's considered valid code - not just for the warning itself but because it affects what's considerd valid code for introspection, which can change what code gets compiled in generic code, which isn't good. And -d isn't anywhere near as useful as it used to be, since deprecation is a warning instead of an error, and it's arguably bad to make deprecation warnings go away, so arguably, -d should be removed as well (though I wouldn't expect it to be). So, ideally, we'd get rid of -wi, -w, and -d, which would fix the flag proliferation in this case, but we're probably stuck with all of them given Walter's attitude on the matter (though maybe we could talk Walter into making -w act like -wi, making it redundant). However, since -wi is really the only one that makes sense to use, you can just use -wi and not worry about the others, even if we're stuck with them being in the compiler. So, while the flag situation with regards to warnings isn't ideal, I don't think that it's all that big a problem either. - Jonathan M Davis
Nov 13 2013
prev sibling parent Jeremy Powers <jpowers wyrdtech.com> writes:
On Wed, Nov 13, 2013 at 11:13 AM, Dicebot <public dicebot.lv> wrote:

 What about connecting it to date of ....
Using a date is the wrong approach for deprecation. When you are deprecating something, you are stating that in a future release it will no longer work - it just happens that releases usually arrive at a point in time. Tying it to a date implies every user will pick up the new version exactly when it is released... which only happens when you have zero users. If you want stuff depending on deprecated functionality to break at a certain point, you should approach it from a version management standpoint. With the existing deprecation annotation, you can tag with versions to help. Your step #2 should be 'removal version' rather than 'removal date' - and then perhaps tie in with dependency management versions or some such.
Nov 13 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-11-13 18:19, Dicebot wrote:
 There is one thing that seems really inconvenient to me but I'd like to
 see community opinion before writing a DIP :) It is all about current
 semantics of "deprecated" attribute.

 Right now using deprecated symbols is a warning. And if you use "-w"
 switch (like most pedantic projects do) it is an error that halts the
 compilation. It is possible to use "-d" to avoid breaking stuff but then
 it will just work silently, with no message at all.

 In practice, I tend to always apply the following deprecation path:

 1) Modify the code to print message about upcoming deprecation (via
 pragma(msg))
 2) On previously defined date mark symbol as deprecated and define
 expected removal date
 3) Remove it completely

 It is very inconvenient to do manually but necessary to make deprecation
 process smooth - initially I just want to make users aware that some
 time should be scheduled to adjust their code in future, without any
 interfering with normal compilation. Then do actual deprecation that
 will result in an error but still provide meaningful message about
 changes that need to be made. And only after that removal is viable.

 I'd really love to be able to provide date/time parameter in some way to
 deprecate attribute and let compiler do all this routine for me
 automatically - just print message (not a warning) if compiled before
 the date, act as it does now after.

 So far I have not found see any way to define a good deprecation path
 with an existing toolset.

 Opinions / recommendations?
AST macros :) -- /Jacob Carlborg
Nov 13 2013