VB.NET类或模块的目的是什么?

新手酱在这里…所以,我试图找到答案,但不能.

有课程或模块的目的是什么?我读到的所有东西都试图告诉我它是什么,但不是它的用途.我为什么要做一个?

我读到的所有内容似乎都是对阅读教程的人做出假设,好像我知道的很多.

模块实际上非常类似于仅包含共享成员的类.事实上,在C#中,没有像“模块”这样的结构.如果没有至少一个模块或类,你就无法编写任何应用程序,所以我怀疑你真正的问题不是“为什么要使用类和模块”,而是“为什么要使用多个类和模块以及什么时候开始新的模块” .由于模块和类本质上是相同的,我只关注为什么你会有多个类.创建新类主要有四个主要原因:

>将数据存储在谨慎的项目中
>组织您的代码
>在代码中提供接缝
>将代码划分为多个层并支持n层

现在,让我们更详细地看一下每一个:

将数据存储在Discreet项目中

通常,您需要存储关于单个项目的多个数据,并将这些数据作为单个对象在方法之间传递.例如,如果您编写的应用程序适用于某个人,您可能希望存储有关此人的多个数据,例如他们的姓名,年龄和头衔.显然,您可以将这三个数据存储为三个单独的变量,并将它们作为单独的参数传递给方法,例如:

Public Sub DisplayPerson(name As String,age As Integer,title As String)
    Label1.Text = name
    Label2.Text = age.ToString()
    Label3.Text = title
End Sub

但是,将所有数据作为单个对象传递通常更方便,例如,您可以创建MyPersonClass,如下所示:

Public Class MyPersonClass
   Public Name As String
   Public Age As Integer
   Public Title As String
End Class

然后你可以在一个参数中传递一个人的所有数据,如下所示:

Public Sub DisplayPerson(person As MyPersonClass)
    Label1.Text = person.Name
    Label2.Text = person.Age.ToString()
    Label3.Text = person.Title
End Sub

通过这种方式,它可以在将来更容易修改您的人.例如,如果您需要添加为人员存储技能的功能,并且您没有将人员数据放入类中,则必须转到代码中传递人员数据的每个位置并添加其他参数.在一个大型项目中,找到所有要修复的地方可能非常困难,这可能会导致错误.但是,当您开始需要存储多个人的列表时,对课程的需求变得更加明显.例如,如果您需要为10个不同的人存储数据,则需要一个列表或变量数组,例如:

Dim names(9) As String
Dim ages(9) As Integer
Dim titles(9) As String

当然,名称(3)和年龄(3)都存储同一个人的数据并不是很明显.这是你必须要知道的,或者你必须在评论中写下它,所以你不要忘记.但是,当您有一个类来存储一个人的所有数据时,这会更清晰,更容易做到:

Dim persons(9) As Person

现在,很明显人(3).姓名和人(3).年龄都是同一个人的数据.通过这种方式,它是自我记录的.无需评论即可澄清您的逻辑.结果,代码将不再容易出错.

通常,类不仅包含特定项的数据,还包含对该数据起作用的方法.这是一种方便的机制.例如,您可能希望将GetDesciption方法添加到person类,例如:

Public Class MyPersonClass
   Public Name As String
   Public Age As Integer
   Public Title As String

   Public Function GetDescription() As String
       Return Title & " " & Name
   End Function
End Class

然后你可以像这样使用它:

For Each person As MyPersonClass In persons
    MessageBox.Show("Hello " & person.GetDescription())
Next

正如我相信你会同意的那样,比做这样的事情更清洁,更容易:

For i As Integer = 0 To 9
    MessageBox.Show("Hello " & GetPersonDescription(title(i),names(i)))
Next

现在假设你想为每个人存储多个昵称.你可以很容易地看到,人(3).Nicknames(0)比一些疯狂的二维数组简单得多,比如昵称(3)(0).如果您需要存储关于每个昵称的多个数据,会发生什么?正如您所看到的,不使用类会很快变得混乱.

组织您的代码

