现在,我正在开发一个 Web 应用程序,该应用程序从可能返回空结果的数据库中接收大量数据。当通过应用程序的圈复杂度时,许多函数的权重在 10 到 30 之间。在大多数情况下,大多数具有高数字的函数都有很多类似于以下的行:
If Not oraData.IsDBNull(4) Then row("Field") = oraData.GetString(4)
这引出了我的问题,尝试降低这些数字的最佳方法是什么?现在,我正在考虑将大多数功能置于 10 以下。
现在,我正在开发一个 Web 应用程序,该应用程序从可能返回空结果的数据库中接收大量数据。当通过应用程序的圈复杂度时,许多函数的权重在 10 到 30 之间。在大多数情况下,大多数具有高数字的函数都有很多类似于以下的行:
If Not oraData.IsDBNull(4) Then row("Field") = oraData.GetString(4)
这引出了我的问题,尝试降低这些数字的最佳方法是什么?现在,我正在考虑将大多数功能置于 10 以下。
第一个问题是:你为什么“挂”在 CC 上?它是一种评估代码密集程度的工具,经验法则应该是“cc 数字不要太高”。
它可能会击中所有这些“IF”并提出该数字 - 因此通过调用一个包装函数来减少 if 的数量,该函数从处理空值的结果集中提取数据或更改查询以使其不返回空值。
请记住,空值确实提供了信息并且并非无用。例如共和党还是民主党?使用 null 表示没有选择。
分解成函数,可能是这样的:
//Object Pascal
procedure UpdateIfNotNull( const fldName: String; fldIndex : integer );
begin
if oraData.IsDBNull( fldIndex ) then
row( fldName ) := oraData.GetString(fldIndex);
end;
当然,您可以扩展程序签名,以便“oraData”和“row”可以作为参数传递。
使用扩展方法怎么样。
Imports System.Runtime.CompilerServices
Module Extensions
<Extension()> _
Public Function TryGetString(ByVal row As IDataRecord, i As Integer) As String
If row.IsDBNull(i) Then
Return null
End If
Return row.GetString(i);
End Function
End Module
然后你可以简单地写:
row("Field") = oraData.TryGetString(4)
这样可以流畅地读取并降低函数的圈复杂度。
你看到这个问题了吗?他在问类似的问题(但我认为是在更基本的层面上)……但这意味着这里的答案可能没有太大帮助。
我肯定会同意这里的其他建议:如果有重复的语句可以整齐地打包到函数/过程中,这可能是一种可以采用的方法,只要你不只是转移 CC。如果你从一个 CC 为 35 的 proc 转移到三个 CC 分别为 15、10 和 10 的 proc,我不确定你是否获得了太多。(这不是一个糟糕的第一步,但理想情况下你可以在更大范围内简化某些事情,以减少系统该区域的总 CC。)
可以将if重构为单独的实用程序函数以减少 CC。可能需要许多函数或依赖于类型区分的函数来处理不同的数据库类型(字符串、整数等)
但是,我认为任何解决方案都会导致代码的可维护性或可读性降低(即,您可能会恶化其他指标!)并且 QA 会根据这个理由允许它通过。