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

方法内聚性

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.62/5 (8投票s)

2005年7月14日

CPOL

4分钟阅读

viewsIcon

40949

本文重点讨论在编写程序时构建类以及需要牢记的内聚性因素。

引言

“内聚性”一词指的是粘合、结合在一起的行为、过程或状态。它已广泛应用于物理学、生物学和数学领域,并且让您惊讶的是,也应用于写作领域。内聚性就像胶水一样,将写作内容粘合在一起。编写代码,无论是结构化还是面向对象的,都需要稍微考虑一下内聚性。控制流的转移、关键字的重复和变量的引用是编程时需要注意的一些程序元素,以确保内聚性。是的,下次编写代码时,请考虑内聚性!

类的内聚性

类的内聚性被认为是面向对象设计和软件度量中的最重要的特征之一。

类是面向对象程序的基本单元,并充当封装单元,从而促进其可修改性和可重用性。类的质量由内聚性度量决定,该度量是指类中成员之间的相关程度。高内聚性是类的理想特性。

成员方法服务于共同的目的,并允许您在逻辑上组织一个类。但是,编写不当的方法会降低类的实现或管理例程——这被称为“对象策略”。

示例

如果您有十个方法充当网络操作的实用程序,那么您可以将类分成两个类:一个用于实用程序,另一个用于网络操作。

有几种度量标准可以衡量面向对象系统中的类内聚性——根据类中成员方法之间的连接,以及其他一些基于实例变量使用标准。

现在,让我们来看看方法的内聚性以及它们在 .NET 中的实现方式。

方法内聚性

方法内聚性侧重于您在类中编写的方法。一个方法应该清楚地说明编写它的意图。否则,它就是弱内聚性的。您在一个方法中积累的任务越多,就越有可能编写错误的代码。

软件质量人员已经确定并接受了几种内聚性级别。以下是从最可接受到最不可接受形式的方法内聚性的列表。

功能内聚性

一个方法只做一件事;只有一件事。没有添加任何复杂性。

Public Sub New()
    Mybase.New()
    InitializeObject()
End Sub

上述示例方法执行初始化过程。仅此而已。在编写类时,这种内聚性级别是高度理想和可接受的。

顺序内聚性

一个方法按顺序执行一系列步骤,这些步骤共同构成了整个过程。

Public Shared Sub Main()
    ' Create an instance of StreamWriter to write text to a file.
    Dim sw As StreamWriter = New StreamWriter("TestFile.txt")
    ' Add some text to the file.
    sw.Write("This is the ")
    sw.WriteLine("text for the file.")
    sw.Close()
End Sub

上述方法执行一系列任务,例如打开文件、写入文件和关闭文件。假设您想插入一个额外的步骤(读取文件、排序数据、处理数据),这将削弱内聚性。或者,您可以将控制权转移到另一个方法来执行这些任务,然后返回到关闭文件。

通信内聚性

这种内聚性级别允许您在一个方法中编写多个任务。您包括了不可避免地不相关的任务。

看看这个方法

Private Sub CreateDataTableAndDisplay()
    Dim Table1 As DataTable = New DataTable()
    Dim Table2 As DataTable = New DataTable()
    Dim myColumn As DataColumn 
    Dim myRow As DataRow 
    Dim myDataView As DataView 

    ' Create first column
    myColumn = New DataColumn()
    myColumn.DataType = System.Type.GetType("System.Int32")
    myColumn.ColumnName = "id"
    Table1.Columns.Add(myColumn)
    Table2.Columns.Add(myColumn)
    ' Create second column.
    myColumn = New DataColumn()
    myColumn.DataType = Type.GetType("System.String")
    myColumn.ColumnName = "item"
    Table1.Columns.Add(myColumn)
    Table2.Columns.Add(myColumn)
    ' Create new DataRow objects and add to DataTable. 
    Dim i As Integer
    For i = 0 to 9 
        myRow = myDataTable.NewRow()
        myRow("id") = i
        myRow("item") = "item " & i
        Table1.Rows.Add(myRow)
        myRow("item") = "Grade " & i
        Table2.Rows.Add(myRow)
    Next
    ' Create a DataView using the DataTable.
    myDataView = New DataView(Table1)
    ' Set a DataGrid control's DataSource to the DataView.
    DataGrid1.DataSource = myDataView
    MyDataView = New DataView(Table2)
    DataGrid2.DataSource = myDataView
End Sub

在上述方法中,您可以看到需要通过在运行时创建的两个表中的数据来填充两个数据网格。即使执行第二个表的任务是可以接受的,但是当您开始添加更多内容时,内聚性级别将会崩溃,并且您的方法将看起来很糟糕。

时间内聚性

它允许单个方法执行需要在同一时间执行的一堆活动。这是最不可接受的内聚性级别,程序员必须避免。

Sub GetRequiredData(Option as Boolean) 
    Dim ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0; " & _ 
                  "Data Source=c:\purchase.mdb"
    Dim Conn As New OleDbConnection(ConnStr)
    Dim Comm1 As New OleDbCommand("Select prod_id, prod_name from product, Conn)
    Dim Comm2 As New OleDbCommand("Select item_id, item_name from item, Conn)
    Conn.Open()
    If Option = True then
        Dim myReader1 As OleDbDataReader = Comm.ExecuteReader()
        Call DisplayData(myReader1)
    Else
        Dim myReader2 As OleDbDataReader = Comm.ExecuteReader()
        Call DisplayData(myReader2)
    End if
    Conn.Close()
End Sub

在上述方法中,您会注意到作者使用了 If 条件来确定要调用的方法。相反,他可以完全使用两个单独的方法。

还有其他方法内聚性级别,例如逻辑内聚性和巧合内聚性,它们会做脏活,程序员不应遵循。

结论

类中的方法需要松散耦合,这样它们就不会依赖其他方法的操作。当方法访问或共享全局变量时,它们会变得彼此不希望地耦合。相反,这些应该作为参数传递给一个方法。同样,如果一个方法包含在类中只是为了写入全局变量,以利于其他方法,那么内聚性级别会大大降低。

© . All rights reserved.