打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
VFP:如何建立自己的开发环境
 

VFP:如何建立自己的开发环境  

2008-12-02 16:23:32|  分类: Visual FoxPro |  标签:vfp  编程   |举报 |字号 订阅

如何建立自己的开发环境

作为一个VFP开发人员,如果没有搭建一个方便实用的开发环境,是无法实现"快速开发"的目标的。

一个好的自定义开发环境,不断可以提高开发速度,同时也有很多其它的好处。它可以让你更好的管理你的代码、更简单的开始新项目、更好的对项目进行扩展……这些,如果离开了一个固定的开发环境,很多就不太现实了。

一个开发环境,不仅仅是几段代码在某个时刻被运行那么简单。一个开发环境,它要在开发过程中,对开发项目时所需要的资源进行调度以方便应用;要对运行环境进行控制以方便调试;还要对编写的代码进行处理以使它们可以方便的测试与使用……

·在建立自己的开发环境之前,你需要先回答一下这些问题:
·你是否有良好的代码风格(大小写、块语句的缩进、长语句的续行处理、代码注释的编写等)?
·你是否已经学会将一段较长的代码分割成若干个函数以使它们更具灵活性?
·你是否能理解VFP脚本与VFP宏的不同与适用范围?
·你是否有一定的函数编写能力,并知道如何编写“安全”的函数?
·你是否已需要开发多个项目?

如果这些你的回答都是“是”的话,那么,你确实需要搭建一个自己的开发环境了。
除了最后一条之外,其它的如果你的回答是“否”的话,那么,在搭建自己的开发环境之前,你先要提高自己或者改变自己的编程习惯以达成上面这些条件。

在这里,我不想讨论“为什么要搭建”,也不想讨论“没有它要怎么做”这类的问题,同样,我也不讨论面对一个问题有多少种解决办法,我会直接给出一个(或者多个)解决办法。我假设继续看下去的朋友已经认为需要有一个适合自己的开发环境来支持自己进行VFP项目的开发了。
至于如何提高代码的质量,如何命名,如何编写安全的代码,以及一些扩展性的问题,如耦合等,则会在以后另行写文章讨论。

 

☆第一个问题:目录结构

首先,我们要确定自己的项目以什么样的目录结构来保存在硬盘中。
一般来说,初级的开发者常常不习惯将不同的文档放在不同的目录中,他们更喜欢随意的将同一个项目中所有的文件放到一个目录里。在这里,我给出的方案是:至少要建立Form、Report、Prog、Library、Data、Graphical、Include等的存放目录,至于目录名,可以使用一些常用的缩写之类的,如frm、rpt、prg、lib、data、bmp、inc、doc等,它们用于存放所有项目共用的相应类型的文档。然后使用一个Project目录,在它里面为每一个项目建立一个子目录,这些子目录中保存每个项目独有的文档,同样,也可以建立上述的那些子目录来分类保存,但一般情况下,在一个具有较高复用性的系统中,一个项目独有的代码与文档并不多,不分子目录也是可以的。
我们可将所有的项目文件(*.PJX)都放在开发环境的根目录下。这样的好处上,所有项目引用的文件,都将位于项目文件所在的目录或它的子目录树中。这样的好处是可以通过对所有“路径”来验证以确定没有引用之外的任何代码。

这样,我们就得到一个目录结构:
Root (根目录,存放项目文件)
├bmp(通用的图片图标等)
├frm(通用表单)
├lib(通用类库)
├prg(通用过程)
├rpt(通用报表)
├inc(通用头文件)
├doc(开发文档)
├debug(调试输出目录)
├bak(备份目录)
└Projects(项目专用目录)
 ├项目1(存放此项目专用的各种文件)
 └项目2
  ├bmp(项目专用图片)
  ├...
  └
有了这样的一个结构,我们只需要打开根目录就可以找到我们所需要进行开发的项目了。无论开发哪一个项目,都将是同样的一个开发环境,这一点有利于我们将注意力从一个项目转到另一个项目而不需要考虑目录的问题。

 

