65.9K
CodeProject 正在变化。 阅读更多。
Home

Microsoft VisualBasic 的代码风格指南

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2016年5月20日

CPOL

6分钟阅读

viewsIcon

12962

Microsoft VisualBasic 的代码风格指南

 

下载后,将项目引用添加到

Microsoft.VisualBasic.Architecture.Framework/+Microsoft.VisualBasic.Architecture.Framework.vbproj

VisualBasic CLI 程序的代码架构

一个名为 main 的特殊函数是所有 VisualBasic 程序的执行起点。VisualBasic CLI 应用程序应该在一个名为 Program 的模块中定义 Main 入口点,并从一个 Integer Function Main 运行。通过为入口点模块使用 Program 名称,可以更容易识别程序的入口点。

Module Program

    ''' <summary>
    ''' This is the main entry point of your VisualBasic application.
    ''' </summary>
    ''' <returns></returns>
    Public Function Main() As Integer
        Return GetType(CLI).RunCLI(App.CommandLine)
    End Function
End Module

在 VisualBasic 中使用 Integer Function 而不是 Sub,这使得您的代码风格与 C++ 中的 main 函数相比更加标准化。

int main(int argc, char *argv[]) {
    // blablabla...
}

其中,类型 CLI 是一个模块,包含您应用程序的所有 CLI 命令的 CLI 接口。扩展函数 RunCLI 是 VisualBasic App 帮助器中的一个 CLI 扩展方法:Microsoft.VisualBasic.AppApp.CommandLine 的属性值是用户用于启动此应用程序并调用 CLI 模块中公开的一些 CLI 命令的当前应用程序的命令行参数。

如何定义 CLI 模块?

Module 是 VisualBasic 中的静态 Class 类型,通常用于 一组相似或功能相关的实用函数的 API 导出和通用方法定义

因此,VisualBasic 中的 CLI 模块可以解释为:一个用于向用户公开 CLI 接口 API 的模块。

这是一个示例

Partial Module CLI

    <ExportAPI("/Print", Usage:="/Print /in <inDIR> [/ext <ext> /out <out.Csv>]")>
    Public Function Print(args As CommandLine.CommandLine) As Integer
        Dim ext As String = args.GetValue("/ext", "*.*")
        Dim inDIR As String = args - "/in"
        Dim out As String = args.GetValue("/out", inDIR.TrimDIR & ".contents.Csv")
        Dim files As IEnumerable(Of String) =
            ls - l - r - wildcards(ext) <= inDIR
        Dim content As NamedValue(Of String)() =
            LinqAPI.Exec(Of NamedValue(Of String)) <= From file As String
                                                      In files
                                                      Let name As String = file.BaseName
                                                      Let genome As String = file.ParentDirName
                                                      Select New NamedValue(Of String)(genome, name)
        Return content.SaveTo(out).CLICode
    End Function
End Module

此示例代码可在:github 找到

如何在您的应用程序中公开 CLI 接口 API?

用于解析用户命令行的包装器已在命名空间中定义:Microsoft.VisualBasic.CommandLine

并且 CLI 接口应按此示例的格式定义

Imports Microsoft.VisualBasic.CommandLine
Imports Microsoft.VisualBasic.CommandLine.Reflection

<ExportAPI("/Print", Usage:="/Print /in <inDIR> [/ext <ext> /out <out.Csv>]")>
Public Function CLI_API(args As CommandLine) As Integer

使用 VisualBasic 命令行解析器

为了学习如何使用命令行解析器,我们首先学习 VisualBasic 命令行参数的语法。VisualBasic 中典型的命令行参数由两部分组成:1. 命令名称 2. 参数

这是一个简单的例子

App.exe /API1 /test /msg "Hello World!!!" /test2-enable /test3-enable

在此 CLI 中,标记 App.exe 是您应用程序的可执行文件名;/API1 标记是 命令名称;然后最后几个标记是参数,在 VisualBasic 中使用命令行就像在 VisualBasic 中进行函数式编程一样

Module App
    Public Function API1(test As Boolean, 
                         msg As String, 
                         test2Enable As Boolean, 
                         test3Enable As Boolean) As Integer
End Module

您在控制台终端中调用 CLI 命令就像在 VisualBasic 代码中调用函数一样

Dim code As Integer = App.API1(True, "Hello World!!!", True, True)

注意: VisualBasic CLI 参数没有顺序,因此所有这些 CLI 示例彼此相等

App.exe /API1 /msg "Hello World!!!" /test2-enable /test3-enable /test
App.exe /API1 /msg "Hello World!!!" /test /test2-enable /test3-enable
App.exe /API1 /test /test2-enable /test3-enable /msg "Hello World!!!"
App.exe /API1 /test2-enable /test /test3-enable /msg "Hello World!!!"

