为非VB6人员挑选一个VB6项目

时间:2008-11-11 21:08:06

标签: .net sql-server vb6

我被赋予了修改VB6项目的任务。没有什么是非常严重的,添加了几个表单并修复了一些bug。该项目使用SQL Server(如果有任何相关性)。

我的编程背景是VB / C#.NET,PHP,C ++,主要是MySQL,尽管我使用的SQL Server规模要小得多。任何人都可以给我什么样的建议或VB6编程的资源。自从我完成任何VB .NET工作已经有几年了,虽然我可以阅读VB6代码并了解发生了什么,但我不确定我能够开始写作和/或修改没有破坏任何东西的机会。

其他人可以提供什么样的建议?任何资源和/或故事都会很棒。随意提供您可能感觉相关的内容,但我忽略了。

谢谢!

10 个答案:

答案 0 :(得分:14)

可能已经存在,但请确保 Option Explicit 位于所有文件的顶部。它强制变量声明,并减少错误无意中动态创建变量的可能性。

答案 1 :(得分:13)

VB6有一个破碎的类型系统 - 事实上它有两个不完全兼容的类型系统。在架构上,VB4-6是一个比COM更薄的包装器,并使用COM的类型系统。 VB的早期版本有自己的类型系统,它是传统BASIC和C之间的交叉。这两个版本不能自由混合和匹配。

没有继承,也没有真正的异常处理,所以期望为错误处理和反复重复的基本表单函数编写大量的样板代码。这就是VB获得剪切和粘贴软件工程的声誉。

您可以在VB中声明的某些类型不是“自动兼容”,这意味着它们不能通过COM边界序列化或存储在Variant中(稍后会详细介绍)。这些类型可以追溯到VB不支持COM的VB4-6之前的日子。 其中一种类型是记录(如c结构)类型,其名称可以逃避我,因此结构的可扩展集合或关联数组(这是人们可能想要做的自然事物)是不可能的。定义一个类(见下文)是可能的,但有些笨拙。

VB不支持多线程,其解决方法有很多问题。如果您使用MTS或COM +进行3层开发,第一个可能会咬你。创建VB模块实际上是在幕后创建一个单独的COM对象。这将住在自己的单线程公寓。公寓本质上是轻量级运行COM服务器,具有序列化/反序列化机制(称为消息泵),其中调用被序列化并排队等待单个线程。如果您(在表面上)做了明智的事情并尝试模块化您的代码,您将在您的中间层创建热点。解决方案:更多剪切和粘贴。

第二个主要问题是COM的垃圾收集是相当基本的 - 一个简单的引用计数机制。这意味着COM组件崩溃或由于某种原因在自身泄漏内存后没有整理。还记得VB6如何只是COM上的薄层吗?这种紧密耦合意味着在使用UI管理代码时必须非常小心,该代码保存对控件的引用,外部应用程序上的OLE自动化(例如Excel)或其他任何设置引用的内容。 VB很擅长做背后隐藏的东西而不知道什么时候自己清理。它也是幕后产生的循环引用的来源。得到这个错误,它会泄漏资源 - 你需要小心这一点。

另一个主要问题是变种。我见过的Variant类型的最佳描述是'Spreadsheet Cell'。这些可能会造成很多恶作剧,特别是Variant Arrays。许多API仅适用于变体或具有使用变体的随机部分(Excel会执行此操作),因此您无法始终避免使用它们。如果你在COM边界上串行化(例如多个断开连接的Recordset),你很快就会学会厌恶Variant Arrays。

您可能会发现VB的类型系统如此破碎,以至于维护非平凡复杂数据结构的最简单方法是执行一个库,该库以字符串形式对其进行编码,并基本上对其进行串行化和反序列化。 VB6应用程序中的复杂数据结构几乎不起作用。

最后,在使用VB6的GUI工具包之后,您将了解到WinForms团队从VB6团队的错误中学到了多少。

虽然它被宣传为简单易用,但是由于所有的架构缺陷和小问题,在VB中构建一个非平凡的应用程序而不会弄得一团糟。这是Spolsky Law of Leaky Abstractions.的一个很好的例子。

Appleman的Developing COM/ActiveX Components in Visual BASIC 6对COM与VB6交互的细节有很好的处理。他在Win32 and VB programming.上也做得很好。

