偶以前是搞VC的,近期接到一个任务维护一个旧的VB程序,是从VB4作起的,经历了VB4、VB5、VB6,可能是由于以前受限太多,所以现在有如下几点毛病(我认为是毛病,与VC做比较),请各位大侠指点:怎样做最正确、怎样做最适合我的情况
1、使用了很多、相当多的全局变量,并且很多是定义在Modules里面,生存期太长,并且容易发生命名冲突、交叉访问,没有保护级别,交叉使用了也难以发现;
2、变量命名不规范,很多如xpm、ypm、xpm0、ypm0一类的命名,难以记忆,同时VB6的辅助功能似乎也不够,鼠标指向某个变量时无变量类型、注释等信息显示;
3、辅助功能的另一个缺陷就是不支持鼠标中轴,上下翻页时托拽的好辛苦;
4、窗体和Modual命名也不规范,不知道能不能改名;
5、有个Main的入口和一个主Form,Mian调用Form后一直在后台循环,监视两个通讯口状态(据说是防止响应通讯事件的延迟),虽然使用DoEvents,但是CPU资源的占用一直是100%;在VC里常用的方法是使用一个辅助线程“等待”通讯事件,基本上不用担心响应延迟,这里似乎应该也可以这样做,不过水平有限,暂时还没查到相关资料;
6、需要兼容98与2K,不知道需要注意哪些方面?现在偶就知道Sleep在98下不能使用;
7、绘图控件似乎只能操作Interge,而我需要Double操作,最少也是long吧……有效位数不能太少;
8、界面挺难看,没有色彩没有动态窗体,有些Form里使用的背景色灰度还不同;
9、Project窗口里有太多Form,不知道如何把它们分门别类放置,Modules想来也会有类似情况;
10、只有个别几个结构类型,没有类,转换到类体系工作量似乎太大了,心里有点虚;
另外提几个问题:
1、不知道在FormP里定义的Private变量,如何给FormP调用的子FormS使用?
2、如果Form里定义了Public变量,Unload Form后哪些变量是否还存在?如果是其他类型呢?有的书上说Public和Static一样,不理解……
3、无论在哪里自定义一个类型(结构)后,其他地方都可以使用它定义变量么?不需要C++里的头文件或者声明么?
4、如果把这个项目移植到VC.net是否实际:工作量会增加么?兼容性会受影响么?看一些资料提到VC.net的许多新特性,和C++越来越相似了,如可以赋初值(可以使用时才定义)、可以继承类(而不是实现接口)等,感觉蛮亲切的。
5、据说VB调用API容易引发错误,而且On Error无法捕捉到,所以易死机,不知道是否确有其事?
先问这么多了,各位大佬给诊诊吧,谢了先!
我一开始就主张重写,用VC重写,再要不就用VB.net重写,可惜头头不同意呀!
各位大佬,对诊下药可能过于烦琐,您就给我开几个健身的方子吧,比如用VB做项目比较好的习惯是怎样的:变量定义、生存期、保护级别、窗体和模块的关系等。
其实想开了这次维护虽然痛苦了点,但是真的体会到了文档、编程风格、设计模式等的重要性了,反正也不赶时间,我打算一边改写一边学习使用ROSE2K,如果有兴趣讨论ROSE的朋友可以MSN联系:rainee_my@hotmail.com
另外提几个问题:
1、不知道在FormP里定义的Private变量,如何给FormP调用的子FormS使用?
In FormP:
private m_sPage as string
friend property get Page() as string
Page=m_sPage
end property
friend property let Page(byval sPage as string)
m_sPage=spage
end property
In FormS:
FormP.Page=
2、如果Form里定义了Public变量,Unload Form后哪些变量是否还存在?如果是其他类型呢?有的书上说Public和Static一样,不理解……
全局的public,private的应该都还在 ,Public 和static应该不一样,public应该可以被外部访问,static不可以
3、无论在哪里自定义一个类型(结构)后,其他地方都可以使用它定义变量么?不需要C++里的头文件或者声明么?
模块里声明的public type 是这样的
4、如果把这个项目移植到VC.net是否实际:工作量会增加么?兼容性会受影响么?看一些资料提到VC.net的许多新特性,和C++越来越相似了,如可以赋初值(可以使用时才定义)、可以继承类(而不是实现接口)等,感觉蛮亲切的。
不知道
5、据说VB调用API容易引发错误,而且On Error无法捕捉到,所以易死机,不知道是否确有其事?
应该捕捉不到,API应用不当造成非法操作是很经常地
多谢大家支持。
关于变量我经过测试总结了一点东西:
变量定义、生存期(作用域略)
过程级:
允许定义Dim或者Static两种方式,Dim的生存期仅在过程中,Static的生存期等于程序的生存期;
Static Function中Dim声明等同于Static;
"
窗体级:
允许定义Dim、Private、Public三种方式,Dim = Private;
生存期从窗体产生到窗体Unload并且窗体名Set nothing为止,仅Unload而未设置Set Form = nothing不能释放变量内存
"
模块级:
Dim = Private,Global = Public;
生存期等于程序的生存期;
"
类:未测试,应该同C++近似吧
"
注意事项:
仅过程级中可以定义Static类型;
常量、固定长度字符串、数组、自定义类型、断言等不得使用Public类型;
Form也应该看作一个特殊一点的class
至于private ,public ,global,dim ,我是这样理解的
global完全是用于兼容以前的vb4而保留的
我在写程序的时候从来不用的
模块级的边两都用private ,public,而不用dim
至于管理,一般都是
Project Folder
|
+--Form(Folder)
+--Class(Folder)
+--Module(Folder)
+--Projects Relation Files(Like .vbp,.vbg)
+--_Resource(Folder)
| |
| +--Cursor(Folder)
| +--Icon(Folder)
| | +--16x16(Folder)
| | +--32x32(Folder)
| +--Images(Folder)
|
+--_Documents(Folder)
|
+--_History(Folder)
+--_Release(Folder)
|
|
以上仅供参考,一般都会吧_Document等放到上一层的Folder中,在此简单写了
楼主讲的问题正是困扰在下的问题,
与楼主不同的是,在下是今年才毕业学生,没有太多经验
而我的项目负责人,比我早一年毕业,很喜欢“修修补补”,
想在哪加变量就在哪加变量,想起什么名字就起什么名字,没有注释,也没有文档。
程序构架也从不与我商量,甚至不告知。丝毫不考虑我的感受。
很多东西都要靠我自己读源代码来消化体会。
经常会出现楼主讲的第一种错误:
1、使用了很多、相当多的全局变量,并且很多是定义在Modules里面,生存期太长,并且容易发生命名冲突、交叉访问,没有保护级别,交叉使用了也难以发现;
很多时候,讲起来我这种做维护的是比较卑贱的,但是我觉得如果我和他换个位子,
他未必能做得比我更好。
1、使用了很多、相当多的全局变量,并且很多是定义在Modules里面,生存期太长,并且容易发生命名冲突、交叉访问,没有保护级别,交叉使用了也难以发现;
尽量不要在Modules中定义全局变量,对确实需要的,加上注释。对常量,使用Const声明。如果一个From中的变量需要在其它From中调用,可以在这个From中声明一个Public变量,用FromName.变量的方式调用,可以解决命名冲突、交叉访问以及生存期太长(占用内存)的问题
2、变量命名不规范,很多如xpm、ypm、xpm0、ypm0一类的命名,难以记忆,同时VB6的辅助功能似乎也不够,鼠标指向某个变量时无变量类型、注释等信息显示;
VB有自己的命名规范,和C不太一样,如Dim intPos as integer,dim strName as string ,dim blnFlag as boolean等,即范围前缀(m,g)+数组前缀(a)+类型前缀(int,str ...)+变量名,如模块级字符型数组变量:mastrID,全局级整型变量:gintYear,过程级长整型变量:lngX。良好的命名习惯可以减少很多不必要的失误,另外,在From或Modules的第一行加上option explicit(变量使用前必须声明)是一个非常好的习惯。变量、对象、控件的命名规范可以在MSDN中找到。
3、辅助功能的另一个缺陷就是不支持鼠标中轴,上下翻页时托拽的好辛苦;
这个有解决方法。
4、窗体和Modual命名也不规范,不知道能不能改名;
窗体以frm为前缀,模块以mdl为前缀,类模块以cls为前缀。工程建立后,可以改变窗体和模块的名称,但文件名不会改,想连文件名一起改过来,必须另存为。最好的办法是干脆新建一个窗体或模块,用规范的名字命名后把代码粘过来。
5、有个Main的入口和一个主Form,Mian调用Form后一直在后台循环,监视两个通讯口状态(据说是防止响应通讯事件的延迟),虽然使用DoEvents,但是CPU资源的占用一直是100%;在VC里常用的方法是使用一个辅助线程“等待”通讯事件,基本上不用担心响应延迟,这里似乎应该也可以这样做,不过水平有限,暂时还没查到相关资料;
涉及到具体代码,可以发上来大家讨论一下。
6、需要兼容98与2K,不知道需要注意哪些方面?现在偶就知道Sleep在98下不能使用;
VB里有Sleep这个函数吗?
7、绘图控件似乎只能操作Interge,而我需要Double操作,最少也是long吧……有效位数不能太少;
不知道你说的哪个绘图控件,大家讨论一下。
8、界面挺难看,没有色彩没有动态窗体,有些Form里使用的背景色灰度还不同;
VB界面可以做得非常好看,而且也不会比VC麻烦。
9、Project窗口里有太多Form,不知道如何把它们分门别类放置,Modules想来也会有类似情况;
好象没有别的方法吧,呵呵
10、只有个别几个结构类型,没有类,转换到类体系工作量似乎太大了,心里有点虚;
VB支持类,只不过不完全,比如不能重写构造函数,不能继承。
另外提几个问题:
1、不知道在FormP里定义的Private变量,如何给FormP调用的子FormS使用?
Private变量不能在别的窗体中调用
2、如果Form里定义了Public变量,Unload Form后哪些变量是否还存在?如果是其他类型呢?有的书上说Public和Static一样,不理解……
Unload From后,From里的变量自然就释放了。demo001说的问题,实际是当你调用print from2.i时,from2已经被load了。也就是说调用一个From中的变量时,如果这个FROM没有被Load,VB会自动先Load它,demo001不妨在From_Load中写一行代码来验证一下。
3、无论在哪里自定义一个类型(结构)后,其他地方都可以使用它定义变量么?不需要C++里的头文件或者声明么?
必须在模块中声明为public
4、如果把这个项目移植到VC.net是否实际:工作量会增加么?兼容性会受影响么?看一些资料提到VC.net的许多新特性,和C++越来越相似了,如可以赋初值(可以使用时才定义)、可以继承类(而不是实现接口)等,感觉蛮亲切的。
楼主应该说的是VB.net吧?VB.net实际上和VB已经有很大区别了。不知道楼主的这个软件主要是做什么用的,如果包含较多的图形处理的话,还是用vb.net重写吧。VB.net在图形处理上与VB有本质上的区别。除此之外,VB大部分的语句和函数都可以在VB.net中使用,只不过感觉有点不伦不类,你可以用VB.net的VB6升级向导试试,不过估计自己还是要做很多工作。
5、据说VB调用API容易引发错误,而且On Error无法捕捉到,所以易死机,不知道是否确有其事?
on error无法捕捉到API错误。VB调用API只要注意到变量类型的转换、内存的释放等几个地方就行了,没那么可怕的。
本人的一点经验,大家有兴趣共同讨论一下。
、如果Form里定义了Public变量,Unload Form后哪些变量是否还存在?如果是其他类型呢?有的书上说Public和Static一样,不理解……
Unload From后,From里的变量自然就释放了。demo001说的问题,实际是当你调用print from2.i时,from2已经被load了。也就是说调用一个From中的变量时,如果这个FROM没有被Load,VB会自动先Load它,demo001不妨在From_Load中写一行代码来验证一下。
--------------------------------
楼主已经说了,Set nothing之后,才能完全被销毁,这个说法是对的
不管你
Set o=New Form2
o.show
还是
Form2.show
最后只有set nothing才能完全销毁,否则,你还是可以引用其公共变量
别人的代码的确是个头痛的事,尤其是改不规范的代码,如果工作量太大,我宁愿重写
VB.net中,Main函数仍然可以做为程序的入口,不过在Main函数执行完后,程序也就终止了。
例如在VB6中我们常常这样写
sub main()
init()
frmMain.show
end sub
但是在vb.net中执行完from_load过程,程序就退出了,不是象VB那样继续运行。可以把main函数的代码移到启动窗体的load事件中去,也可以用application.run的方式作为程序的入口点。
firechun(天火)
据我分析,Form2的对象实例和其全局变量不是在一起的
这也就是为什么,你Unload,仍然可以引用Form2.i
要想完全切地地销毁Form2
正确的写法:
Unload Form2
Set Form2=Nothing
这样首先卸载Form2对象,然后销毁Form2数据区
至于你说的Debug.Print Form2.i 仍然是可以的
不错,那是因为Form2重新被实例化,i是重新分配的内存,数值是空的
会自动Initialize,而不是Load
Load事件应该只有再Load Form,Form.Show的时候才触发
所以如果你不Set Nothing仅仅是Unload, 那么全局变量是不被销毁的
你仍然可以引用到Form2里的全局变量(数值不会变的)
说的不对的地方,各位斧正
Rainee(补天)
不过看起来两个函数都应该加上by ref才好,效率比较高。
--------------------------------------------
这个怎么说,你是说按地址方式引用比较快,是这个意思吧
可是通常考虑到封装的概念,对接口的要求会比较严格
我们规范的写法,在不是特殊情况下都要求使用ByVal
又学到了不少东西:)
to nik_Amis(Azrael)
关于Byref我有了点感觉了,确实大部分情况下都应该使用传值方式,可以防止函数体内意外的内存操作影响原值,只需要在自定义类或结构(体积比较大)和字符串(个人感觉应该是)两种情况下使用。而且VB.net也把函数参数默认的Byref方式变成了默认Byval了。
to firechun(天火)
手误,是准备移植到VB.net的,不过昨天尝试了一下,在项目升级后除了一大堆的未声明变量以外,连Mian入口的Modual都被遗失了,估计会有办法解决的,不过暂时不知道从何处下手,只好在VB6中先完成一些规范化的工作。
你对Form运作的阐述很精辟,受益匪浅。
今天加入了Option Explicit声明,结果一整天都在做定义变量的工作,到现在还没有结束,汗啊……
那个Main里面的循环极度简单,就是DoEvent、判断串口(两个)写缓冲的状态并做处理、Loop,至于是否如上面说的会有延迟,等我完成了“规范”的工作之后实际测试一下吧;
Sleep是指调用API函数,抱歉没有说明;我的意思是如何处理98、2K甚至XP的兼容性,各位有什么经验,前车之辙,后车之鉴嘛;
绘图控件就是那个PictureBox,不过不是Integer,而是Single;主要用它做一些平面的绘图,如果让我重做,可能我会选择使用OpenGL了,不过我可不是OpenGL高手,就想借个项目学习一下罢了:)
to demo001
辛好我的鼠标就是双飞燕,呆会儿试试去。
听你说起你的项目负责人似乎挺有怨气,其实很多地方都会有这种情况,毕竟安排和管理人是很复杂的事情,先做好你手头的工作,有空多学习,早晚有一天你会有机会施展拳脚的。