17

先日、NDepend (すばらしいツールでチェックしてください)を使用して、維持しているレガシーシステムを少し調べていました。私の発見はほとんど私が私のスクリーン全体に一口のコーヒーをスプレーするようにさせました。循環的複雑度の降順でランク付けされたこのシステムの上位3つの関数は次のとおりです。

  1. SomeAspNetGridControl.CreateChildControls(CC of 171 !!!)
  2. SomeFormControl.AddForm(94のCC)
  3. SomeSearchControl.SplitCriteria(85のCC)

私は171を意味します、すごい!!! 20以下でいいのではないですか?だから、これは私に不思議に思いました。あなたが維持している、またはリファクタリングした最も複雑な機能は何ですか?そして、そのようなメソッドをどのようにリファクタリングしますか?

注:私が測定したCCは、ILではなくコード上にあります。

4

4 に答える 4

18

これは、私が数年前に取り組んだ1970年代のビンテージCOBOLと比較した場合の子供向けのものです。オリジナルのMcCabeツールを使用して、一部のコードのCCをグラフィカルに表示しました。機能パスを示す線が非常に密集していてスパゲッティのようだったため、プリントアウトは真っ黒でした。数字はありませんが、171よりずっと高くなければなりませんでした。

何をすべきか

コードごとの完了(初版):

スコアが次の場合:

  • 0-5-ルーチンはおそらく問題ありません
  • 6-10-ルーチンを簡素化する方法について考え始める
  • 10+-ルーチンの一部を2番目のルーチンに分割し、最初のルーチンから呼び出します

元のルーチンを分割するときに、単体テストを作成することをお勧めします。

于 2009-09-01T23:40:43.590 に答える
3

これは、現在製品に同梱されているC /C++コード用です。

確実に識別できる最高のCC値(つまり、ツールがmain(...)の無関係なインスタンスの複雑さの値を誤って追加しているとは思わない):

  • 画像処理機能:184
  • 検証付きのデータベースアイテムローダー:159

CC = 339のテストサブルーチンもありますが、これは厳密には出荷製品の一部ではありません。そこに実装されているテストケースを実際にどのように検証できるのだろうかと思います...

はい、有罪を保護するために関数名は抑制されています:)

変更方法:

この問題を解決するための取り組みはすでに実施されています。問題は主に2つの根本的な原因によって引き起こされます:

  1. スパゲッティコード(カプセル化なし、コピー&ペーストが多い)
  2. 実際のソフトウェア構築/エンジニアリング/大工のトレーニングを受けていない一部の科学者によって製品グループに提供されたコード。

主な方法は、スパゲッティのまとまりのある部分を識別し(スレッドを引っ張る:))、looooong関数をより短い関数に分割することです。多くの場合、関数またはヘルパークラス/オブジェクトに抽出できるマッピングまたは変換があります。手作りのコンテナーやイテレーターの代わりにSTLを使用するように切り替えると、多くのコードも削減できます。C文字列の代わりにstd::stringを使用すると、非常に役立ちます。

于 2009-09-07T12:14:39.133 に答える
0

私はこのブログエントリからこれについて別の意見を見つけました。これは、さまざまなコードベースと比較するときに意味があり、うまくいくようです。私はそれが非常に意見の多いトピックであることを知っているので、YMMV。

  • 1-10-単純で、リスクはあまりありません
  • 11-20-複雑で低リスク
  • 21-50-複雑すぎる、中程度のリスク、注意
  • 50以上-複雑すぎる、テストできない、リスクが高い
于 2019-02-06T12:07:07.557 に答える
0

これらはPerfectTINの6つの最も複雑な機能であり、数週間以内に本番環境に移行することを願っています。

32      32      testptin.cpp(319): testmatrix
36      39      tincanvas.cpp(90): TinCanvas::tick
53      53      mainwindow.cpp(126): MainWindow::tick
56      60      perfecttin.cpp(185): main
58      58      fileio.cpp(457): readPtin
62      62      pointlist.cpp(61): pointlist::checkTinConsistency

2つの数値が異なる場合、それはswitchステートメントによるものです。

testmatrix連続した複数のorder-2およびorder-1forループで構成されており、理解するのは難しくありません。私がベジトポでそれを書いた何年も後にそれを見て私を困惑させたのは、それが83までに何かを改造する理由です。

2つのtickメソッドは1秒間に20回実行され、いくつかの条件をチェックします。複雑さに少し問題がありましたが、バグは、メニュー項目がグレー表示されるべきでないときにグレー表示されたり、TIN表示が不安定に見えたりすることよりも悪いことではありません。

TINは、ポイント、エッジ、および三角形がすべて互いに向き合っている、バリアントのウィングエッジ構造として格納されます。checkTinConsistency構造が複雑であり、それが間違っている可能性があるいくつかの方法があるため、それがそうであるように複雑でなければなりません。

PerfectTINで見つけるのが最も難しいバグは、循環的バグではなく、並行性バグでした。

Bezitopoで最も複雑な関数(私はBezitopoからコードをコピーしてPerfectTINを開始しました):

49      49      tin.cpp(537): pointlist::tryStartPoint
50      50      ptin.cpp(237): readPtin
51      51      convertgeoid.cpp(596): main
54      54      pointlist.cpp(117): pointlist::checkTinConsistency
73      80      bezier.cpp(1070): triangle::subdivide
92      92      bezitest.cpp(7963): main

maininbezitestは、ifステートメントの長いシーケンスです。三角形をテストする必要がある場合は、を実行しtesttriangleます。測定単位をテストする必要がある場合は、を実行しtestmeasureます。等々。

の複雑さsubdivideは、丸め誤差が関数がチェックしなければならない見栄えの悪い条件を生成することはめったにないためです。

現在はtryStartPointその一部として使用されているものmaketin(現在はわずか11の複雑さ)で、さらに複雑になっています。GUIから呼び出して画面を更新する必要があったため、ループの内側を別の関数に分割しました。

于 2020-05-15T09:37:32.403 に答える