☆第二个问题:类的派生与管理

当我们不仅仅只开一个项目时,我们就需要考虑如何将在其它项目开发过程中编写的类应用到新的项目中的问题。一个良好的非专用类,是可以很简单的应用到多个不同的项目中的。将它们从一个类库复制到另一个类库,或者将一个类库从一个目录复制另一个目录来使用它们是不可取的,我们要先将自定义类分为两大类:一种是只用于特定用途的,比如一个项目要求使用一种特别的格式来导出数据,它不可能应用于其它的项目。另一种是可以应用于其它项目的,比如一个增强功能的Grid控件。
对于前者,我们将它放到该项目的专用目录中,对于后者,我们将它放到root\lib里的某个类库中。

绝大多数的VFP的标准类我们不直接使用。我们为所有可以派生的类都派生出一个我们的基类,如MyTextBox、MyCombo、MyLabel……我们把它们放到MyBaseControl.vcx中。

这里需要注意的是,页框与表格控件的派生有一些不同于其它的类。
页框(PageFrame)它内部的页面(Page)需要指定MemberClass和MemberClassLibrary属性。
类似的还有Command Group和Option Group。
而Grid中内含的Column则要麻烦得多,因为Column是不可以进行可视化派生的,也就是说,我们无法从Column基类派生一个新的类放到一个VCX文件中。所幸的是,我们可以在prg文件中来完成这一工作,虽然麻烦了一些,但至少我们还是可以实现它:
  ****************************************
  * MyColumn.prg
  *基于Column的派生类
  ****************************************
  * Mycolumn 基类
  Define Class MyColumn As Column
    FontName="宋体"
    Add Object Header1 As MyHeader
    Add Object Text1 As MyText
  EndDefine
  * MyHeader 基类
  Define Class MyHeader As Header
    Alignment= 2
    FontName="宋体"
  EndDefine
这样派生出的类,将是所有项目中使用的类的始祖,任何一个项目,它里面使用的类,都将来自于从这些类的派生。
一般来说,如果你需要对一个类的很多个属性进行设置时,那么,你就需要考虑是否为它建立一个类来进行这些处理了。另外,如果你为一个类增强了一些功能,那么,你也应当考虑是否派生一个类或者直接在这个类上实现这里功能。
对于你的表单来说,你的代码应当主要是控制多个控件之间协同工作以及响应用户的事件,再就是一些简单的处理代码。如果表单里的代码很多的话,你就无法将数据处理的代码与响用事件的代码很好的区分开来,这将给你以后的开发带来麻烦。

对于具体的应用,我们将不断的丰富我们的类库(注意不是内裤,我们不是超人,要那么多内裤没用)。
举个例子来说,当我发现Combo是下拉组合框或下拉列表框时我们对用户的动作的回应有很大的不同,所以,我建立了MyComboList与MyComboInput两个类,我把它们单独放到root\lib\MyControlEx.vcx中,它们只是设置了几个属性以使它们在应用时不需要再一个一个的设置了。
后来我发现我需要一个显示用户列表的控件,它在很多地方都需要用到,我就从MyComboList派生了一个cboUser,我将它放到另一个名为root\lib\UI.vcx类库中。
在一个项目中,应用商要求这个列表还显示相应的用户是否在线,于是,我从cboUser派生了cboUserTestOnLine。为了确定将它放到哪里我曾犹豫过,因为当时来说,它只是这一个项目使用了。但考虑到以后可能也有地方用得上它,我把它放到了root\lib\UI2.vcx中,这个UI2.vcx里保存的主要是一些从UI.vcx里的类派生出的新类。

对于多层的派生,有时候确实是很难搞清它们之间的关系,尤其在命名中出现重复的时候,A派生了B,B又派生了C,然后C又派生了一个叫B的家伙……好在我及时发现这一问题,虽然没有办法解决,但我找到一个避免重名的办法。我在每个类的Comment属性里保存它的派生关系,如,在cboUserTestOnLine的Comment属性里我写的是:MyComboList>cboUser>cboUserTestOnLine