当你编写一个冗长的程序时,如果你没有正确组织你的代码,它会很快变得非常混乱并导致非常错误的代码.在与意大利面条代码的斗争中,你最重要的武器就是创造更多的课程.理想情况下,每个类只包含逻辑上彼此直接相关的方法.每种新类型的功能都应该分解为一个新命名的类.在一个大型项目中,这些类应该进一步组织成单独的命名空间,但如果你不至少将它们分成几个类,那么你真的会弄得一团糟.例如,假设您将以下方法全部投入到同一模块中:

> GetPersonDescription
> GetProductDescription
> FirePerson
> SellProduct

我相信你会同意,如果将这些方法分解为单独的类,例如:

>人

> GetDescription
>火

>产品

> GetDescription
>卖

这只是一个非常非常简单的例子.当你有成千上万的方法和变量处理许多不同的项目和不同类型的项目时,我相信你可以很容易地想象为什么类对于帮助组织和自我记录代码很重要.

在您的代码中提供接缝

这个可能会更高级,但它非常重要,所以我会尝试用简单的术语来解释它.假设您创建了一个trace-logger类,它将日志条目写入跟踪日志文件.例如:

Public Class TraceLogger
    Public Sub LogEntry(text As String)
        ' Append the time-stamp to the text
        ' Write the text to the file
    End Sub
End Class

现在,假设您希望记录器类能够写入文件或数据库.此时很明显,将日志条目写入文件实际上是一种独立的逻辑类型,它应该一直在它自己的类中,因此您可以将其分解为单独的类,如下所示:

Public Class TextFileLogWriter
    Public Sub WriteEntry(text As String)
        ' Write to file
    End Sub
End Class

现在,您可以创建一个通用接口并在两个不同的类之间共享它.这两个类都将处理写入日志条目,但它们将以完全不同的方式执行功能:

Public Interface ILogWriter
    Sub WriteEntry(text As String)
End Interface

Public Class TextFileLogWriter
    Implements ILogWriter

    Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry
        ' Write to file
    End Sub
End Class

Public Class DatabaseLogWriter
    Implements ILogWriter

    Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry
        ' Write to database
    End Sub
End Class

现在,您已将数据访问逻辑分解为自己的类,您可以像这样重构您的记录器类:

Public Class TraceLogger
    Public Sub New(writer As ILogWriter)
        _writer = writer
    End Sub

    Private _writer As ILogWriter

    Public Sub LogEntry(text As String)
        ' Append the time-stamp to the text
        _writer.WriteEntry(text)
    End Sub
End Class

现在,您可以在更多情况下重用TraceLogger类,而无需触及该类.例如,你可以给它一个ILogWriter对象,它将条目写入windows事件日志,电子表格,甚至是电子邮件 – 所有这些都没有触及原始的TraceLogger类.这是可能的,因为您在逻辑中创建了条目格式和条目写入之间的接缝.

格式不关心条目的记录方式.它关心的是如何格式化条目.当它需要编写和输入时,它只是要求一个单独的编写器对象来完成这部分工作.作者如何以及在内部实际做什么是无关紧要的.类似地,编写器不关心条目是如何格式化的,它只是期望传递给它的任何东西都是需要记录的已经格式化的有效条目.

您可能已经注意到,TraceLogger现在不仅可以重用于写入任何类型的日志,而且编写器可以重用于将任何类型的日志写入这些类型的日志.例如,您可以重用DatabaseLogWriter来编写跟踪日志和异常日志.

关于依赖注入的一点关注

只是幽默我,一点点,因为我对这个问题做了一些关于我的重要事情的答案……在最后一个例子中,我使用了一种称为依赖注入(DI)的技术.它被称为依赖注入,因为writer对象是logger类的依赖项,并且依赖项对象通过构造函数注入到logger类中.通过这样做,您可以在没有依赖注入的情况下完成类似的事情:

