Click here to Skip to main content
13,802,091 members
Click here to Skip to main content
Add your own
alternative version

Stats

6.8K views
3 bookmarked
Posted 20 May 2016
Licenced CPOL

Code style guidelines for Microsoft VisualBasic

Rate this:
Please Sign up or sign in to vote.
Code style guidelines for Microsoft VisualBasic

 

When after downloads, add project reference to 

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

Code Architecture of a VisualBasic CLI program

A special function named main is the starting point of execution for all VisualBasic programs. A VisualBasic CLI application should define the Main entry point in a Module which is named Program and running from a Integer Function Main. By using the name of Program for the entry point module, this will makes more easily recognize of your program's entry point.

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

By using a Integer Function instead of Sub in VisualBasic, this makes your code style is more standard compare with the main function from C++.

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

Where, the type CLI is the CLI interface which it is a module that contains all of the CLI command of your application. And the extension function RunCLI is a CLI extension method from the VisualBasic App helper: Microsoft.VisualBasic.App. The property value of App.CommandLine is the commandline argument of current application that user used for start this application and calling for some CLI command which is exposed in CLI module.

How to define the CLI module?

Module is a static Class type in the VisualBasic, and it usually used for the API exportation and common method definition for a set of similarity or functional correlated utility functions.

And then so that the CLI module in the VisualBasic can be explained as: A module for exposed the CLI interface API to your user.

Here is a example:

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

This example code can be found at: github

How to expose the CLI interface API in your application?

A wrapper for parsing the commandline from your user is already been defined in namespace:Microsoft.VisualBasic.CommandLine

And the CLI interface should define as in the format of this example:

<code>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
</code>

Using the VisualBasic CommandLine Parser

For learn how to using the CommandLine Parser, we first lean the syntax of the VisualBasic commandline arguments. A typical commandline arguments in VisualBasic is consist of two parts: 1. Command Name 2. Arguments

Here is a simple example:

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

Where in this CLI, token App.exe is the executable file name of your application; And /API1 token, is the Command Name; And then the last tokens are the parameter arguments, using the commandline in VisualBasic just like function programming in VisualBasic:

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

You call your CLI command in the console terminal is just like call a function in the VisualBasic Code:

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

NOTE: There is no order of the VisualBasic CLI arguments, so that all of these CLI examples are equals to each other:

<code>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!!!"
</code>

Simple Example of VisualBasic CLI application(Example source code at here):

<code>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
</code>

Here are some mostly used function in VisualBasic CLI parser for this Example CLI:

<code>App.exe /Test-Example /b /n 52 /xml "~/test.Xml" /num_threads 96 /path "~/tmp/test.log"
</code>
Function Usage Example
CommandLine.GetBoolean(String) As Boolean Get a boolean flag argument from the CLI Dim b As Boolean = args.GetBoolean("/b")
CommandLine.GetInt32(String) As Integer Get a parameter value as Integer Dim n As Integer = args.GetInt32("/n")
CommandLine.GetObject(Of T)(String, System.Func(Of String, T)) As T Get a parameter string value and then apply a string parser on it for load an .NET object Dim x As T = args.GetObject(of T)("/xml", AddressOf LoadXml)
CommandLine.GetValue(Of T)(String, T, System.Func(Of String, T)) As T Get a parameter value, if the parameter is not exist, then default value will be returns, this method is usually used on optional value Dim n As Long = args.GetValue("/num_threads", 100L)
CommandLine.Item(String) As String Default readonly property for read string value of a specific parameter Dim path As String = args("/file")

List(Of T) operation in VisualBasic

For enable this language syntax feature and using the list feature in this section, you should imports the namespaceMicrosoft.VisualBasic at first

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

For Add a new instance

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

For Add a sequence of new elements

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

if want to removes a specific element in the list

<code>list -= x
</code>

Or batch removes elements:

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

Here is some example of the list + operator

