DotNetNuke中的函数式编程手法分析
"Dear, you love me, you just don't know you love me"是美国肥皂剧FRIENDS中的经典台词,中文翻译为《老友记》或者《六人行》,比较一下这句:"Programmer, you use FP, you just don't know you use FP",句式上和逻辑上是不是很相似?
现在我想说说FP,Functional Programming,中文翻译为函数式编程,与“命令编程”(例如 C、Pascal语言)中的惯常用法相对应,FP在和FORTRAN同样古老的Lisp语言中首次出现,我接触此概念在Python语言中(可爱的Python是相当好的专栏),现在我惊奇的发现它的一些惯用法又在VB.NET开发的DotNetNuke中出现。我猜测,写出DotNetNuke的程序员一定学过Lisp等函数式编程语言。
来看看这个:
''' ----------------------------------------------------------------------------- ''' GetHtmlText gets the HtmlTextInfo object from the Database ''' [cnurse] 11/15/2004 documented ''' ----------------------------------------------------------------------------- Public Function GetHtmlText(ByVal moduleId As Integer) As HtmlTextInfo Return CType(CBO.FillObject(DataProvider.Instance().GetHtmlText(moduleId), &
GetType(HtmlTextInfo)), HtmlTextInfo) End Function
模块位于DotNetNuke_3.0.9\DesktopModules\HTML\HtmlTextController.vb中,我没有精选代码,只是随便找了一个,这种只有一行代码的函数在DNN总非常多。
函数式编程优点不说了,在可爱的 Python:Python 中的函数编程中说了很多了,缺点我认为就是太难理解,至少不直观,也许是我命令式编程接触的多有关吧,充分理解这种程序其实也简单——单步调试,多花时间而已,不过要注意,按F11逐语句而不是F10逐过程,要不然一眨眼就执行过去了,也就没得看了。
好了,这纯粹是按键+记录的体力活,在Return语句上设了断点后,F5,GO!相应的执行顺序为:
- DataProvider.Instance()
- SqlDataProvider.GetHtmlText(ByVal moduleId As Integer) As IDataReader
- DotNetNuke.Common.Utilities.CBO.FillObject(ByVal dr As IDataReader, ByVal objType As Type) As Object
- CType(CBO.FillObject(DataProvider.Instance().GetHtmlText(moduleId), GetType(HtmlTextInfo)), HtmlTextInfo)
好,执行完了,还是没看懂?正常,因为你的阅读速度太快了,如果你像我一样,花了10分钟走这个流程,然后再多看看代码,一定就半懂不懂了,好了,无论如何,我还是有点懂了:
1.DataProvider.Instance()获得的是数据库提供者的一个实例,设计模式Singleton,我发现DNN的数据库连接复用非常有效,有效的只有第一次启动的时候会创建,也就是调用CreateProvider(),然后除非你重新启动机器或者等待5分钟以上不去使用数据库连接,否则都不会再创建数据库连接了。
2.GetHtmlText纯粹的就是业务逻辑层中的概念,也是执行一行语句:
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier &
"GetHtmlText", moduleId), IDataReader)
ExecuteReader在Microsoft.ApplicationBlocks.Data.SqlHelper中,动态生成查询,然后返回SqlDataReader,再转型成IDataReader接口,值得一提的是Microsoft.ApplicationBlocks.Data没有提供源代码,原因嘛,DNN在文档Data Access.doc中提到是enables us to upgrade the component seamlessly as new features/fixes become available,看不懂。
3.CBO是DNN中的精华,功能就是利用.NET中的反射机制,动态根据请求生成数据库返回数据集同新生成的.NET对象之间的同步数据,对于.NET对象没有任何要求,对于数据库返回记录要求支持IDataReader接口,其中数据库到.NET对象赋值在CBO.CreateObject,然而方向相反的.NET对象到数据库却还没有实现类似机制,采用的是类似
SqlHelper.ExecuteNonQuery(ConnectionString,DatabaseOwner & ObjectQualifier &那样的长长的对应每个类一个的机制,原因也许是.NET类库没有提供IDataWriter接口。
"UpdateHtmlText", moduleId, desktopHtml, desktopSummary, userID)
4.没啥说的了,转型而已,同C#中的(HtmlTextInfo)Object相同
通用的代码是否偏向于动态?同C/C++平台相比,更动态.NET是否更多的偏好函数式编程手法?