代码之家  ›  专栏  ›  技术社区  ›  Bob Kaufman

创建一个catch all apptoolbox类-这是一个坏做法吗?

  •  6
  • Bob Kaufman  · 技术社区  · 15 年前

    永远不确定在哪里放置函数,例如:

    String PrettyPhone( String phoneNumber ) // return formatted (999) 999-9999
    String EscapeInput( String inputString ) // gets rid of SQL-escapes like ' 
    

    我创建了一个 Toolbox 类,用于作为不完全适合其他类的函数的存储库的每个应用程序。我读过这样的类是糟糕的编程实践,特别是糟糕的面向对象设计。然而,所说的参考似乎更多的是个人设计师和开发人员的意见,而不是一个过份的共识。所以我的问题是,“一网打尽”工具箱是一个糟糕的设计模式吗?如果是,为什么,还有什么选择呢?

    8 回复  |  直到 15 年前
        1
  •  6
  •   cdiggins    15 年前

    好问题。我总是发现任何足够复杂的项目都需要“实用程序”类。我认为这仅仅是因为面向对象编程的本质迫使我们把事物放在一个整洁结构化的层次分类法中,而这并不总是可行或合适的(例如,尝试为哺乳动物创建一个对象模型,然后将鸭嘴兽挤进去)。这是激励工作的问题 aspect oriented programming (C.F.) cross cutting concern )通常,进入实用程序类的是交叉关注的事情。

    使用工具箱或实用程序类的一个替代方法是使用扩展方法为基元类型提供所需的附加功能。然而,对于这是否构成了良好的软件设计,陪审团仍然没有定论。

    关于这个问题,我的最后一句话是:如果你需要的话,就去做吧,只要确保你没有剪出更好的设计。当然,如果需要的话,以后您可以随时重构。

        2
  •  2
  •   Serge    15 年前

    我认为首先想到的是静态助手类。这是很常见的,有些人甚至把它称为面向对象设计的一部分。然而,helper类最大的问题是它们往往成为一个大的转储。我想我看到这发生在我参与的一些大型项目上。你在一个类中工作,不知道把这个和那个函数放在哪里,所以你把它放在助手类中。在这一点上,你的帮助者不能很好地沟通他们所做的事情。类名中的“helper”或“util”本身并不意味着什么。我认为几乎所有的OO大师都反对帮助者,因为如果你有足够的想法,你可以很容易地用更具描述性的类替换它们。我倾向于同意这种方法,因为我认为帮助者违反了单一责任原则。老实说,把这个和一粒盐一起吃。我有点固执己见。

        3
  •  2
  •   rojoca    15 年前

    在这些示例中,我更倾向于扩展字符串:

    class PhoneNumber extends String
    {
         public override string ToString()
         {
             // return (999) 999-9999
         }
    }
    

    如果你写下所有你需要这些函数的地方,你可以找出它的实际用途,然后把它添加到适当的类中。这有时会很困难,但仍然是你应该瞄准的目标。

    编辑:

    正如下面指出的,您不能重写C中的字符串。我想说的是,这个操作是在一个电话号码上进行的,所以这就是函数所属的位置:

    interface PhoneNumber
    {
        string Formatted();
    }
    

    如果您有不同的格式,您可以交换电话号码的实现,而不必将代码与if语句混淆,例如,

    而不是:

    if(country == Countries.UK) output = Toolbox.PhoneNumberUK(phoneNumber);
    else ph = Toolbox.PhoneNumberUS(phoneNumber);
    

    您只需使用:

    output = phoneNumber.Formatted();
    
        4
  •  1
  •   ChaosPandion    15 年前

    这没什么问题。一件事是尝试将其分解为逻辑部分。通过这样做,你可以保持你的智能感知干净。

    MyCore.Extensions.Formatting.People
    MyCore.Extensions.Formatting.Xml
    MyCore.Extensions.Formatting.Html
    
        5
  •  1
  •   Jeffrey L Whitledge    15 年前

    我的经验是效用函数很少单独出现。如果您需要格式化电话号码的方法,那么您还需要一种方法来验证电话号码和解析电话号码。按照雅格尼原理,在实际需要之前,你肯定不会想写这样的东西,但我认为继续进行并将这些功能分为单独的类是很有帮助的。随着时间的推移,这些类从单个方法增长到次要子系统将自然发生。我发现这是使代码长期保持组织、可理解和可维护性的最简单方法。

        6
  •  1
  •   Robert Rossney    15 年前

    当我创建一个应用程序时,我通常创建一个静态类,该类包含静态方法和属性,我无法确定将它们放在哪里。

    这不是一个特别好的设计,但这正是关键所在:它给了我一个地方来本地化我还没有想到的一整套设计决策。通常,随着应用程序的增长和重构的改进,这些方法和属性实际应该驻留在哪里变得更加清晰。幸运的是,重构工具的状态是这样的,这些更改通常不会异常痛苦。

    我试过用另一种方法,但另一种方法基本上是在我对应用程序有足够了解以正确设计对象模型之前实现一个对象模型。如果我这样做 那个 我花了相当多的时间和精力,想出了一个平庸的解决方案,在未来的某个时刻,我必须从头开始重新审视和重建。好吧,好吧,如果我知道我要重构这段代码,那我跳过设计和构建那些实际上不起作用的不必要的复杂类的步骤如何?

    例如,我构建了一个正被多个客户使用的应用程序。我很早就发现,我需要一种方法来分离出需要为不同客户不同工作的方法。我构建了一个静态实用程序方法,我可以在程序中任何需要调用自定义方法的地方调用它,并将它固定在我的静态类中。

    几个月来效果不错。但有一点,它刚刚开始看起来丑陋。所以我决定把它重构成它自己的类。当我在代码中查看调用这个方法的所有地方时,很明显所有定制的方法都需要成为抽象类的成员,客户的程序集需要包含一个实现所有抽象方法的派生类,然后程序只需要o从配置中获取程序集和命名空间的名称,并在启动时创建自定义功能类的实例。对于我来说,找到所有必须定制的方法都非常简单,因为我需要做的就是找到每个调用我的load-a-custom-feature方法的地方。我花了一个下午的时间来完成整个代码库,并使这个设计合理化,最终的结果是非常灵活和健壮的,并且解决了正确的问题。

    问题是,当我第一次实现这个方法(实际上是三个或四个相互关联的方法)时,我意识到这不是正确的答案。但我不知道该怎么做才是正确的答案。所以我用了最简单的错误答案,直到正确的答案变得清晰。

        7
  •  0
  •   Mark Kadlec    15 年前

    我认为它之所以不受欢迎是因为“工具箱”可以增长,每次您想调用一个函数时都会加载大量的资源。

    将方法应用于实际类中的对象也更为优雅,这只是更为合理。

    尽管如此,我个人并不认为这是一个问题,但会因为上述原因而避免它。

        8
  •  0
  •   Wim    15 年前

    我发表了一个评论,但我想我会详细阐述一下。

    我要做的是创建一个带有名称空间的公共库:【组织】。【产品】。作为根和子名称空间助手的公共库。

    这里的一些人提到了一些事情,比如创建一个班级,推一些他们不知道放在哪里的东西。错了。我会说,即使您需要一个helper方法,它也与某些东西相关,因此创建一个正确命名的(iohelper、stringhelper等)静态helper类,并将其放在helpers名称空间中。这样,你得到了一些结构,你得到了一些关注的分离。

    在根命名空间中,可以使用需要状态的实例实用工具类(它们存在!)不用说,也要使用适当的类名,但不要在其后面加上helper。