为什么helperclasses反模式

时间:2014-02-26 18:23:47

标签: oop design-patterns

最近question让我重新思考这整个辅助类都是反模式的东西。

asawyer在评论中指出了一些链接: Helper classes is an anti-pattern

虽然这些链接详细说明了助手如何与众所周知的oop原则相冲突,但我仍然不清楚。

例如“不要重复自己”。如何在不创造某种帮助的情况下取得成功呢? 我认为你可以派生出某种类型并为它提供一些功能。 但我一直认为这并不实用。

让我们看看下面的例子, 请记住,我尽量不使用任何更高级的语言功能,也不使用“特定于语言”的东西。所以这可能是丑陋的嵌套而不是最佳......

//Check if the string is full of whitepsaces
bool allWhiteSpace = true;

if(input == null || input.Length == 0)
    allWhiteSpace  = false;
else 
{
    foreach(char c in input)
    {
        if( c != ' ')
        {
            allWhiteSpace = false;
            break;
        }
    }
}

让我们创建一个名为StringHelper的错误辅助类,代码变短:

bool isAllWhiteSpace = StringHelper.IsAllWhiteSpace(input);

所以既然这不是我们唯一需要检查的时间,我想这里就是“不要重复自己”了。

我们如何在没有帮助的情况下取得成功?考虑到这段代码没有绑定到一个类?

我们需要继承字符串并将其称为BetterString吗?

bool allWhiteSpace = better.IsAllWhiteSpace;

还是我们创建了一个类? StringChecker

StringChecker checker = new StringChecker();

bool allWhiteSpace = checker.IsAllwhiteSpace(input);

那么我们如何才能实现这一目标呢?

某些语言(例如C#)允许使用ExtensionMethods。他们算作助手吗?我倾向于选择那些超过辅助课程。

2 个答案:

答案 0 :(得分:7)

  

免责声明:以下答案是基于我自己的经验而我没有说明是非。

恕我直言,帮助程序既不好也不坏,这完全取决于您的业务/域逻辑和您的软件架构。 这是为什么: 让我们说我们需要实现你提出的白色空间的概念,所以首先我会问自己。 我什么时候需要检查白色空格? 因此,想象一下以下场景:一个包含用户,帖子,评论的博客系统。因此,我将有三个类:

Class User{}
Class Post{}
Class Comment{}

每个类都有一些字符串类型的字段。无论如何,我需要验证这些字段,所以我会创建类似的东西:

Class UserValidator{}
Class PostValidator{}
Class CommentValidator{}

我会将验证政策放在这三个类中。但等待!所有上述类都需要检查null或所有空格? Ummmm .... 最好的解决方案是在树中将它更高,​​并将其放在一个名为Validator的类中:

Class Validator{
   //some code
   bool function is_all_whitespaces(){}
}

所以,如果你需要函数is_all_whitespaces(){}是抽象的(类验证器也是抽象的)或者把它变成一个接口,这将是另一个问题,它主要取决于你的思维方式。 回到这一点,我会让我的课程(为了给出一个例子)看起来像:

Class UserValidator inherits Validator{}
Class PostValidator inherits Validator{}
Class CommentValidator inherits Validator{}

在这种情况下,我真的根本不需要助手。但是我们假设你有一个名为multiD_array_group_by_key的函数 并且你在不同的位置使用它,但是你不喜欢在某些OOP结构化的地方拥有它,你可以在某些ArrayHelper中使用它,但是你完全面向对象后退了一步。

答案 1 :(得分:2)

帮助程序类很糟糕,因为精心设计的OO系统将清楚地理解每个类的职责。例如,List负责管理有序的项目列表。有些人是OOD的新手,他们发现某个课程有方法可以对其数据进行处理,有时会问"为什么List dispayOnGUI方法(或类似的东西)? &#34 ;.答案是List不关心GUI。

如果你打电话给班级a"帮助"它真的没有说出该课程应该做什么。

一个典型的情况是会有一些类,有人认为它变得太大,并把它分成两个较小的类,其中一个是帮手。通常不清楚帮助程序中应该使用哪些方法以及原始类中应该保留哪些方法:未定义帮助程序的责任。

除非你对OOD有经验,否则很难解释,但让我用类比来表达。顺便说一下,我觉得这个比喻非常强大:

想象一下,您有一个庞大的团队,其中有成员具有不同的职位名称:例如,前端开发人员,后端开发人员,测试人员,分析师,项目经理,支持工程师,集成专家等(如您所愿) )。

您可以将每个角色视为一个阶级:它具有一定的责任,履行这些职责的人员希望拥有执行这些职责所需的知识。这些角色将以类似于交互的方式进行交互。

现在想象一下,发现后端开发人员发现他们的工作太复杂了。如果它只是一个吞吐量问题,你可以雇用更多,但问题可能是任务需要太多领域的太多知识。决定通过创建一个新角色来分割后端开发人员角色,并且可能雇用新人来填补它。

如果新职位描述是"后端开发人员帮助&#34 ;?会有多大帮助?不是很......申请人可能会被赋予随意的任务,他们可能会对他们应该做的事感到困惑,他们的同事可能不明白他们应该做什么。

更严重的是,帮助者的知识可能必须与原始开发人员完全相同,因为我们并没有真正缩小实际责任。

所以"助手"在定义新角色的职责方面,我并没有真正说些什么。相反,最好分离一下角色的数据库部分,以便"后端开发者"分为"后端开发人员"和"数据库层开发人员"。

调用类是一个帮助器有同样的问题,解决方案是相同的解决方案。你应该多考虑一下新课程的责任。理想情况下,它不仅应该削减一些方法,而且还应该采用一些数据,它负责管理,从而创建一个比原始大类真正更容易理解的解决方案,而不是简单地放置两个不同的地方同样复杂的逻辑。

在某些情况下,我发现辅助类设计得很好,但它缺少的是一个好名字。在这种情况下,称之为" Builder"或"格式化程序"或"上下文"而不是"助手"立即使解决方案更容易理解。