重构c#:如果要更新的属性在每种情况下都不同,如何删除重复的代码

时间:2011-09-07 15:44:04

标签: c# refactoring code-duplication

在对原型进行了一段时间的黑客攻击之后,我最终得到了一些方法来更新对象上的布尔标志,然后更新接口并根据新值进行一些处理。这几乎完全相同 - 但它们更新的价值是不同的

例如 - 假设我们有一堆彩色盒子要更新 - 我可能有一些看起来像这样的方法:

        protected void SetBlueBoxVisibility(bool blueBoxVisibility)
    {
        Project project = LoadProject();
        project.ShowBlueBox = blueBoxVisibility
        ReDrawSomeThings();
        CalcualteSomeStuff();
        Project.UpdateBoxStatus();
        SaveProject(project);
        ShowBlueBoxPanel(blueBoxVisibility);
        RaiseStatusUpdated();
    }

    protected void SetRedBoxVisibility(bool redBoxVisibility)
    {
        Project project = LoadProject();
        project.ShowRedBox = redBoxVisibility
        ReDrawSomeThings();
        CalcualteSomeStuff();
        Project.UpdateBoxStatus();
        SaveProject(project);
        ShowRedBoxPanel(redBoxVisibility);
        RaiseStatusUpdated();

    }       

现在,很明显 - 大部分内容都是重复的 - 当我来改变任何东西时,这是一种痛苦。特别是如果我最终得到二十种不同的盒子颜色而不仅仅是两种颜色!

我当时认为必须有一种方法来删除更改的代码,并以更通用的方法收集相同的内容 - 但是我很难做到如何做到这一点。

我听说过关闭 - 但是我没有充分了解他们是否会在这里提供帮助。

我想可能以下可能是正确的 - 但我不知道如何告诉通用方法操作哪个属性 - [项目变量更新]

        protected void SetRedBoxVisibility(bool redBoxVisibility)
    {
        SetGenericBoxVisibility([Project Variable To Update],redBoxVisibility)
        ShowRedBoxPanel(redBoxVisibility);
        RaiseStatusUpdated();   
    }

    protected void SetBlueBoxVisibility(bool blueBoxVisibility)
    {
        SetGenericBoxVisibility([Project Variable To Update],blueBoxVisibility)
        ShowBlueBoxPanel(blueBoxVisibility);
        RaiseStatusUpdated();   
    }

    protected void SetGenericBoxVisibility([Project Variable To Update], boxVisibility)
    {
        Project project = LoadProject();
        project.**[Project Variable To Update]** = boxVisibility
        ReDrawSomeThings();
        CalcualteSomeStuff();
        Project.UpdateBoxStatus();
        SaveProject(project);
    }

关于如何处理这类事情的任何指针都很有用:)

3 个答案:

答案 0 :(得分:3)

好吧,你可以提取它:

protected void SetGenericBoxVisibility(Action<Project> propertySetter,
                                       Action<bool> panelShower,
                                       bool boxVisibility)
{
    Project project = LoadProject();
    propertySetter(project);
    ReDrawSomeThings();
    CalculateSomeStuff();
    Project.UpdateBoxStatus();
    SaveProject(project);
    panelShower();
    RaiseStatusUpdated();
}

然后:

protected void SetBlueBoxVisibility(bool blueBoxVisibility)
{
    SetGenericBoxVisibility(project => project.ShowBlueBox = blueBoxVisibility,
                            () => ShowBlueBoxPanel(blueBoxVisibility));
}

protected void SetRedBoxVisibility(bool redBoxVisibility)
{
    SetGenericBoxVisibility(project => project.ShowRedBox = redBoxVisibility,
                            () => ShowRedBoxPanel(redBoxVisibility));
}

这不是非常很好,诚然......

答案 1 :(得分:1)

我认为你可能有更大的问题 - 每盒更新一种方法根本不适合。你有SetGenericBoxVisibility但是通过继续使用Set * BoxVisibility方法撤消任何好的工作。我不知道你正在使用哪种技术 - 如果它是WPF调查MVVM,那么你可以简单地更新你的ViewModels。如果它是WinForms,您应该创建某种字典 - Dictionary<BoxType, Box> _boxLookup其中BoxType是您定义的类型的枚举。然后,要设置框可见性,您可以执行_boxLookup[BoxType.Red].Property = value;,或者您可以使用方法来操作框,并获取BoxType参数。

然而,一些更多的上下文将非常有用,因为即使这个解决方案也不理想。移动一些其他代码或深入了解您使用多个框解决问题的大局应该会导致更多'aha'时刻..

答案 2 :(得分:1)

我认为要真正重构你需要制作一个IBox界面。基本上,该接口充当一个契约,定义所有Box对象必须至少具有的方法和属性。

interface IBox {
 //your generic properties and method stubs
 Bool visibility;
}

现在,为每个“盒子”实现界面

class blueBox : IBox
{
 //here you will have your concrete implementations of the above methods and properties
public Bool visibility   {get; set;} // this doesn't make sense with auto getter setters. you would need to write your bluebox specific getter and setters

}

class redBox : IBox
{
//more concrete implementation

}


public myMethod_To_Do_Stuff(IBox myBox) { // see how I am passing the interface not the conrete classes

myBox.visibility = true;

}