Public Class TraceLogger
    Public Sub New(mode As LoggerModeEnum)
        If mode = LoggerModeEnum.TextFile Then
            _writer = New TextFileLogWriter() 
        Else
            _writer = New DatabaseLogWriter() 
        End If
    End Sub

    Private _writer As ILogWriter

    Public Sub LogEntry(text As String)
        ' Append the time-stamp to the text
        _writer.WriteEntry(text)
    End Sub
End Class

但是,正如您所看到的,如果您这样做,现在您需要在每次创建新类型的编写器时修改该记录器类.然后,只需创建一个记录器,就必须引用每种不同类型的编写器.当你以这种方式编写代码时,很快,每当你包含一个类时,你突然不得不引用整个世界来做一个简单的任务.

依赖注入方法的另一种替代方法是使用继承来创建多个TraceLogger类,每种类型的编写器一个:

Public MustInherit Class TraceLogger
    Public Sub New()
        _writer = NewLogWriter() 
    End Sub

    Private _writer As ILogWriter

    Protected MustOverride Sub NewLogWriter()

    Public Sub LogEntry(text As String)
        ' Append the time-stamp to the text
        _writer.WriteEntry(text)
    End Sub
End Class

Public Class TextFileTraceLogger
    Inherits TraceLogger

    Protected Overrides Sub NewLogWriter()
        _Return New TextFileLogWriter() 
    End Sub
End Class

Public Class DatabaseTraceLogger
    Inherits TraceLogger

    Protected Overrides Sub NewLogWriter()
        _Return New DatabaseLogWriter() 
    End Sub
End Class

使用继承这样做比使用模式枚举方法更好,因为您不必仅仅为了记录文本文件而引用所有数据库逻辑,但在我看来,依赖注入更清晰,更灵活.

返回逻辑接缝摘要

因此,总而言之,逻辑中的接缝对于代码的可重用性,灵活性和可互换性非常重要.在小型项目中,这些事情并不是最重要的,但随着项目的发展,明确的接缝可能变得至关重要.

创建接缝的另一大好处是它使代码更稳定和可测试.一旦您知道TraceLogger的工作原理,就可以将其扩展以供将来使用,例如将日志写入电子表格,而无需触及实际的TraceLogger类.如果您不必触摸它,那么您不会冒险引入新错误并可能危及已使用它的其余代码.此外,单独测试每段代码变得更加容易.例如,如果你想测试TraceLogger类,你可以只为你的测试使用一个假的编写器对象,它只记录到内存,控制台或其他东西.

将您的代码划分为图层并支持N层

一旦将代码正确组织到单独的类中,每个类只负责一种类型的任务,那么您就可以开始将类组合在一起.图层只是代码的高级组织.语言中没有任何特定内容可以使技术上的某个层成为一个层.由于语言中没有任何内容可以清楚地表明每个层的开始和结束位置,因此人们通常会将每个层的所有类放入不同的名称空间中.因此,您可能拥有看起来像这样的名称空间(每个名称空间是一个单独的图层):

> MyProduct.Presentation
> MyProduct.Business
> MyProduct.DataAccess

通常,您始终希望代码中至少包含两个层:表示层或用户界面层以及业务逻辑层.如果您的应用程序执行任何数据访问,那么通常也会将其放在自己的层中.每层应尽可能独立且可互换.因此,如果上面示例中的TraceLogger类位于业务层中,则它应该可以通过任何类型的UI重用.

通过提供进一步的组织,自我记录,可重用性和稳定性,层可以扩展所有以前的主题.但是,图层的另一个主要好处是可以更轻松地将应用程序拆分为多个层.例如,如果您需要将业务和数据访问逻辑移动到Web服务中,那么如果您已将代码干净地写入已定义的层中,则这样做非常简单.但是,如果所有这些逻辑混合在一起并相互依赖,那么尝试将数据访问和业务逻辑分解为单独的项目将是一场噩梦.

我要说的结束

简而言之,您永远不需要创建多个类或模块.始终可以将整个应用程序编写在单个类或模块中.毕竟,在面向对象语言被发明之前,开发了整个操作系统和软件套件.但是,面向对象编程(OOP)语言如此受欢迎是有原因的.对于许多项目,面向对象非常有益.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")