3

我正在重构一个相当大的项目,我有兴趣寻找和减少代码克隆,以实现更好的标准化和易于开发。

我有一个代码片段不断出现在“精确匹配”中(使用 Visual Studio 2012 的“查找代码克隆”功能)。

这里是:

                End If
            End Using
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Using
End Using
Return Nothing

基本上,我有一大堆类似的功能(结构类似,但实际功能不同),它们都以这样的方式打开:

Const sql As String = ...
Using cn As SqlConnection...
    Using cmd As SqlCommand(sql,cn)
        ... Maybe add some SqlParameters
        cn.Open()
        ... Something with cmd.Execute...

现在,我认识到第一个代码块很多很多方法中都是相同的,但是我想不出一种方法来提取该代码,编写一次并在每次需要该功能时简单地调用它。在我看来,发生了太多的控制流。

所以,我不知道如何解决这个问题(我只是假设我可以“解决”这个问题,因为微软已将其标识为“克隆代码”)。

我正在考虑制作少量函数来做相同类型的事情(比如从表中返回一个计数,返回一个最高值等......),并且只有 SQL 真正不同被执行。不过,这可能有点棘手,因为有时参数(类型和数量)会有所不同。

有什么想法吗?

4

3 回答 3

2

我不会关心那些。你的常识性第一印象是正确的。虽然从技术上讲,语法被重复多次,但它并不是真正的逻辑或任何类型的算法的重复。这并不是说没有办法减少这种重复,只是这样做,您最终可能会在代码中得到更糟糕的设计。

例如,您可以创建一个方法来完成所有设置和拆卸,然后在中间调用一个实际使用连接来完成工作的方法,例如:

Public Function PerformDbTask(task As IMyDbTask)
    Using cn As SqlConnection...
        Using cmd As SqlCommand = cn.CreateCommand()
            Try
                cn.Open()
                task.Perform(cmd)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Using
    End Using
    Return Nothing
End Function

然而,你真正得到了什么?可能一点也不多,但你已经失去了很多灵活性。因此,除非这种设计对于您正在尝试做的事情实际上是必要的,否则我不会浪费时间尝试解决不存在的问题。

于 2013-01-02T16:50:28.533 回答
1

您可以创建一个实现构建器模式的类,最终看起来像

Dim list =
    SqlBuilder.Query("SELECT ...")
              .WithConnection("...connection string...")
              .WithParameter(userName)
              .WithParameter(lastTrackId)
              .RetrieveTopRows(10)
于 2013-01-02T16:44:40.080 回答
0

您的问题是您正在使用与标记序列匹配的克隆检测器(因此它与您展示的块结束序列匹配),而不是与代码结构匹配的克隆检测器。虽然令牌序列技术上是一个克隆,但它并不是一个有趣的克隆。令牌克隆检测器会产生许多这样的“误报”克隆,这只会浪费您的时间。

构建令牌序列检测器更容易,这就是他们将其内置到 MS Studio 中的原因。如果您想要更好的探测器,您必须走出 Studio。

您应该研究与抽象语法树匹配的克隆检测器。它们不会产生这种误报,并且可以找到具有复杂参数(与单令牌参数相反)的克隆。

您还应该了解,仅仅因为某些东西已被识别为克隆,并不总是容易或不可能将其重构掉。您拥有的语言可能没有足够强大的抽象机制来处理这种情况。

于 2013-01-02T18:00:58.467 回答