F#探险之旅(六):F#代码的组织

简介:

前言

是的,我们已经学习了如何在F#中使用各种范式(函数式、命令式、面向对象)进行编程。但是目前还仅限于在单个模块内编写,要知道,不管是采用哪种语言或者范式编程,如果项目规模大了,都不适合把所有代码放在单个模块内。

在常规的.NET项目中(比如C#+ASP.NET),我们往往会选择使用Solution的概念作为整个(独立)问题域的解决方案,Solution以下则是Project、File。这些概念在物理上往往表现为程序集(类库或可执行程序)、类文件等,如果项目和文件数量较多,就该好好考虑如何在组织它们。下面从这三个层次上分别来讨论一下。

Solution层次 

这里主要考虑的是Project之间的相互关系,此时基本上我们可以忽略语言的不同,也可以说在这个层次上,语言的影响不大。所以说我们把那些在用C#开发时采用的代码组织原则搬过来用。比如Martin Fowler在《企业应用架构模式》中谈到的内容,比如Robert Martin在《敏捷软件开发》中提到的关于包的设计原则,还包括.NET社区中关于PetShop架构的讨论等等,都可以加以借鉴。关于这方面的内容已有大量相关的讨论,在此不再赘述。

这里只谈一个具体的问题:如何添加对其它程序集的引用。在F# CTP 1.9.6.0之前,添加对程序集的引用需要#I和#r指令,#I用来指定要引用的程序集的目录,#r则用来指定要引用程序集的路径(包含文件名,可以是相对路径或绝对路径)。这两个指令既可以放在代码文件中,也可以放在编译选项中。其中有个小窍门,注册表中.NETFramework节点下包含了各.NET版本的一些信息,其中的AssemblyFoldersEx中有若干个目录信息,如果程序集所在目录出现在AssemblyFoldersEx中,就可以直接使用#r和文件名来添加引用了。

在CTP版本中,可以像常规的C#/VB.NET项目中那样,为项目添加对其它程序集的引用(包括引用同一解决方案中的其它项目):
 

而#r只能用于fsx脚本文件或者放在编译选项中。

Project层次 

现在假定你已经对上述设计原则有了足够的了解,并运用这些原则完成了设计,下一步就是如何使用F#来实现这些设计。现在我们进入到了Project这个层次,需要考虑Project中各代码实体之间的关系,这些实体可以是物理上的源码文件,也可以是逻辑上的模块、类型、配置等。F#中最基本的组织结构是命名空间和模块,命名空间的概念与C#中的一样。借助于Reflector可以看到模块在编译之后就是静态类,我们在为模块添加成员时要了解,这是在向一个静态类添加成员。关于命名空间和模块的相关知识,强烈推荐Lvxuwen的如何组织程序(

File层次 

现在考虑源码文件内部的基本问题。在使用函数式编程范式时,除了模块,还可以采用F#的自定义类型,F#中的类型分为两类,一是元组(Tuple)或记录(Record)类型,它们类似于C#中的类;二是Union类型,有时又称为Sum类型。通过Reflector可以看到,元组值是Tuple类型的实例,而Tuple实现了 Microsoft.FSharp.Core.IStructuralHash和System.IComparable接口;记录和Union则直接实现了这两个接口。要了解IStructualHash接口的更多内容,请参考Jome Fisher的文章。

而在使用面向对象编程范式时,我们可以像在C#中那样定义.NET类型,比如接口、类、结构、枚举、委托等等。当然这其中的编程细节比较多(建议看看我前面写过的几篇随笔),而且对于同一问题可以采取不同的方案。这需要我们去多多学习和实战,根据不同的需要作出选择。

这里来看另一个具体的问题:如何使用F#中的签名文件(Signature file)。在学习C语言时,接触过函数原型的概念,它给出了函数的名称、参数类型和返回类型,函数签名的含义与函数原型是一样的。如果我们把模块内的函数签名抽取出来,放在单独的一个文件中,这就是签名文件的由来。它的作用在于,它可以控制模块内函数的访问修饰符。如果要使用签名文件,那么它必须与其控制的模块文件成对出现,并且文件名相同。比如:

复制代码
F# Code - myModule.fsi
#light
module FsLib.MyModule

/// 获取一个浮点数的平方值
val square: float -> float

/// 获取一个浮点数的立方值
val cube: float -> float
复制代码

 

复制代码
F# Code - myModule.fs
#light
module FsLib.MyModule

open System

let pow x y = Math.Pow(x, y)

let square x = pow x 2.0
let cube x = pow x 3.0
复制代码


*.fsi即签名文件,这里定义了两个函数的签名:square和cube。*.fs即实现文件,它必须要提供对应的签名文件的所有函数的实现。其它程序集的模块,只能访问*.fsi中具有签名的函数。通过Reflector可以看到,对于myModule.fs中的三个函数,square和cube的修饰符为public,而pow则为internal

由此看来签名文件的作用很像C#中的接口。但事实上,编译后并没有真正生成接口。需要注意的是,如果要为代码添加XML文档注释,需要加在签名文件(如果模块有的话)而不是模块中。下面来看看如何在代码中添加注释。

常规注释 

在F#中,单行注释使用//,而多行注释则使用(* … *)。

XML文档注释 

如果为代码添加了文档注释,可以在编译时生成XML文档,然后借助于一些工具(如SandCastle)就可以生成容易使用的帮助文档。在上面的代码中可以看到,直接使用///可以为模块或其成员添加文档注释,这个要比C#中简便一些。同时也完全可以使用C#中那样完整的文档注释格式(比如使用Summary、Param等节点)。

最后,如果要在F#使用C#类库中的代码,可以参考前面写过的一篇随笔:F#命令式编程,了解关于这方面的内容。

F#的Project可以编译为类库或可执行应用程序(控制台应用程序或Windows应用程序)。我打算在后面的随笔就这两方面展开讨论,并尝试一些有实战意义的小型项目,相信到那时对代码组织的认识会更为准确。

小结 

在初学F#时,我们可以很随便地将代码放在同一模块内做些尝试或者测试。但我们程序员不该是随便的人,随着项目规模的增大,代码的组织问题会变得越发重要,我们应当越加重视。在VS中进行开发时, 整个项目的组织自然地分为了Solution、Project、File三个层次,本文在这三个层次上就代码组织的基本问题做了讨论,写得比较简单,欢迎您来留言讨论 。

(要了解本人所写的其它F#随笔请查看 F#系列随笔索引

参考 
《Foundations of F#》 by Robert Pickering
Detailed Release Notes for the F# Sep 2008 CTP release
园子里Lvxuwen的如何组织程序(
F#先锋维坦F# CTP 1.9.6.0 发行说明(Release Notes)摘要


本文转自一个程序员的自省博客园博客,原文链接:http://www.cnblogs.com/anderslly/archive/2008/11/05/fsharp-adventure-code-organization.html,如需转载请自行联系原作者。

目录
相关文章
|
4月前
|
弹性计算 Java 程序员
推荐程序员必知的四大神级学习网站
今天给大家整理一些小编经常学习和访问的学习网站,供大家参考学习。
|
2天前
|
开发者
代码之外:软件开发者的职业素养提升之道
软件开发不仅是编写代码,更涉及职业素养的全面提升。本文探讨了软件开发者如何在沟通技巧、团队合作、持续学习、时间管理和职业规划等方面提升自我。良好的沟通能促进团队协作,持续学习助你紧跟技术潮流,高效时间管理则有助于实现工作与生活的平衡。通过这些方面的努力,开发者能够打造更加成功的职业生涯。
|
8天前
|
算法 数据库 开发者
探索代码之美:从问题到解决方案的旅程
【9月更文挑战第12天】本文通过深入浅出的方式,探讨编程过程中遇到问题的普遍性和解决问题的重要性。文章不仅分享个人的技术感悟,还提供了实用的编程技巧和策略,旨在鼓励读者面对编码挑战时保持积极的态度,并找到创造性的解决方案。
16 0
|
2月前
|
JavaScript 前端开发 Java
代码之舞:从编程新手到资深开发者的旅程
【7月更文挑战第19天】编程,一种现代魔法,让无数人为之着迷。本文将通过个人的技术感悟,探讨如何从一个对代码一无所知的新手成长为一名能够自如驾驭复杂项目的资深开发者。我们将穿越编程语言的选择、学习资源的利用、项目实践的重要性以及持续学习的必要,最终达到技术与创造力的和谐共舞。
47 10
|
3月前
|
前端开发 开发者
编织代码的诗篇:我的技术感悟之旅
【6月更文挑战第10天】在数字世界的织布机上,每一行代码都如同细腻的丝线,交织成我技术生涯的华美篇章。本文将带你穿梭于我与代码共舞的日子,感受那些静默中涌现的灵感,以及在挑战与创造间不断进化的思维。
25 3
|
3月前
|
Oracle IDE Java
启航Java编程:基础三部曲-第一部
启航Java编程:基础三部曲-第一部 揭秘Java:从Hello World开始的编程之旅
30 0
|
4月前
|
算法 Java 程序员
程序员职业发展之旅:从代码入门到身体管理的完美进化
程序员职业发展之旅:从代码入门到身体管理的完美进化
30 1
|
4月前
|
算法 程序员 开发者
代码与禅意:技术修炼中的悟性之旅
【5月更文挑战第30天】 在编程世界的林间小径上,每一位开发者都是一位探索者。本文将带你走进程序员的内心世界,透过技术的表象,探讨那些看似无形却能显著提升开发效率和代码质量的“软技能”。从心法到手法,从个人的静心冥想到团队间的默契配合,我们将一探究竟,如何在技术的海洋中找到自己的航向,以及如何让每一行代码都充满“禅意”。
|
4月前
|
算法 程序员 UED
探索编程之道:从功能实现到艺术创造
【2月更文挑战第18天】 在数字世界的构建中,编程已不仅仅是逻辑与算法的堆砌,它正逐步演变成一种创造性表达的手段。本文将探讨编程从基础的功能实现向高级的艺术创造的转变过程,分析编程者如何通过技术深入、创新思维和持续实践,提升其技艺至艺术境界。我们将审视几个关键要素——技术的深度理解、设计的美学融入以及代码的工艺精神,并讨论它们如何共同作用于编程实践中,以培养出能够编织数字世界之美的编程艺术家。
|
12月前
|
存储 JavaScript 前端开发
关于缺少编程基础的朋友想转行 ABAP 开发岗提出的一些咨询问题和解答
关于缺少编程基础的朋友想转行 ABAP 开发岗提出的一些咨询问题和解答