Delphi 5:模拟“过时”或“弃用”方法的想法?

时间:2009-01-12 20:28:19

标签: delphi deprecated

我想将方法​​标记为过时,但Delphi 5没有这样的功能。

为了举例,这里有一个虚构的方法,它已被弃用,并且是新的首选形式:

procedure TStormPeaksQuest.BlowHodirsHorn; overload; //obsolete
procedure TStormPeaksQuest.BlowHodirsHorn(UseProtection: Boolean); overload;

注意:对于这个假设的例子,我们假设使用无参数版本是非常糟糕的。没有“使用保护”的问题 - 没有好的解决方案。没有人喜欢使用保护,但没有人愿意使用保护。所以我们让调用者在blowing Hodir's horn时决定是否要使用保护。如果我们默认无参数版本使用保护继续

procedure TStormPeaksQuest.BlowHodirsHorn;
begin
    BlowHodirsHorn(False); //No protection. Bad!
end;
然后开发人员面临各种令人讨厌的东西的风险。如果我们强制无参数版本使用保护:

procedure TStormPeaksQuest.BlowHodirsHorn;
begin
    BlowHodirsHorn(True); //Use protection; crash if there isn't any
end;
如果开发人员没有得到任何保护,或者没有任何保护,那么就有可能出现问题。

现在我可以重命名过时的方法:

procedure TStormPeaksQuest.BlowHodirsHorn_Deprecatedd; overload; //obsolete
procedure TStormPeaksQuest.BlowHodirsHorn(UseProtection: Boolean); overload;

但这会导致编译错误,人们会嘲笑我(我真的不想听到他们的抱怨)。我希望他们得到 nag ,而不是实际错误。

我想添加一个断言:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   Assert(false, 'TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)');

   ...
end;

但我不能保证开发人员不会在没有断言的情况下发布版本,导致客户出现严重崩溃。

如果开发人员正在调试,我想过只使用一个断言:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   if DebugHook > 0 then
      Assert(false, 'TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)');

   ...
end;

但我真的不想导致崩溃。

我想过显示一个MessageDlg,如果它们在调试器中(这是我过去所做的一种技术):

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   if DebugHook > 0 then
        MessageDlg('TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)', mtWarning, [mbOk], 0);

   ...
end;

但这仍然太具有破坏性。并且它导致代码在显示模式对话框时遇到问题,但对话框显然不明显。

我希望有一些警告信息可以让他们唠叨 - 直到他们掏出他们的眼睛并最终改变他们的代码。

我想也许我添加了一个未使用的变量:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
var
   ThisMethodIsObsolete: Boolean;
begin
   ...
end;

我希望只有在有人引用代码时才会引起提示。但即使您没有调用实际使用过时的方法,Delphi也会显示提示。

有人能想到别的吗?

7 个答案:

答案 0 :(得分:5)

这样的东西
procedure TStormPeaksQuest.BlowHaldirsHorn; //obsolete
begin
  if DebugHook > 0 then asm int 3 end;  
  // This method is Obsolete!  Use XXXXX instead.
  Abort; // Optional, makes method useless  
  // old code here . . . 
end;

断言与表演之间的妥协。开发人员只需要按F9继续。您可以放入Abort,然后该方法将不执行任何操作,这将迫使他们切换方法,并且中断使他们意识到它。

就个人而言,我建议升级到较新版本的Delphi。 2007年和2009年是很棒的版本,非常值得升级。

答案 1 :(得分:4)

我最终使用的是选择加入系统的组合,其中您同意不使用任何已弃用的代码,否则输出调试字符串和断点。

strict html一样,我创建了Strict定义。

如果定义了Strict,则所有常用单位都会定义过时的代码。这样开发人员就会同意他们不会在项目中弃用代码:

{$IFNDEF Strict}
procedure TStormPeaksQuest.BlowHaldirsHorn; overload; //obsolete
{$ENDIF}
procedure TStormPeaksQuest.BlowHaldirsHorn(UseProtection: Boolean); {$IFNDEF Strict}overload;{$ENDIF}


{$IFNDEF Strict}
procedure TStormPeaksQuest.BlowHaldirsHorn; //obsolete
begin
   OutputDebugString(PAnsiChar('TStormPeaksQuest.BlowHaldirsHorn is deprecated. Use BlowHaldirsHorn(Boolean)'));

   //Don't debugbreak without a debugger attached!
   if DebugHook > 0 then
        Windows.DebugBreak;

   ...