<code>' 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
</code>

And using the + operator for add a new object into the list, this syntax can makes the code more readable instead of the poorly readable code from by using method List(of T).Add:

<code>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
    })
</code>

VisualBasic identifer names

1. Directory type

If possible, then all of the directory path variable can be UPCASE, such as:

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

2. Module variable

  • All of the module variable should in format like _lowerUpper if the variable is private
  • But if the variable is Public or Friend visible, then it should in format like UpperUpper

Here is some example:

<code>' Private
Dim _fileName As String
Dim _inDIR As Directory

' Public
Public ReadOnly Property FileName As String
Public ReadOnly Property InDIR As Directory
</code>

3. Local varaible and function parameter

If possible, all of the local varaible within a function or sub program and the parameters of a function, should be in formatlowerUpper

4. Function And Type name

For Public member function, the function name is recommended in formats UpperUpper, but if the function is Private, Friend, or Protected visible, then your function is recommended start with two underlines, likes __lowerUpper. The definition of the Class, Structure names is in the same rule as function name.

Here is some function name examples(Example picked from here):

<code>' 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()
</code>

  • Interface type name should start with a upcase character I, like IEnumerableIList, etc
  • Enum type name should end with a lower case character s, like MethodTypesFormatStyles

At last, for improves of the code readable, try Make your identifier name short enough as possible

Code standard overview example

String manipulate

1. String.Format

For formatted a string output, then recommended used String.Format function or string interpolate syntax in VisualBasic language. And by using the String.Format function, then format control string is recommended puts in a constant variable instead of directly used in the format function:

<code>Const OutMsg As String = "Hello world, {0}, Right?"
' blablabla.......
Dim msg As String = String.Format(OutMsg, name)
</code>
2. String contacts

For contacts a large amount of string tokens, the StringBuilder is recommended used for this job, not recommend directly using & operator to contacts a large string collection due to the reason of performance issue.

<code>' 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.
</code>

If you just want to contact the string, then a shared method String.Join is recommended used. If the string tokens will be join by a specific delimiter, then using String.Join instead of StringBuilder.Append

<code>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)
</code>

Or just use String.Join, this method is more clean and readable than StringBuilder.Append:

<code>Dim tokens As String()
Dim out As String = String.Join(" ", tokens)
</code>
3. String interpolate

The string interpolate syntax in VisualBasic language is recommended used for build SQL statement and CLI arguments as this syntax is very easily for understand and code readable:

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

So, using this syntax feature makes your code very easy for reading and understand the code meaning, right?

Linq Expression

All of the Linq Expression is recommended execute using LinqAPI if the output type of the expression is a known type:

Appendix

Here are tables of names that i used in my programming, and continues updated....

1.Some common used name for common types

System.Type Recommend Name Example
System.Text.StringBuilder sb

 

<code>Dim sb As New StringBuilder
</code>

 

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

 

<code>Dim s As String
Dim str As String
Dim name As String
Dim sId As String
Dim id As String
Dim x As String
</code>

 

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

 

<code>Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim x As Integer
</code>

 

System.Object x, o, obj, value

 

<code>Dim x As Object
Dim o As Object
Dim obj As Object
Dim value As Object
</code>

 

 

2.Name for some meaning

Meaning Recommend Name Example
Commandline arguments args, CLI
Dim args As CommandLine
Dim CLI As String
Dim args As String()
SQL query SQL, sql, query
Dim SQL As String = "SELECT * FROM table LIMIT 1;"
Iterator 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 query expression 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)
Query Result/Function Returns 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Mr. xieguigang 谢桂纲
Student 中国南方微生物资源利用中心(SMRUCC)
China China
He is good and loves VisualBasic!



github: https://github.com/xieguigang

You may also be interested in...

Pro

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.181215.1 | Last Updated 20 May 2016
Article Copyright 2016 by Mr. xieguigang 谢桂纲
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid