这种不良做法/反模式的名称是什么?

Joh*_*ell 44 c# anti-patterns

我试图向我的团队解释为什么这是不好的做法,我正在寻找一个反模式参考来帮助解释.这是一个非常大的企业应用程序,所以这里有一个简单的例子来说明实现的内容:

public void ControlStuff()
    {
        var listOfThings = LoadThings();
        var listOfThingsThatSupportX = new string[] {"ThingA","ThingB", "ThingC"};
        foreach (var thing in listOfThings)
        {
            if(listOfThingsThatSupportX.Contains(thing.Name))
            {
                DoSomething();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我建议我们在'Things'基类中添加一个属性来告诉我们它是否支持X,因为Thing子类需要实现有问题的功能.像这样的东西:

public void ControlStuff()
    {
        var listOfThings = LoadThings();
        foreach (var thing in listOfThings)
        {
            if (thing.SupportsX)
            {
                DoSomething();
            }
        }
    }
class ThingBase
{
    public virtual bool SupportsX { get { return false; } }
}
class ThingA : ThingBase
{
    public override bool SupportsX { get { return true; } }
}
class ThingB : ThingBase
{
}
Run Code Online (Sandbox Code Playgroud)

所以,很明显为什么第一种方法是不好的做法,但这又叫什么呢?另外,有没有比我建议的更适合这个问题的模式?

And*_*rsK 76

通常,更好的方法(IMHO)将使用接口而不是继承

那么只需检查对象是否已实现接口.

  • **检查对象是否已实现接口**,尽管可能是猖獗的,这是一件坏事. (15认同)
  • 我完全和你在一起,OP的方法都不能很好地解决问题.应该有一个ISupportX接口,相应的"东西"如果支持它就会实现.否则ThingBase和所有派生的东西都会成为胖子.这不符合OO"关注分离"原则. (10认同)
  • `myObj is ISomething`可能违反Liskovs Substitution Principle. (4认同)
  • @HemalPandya为什么这是一件坏事? (3认同)

Mis*_*ble 40

我认为反模式名称是硬编码的 :)

是否应该ThingBase.supportsX至少在某种程度上取决于什么X.在极少数情况下,知识可能只是在ControlStuff().

但更常见的情况X可能是,在某些情况下ThingBase可能需要使用ThingBase.supports(ThingBaseProperty)或某些方式公开其功能.


Dyl*_*ith 22

IMO这里的基本设计原则是封装.在您提出的解决方案中,您已将逻辑封装在Thing类中,而在原始代码中,逻辑会泄漏到调用者中.

它也违反了Open-Closed原则,因为如果你想添加支持X的新子类,你现在需要去修改包含那个硬编码列表的任何地方.使用您的解决方案,您只需添加新类,覆盖方法即可完成.


Sha*_*ard 11

不知道一个名字(怀疑这样存在),但想到每一个"东西"作为一辆车 - 有些车有巡航控制系统而其他人没有.

现在,您拥有自己管理的车队,并希望了解哪些车辆具有巡航控制权.

使用第一种方法就像查找所有具有巡航控制功能的汽车模型的列表,然后驾车开车并在该列表中搜索每一个 - 如果有的话意味着汽车有巡航控制,否则它没有.累赘吧?

使用第二种方法意味着每辆拥有巡航控制系统的汽车都带有贴纸,上面写着"我有巡航控制",您只需要查找贴纸,而无需依赖外部信息来为您提供信息.

不是非常技术性的解释,但简单而重要.

  • 第二种方法的缺点是所有的汽车都有贴纸,说明他们是否有巡航控制,而且贴纸是永久性的. (3认同)
  • 贴纸仍然存在,将其设置为false只是将文本从"我有巡航控制"更改为"我没有巡航控制",SupportsX的功能仍然存在,无论如何. (3认同)

Ben*_*ict 7

这种编码实践很有意义,这是一种非常合理的情况.它可能不是哪个东西实际上支持X的问题(当然每个东西上的接口会更好),而是支持X的东西是你想要启用的东西.您所看到的标签就是配置,目前是硬编码的,对此的改进是最终将其移动到配置文件或其他方式.在你说服你的团队改变它之前,我会检查这不是你所转述的代码的意图.


Sar*_*tha 7

写太多代码反模式.这使得阅读和理解变得更加困难.

正如已经指出的那样,使用接口会更好.

基本上,程序员没有利用面向对象的原则,而是使用过程代码来做事.每当我们达到"if"语句时,我们应该问自己,我们是否应该使用OO概念而不是编写更多的过程代码.


Myk*_*tis 5

它只是一个糟糕的代码,它没有它的名称(它甚至没有OO设计).但争论可能是第一个代码不允许开放关闭原则.支持的事物列表发生变化时会发生什么?你必须重写你正在使用的方法.

但是当你使用第二个代码片段时会发生同样的事情.让我们说支持规则发生了变化,你必须转到每个方法并重写它们.我建议你有一个抽象的支持类,并在它们改变时传递不同的支持规则.