0

我有一个方法 DoCleanUp(),它将要求用户继续,然后清除当前工作区。如果用户选择取消此过程,它将返回。

我的问题是,哪个签名最能表明“取消”?

  1. bool DoCleanUp(); // return false to indicate canceled.

  2. bool DoCleanUp(); // return true to indicate this method should be canceled.

  3. void DoCleanUp(bool& cancel); // check parameter 'cancel' to see if this method was canceled.

更新:至于语言,它是 C++\CLI 或 C#。

UPDATE2:现在假设我必须在 DoCleanUp 方法中保存一个文件。我会提示一个对话框询问用户是否保存/不保存/取消文件。根据答案,这是我想出的:

void DoCleanUp();

DialogResult AskToSaveFile(); // return yes/no/cancel

void DoCleanUp( bool saveFile );

用法:

void DoCleanUp()
{
    DialogResult result =  AskToSaveFile();

    if( result == DialogResult::Cancel )    return; 

    bool saveFile = (result == DialogResult::Yes) ? true : false;
    DoCleanUp( saveFile );
}

然后通过调用 DoCleanUp(),您知道用户将有机会取消;
通过调用 DoCleanUp(bool saveFile),您可以控制是否保存文件,而无需询问用户。
这样更好看吗?

4

9 回答 9

5

这是一个经典的单一责任问题。

您不确定签名的原因是该方法正在做两件事。

我会创建两种方法:

bool CheckIfTheUserWantsToCancel()
void DoCleanUp()

编辑

根据对问题的评论和编辑,我将创建第三种方法:

void SaveFile()

然后 DoCleanUp 将首先调用 CheckIfTheUserWantsToCancel,然后如果未取消将调用 SaveFile。

恕我直言,这比试图记住参数为 false 的 DoCleanUp 将在不询问用户的情况下保存文件要好得多,还是相反?

于 2009-12-28T19:58:42.510 回答
3

如果没有更多细节,我会说答案 1 是最好的恕我直言。第三个相当难看,因为它需要更多的调用代码。

但也许考虑重写代码到这个

void CleanUp() {
   switch (AskUser()) {
     case ButtonOk: CleanUpDesk(); break;
     case ButtonNo: break;
     default:
     case ButtonCancel: CancelCleanUpDesk(); break;
   }
}

这似乎本着单一责任的精神。我的代码以某种方式将您的问题分为两个步骤:询问用户和执行操作。

于 2009-12-28T19:57:05.827 回答
1

我会使用你的 1 版本。

bool DoCleanUp(); // return false to indicate canceled.

假设是,当清理完成时它返回 true。返回 false 将指示“错误”状态。返回一个 int 甚至可能是有意义的。在这种情况下,约定通常是 0 代表成功,其他一切都是错误代码。

无论您决定什么,请记录您的返回值的含义!

于 2009-12-28T19:56:51.377 回答
1

令人困惑的一点是调用它 DoSomething(),而它可能什么都不做。怎么样

if (QueryCleanup())     // boolean
    DoCleanup();        // void

更详细但更清晰,即使没有看到声明。

于 2009-12-28T20:06:47.673 回答
0

您不应该对状态(或状态消息)使用布尔值。创建一个枚举:

public Enum CleanupStatus
{
    Ok = 0,
    Cancel
}

这样更清楚返回值是什么......如果您需要添加更多状态,您可以。

(这全部来自 Code Complete 2,如果您还没有阅读,请阅读它。)

于 2009-12-28T20:31:15.130 回答
0

你基本上有两个要求。外部请求是创建一个新的工作区。内部请求是保存当前工作空间。如果外部请求继续,您希望返回 true,如果外部请求被中止,则返回 false。内部请求的动作对外部请求并不重要,因此应该是某种委托/函子/闭包。

创建一个类来泛化这个:

class YesNoCancel {
   string question; // question to ask the user about the inner state
   delegate doit; // function to call to 
   delegate dontdoit;
public:
   YesNoCancel(string question, delegate doit, delegate dontdoit = null) {...}

   bool run() {
     switch (AskUser(question)) {
     case ANSWER_YES: doit(); return true;
     case ANSWER_NO: return true;
     case ANSWER_CANCEL: if (dontdoit) dontdoit(); return false;
};

//usage

void NewWorkspace() {
    if (m_workspace) {
        YesNoCancel ync("Save current workspace?", saveworkspace);
        if (!ync.run()) return;
    }
    // new workspace code
}

void CloseApp() {
    YesNoCancel ync("Save current workspace?", saveworkspace);
    if (ync.run()) ExitApplication();
}
于 2009-12-28T23:29:55.850 回答
-1

我相信选项三最清楚。当您将 bool 作为返回类型时,并不清楚它的用途。

于 2009-12-28T19:55:25.543 回答
-1

我通常和

 bool DoCleanUp();  // Returns true if cancel

但主要取决于调用代码是否如下所示:

 if (DoCleanUp()) {
     // Do cancel up code
 }

或者:

 if (DoCleanUp()) {
     // Do non-cancel post clean up code
 }

基本上我试图让我的测试不必使用等价的!或语言,因为我发现很难看到。

我绝对不会做3号。

于 2009-12-28T19:55:37.780 回答
-1

我更喜欢第三个签名,只是因为通过查看它(没有任何额外的文档),我可以更多地了解该方法的作用。不过,我会把这个参数称为更明确的东西,比如 processCancelled。

于 2009-12-28T19:55:44.707 回答