这里顺便说一下,关于类的命名,我对于没有使用数据的类,我用My开头,如果它是使用了系统中的数据的,则以类的通用简写开头,当然,那些非可视类(从Custom派生)则没有按这个规则。

 

☆第三个问题:项目切换工具

当有多个项目时,我们可能需要快速的更改工作环境的设置,以便适合不同项目的任务需要。
一般情况下,可以使用ProjectHook来解决这一问题。
如何更有效的使用ProjectHook呢?我在它的Activate事件里写的是:
  Do (ForceExt(_VFP.ActiveProject.Name,'act'))
这需要我建立一个扩展名为act的文件,它实际上是一个prg。在它里头我为具体的项目设置搜索路径,设置代码(Set Procedure To ...),设置引用类库列表(Set Classlib To ...)以及设置数据源(因为我使用远程数据,我只需要建立连接即可)等工作。
如果需要更改这一初始动作,我修改这个act文件即可,不必先关闭项目,这就是这样做的好处。
在软件开发中要避免使用全局变量这类东西。如果使用了全局变量或者在_Screen、_VFP里建立了属性或者对象的话,那么,在切换项目时就需要处理它们。这些都可以在这个act文件里去做,当然,这个文件的扩展名不一定非得是act,完全可以自己确定名称。使用prg也不是什么坏主意。

一般来说,我会把连接数据库的信息(即连接配置串)写入到一个扩展名为Dat文件中,在开发中我用与项目同名但扩展名不同的文件保存,它是加密保存的,这样,发布项目时,可以连它一起发布,而开发时则可以调用它以得到数据进行测试。

因此,一个项目会在主目录下有多个文件,它们的扩展名分别为:PJX,PJT,ACT,DAT,另外在开发与修改后还会出现FXP,BAK等。
项目的启动环境一般也就是用于调试的环境,做好这一步,也就等于建立了一个良好的高试环境了。至于如何进行测试与调试,那就是另外的事了。

 

☆第四个问题:如何制作通用控件

这确实是影响到开发速度的一个问题。

很多时候,我们制作的类都需要后台数据库有特定的表才能常运行。
那么,我们如果在一个项目中引用这一个文件,那最好的情况是我们的开发环境能自动的将相的表添加到数据库中,如果数据库中已经有这个表了那就什么也不做。
这并不是一个很麻烦的事。如果我们引用一个类库,那么,这个类库被加入到项目中时,通过ProjectHook就可以实现它。与之相应的,我们编写一个类的时候,如果它需要后台有某个或多个表,那么,我们应该将这个信息在类里面体现出来,简单的办法是使用vcx文件的user字段。其实user字段的作用很大,我们很多开发中的扩展功能都可以通过它来实现,比如类的签名,类的版本控制,类的适用范围(相应的VFP版本)等等。

当然,还有一些控件的正常运行有可能需要系统中有特定的类,也就是说,它不能单独起作用,那么,最好的办法就是将它们放到同一个类库中。一般情况下,这会有违前面“第二个问题”中的类派生的规则,但也不是不能接受的。
合并存放的规则是:如果多个类需要互相支持,将它们放到同一个类库里时,尽可能放到派生层最多的那个类所在的类库里。

其实,很多时候,我们对类的功能扩展并不是一次就能做到位的,也许这次给它添加了一点功能,下次做另一个项目时才发现,它还需要再添加另一个功能……
这是很正常的事。一般情况下,我们可以将一个功能添加到一个已经存在的并被使用的类中,但要注意的是,一定要做好测试,不仅仅要测试新功能,还要测试一下原有的功能,确保新添加的功能对原有功能没有产生新的影响。一般来说,尽可能为添加的新功能做一个开关属性,开关属性的意思是:如果不对这个属性进行设置,那么,为新功能而编写的代码将不会被执行。这可以最大限度的减少对已经使用的类进行的修改影响到原有的项目。
如果新的功能是一个很独立的功能,那么,也可以为它派生新的子类出来实现,这更加不会影响到原有的类了,只是要注意的是,如果无休止的这样派生下去,你最终会得到一个非常庞大的类库列表!所以,定期将已经稳定的功能合并到父类中去是一个不错的主意。
在一个项目开发的过程中,可以不考虑功能合并的事,把为新功能而产生的类放到项目专用目录里有类库中,在有时间时将它们一点点合并到通用类里去,一旦完成合并,它就可以应用到新的项目中了,也会自动影响到原有的其它项目。而相应的代码在原项目中通过应用也已经证明它的安全与稳定了,相应的测试工作也会轻松很多。

 