P.S。 (感谢提醒我Daok),如果您发现某人一直在使用On Error Resume Next,则表示您允许head-butt他们。

答案 2 :(得分:8)

由于我在Visual Basic上切了我的话(简历说VB3-6 10多年),我会尝试用“On Error Resume Next”以外的方式回答你的问题(它确实如此,但是你'会发现它到处都是,或者你不会,这更糟糕)。您可以执行以下操作:

  1. 当你接管一个VB项目时,最困难的事情通常是让它在你的机器上编译。这通常是由于对原始开发人员机器上安装的内容的破坏引用,而不是对您的机器(a.k.a。“DLL Hell”)的引用。您只能希望安装程序仍然存在于某处,或者如果不存在,您总是可以将DLL和OCX丢弃到系统目录中(请记住注册它们)。有时DLL Hell来自破坏的内部引用。 VB开发人员通常喜欢将应用程序划分为尽可能多的不同组件项目。当你把所有东西都合并到一个该死的项目时,你的兼容性问题往往会消失。
  2. 一旦所有内容都编译完毕,你就有99%。这里的帖子中提到的大多数常见问题都是立即在应用程序中出现的问题。如果您继承的应用程序是一个简单,可靠的应用程序,这些年来一直在悄悄地嗡嗡作响(它发生在VB中),您可能会很好。
  3. 一旦你在IDE中编译和使用了应用程序(我认为这就是当时的内容),你可以开始尝试在这里和那里做一些小改动。
  4. 在此处发布您的问题。提醒过去很有趣。
  5. 对于一般的Visual Basic,我会说不相信反炒作。它是一种允许良好代码或错误代码的语言,与其他语言非常相似。请记住,所有可怕的VB程序员现在都是糟糕的C#程序员。

答案 3 :(得分:7)

请不要使用“错误恢复”。

答案 4 :(得分:6)

如果您的应用程序使用ActiveX DLL项目,那么您确保这是最小化DLL Hell

的情况
  • 将您的DLL设置为BinaryCompatibility。
  • 确保您拥有兼容性 目录。
  • 将最新版本的DLL放入 那里。
  • 指向二进制文件     与该DLL的兼容性。
  • 确保您的EXE和DLL编译 到它的项目目录。
  • 从它的项目中运行EXE 测试时的目录。它将使用您编译的DLL。
  • 你需要编写一个实用工具 你可以编译每个项目 分开正确的顺序。 VB6 Compilier可以从命令行运行。
  • 使用Virtual PC或测试您的设置 另一台电脑。

尽管缺少继承,但您会发现VB6能够实现许多常见的面向对象设计模式。如果您查看设计模式,可重用面向对象软件的元素,您将看到大多数模式涉及实现接口而不是继承行为。他们从第16页开始讨论这个问题。

强类型集合并不是直接实现的,您可以使用包含readonly Item属性在内的所有内容编写集合。完成后,您需要点击{F2}并调出对象浏览器。找到您创建的集合类,然后右键单击Item。

你需要

  • 选择属性
  • 单击“高级按钮”
  • 将过程ID更改为默认

然后Item将成为默认属性,Strongly类型集合将按预期运行。

要在集合类中启用For Each,您需要添加此

Public Property Get NewEnum() As IUnknown
    Set NewEnum = mCol.[_NewEnum]
End Property

mCol是私有Collection变量的名称

再次使用对象浏览器并右键单击NewEnum。

你需要

  • 选择属性
  • 单击“高级按钮”
  • 将过程ID更改为-4

请记住,Integer是16位,Long是32位。我建议将大多数整数变量声明为Long。在当天,它对于速度和内存占用至关重要,但对于今天的计算机,最好只使用Long而不用担心超出限制。

与其他地方建议使用Option Explicit。

Visual BASIC 6非常擅长隐式类型转换。如果您想确定,可以使用Cxxx系列转换功能。

Variant在处理各种对象类型(包括类)时优于.NET的对象。如果您需要创建一个处理数据库的自定义表单,并且用户可以选择要用于该表单的表,您可能会发现它很有用。使用Variant可以更轻松地处理不同表的字段属于不同类型的事实。

Visual Basic 6可用于制作多层应用程序。表单可以实现类似Classes的接口。

请记住,在编译和编辑表单时会运行ActiveX控件。如果您不了解它,可能会引起各种陌生感。如果您有自己的ActiveX控件,这尤其成问题。

答案 5 :(得分:2)

相反使用on error resume next而不是on error goto X,但总是立即捕获错误,然后重置错误处理。

示例:

...
On Error Resume Next
oDbConn.Open sDbConnString
Select Case Err.Number
  Case &H80004005
    MsgBox "Cannot connect to SQL-server, check your settings."
    frmSettings.Show
    Exit Sub
  Case Else
    ShowErrorAndQuit Err
End Select
On Error Goto 0
...

答案 6 :(得分:2)

声明对象时的一般智慧是避免使用“Dim myObj As New MyClass”。而是使用“Dim myObj As MyClass”并在需要时使用“Set myObj = New MyClass”显式实例化对象。前一种方法在遇到“Dim”时不会实例化对象,但会在第一次引用对象的一个​​属性或方法时自动执行。这需要运行时要做的一些额外开销,因为它必须在每个属性/方法引用之前检查对象是否存在。此外,该对象声明方法还有一些其他古怪的副作用。例如,如果myObj设置为Nothing,并且程序遇到另一个引用,则会自动创建一个新实例。如果出现这种情况,可能会导致程序出现问题,但不会产生错误,告诉您对象不存在,这可能导致一些难以追踪的错误。通常,最好使用“Set = New”语法自己显式创建和销毁对象实例。 “Dim As New”语法的支持者通常会提到更好的可读性,但它有时可能会遇到陷阱。

答案 7 :(得分:1)

发布在这里并说“On Error Resume Next”的人是有史以来最糟糕的语言功能。

最糟糕的语言功能是“ On Error Resume ”。请相信我。

对于VB受损者,On Error Resume Next表示“出现问题,到下一行”。 On Error Resume意味着“出了问题,最好一次又一次地再试一遍......”。

答案 8 :(得分:1)

我个人喜欢On Error goto ErrorHandler,每个函数底部都有一个错误处理程序。

请记住,在调用方法时绝不要包含括号,除非您要查看其返回值。在单参数方法上很容易摆脱这种情况,但有时它会咬你,因为传递(变量)与传递变量相同。

编写VB的人不太确定他们是首选0索引数组还是1索引数组。您可以使用UBound / LBound来检查数组的开始和结束位置。

请勿使用“textcomparison”转换大小写。将字符串作为文本进行比较不仅仅是忽略大小写。只需将一个或两个字符串转换为大写。

项目 - >属性 - >如果您在运行时调用它们,则必须关闭有关未使用的ActiveX控件的信息。

工具 - >编辑器 - >自动语法检查。如果您不习惯,可以将其关闭。

工具 - >编辑器 - >需要变量声明。上。

工具 - >环境 - >程序启动时 - >保存更改。如果关闭,即使您运行它也不会保存您的程序。

使用Run->以完全编译开始,不运行 - >开始,运行代码。

答案 9 :(得分:0)

除非确实需要,否则不要使用On Error Resume Next(有一些独特的情况,例如错误处理后的最终清理或VB Collection元素存在检查,但通常你不需要它在函数体内)。

实现正确的错误处理,不要使用多个退出点,不要使用If-Then单行,使用Case Else块,不要使用Subs - 类似下一个非常简单的函数skeletion:

Private Function MyFunc() As Boolean
    On Error Goto ErrHandler

    ''some code here
    If SomeBadExitConditionIsSet Then
        GoTo FuncExit
    End If

    ''some more code here
    MyFunc = True

FuncExit:
    ''kill error handling to avoid error cycling
    On Error Resume Next
    ''cleanup code here - you need to check Err.Number after critical operations!
    ''single exit point
    Exit Function

ErrHandler:
    ''you can insert local specific error processing here, do not forget save Err.Number etc
    ''there is possibility to raise errors to caller function, 
    ''but in this function we do not do that
    Select Case MyGlobalErrHandler(Err.Number, Err.Description)
        Case eRetry
            Resume    ''this is useful while debugging - good place to "Set Next Statement"
        Case eIgnore
            Resume Next
        Case eCancel
            Resume FuncExit
        Case Else
            Resume FuncExit
    Select End
End Function