【问题标题】:Should I leave non-function values in modules or bring them to the main program file?我应该将非函数值留在模块中还是将它们带到主程序文件中?
【发布时间】:2023-03-21 23:56:01
【问题描述】:

这是一个关于我应该如何组织我的 F# 代码的问题。我希望它没有违反SO 规则。

我的项目中有几十个源文件(名称以.fs 结尾)。每个文件都包含一个模块。在其中一些文件/模块中,我只定义了函数。在其他我定义函数和其他值(不是函数)。

Solution Explorer (Visual Studio) 中的最后一个文件是 Program.fs,它实际上包含的代码很少。大多数计算都是在“上面”完成的。

我正在考虑将其他模块中声明的非函数值移动到Program.fs。这些是我从这个变化中看到的优点和缺点:

优点:

1) 更好地了解程序流程。

2) 更容易选择某一行以上的所有代码并将其发送到 FSI 中执行。

3) 在编辑器中搜索这些值稍微容易一些。

4) 通过在声明值的行上放置断点可能更容易调试。

缺点:

1) Program.fs 可能会变得大而笨重。

2) 模块化损失。

3) 实施更改后,如果模块 B 中的值 y 的计算取决于模块 A 中的值 x “高于”它,那么我不能再将 y 作为值,它必须声明为x 的函数。同样,如果模块 B 中的函数声明依赖于模块 A 中的值,我必须在函数定义中添加一个参数。

以下是在两种替代方法下创建的同一个小程序的两个示例。总体而言,两者哪个更好?

// ///////////////// Values in modules \\\\\\\\\\\\\\\\\\\\

// File A.fs

module A

let i = 1
let add x y : float = x + y

// File B.fs

module B

let sqr z = z * z + float i
let x = sqr 99.9

// File Program.fs

open A
open B

let y =
    add (float i) x 
    |> sqr

printfn "%f" y

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

// This is the calculated value for y: 99640524.640100

// ///////////////// Values in Program.fs \\\\\\\\\\\\\\\\\\\\

// File A.fs

module A

let add x y : float = x + y

// File B.fs

module B

open A

let sqr i z = z * z + float i // notice the additional parameter

//File Program.fs

open A
open B

let i = 1
let x = sqr i 99.9

let y =
    add (float i) x 
    |> sqr i

printfn "%f" y

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

// This is the calculated value for y: 99640524.640100

【问题讨论】:

  • 只是为了更好地了解,你有多大和多少文件?
  • 我的项目中有60个文件。最大的(到目前为止)文件有 2600 行(大约有 12 个类,这是唯一一个有类的文件)。然后我有一些 200-500 行,其他的都很小。将添加更多类。包含非函数值的文件只有5个左右。

标签: module f#


【解决方案1】:

正如您介绍的那样,第二个版本(将值移至 Main)更好恕我直言。你几乎用#1的优势把它钉牢了,而且它是一个非常大的优势。至于你列出的缺点:

  1. Large main:是的,取决于我们在谈论多少东西,最坏的情况是您可以将值保留在另一个模块中,仅由 main 使用并且仅用于值。想想“配置模块”
  2. 模块化损失:我看不到 为什么。如果有的话,它会增加模块化吗?你的主要没有 依赖于模块 X 有一些价值,它提供了它。然后,您可以将模块与另一个满足相同接口的模块交换,而不必关心它可能对其他模块产生的连锁反应。如果您有大量的模块层次结构,您可以根据依赖倒置原则考虑在主程序中表示它 - 这需要一些工作,但好消息是在函数式语言中您不需要 IoC 容器,部分应用程序可以完成工作
  3. 如果模块 B 依赖于模块 A 中存在的值,那么一开始就不是很模块化,是吗?您必须将其更改为函数是一件好事 - 它会明确说明现在隐含的内容

请注意,我是根据我主要的 OOP 经验编写的,因此在函数式编程中,其中一些可能不适用

【讨论】:

    猜你喜欢
    • 2014-08-02
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2011-06-12
    • 2012-09-20
    相关资源
    最近更新 更多