☆第五个问题:测试与调式
不进行测试是不可能做好一个项目的。不进行跟踪调试,是很难解决程序问题的。
每一段代码,都应当是在编写后就立即进行测试,如果有任何一点问题,都要进行跟踪调试。
对于一个函数来说,它的说明一般应当包含一个简单的测试用例,如:
  ********************************************************************************
  * AScanEx(ArrayName,vScanVal[, nSeekCol[, nRetCol]])
  * 在数组指定列中寻找一个值
  * 参数
  *  ArrayName :必需,数组名,必需使用传址方式(@)
  *  vScanVal :必需,要查找的值
  *  nSeekCol :可选,在此列中查找,默认查找第一列
  *   nRetCol :可选,返回此列中值,默认返回nSeekCol列的值
  * 返回值
  *  成功返回该行指定列的值,失败返回空值
  * 调用示例
  * AMembers(arMembers,_Screen,1)
  * ?AScanEx(@arMembers,"FONTNAME",1,2) && Return "Property"
  *-------------------------------------------------------------------------------
  Function AScanEx(ArrayName,vScanVal,nSeekCol,nRetCol)
   External Array ArrayName && 这是一个数组
   *检查是不是数组
   If Type('m.ArrayName[1,1]')#'U' Then
   ...
这有利于以后对它进行修改时检查代码是否还能满足之前的使用需要。

对于类中事件与方法的代码的测试则会复杂一些。有些自定义方法可能可以脱离对象单独测试,但大多数时候你需要一个环境来进行测试。为类建立测试表单是有一定必要的。我们可以用一个表单加上相应的类,以及一些辅助的控件来实现,如果必要,在表单中还可以使用Label来指出要进行哪些动作来进行测试,还需要观查结果是不是什么。
这样的一个表单,我们放到哪里呢?
两个选择:一个是可以放到这个类所在的类库的VCX文件的相应记录的User字段,如果你已经使用了这个字段,那么,你还可以考虑将它放到一个专门用来测试的目录,比如root\test或者root\debug下。当然,你应当在这个类的说明中指出,使用哪个表单来对它进行测试。做这件事所需的时间并不多,但它对后续的开发与应用以及将来可能会对这个类进行的扩展都是有相当大的作用的。

对于每一段代码都要进行测试,这是一个必要的工作。也许代码确实很简单,也许编写时认为它没有任何问题,但不经过实际运行,不测试,是不能确定它没有问题的。事实上,就算是通过了测试,代码也可能还存在一些不为人知的问题。小心的编写代码,仔细的测试,这是一个程序员必备的素质。

单步跟踪至少在两种情况下需要:第一,一段代码出错或者运行结果与预期不符;第二,一段复杂的计算算法或一段很重要或使用频率很高的代码。这样的代码,即使是一个有多年代码编写经验的程序员来编写,也应当仔细的做好测试,一步步跟踪代码的执行过程,观察每个变量的变化是否与预想的一致,从而确认它的正确。

 

☆第六个问题:辅助工作的开发与使用
作为一个自定义的开发环境,如果有一些辅助工具来辅助自己的进行开发,那将大大提高自己项目的进度。