end;

因此,如果开发人员希望拥有适当的代码,在新事物被弃用时不得不执行代码更改,他们可以:

{$DEFINE Strict}

如果没有,那么总是是一个OutputDebugString,而Debug View的任何人都可以看到(甚至是客户)。看到带有输出调试字符串的商业软件(甚至微软)很有趣。

最后,如果附加了一个调试器,那么它们将无处获得调试断点。如果有人问起,我可以借此机会取笑他们。

答案 2 :(得分:2)

这并不能完全回答您的问题,但它可能会提供另一种解决方案。你能不能用默认值更新原始功能......

procedure TStormPeaksQuest.BlowHaldirsHorn(UseProtection: Boolean = False);

...因此遗留代码编译和行为相同,但新功能可供新开发人员使用。

答案 3 :(得分:0)

为什么要这样做?为什么不想升级Delphi版本?

如果没有弃用的标记,您实际上没有干净的选项来过滤使用不推荐的方法。所以这取决于你想要让步的地方:

  • 重命名在编译时捕获错误(除非在范围内有另一个具有相同名称的方法/函数)。
  • 所有其他方法仅在运行时捕获。这有可能会进入生产代码。

您可以做的是创建一个已弃用的日志。这不会让任何人感到沮丧,如果它输入生产代码,那就不是彻底的灾难。但是如果你的测试有完整的覆盖范围,那么你将会抓住所有的罪魁祸首。您只需在(测试)运行后检查日志文件。

当然最好的方法是使用grep查找代码的所有出现并更改它。

答案 4 :(得分:0)

我同意一个可选参数,如果它能完成这项工作的话。但我可以想到情况是可选的params不适合。例如,我已将函数移动到新单元中,但保留旧单元并将其标记为已弃用。

我猜你使用的解决方案也取决于团队的纪律。他们是否积极注意并努力纠正其应用的所有提示和警告?希望他们这样做,但我很惭愧承认我与之合作的团队(包括我自己)并没有留在所有的提示和警告之上。我时不时地修复了许多提示&警告在时间允许的情况下,我们绝对应该修复警告,但实际上我们必须完成工作,更专注于新功能和截止日期。

所以我的观点是,即使您可以将其标记为已弃用或提供类似的提示/警告,您是否认为您的团队会花时间更改其代码?

答案 5 :(得分:0)

这不是一个完整的解决方案,因为你无法区分他们是否使用过该方法,但是如果它在Delphi 5中可用,但你可以使用$MESSAGE编译器指令在编译时发出警告。

答案 6 :(得分:0)

没有什么能说“修复我!”像编译器休息一样 也就是说,我有一位同事定期修改“常用代码”例程的签名......是的,这很烦人!

我的首选(即我们的团队尚不完全:/)方法如下:

  1. 所有开发人员必须能够轻松地在自己的计算机上执行所有项目的完整构建。
  2. 决定更改公共代码的人应对后果承担责任。即修复所有受影响的代码
    • 当然,有时说开发人员可能不适合正确实施和验证所有修复程序。
    • 但是,出于同样的原因,开发商强加于他们自己的代码中“采用新合同”可能在新合同的细节上不明确。即
      • 为了使用保护措施,还有什么特别需要做的吗?
      • 如何实施保护措施?
      • 关于如何破坏现有代码有什么顾虑?
    • 这是一套全面的测试用例很重要的主要原因。
  3. 通常,您希望尽快应用所有更改的涟漪效果。即虽然变化的细节在原始开发人员的脑海中是新鲜的 - 在注意力转移到别的东西之前!
  4. 涟漪效应是如此巨大(数千行),你想要在很长一段时间内应用这种变化应该是罕见的。
    • 如果是这种情况,请在构建过程中集成一个简单的代码度量收集工具,以报告未完成实例的数量。
  5. 我认为第2点至关重要,尤其是因为它强调了团队内部合作与沟通的必要性。

    回到我的开场白,越早抓住并修复错误,就越好 让编译器报告休息! - 这是我们的“最早机会”错误报告机制。

    那是我的两个人! :d