VisualBasic CLI 应用程序的简单示例(示例源代码在此处

Imports Microsoft.VisualBasic.CommandLine
Imports Microsoft.VisualBasic.CommandLine.Reflection

Module Program

    Public Function Main() As Integer
        Return GetType(CLI).RunCLI(App.CommandLine)
    End Function
End Module

Module CLI

    <ExportAPI("/API1",
           Info:="Puts the brief description of this API command at here.",
           Usage:="/API1 /msg ""Puts the CLI usage syntax at here""",
           Example:="/API1 /msg ""Hello world!!!""")>
    Public Function API1(args As CommandLine) As Integer
        Call Console.WriteLine(args("/msg"))
        Return 0
    End Function
End Module

以下是此 示例 CLI 中 VisualBasic CLI 解析器的一些常用函数

App.exe /Test-Example /b /n 52 /xml "~/test.Xml" /num_threads 96 /path "~/tmp/test.log"
函数 用法 示例
CommandLine.GetBoolean(String) As Boolean 从 CLI 获取布尔标志参数 Dim b As Boolean = args.GetBoolean("/b")
CommandLine.GetInt32(String) As Integer 将参数值获取为 Integer Dim n As Integer = args.GetInt32("/n")
CommandLine.GetObject(Of T)(String, System.Func(Of String, T)) As T 获取参数字符串值,然后对其应用字符串解析器以加载 .NET 对象 Dim x As T = args.GetObject(of T)("/xml", AddressOf LoadXml)
CommandLine.GetValue(Of T)(String, T, System.Func(Of String, T)) As T 获取参数值,如果参数不存在,则返回默认值,此方法通常用于可选值 Dim n As Long = args.GetValue("/num_threads", 100L)
CommandLine.Item(String) As String 用于读取特定参数字符串值的默认只读属性 Dim path As String = args("/file")

VisualBasic 中的 List(Of T) 操作

要启用此语言语法特性并使用此部分中的列表特性,您应该首先导入命名空间 Microsoft.VisualBasic

Dim source As IEnumerable(Of <Type>)
Dim list As New List(of <Type>)(source)

用于添加新实例

list += New <Type> With {
    .Property1 = value1,
    .Property2 = value2
}

用于添加一系列新元素

list += From x As T
        In source
        Where True = <test>
        Select New <Type> With {
            .Property1 = <expression>,
            .Property2 = <expression>
        }

如果想从列表中删除特定元素

list -= x

或批量删除元素

list -= From x As T
        In source
        Where True = <test>
        Select x

以下是列表 + 运算符的一些示例

' This add operation makes the code more easily to read and understand:
' This function returns a list of RfamHit element and it also merge a
' list of uncertainly elements into the result list at the same time
Public Function GetDataFrame() As RfamHit() Implements IRfamHits.GetDataFrame
    Return hits.ToList(Function(x) New RfamHit(x, Me)) + From x As Hit
                                                         In Uncertain
                                                         Select New RfamHit(x, Me)
End Function

使用 + 运算符将新对象添加到列表中,这种语法可以使代码更具可读性,而不是使用方法 List(of T).Add 造成的差可读性代码

genomes += New GenomeBrief With {
    .Name = title,
    .Size = last.Size,
    .Y = h1
}

' Using the + operator to instead of this poorly readable function code
genomes.Add(New GenomeBrief With {
        .Name = title,
        .Size = last.Size,
        .Y = h1
    })

VisualBasic 标识符名称

1. 目录类型

如果可能,所有目录路径变量都可以是 大写,例如

Dim DIR As String = "/home/xieguigang/Downloads"
Dim EXPORT As String = "/usr/lib/GCModeller/"

2. 模块变量

  • 如果变量是 私有 的,所有模块变量都应采用 _lowerUpper 格式
  • 但如果变量是 PublicFriend 可见的,则应采用 UpperUpper 格式

这是一个示例

' Private
Dim _fileName As String
Dim _inDIR As Directory

' Public
Public ReadOnly Property FileName As String
Public ReadOnly Property InDIR As Directory

3. 局部变量和函数参数

如果可能,函数或子程序中的所有局部变量以及函数参数都应采用 lowerUpper 格式

4. 函数和类型名称

对于 Public 成员函数,函数名建议采用 UpperUpper 格式,但如果函数是 Private、Friend 或 Protected 可见的,则建议您的函数以两个下划线开头,例如 __lowerUpperClass、Structure 名称的定义与函数名相同。

以下是一些函数名示例(示例选自此处

' Private
Private Function __worker(Of T As I_GeneBrief)(genome As IGenomicsContextProvider(Of T),
                                            getTF As Func(Of Strands, T()),
                                            getRelated As Func(Of T, T(), Integer, T()),
                                            numTotal As Integer,
                                            ranges As Integer) As Density()
' Public
Public Function DensityCis(Of T As I_GeneBrief)(
                            genome As IGenomicsContextProvider(Of T),
                            TF As IEnumerable(Of String),
                            Optional ranges As Integer = 10000) As Density()

  • 接口类型名称应以大写字母 I 开头,例如 IEnumerableIList
  • 枚举类型名称应以小写字母 s 结尾,例如 MethodTypesFormatStyles

最后,为了提高代码可读性,请尝试 尽可能缩短标识符名称

Code standard overview example

字符串操作

1. String.Format

对于格式化字符串输出,建议使用 String.Format 函数或 VisualBasic 语言中的字符串插值语法。并且通过使用 String.Format 函数,建议将格式控制字符串放入常量变量中,而不是直接在格式函数中使用

Const OutMsg As String = "Hello world, {0}, Right?"
' blablabla.......
Dim msg As String = String.Format(OutMsg, name)
2. 字符串连接

为了连接大量字符串标记,建议使用 StringBuilder 来完成此任务,不建议直接使用 & 运算符 连接大量字符串集合,原因在于性能问题

' Convert the input string to a byte array and compute the hash.
Dim data As Byte() = md5Hash.ComputeHash(input)

' Create a new Stringbuilder to collect the bytes
' and create a string.
Dim sBuilder As New StringBuilder()

' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
For i As Integer = 0 To data.Length - 1
    sBuilder.Append(data(i).ToString("x2"))
Next i

Return sBuilder.ToString() ' Return the hexadecimal string.

如果您只是想连接字符串,建议使用共享方法 String.Join。如果字符串标记将由特定分隔符连接,则使用 String.Join 而不是 StringBuilder.Append

Dim tokens As String()
Dim sb As New StringBuilder

For Each s As String In tokens
    Call sb.Append(s & " ")
Next
Call sb.Remove(sb.Length -1)

或者直接使用 String.Join,这种方法比 StringBuilder.Append 更简洁易读

Dim tokens As String()
Dim out As String = String.Join(" ", tokens)
3. 字符串插值

VisualBasic 语言中的字符串插值语法建议用于 构建 SQL 语句和 CLI 参数,因为这种语法非常易于理解和代码可读

Dim SQL As String = $"SELECT * FROM table WHERE id='{id}' AND ppi>{ppi}"
Dim CLI As String = $"/start /port {port} /home {PathMapper.UserHOME}"

所以,使用这种语法特性会使您的代码非常容易阅读和理解代码含义,对吗?

Linq 表达式

如果表达式的输出类型是已知类型,建议所有 Linq 表达式都使用 LinqAPI 执行

附录

以下是我在编程中使用的一些名称表,并将持续更新....

1. 常用类型的一些常用名称

System.Type 推荐名称 示例
System.Text.StringBuilder sb

 

Dim sb As New StringBuilder

 

System.String s, str, name, sId, id, x

 

Dim s As String
Dim str As String
Dim name As String
Dim sId As String
Dim id As String
Dim x As String

 

System.Integer, System.Long i, j, n, x

 

Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim x As Integer

 

System.Object x, o, obj, value

 

Dim x As Object
Dim o As Object
Dim obj As Object
Dim value As Object

 

 

2. 一些有意义的名称

含义 推荐名称 示例
命令行参数 args, CLI
Dim args As CommandLine
Dim CLI As String
Dim args As String()
SQL 查询 SQL, sql, query
Dim SQL As String = "SELECT * FROM table LIMIT 1;"
迭代器 i, j, k, l
For i As Integer = 0 to [stop]
    For j As Integer = i to [stop]
        For k As Integer = j to [stop]
        Next
    Next
Next

Dim l As Integer = 100

Do while l = 100
    ' blablabla...
Loop
Linq 查询表达式 LQuery
Dim LQuery = From path As String
             In ls -l -r -wildcards("*.Xml") <= DIR
             Where InStr(path.BaseName, "xcb") = 1
             Select path.LoadXml(Of KEGG.DBGET.Module)
查询结果/函数返回值 result, rtvl
Dim result As [Module] = 
    LinqAPI.Exec(Of [Module]) <= 
         From path As String
         In ls -l -r -wildcards("*.Xml") <= DIR
         Where InStr(path.BaseName, "xcb") = 1
         Select path.LoadXml(Of KEGG.DBGET.Module)
        
Return result
© . All rights reserved.