2016-10-15 50 views
0

我在Java中遇到的大多數SonarLint規則看起來似乎合理並且合理。然而,自從我開始使用SonarLint for VB.NET以來,我遇到了幾條規則,這些規則讓我質疑它們的有用性,甚至是否它們工作正常。SonarLint - 關於VB.NET的一些規則的問題

我想知道這是否僅僅是一個問題,我使用一些VB.NET構造的次優方式或規則是否真的有缺陷。如果這個問題稍微長一點,我不知道是否應該爲每個單獨的規則創建一個單獨的問題。)

我發現以下規則會留下一些未考慮的事實,而這些規則實際上會變成false -positives:

  • S1871:兩支在同一條件結構應該不會有完全相同的實施
    我發現這是帶來了大量的誤報對我來說,因爲有時候順序其中檢查條件實際上很重要。看看下面的僞代碼示例:

    If conditionA() Then 
        doSomething() 
    ElseIf conditionB() AndAlso conditionC() Then 
        doSomethingElse() 
    ElseIf conditionD() OrElse conditionE() Then 
        doYetAnotherThing() 
    '... feel free to have even more cases in between here 
    Else Then 
        doSomething() 'Non-compliant 
    End If 
    

    如果我想按照這個聲納規則,仍然使代碼行爲相同的方式,我不得不每elseif的條件否定版本添加到第一如果條件。
    另一個例子是下面的開關:

    Select Case i 
        Case 0 To 40 
         value = 0 
        Case 41 To 60 
         value = 1 
        Case 61 To 80 
         value = 3 
        Case 81 To 100 
         value = 5 
        Case Else 
         value = 0 'Non-compliant 
    

    不應該有什麼錯用具有一個開關,最後一種情況。沒錯,我可以事先將value初始化爲0,並忽略了最後一種情況,但是接下來我會再做一次分配操作。而Java規則集使我總是在每個交換機中放置一個default案例。

  • S1764:相同的表達不應該在一個二元運算
    這條規則的兩側使用似乎並沒有考慮到某些功能可能每次調用時返回不同的值,例如集合,其中訪問一個元素從集合中刪除:

    stack.Push(stack.Pop()/stack.Pop()) 'Non-compliant 
    

    我明白,如果這是太多的邊緣情況,使它特殊的例外,雖然。

下面的規則,我實際上並不肯定:

  • S3385:「退出」聲明不應該被用來
    雖然我同意Return是更具可讀性比Exit Sub,是它使用單個Exit For突破ForFor Each循環真的不好?對於Java的SonarLint規則允許在將其標記爲問題之前在循環中使用單個break;。爲什麼VB.NET中的默認值在這方面更嚴格?或者是建立在假定您可以使用LINQ擴展方法和lambda來解決幾乎所有循環問題的規則上?
  • S2374:簽名類型應首選那些無符號
    這個規則基本上規定,無符號類型不應該使用在所有因爲他們「有不同的算術運算符有符號的 - 運營商,很少有開發人員瞭解」。在我的代碼中,我只使用UInteger作爲ID值(因爲我不需要負值,而Long在我的情況下會浪費內存)。它們存儲在List(Of UInteger)中,並且只與其他UInteger相比。這條規則是否與我的案例相關(比較規則中提到的這些「算術運算符」的一部分)以及這個陷阱究竟是什麼?如果不是,那麼將這個規則應用於涉及無符號類型的算術運算而不是它們的聲明會更好嗎?
  • S2355:數組常量應該被用來代替陣列創建表達式
    也許我不知道VB.NET不夠好,但我究竟會滿足下列情況下,這個規則,我想創建一個固定大小的數組,初始化長度只在運行時才知道?這是否爲假?

    Dim myObjects As Object() = New Object(someOtherList.Count - 3) {} 'Non-compliant 
    

    當然,我可能只是使用List(Of Object)。但我很好奇。

+0

每個帖子上有不止一個問題是不被接受的;因爲你正在或多或少地要求編碼教程。對於第一個片段,你需要做的是擺脫'如果conditionA()然後'讓機器人開心。雖然規則通常可能是一個好主意,但將'conditionA'留在原地可能是有價值的:a)您可以看到它一目瞭然b)它可能是不斷變化的需求的佔位符。與案例陳述一樣。 Exit Sub/Return和Exit For也有區別。如果機器人不知道,那就擺脫它。 – Plutonix

+0

把'如果conditionA()'排除在等式之外會改變結果。假設條件A(),條件B()和條件C()都被評估爲「真」。正如我所說,訂單很重要。實際上,如果您將第一個案例提取出來,則必須將否定版本的conditionA()添加到所有ElseIf構造,以獲得相同的結果。 很抱歉有多個問題。該帖子實際上更直接針對SonarLint開發者自己,因爲他們的網站指向Stackoverlow的問題。因此,我只是試圖將多個潛在問題分解成一個職位。 –

回答

1

感謝您提出這些觀點。請注意,並非所有規則都適用於每次。有時我們需要在誤報/誤報/實際情況之間進行平衡。例如,在運算符規則的兩側使用相同的表達式。是否有相同操作數的錯誤?不,這不對。如果是,那麼編譯器會報告它。這是一種難聞的氣味,通常是一個錯誤?是的,在很多情況下。例如見Roslyn。我們是否應該調整這個規則來排除一些情況?是的,我們應該,2 << 2沒有錯。所以需要進行很多平衡,並且我們試圖解決爲用戶帶來最大價值的實施方案。

對於點你提到:

  • 兩個分支同樣的條件結構應該不會有完全相同的實施

此規則通常規定,有碼匹配的兩個街區究竟是不好的跡象。應該避免複製粘貼代碼的原因很多,例如,如果需要在一個地方修復代碼,則需要在另一個地方修復代碼。你說得對,添加否定條件將會是一團糟,但是如果你用適當的名字將每個條件提取到它自己的方法中(並調用它們內部的否定方法),那麼它可能會提高代碼的可讀性。

對於Select Case,複製粘貼的代碼總是一個不好的標誌。在這種情況下,你可以這樣做:

Select Case i 
    ... 
    Case 0 To 40 
    Case Else 
    value = 0 ' Compliant 
End Select 

或者乾脆刪除0-40的情況。

  • 相同的表達不應該在一個二元運算

的兩側使用我認爲這是一個極端例子。請參閱答案的第一段。

  • 「退出」聲明不應該被用來

這幾乎總是如此,通過選擇其他類型的循環,或改變停止條件,你可以逃脫不使用任何「退出」的語句。從循環中獲得單個退出點是一種很好的做法。

  • 簽名類型應首選那些無符號

這是SonarQube VB.NET的傳統規則,我同意你的看法,它不應該被默認啓用SonarLint。我創建了我們的JIRA以下機票:https://jira.sonarsource.com/browse/SLVS-1074

  • 數組文本應該被用來代替陣列創建表達式

是的,這似乎是個假陽性,我們不應該對數組的創作報告當明確指定大小時。 https://jira.sonarsource.com/browse/SLVS-1075