像我经常使用的一个就是权限工具。
我编写了一个LimitObject类(派生于Custom),它从后台数据库的Limit表加载权限信息,然后它被添加到UserObject(派生于Custom类)中,UserObject会为它指定一个权限信息串,并指示它从数据库取得权限项的相关信息。那么,在代码中,我就可以用_Screen.NowUser.CheckLimit(m.cLimitKey)这样的方式来判断当前用户是否具备一个或多个权限了。
但对于多个项目来说,每次输入权限的名称是很麻烦的,有时还可能输错权限名,这是一个麻烦的地方。
所以我就做了一个表单,它弹出一个列表,我只需要从中选择相应的权限,它就会自动生成对应的代码。
另外,开发中我可能根据需要添加一个新的权限,我也做了一个小工具,输入权限名,选择分组,权限就添加到后台数据库中了。同时它还会自动更新NowUser.Limit里的权限列表。
类似为样的工具可以从方方面面节约开发时间。

这些开发工具,一般是用来设置控件,或者生成代码,或者设置属性,或者升迁表格,随着自己的应用需要随时编写限时应用,可以在项目的ACT文件中将它们加载到菜单或工具栏,也可以通过自定义FoxCode脚本来引发它们,不同情况区别对待。

事实上,这是最能提高开发速度的方式之一。也许做一个小工具会花上半小时,但应有它只需要几天就能把这点时间找回来了。
当你的辅助开发工具越来越多后,你会发现,很多时候你只需要在它们上东点点西点点就能把一个项目搞得差不多了,需要再自己动手写的代码已经没有多少了。

制作这些小工具时也应当像制作一个用户使用的表单一样用心,尤其是要让它们带有足够的说明性文字。也许刚制作出来时你知道一个按钮是做什么的,可是,你不能保证你在几天或几个月或者更久时间后还能记得。将小工具也做得好用易用,这一点不能忽略。

 

☆最后的一点:文档

无论是做一个项目还是做多个项目,或者只是能代码进行整理,都要使用文档记录下来。

这将是你工作的主要记录。不要说看代码。代码里很多东西是分散在不同的类不同的方法中,可能一次要修改很多地方,但用文档来记录,也许就一两句话就可以说清楚的。
记录下你什么时候对什么进行了修改,测试了没有,测试结果是什么,然后如果有的话,再写上它会对哪些产生影响。这是记录性质的文档。

另外,在你进行一个项目时,如果突然想到什么,但又不能放下手头的工作,你也可以把它记录到一个文档里,写下时间和当时的想法就可以了,这是你的开发计划,在你有空闲的时间里,你就可以按上面去找,把需要实现的一一实现。

还有就是每个项目的开发文档,像分析文档、技术报告、概要设计、详细设计、测试报告等一系列的文档,这些文档不仅有利于相应的项目的开发与后续的升级,也有利于你在做更多项目时进行参考。

文档的编写,对于一个没有经验的人来说,确实有些困难,不过这没有关系,你只要把不同的事情用不同的文档记录下来,慢慢你就会写文档了。在网络上也有很多文档模板可以下载。如果你实在找不到,我这里有一套我自己编写的开发文档模板,一共十一个文件,其中十个Word模板一个Excel模板.在什么地方要写什么东西都有相应的说明,照着填就是了。如果你拿到它还不写不出东西来,那说明你对这个项目还没有想好怎么做,你需要的是对相应的项目再多想想,而不是动手做。

我一向认为,开发文档的编写过程,基本上就是对项目的认识与思考过程,文档一点点的完成,对整个项目的思考也就一点点的完善。等文档完成后,再动手写代码,需要的时间是很少的。这对没有多少项目经验的人来说是十分有效的。即使对于一个有很多项目经验的人来说,先写文档后写代码的做法也可以让开发者少做很多不必要的事情。至少,你不会把一个功能做得快完成时才发现它是不需要的。

 


好了,关于建立自己的开发环境需要的知识就说到这里了,如果你有不同看法,或者有什么想法或建议,欢迎在此讨论,或者与我使用email联系:hunter__fox@163.com

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
VFP 基本类的使用指南
看实例学VFP:新类的使用
VFP中实现在浏览器中运行应用程序方法
让VFP程序在浏览器中运行
分享完整的项目工程目录结构
文档API生成神器SandCastle使用心得
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服