重构一个包含太多bool的方法

时间:2012-01-13 14:42:58

标签: c# methods refactoring

我在c#中有这个方法,我希望重构它。有太多的bool和线条。什么是最好的重构。创建一个新课程看起来有点矫枉过正,而简单地削减两个课程似乎很难。任何见解或指针都将受到赞赏。

重构方法

    private DialogResult CheckForSireRestrictionInSubGroup(bool deletingGroup,string currentId)
    {
        DialogResult result = DialogResult.No;
        if (!searchAllSireList)
        {
            DataAccessDialog dlg = BeginWaitMessage();
            bool isClose = false;
            try
            {
                ArrayList deletedSire = new ArrayList();
                ISireGroupBE sireGroupBE = sireController.FindSireGroupSearch();

                if (sireGroupBE != null)
                {
                    //if the current group is in fact the seach group before saving
                    bool currentGroupIsSeachGroup = sireGroupBE.TheSireGroup.id == currentId; 

                    //if we have setting this group as search group
                    bool selectedAsSearchGroup = this.chkBoxSelectedSireGroup.Checked;

                    //if the group we currently are in is not longer the seach group(chk box was unchecked)
                    bool wasSearchGroup = currentGroupIsSeachGroup && !selectedAsSearchGroup;

                    //if the group is becoming the search group
                    bool becomesSearchGroup = !currentGroupIsSeachGroup && selectedAsSearchGroup;

                    //if the group being deleted is in fact the search group
                    bool deletingSearchGroup = deletingGroup && currentGroupIsSeachGroup;

                    //if the user checked the checkbox but he's deleting it, not a so common case, but
                    //we shouldn't even consider to delete sire in this case
                    bool deletingTemporarySearchGroup = deletingGroup && !currentGroupIsSeachGroup;         

                    //if we are not deleting a temporary search group and it's either
                    //becoming one (without deleting it) or we already are the search group
                    bool canDeleteSires = !deletingTemporarySearchGroup && 
                                          (becomesSearchGroup || currentGroupIsSeachGroup);
                    //we only delete sires if we are in search group
                    if (canDeleteSires)
                    {   
                        if (deletingSearchGroup || wasSearchGroup)
                        {
                            // If we deleted all sires
                            deletedSire = new ArrayList();
                            deletedSire.AddRange( sireGroupBE.SireList);
                        }
                        else
                        {
                            //if we delete a few sire from the change of search group
                            deletedSire = GetDeleteSire(sireGroupBE.SireList);
                        }
                    }

                    EndWaitMessage(dlg);
                    isClose = true;
                    result =  ShowSubGroupAffected(deletedSire);
                }
            }
            finally
            {
                if (!isClose)
                {
                    EndWaitMessage(dlg);
                }
            }
        }

        return result;
    }

4 个答案:

答案 0 :(得分:7)

一种选择是将每个主要布尔值(canDeleteSiresdeletingSearchGroup || wasSearchGroup)重构为名称描述逻辑可读版本的方法:

if (WeAreInSearchGroup())
{
    if (WeAreDeletingAllSires())
    {
        deletedSire = new ArrayList();
        deletedSire.AddRange( sireGroupBE.SireList);
    }
    else
    {
        deletedSire = GetDeleteSire(sireGroupBE.SireList);
    }
}

然后将当前的布尔逻辑封装在这些方法中,如何传递状态(方法参数或类成员)是一种品味问题。

这会将主要方法中的布尔值移除为直接询问和回答问题的较小方法。我已经看到这种方法在“评论是邪恶的”发展风格中使用。说实话,如果你是一个孤独的狼,我发现这有点过分,但在一个团队中,它可以更容易阅读。

出于个人喜好,我也会将你的第一个if语句反转为提前返回,这将减少整个方法的缩进级别:

if (searchAllSireList)
{
    return result;
}

DataAccessDialog dlg = BeginWaitMessage();
bool isClose = false;
try
...
然而,你可能会受到“多重回报是邪恶的”人群的惩罚。我得到的印象是开发实践就像政治......

答案 1 :(得分:1)

这是一个用于删除一些缩进的小型重构:

private DialogResult CheckForSireRestrictionInSubGroup(bool deletingGroup,string currentId)
{
    if (searchAllSireList)
        return DialogResult.No;

    DataAccessDialog dlg = BeginWaitMessage();
    bool isClose = false;

    try
    {
        ISireGroupBE sireGroupBE = sireController.FindSireGroupSearch();

        if (sireGroupBE == null)
            return DialogResult.No;

        //if the current group is in fact the seach group before saving
        bool currentGroupIsSeachGroup = sireGroupBE.TheSireGroup.id == currentId; 

        //if we have setting this group as search group
        bool selectedAsSearchGroup = this.chkBoxSelectedSireGroup.Checked;

        //if the group we currently are in is not longer the seach group(chk box was unchecked)
        bool wasSearchGroup = currentGroupIsSeachGroup && !selectedAsSearchGroup;

        //if the group is becoming the search group
        bool becomesSearchGroup = !currentGroupIsSeachGroup && selectedAsSearchGroup;

        //if the group being deleted is in fact the search group
        bool deletingSearchGroup = deletingGroup && currentGroupIsSeachGroup;

        //if the user checked the checkbox but he's deleting it, not a so common case, but
        //we shouldn't even consider to delete sire in this case
        bool deletingTemporarySearchGroup = deletingGroup && !currentGroupIsSeachGroup;         

        //if we are not deleting a temporary search group and it's either
        //becoming one (without deleting it) or we already are the search group
        bool canDeleteSires = !deletingTemporarySearchGroup && 
                              (becomesSearchGroup || currentGroupIsSeachGroup);

        ArrayList deletedSire = new ArrayList();

        //we only delete sires if we are in search group
        if (canDeleteSires)
        {   
            if (deletingSearchGroup || wasSearchGroup)
            {
                // If we deleted all sires
                deletedSire.AddRange(sireGroupBE.SireList);
            }
            else
            {
                //if we delete a few sire from the change of search group
                deletedSire = GetDeleteSire(sireGroupBE.SireList);
            }
        }

        EndWaitMessage(dlg);
        isClose = true;
        return ShowSubGroupAffected(deletedSire);
    }
    finally
    {
        if (!isClose)
        {
            EndWaitMessage(dlg);
        }
    }
    return DialogResult.No;
}

答案 2 :(得分:0)

实际上,我个人会保持原样。你到处都有的布林虽然效率低下,但却使这个功能易读且容易理解。

你可以做一些事情,比如将所有bool组合成一行(如下所示),但这不像你写的那样可维护。

x =((a& b)&!d)| ë

答案 3 :(得分:0)

也许您可以尝试删除所有评论。您拥有的bool变量为代码理解增加了价值,您可以将其中的几个内联到canDeleteSires中,但我认为这不会添加任何值。

另一方面,该代码在您的表单中,因此在您的控制器中可能更好,因此您可以保持表单简单并且控制器实际控制行为。