代码之家  ›  专栏  ›  技术社区  ›  sdgfsdh

类型为f的静态成员与模块

f#
  •  12
  • sdgfsdh  · 技术社区  · 7 年前

    假设我有这样的类型:

    type Season =
    | Spring
    | Summer
    | Autumn
    | Winter
    

    我想有个功能 next 下一季的回报是:

    let next s = 
      match s with
      | Spring -> Summer
      | Summer -> Autumn
      | Autumn -> Winter
      | Winter -> Spring
    

    有两个地方我可以放置这个函数。

    在命名模块中:

    module Season = 
      let next s = 
        match s with
        | Spring -> Summer
        | Summer -> Autumn
        | Autumn -> Winter
        | Winter -> Spring
    

    或作为类型上的静态成员:

    type Season =
    | Spring
    | Summer
    | Autumn
    | Winter
      with 
        static member next s = 
          match s with
          | Spring -> Summer
          | Summer -> Autumn
          | Autumn -> Winter
          | Winter -> Spring
    

    赞成每种方法的理由是什么?

    2 回复  |  直到 7 年前
        1
  •  3
  •   scrwtp    7 年前

    归根结底,这是一个领域建模的判断调用,这里没有一个确切的正确答案。重要的是每个选择如何影响代码的可读性和可维护性。

    我倾向于使用静态成员来实现与类型高度“一致”的功能,这比任何特定的业务逻辑代码都要重要。思考 Parse 函数或智能构造函数/工厂方法。一般的方法是,如果我通过将类型移动到其他地方来重构代码,那么这些函数就是我绝对希望与它一起移动的函数。将它们作为静态成员也有助于通过IntelliSense发现它们,因为您只需要知道类型的名称即可找到它们。

    另一方面,我将使用一个模块来存储表示一些抽象过程的业务逻辑,如果所讨论的函数在某种程度上特定于该业务逻辑,并且在IT之外不太可能有用,那么我将使用模块中的函数,即使它仍然具有某种类型的特定性。例如,一个非常特定于用途的解析器,由于遗留的原因,只在这个工作流程中有用,它应该是一个let-bound函数,而不是一个静态成员,因为使用该类型的其他客户机通常不应该知道该函数。

    在你的情况下,我会和静态成员一起去 Next 如果在您的上下文中多个不同的模块中使用它是有意义的-如果能够循环使用 Seasons 是定义 Season 是。

    否则,如果您只有一个模块,我们假设 WeatherPatterns ,根据季节变化调整降雨量,这是您代码中唯一关心骑车通过的部分 季节 ,然后我把它作为一个函数放在那个模块中。

        2
  •  2
  •   Jim Foye    7 年前

    您的示例非常简单,因此这里的任何一种方法都可能是好的。但是想象一下,添加更多的函数来获取季节参数。现在类型定义看起来非常混乱。此外,这些功能可能需要利用一些共享的值和功能,这些值和功能可以在季节模块中声明为私有的。