(続)クローンコードを検出する

Understand

はじめに

先日の記事にてCloned Functionsプラグインをご紹介いたしました。(前回の記事:クローンコードを検出する

既に反響をいただいており、頂いたフィードバックの中で、以下のようなものがありました。

  • getter/setterなど、コード行数が非常に短いものが大量に出力されてしまう
  • 実行に時間がかかる

そこで、今回はCloned Functionsプラグインに対し、関数の行数に着目した改善を実施したプラグインを紹介したいと思います。

なお、前回の記事でご紹介した既存のCloned Functionsプラグインでは、Min Token Lengthを指定することで、トークン数の観点で”短い関数”を除外することが可能です。

今回の改善内容

今回の改善内容をひとことで説明すると、「クローンコードの検査対象関数を行数メトリクスを使用してあらかじめ絞ることで、プラグインの実行時間やレポート出力される関数の数を削減する」となります。

本記事の対象者

本記事は既存のプラグインに課題を感じている方向けの記事となります。
このため、ご利用いただく際に、既存プラグインで充足できている方は、本記事の内容は参考程度の内容としてお読みください。

改善内容の説明

既存プラグインの検出手順

Cloned Functionsプラグインでは、主に以下の手順でCloned Functionを抽出しています。
※詳細はプラグインのコードを参照ください

1. 検査対象の関数群をリストアップ
2. 各関数内に登場するトークンを種類毎に分類
3. 分類された種類毎に特定の文字に置き換える
4. 関数を(トークン種類)文字列で表す
5.(トークン種類)文字列同士を比較することで、関数の類似性を検査する
6. 一定の類似性がある場合に、Cloned Functionのペアとして抽出

改善内容

上記検出手順のうち、手順5でトークンの類似性を検査していますが、事前に手順1で検査対象の関数群を抽出する際に、
コード行数(CountLineCode)が一定値以下の関数を除外することにより、プラグインによる検査実行時間の短縮させることが可能です。
(Min CountLineCodeとMin Token Length、Max Token LengthはAND条件として動作します。)

CountLineCode:行数メトリクスのうち、コード行のみをカウントするメトリクスとなります。
詳細は以下の記事をご確認ください。
https://understand.techmatrix.jp/count/

追加した項目説明
Min CountLineCode類似性の検査対象から、
CountLineCodeがここで指定した値以下の関数をあらかじめ除外します。


本プラグイン(ClonedFunctionsWithCoutLineプラグイン)のオプション設定画面

本プラグインのダウンロードとインストール

こちらからzipファイルをダウンロードしてください。
ブラウザーの設定によってzipファイルをダウンロードできない場合があります。
ダウンロード時に警告が表示される場合やその他ご質問などありましたら、SciTools 製品カスタマーセンター までお気軽にお問合せください。
ダウンロードしたupyファイルは、UnderstandのGUI画面にドラッグ&ドロップすることで、プラグインをインストールすることが可能です。

プラグイン活用上の留意事項

保守性や構造化プログラミングを無視した安易なコピープログラミングの結果作成される関数には、一般にいくつかの課題(1つの変更理由で複数箇所の変更が必要になる等)があります。
しかし、Understandに同梱されているCloned Functionsプラグインやその改良版であるClonedFunctionsWithCountLineプラグインで出力された関数ペアはあくまでもコード記述が類似している関数ペアを抽出するに過ぎません。
このため、本プラグインで抽出された関数ペアをリファクタリングする場合には、以下の点に留意する必要があります。

留意事項(DRY原則の誤用)
コードが類似している場合でも、責務が異なる関数である場合には、無理にまとめて複数の責務を持つ関数を作成してしまうと、密結合の原因となり、変更の影響範囲を広げる原因になる場合があります。

(例)夏セール用割引関数とデイリータイムセール用割引関数

夏セール用割引関数とデイリータイムセール用割引関数はコードは類似すると考えられますが、責務が異なります。
責務が異なる、すなわち想定される変更理由が異なるため、これらを1つの関数にまとめてしまうと複数の責務を抱えた関数となり、密結合するため、仕様追加や仕様変更がしづらくなることに繋がると考えられます。
これを無理に進めると条件分岐やネストの多い複雑な関数が作成される結果になり、今後のテスト工数の増大やコードの可読性の低下から開発効率の低下につながると考えられます。
この場合には素直に単一責任の原則に従い、それぞれを単一責務の関数として分けたままにしておいたほうが都合が良いとなります。

○参考
仙塲 大也, 『良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方』, 技術評論社, 2022, p.151
Andy Hunt、Dave Thoma,『達人プログラマー―システム開発の職人から名匠への道』, オーム社, 2020, p.31

まとめ

本プラグインを利用することで、既存のCloned Functionsプラグインを使用するよりも、実行時間の短縮やPC使用リソースの抑制、出力結果の抑制が期待できます。
プロジェクト規模が大きい、PCリソースが足りないなどにより、既存のCloned Functionsプラグインの活用が進まない場合には、ご利用をご検討ください。