什么是帮手?是设计模式吗?是算法吗?


40

也许有点tongue之以鼻,但由于我无法在Google的任何地方找到此答案,因此请确保Software Engineering拥有以下答案:

什么是帮手?

我已经看到该名称在每个地方都被使用(模块名称,类名称,方法名称),好像语义是深刻而有意义的,但是在计算机科学的背景下(尽管我没有学位),我从未在任何地方看到描述或定义!

是设计模式吗?是算法吗?我曾经在一个程序中工作过,在该程序中,模块和类都被称为somethingsomethinghelper(其中某些东西也是相当通用的),然后我立即将其重命名为对我来说有意义的东西,但是我感觉好像在这里丢失了一些东西!


9
当您不知道该如何称呼但您知道它的一个朋友时,便是您所说的东西。有点像称呼您为“扎克的朋友”而不是亚伦。双加不好。
david.pfx 2014年

助手是任何私人成员,直到同构。
Thomas Eding

@ThomasEding很抱歉3年后再回来-但我见过很多称为“ helper”的“公共”成员,包括接口。我想要一个有关您的定义的资料(质量越高越好),因为这肯定会让我感觉到更多的代码味道。
亚伦·霍尔

Answers:


63

Helper类是一种鲜为人知的代码味道,其中的编码人员已识别出一些其他常用操作,并试图通过将它们组合在一个不自然的分组中来使其可重用。随后,接连的开发人员进入该项目,但没有意识到助手类的存在,因此重写了相同的通用操作,甚至创建了更多的助手类。

但是,严重的是,Helper类的主要问题在于它们通常是作用于特定类的操作,这显然从面向对象的角度来看,意味着他们正遭受Feature Envy的严重影响。未能将行为与行为所依据的数据打包在一起,这就是为什么开发人员如此频繁地(以我的经验)找不到它的原因。

除此之外,您已经确定SomethingSomethingHelper实际上是一个可怕的名字。它是不具描述性的,并且不能使您真正了解该类将执行哪种操作(有帮助吗?),这也意味着添加新行为(无论它们是否属于Helper类)时并不明显。我将按照逻辑组合在一起的相关行为来分解此类,然后重命名新类以反映其作用。


9
可以肯定,这SomethingSomethingHelper不是该类的实际名称。是否带有代码气味取决于助手类的具体程度,因为像这样的助手类Math根本没有代码气味。
罗伯特·哈维

10
@RobertHarvey-Enh,我见过的大多数人被命名了SomethingSomethingHelper。地狱,我正在看一个现在HelperMethods<company>.Helpers命名空间中命名的类。对我来说,一Helper门课与属于同一类*Manager
Telastyn

8
@Telastyn:那么,也许这是一个体验。我浏览了当前项目中的帮助程序类(有几个),它们都有有意义的名称。只有一个后缀Helper,并且我认为这是要与.NET Framework中具有相同名称的类进行区分。*Helper如果*有意义的话,我认为可以接受。 HelperMethods只是想象力的失败;至少应该有特定的概念桶。
罗伯特·哈维

4
@RobertHarvey-你可能是对的。我使用现代语言的所有职业都是清理火车残骸。
Telastyn 2014年

1
其中有一个子集,称为“辅助函数”,实际上是有用的且是一个好的模式。例如,在函数中否则需要重复的一组通用行-显示它们的位置的一个示例是当您需要do..whilePython中不支持该语言的循环时(请参见此处的第二个示例)。另一个可能是if / elif /.../ else结构,但需要在顶部和底部重复一个大小写。如果可能的话,应该使它们在该函数中是局部的,并且通常实际上不称为“帮助器”。
Izkata 2014年

5

只要是对外部组件的补充,辅助程序就是一种无害的附加类或方法。如果相反,则表明设计不良,因为如果有任何权限,则代码已被排除在其权限之外。

这是一个无害助手的示例,我使用一种称为FindRep前导零的数量的方法。

digits = digits.Remove(0, TextHelper.FindRep('0', digits, 0, digits.Length - 2));

辅助方法非常简单,但是非常难以复制粘贴,并且该框架未提供任何解决方案。

public static int FindRep(char chr, string str, int beginPos, int endPos)
{
    int pos;

    for (pos = beginPos; pos <= endPos; pos++)
    {
        if (str[pos] != chr)
        {
            break;
        }
    }

    return pos - beginPos;
}

这是一个不好的帮手的例子:

public static class DutchZipcodeHelper
{
    public static bool Validate(string s)
    {
        return Regex.IsMatch(s, @"^[1-9][0-9]{3}[A-Z]{2}$", RegexOptions.IgnoreCase);
    }
}

public class DutchZipcode
{
    private string value;

    public DutchZipcode(string value)
    {
        if (!DutchZipcodeHelper.Validate(value))
        {
            throw new ArgumentException();
        }

        this.value = value;
    }

    public string Value
    {
        get { return value; }
    }
}

-1

我的公司曾经使用Base类/ Helper类方法,其中每个对象都有两个类。您将拥有一个包含所有类属性和定义的Person类,以及一个包含所有操作Person类的方法,SQL语句和逻辑的PersonH​​elper类。这对我们来说效果很好,因为我们所有的应用程序都使用SQL语句来操纵数据,并且我们很容易根据需要查找和修改SQL语句。

从那以后,我们将所有内容都放在了Person / Base类中。我们放弃使用Helper命名约定,因为我们希望项目中的文件更少。另外,某些类名的长度已失去控制。大声笑。

这不是一个很好的例子,但您明白了。

s = CompanyName.PersonHelper.GetPerson()
s = CompanyName.Person.GetPerson()

我并不是说使用助手命名约定是完美的解决方案,但它确实对我们有用了几年。


2
您没有解释原因。
罗伯特·哈维

2
是的,我也想要这种解释。
亚伦·霍尔

@AaronHall认为您不理解他们的选择是一件好事。
Leopold Asperger 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.