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

创建一个包罗万象的AppToolbox类——这是一个糟糕的做法吗?

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

    永远不要确定在哪里放置以下函数:

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

    我创建了一个 Toolbox 每个应用程序都有一个类,它作为一个存储库,存储那些不能整齐地放入另一个类中的函数。我读到过这样的类是糟糕的编程实践,特别是糟糕的面向对象设计。然而,所说的参考似乎更多的是单个设计师和开发人员的意见,而不是一个总体共识。所以我的问题是,包罗万象的工具箱是一种糟糕的设计模式吗?如果是这样,为什么,还有什么替代方案?

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

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

    使用工具箱或实用程序类的一种替代方法是使用扩展方法为基元类型提供额外的所需功能。然而,对于这是否构成良好的软件设计,目前尚无定论。

    我对这个问题的最后一句话是:如果你需要的话,就去做吧,只要确保你不是捷径——更好的设计。当然,如果需要,你可以在以后重构。

        2
  •  2
  •   Serge    16 年前

    我认为首先想到的是静态助手类。它是如此普遍,以至于有些人甚至将其称为面向对象设计的一部分。然而,辅助类最大的问题是它们往往会变成一个大垃圾堆。我想我在参与的一些大型项目中看到了这种情况。你正在处理一个类,不知道该把这个和那个函数放在哪里,所以你把它放在了你的助手类中。此时,你的助手无法很好地传达他们的工作。类名中的“助手”或“util”本身没有任何意义。我认为几乎所有的面向对象大师都反对助手,因为如果你仔细考虑,你可以很容易地用更具描述性的类来替换它们。我倾向于同意这种方法,因为我认为助手违反了单一责任原则。老实说,对此持保留态度。我对OOP有点固执:)

        3
  •  2
  •   rojoca    16 年前

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

    如果你写下所有需要这些函数的地方,你就可以找出实际使用它的地方,然后将其添加到适当的类中。这有时可能很困难,但仍然是你应该追求的目标。

    编辑:

    interface PhoneNumber
    {
        string Formatted();
    }
    

    如果你有不同的格式,你可以交换PhoneNumber的实现,而不会在代码中乱丢If语句,例如。,

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

    您可以使用:

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

    这没什么不对的。一件事是试着把它分解成逻辑部分。通过这样做,你可以保持你的智能清洁。

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

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

        6
  •  1
  •   Robert Rossney    16 年前

    ,我花了相当多的时间和精力想出了一个平庸的解决方案,我必须在未来的某个时候重新审视并从头开始重建。好吧,如果我知道我要重构这段代码,我跳过设计和构建那些不必要的复杂类的步骤怎么样?

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

        7
  •  0
  •   Mark Kadlec    16 年前

    将方法应用于实际类中的对象也更优雅——只是更有意义。

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

        8
  •  0
  •   Wim    16 年前

    我发表了一条评论,但想再详细说明一下。

    我所做的是创建一个具有名称空间的公共库:[Organization]。[产品]。作为根和子命名空间Helpers通用。

    这里的一些人提到了创建一个类,把一些他们不知道还能放在哪里的东西塞进去。错了。我会说,即使你需要一个辅助方法,它也与某些东西相关,所以创建一个命名正确的(IoHelper、StringHelper等)静态辅助类,并将其放入Helpers命名空间中。这样,你就得到了一些结构,也得到了某种关注点的分离。

    在根命名空间中,您可以使用不需要状态的实例实用程序类(它们存在!)。不用说也要使用合适的类名,但不要用Helper作为后缀。