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的如何组织程序(上、下)。

时间: 2024-12-29 20:51:23

F#探险之旅(六):F#代码的组织的相关文章

F#探险之旅(一):选择不同的开发方式

踏上新的旅途 每次旅途都会让人兴奋,都会带来愉快的体验.踏上新的地方,欣赏那些美景,感受那些与自己无关的人和事,身心会得到很大的放松.而回来以后,则会对自己习惯居住的地方产生新的感受,不知你有没有如此的体会呢? 学习F#,也算是这样的旅途吧,毕竟其理念与一直接触的C/C#等很不一样.好奇心遇到未知的事物就会兴奋,就像要踏上新的旅途一样.那为什么叫探险之旅呢? 知识是有时效的资产,咱们微软平台下的开发人员对此应当感受颇深.平台.语言.环境更新地很快,更新意味着旧有知识的贬值,随之带来的是程序员的贬

F#探险之旅(七):在F#中进行单元测试

单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的.很明确的功能是否正确.通常情况下,一个单元测试(用例)用于判断某个特定条件(或场景)下特定函数的行为.如果想对单元测试的好处有更多的了解,可以看一下单元测试实战. 在.NET社区内,NUnit无疑是最经典的单元测试工具,要了解它的用法,建议看一下园子里的一篇很棒的文章NUnit详细使用方法.本文对此不再赘述.另外MbUnit作为后起之秀,也很值得一试. 在F#中, LOP(Language-Oriented Programming)

F#探险之旅(五):透过F#理解函数式编程(中)

列表(List)是函数式编程(FP)的基础.事实上,FP的重要代表Lisp的名字即源自"List Processing",它的发明者John McCarthy于1960年发表的论文向我们展示了,在只给定几个简单的操作符和一个表示函数的记号的基础上,如何构造出一个完整的编程语言,他的主要思想之一是用一种简单的数据结构列表来表示代码和数据. 链表(Linked list)是Lisp的主要数据结构之一,并且Lisp的源代码本身也由列表构成.F#中的列表类型表示为链表,它与C#中的数组.泛型L

F#探险之旅(五):透过F#理解函数式编程(上)

关于函数式编程(Functional programming,FP) 函数式编程(FP)是一种编程范式,它计算机的计算过程视为函数运算,避免状态和数据的修改.与命令式编程相比,它更强调函数的运用.λ运算构建了函数式编程的基础.重要的函数式编程语言包括Lisp.Scheme.Erlang.Haskell.ML.OCaml等,微软则在2005年引入了F#. 此外,包括C/C++/C#/Python/Javascript等很多语言也提供了对FP的部分支持.由此我们可以得出一个结论,随着现实问题复杂度的

F#探险之旅(四):面向对象编程(下)

类的继承 在前面(面向对象(中))介绍过的对象表达式中,已经涉及到了类的继承,我们可以覆盖类的成员实现,然后创建新类的实例.这一节里,我们来看看常规的继承机制,熟悉C#的开发人员会感到更亲切. F# Code - 类的继承 #light type Base = class val state : int new() = { state = 0} end type Sub = class inherit Base val otherState : int new() = { otherState

F#探险之旅(四):面向对象编程(上)

面向对象编程概述(OOP) 面向对象编程是当今最流行的编程范式,看看TIOBE 2008年9月的编程语言排行榜就很清楚了: 在这些主流语言中,除了C,都或多或少地提供对OOP的支持,而Java和C#更是纯粹的面向对象编程语言,C还有一个子集--Objective-C.值得一提的是Delphi的强势回归.下图则是各个编程范式的占有率: OOP编程范式是指使用"对象"及"对象"之间的交互来设计应用程序.OOP的基本概念包括类,对象,实例,方法,消息传递,继承,抽象,封装

F#探险之旅(二):函数式编程(下)

模式匹配(Pattern Matching) 模式匹配允许你根据标识符值的不同进行不同的运算.有点像一连串的if...else结构,也像C++和C#中的switch,但是它更为强大和灵活. 看下面Lucas序列的例子,Lucas序列定义跟Fibonacci序列一样,只不过起始值不同: Code let rec luc x = match x with | x when x <= 0 -> failwith "value must be greater than zero"

F#探险之旅(二):函数式编程(上)

函数式编程范式简介 F#主要支持三种编程范式:函数式编程(Functional Programming,FP).命令式编程(Imperative Programming)和面向对象(Object-Oriented,OO)的编程.回顾它们的历史,FP是最早的一种范式,第一种FP语言是IPL,产生于1955年,大约在Fortran一年之前.第二种FP语言是Lisp,产生于1958,早于Cobol一年.Fortan和Cobol都是命令式编程语言,它们在科学和商业领域的迅速成功使得命令式编程在30多年的

F#探险之旅(四):面向对象编程(中)

对象表达式(Object Expressions) F#中的OOP语法很简洁,而对象表达式则正是这种简洁性的核心所在.通过对象表达式,我们可以创建抽象类或接口的轻量级实现,也可以对一个具体的类进行继承.换言之,可以在实现抽象类或接口,或者继承具体类的同时创建新类型的一个实例.下面来看如何对泛型接口IComparer<'T>应用对象表达式. F# Code #light open System open System.Collections.Generic let revStringCompar