Javaコードでの循環的複雑度の処理

Javaコードで循環的複雑度に対処するDebadattaMishraはじめにJavaでのコード管理という用語を聞いたことがあるかもしれません。これは、ソースコードを管理して、メンテナンス時にある程度扱いやすくする方法を指します。要件は時々変化し、ソースコードはある程度変化することは常に真実です。特定のモジュールに触れるのは非常に危険だと思われるかもしれません。このモジュールは正常に機能しているが、コードは管理できないと言う人もいます。これはほとんどのIT業界で発生しますが、いくつかの理由が考えられます。しかし、コードを書くことは芸術だと言えます。一部の開発者はこの問題を非常に真剣に受け止めています。組織内でコードレビューとコード監査の機会を見つけることができます。より良いコードを書く方法は、この記事の範囲を超えています。この記事では、ソースコードではるかに一般的な循環的複雑度に焦点を当てたいと思います。この概念から身を遠ざけることができるのも事実です。重要な注意点は、コードの複雑さに対処する方法です。

技術

循環的複雑度は、ThomasMcCabeによって造られたメトリックの概念です。これは、メソッドまたはソースコードの構造的な複雑さの概念を提供します。基本的には、さまざまな決定的および条件付きのケースを扱います。いくつかの論理的な決定と条件を含むコードを作成している場合は、そのコードを処理する必要があります。そうしないと、条件が低下する可能性があります。バグ修正といくつかのマイナーな要件変更が原因で発生すると言える主な理由。開発者が機能的なケースのいくつかを忘れた場合、ifまたはネストされたif条件を記述して、1つ以上の論理条件を追加することでバグを修正できます。一般に、循環的複雑度は次の方法で計算できます。

循環の複雑さ=決定ポイントの数+1決定ポイントは、if、if…else、switch、forループ、whileループなどの条件ステートメントである可能性があります。

次の例を参照してくださいStringstr =“ someString”; if(str.equals(case1))何かをする; if(str.equals(case2))何かをする; それ以外の場合はデフォルトのことを行います。

ここで、循環的複雑度は次のようになります。循環的複雑度= if for case1 + if for case2 + else + 1 = 4循環的複雑度は、テストと保守性の分野でより重要です。テストケースを作成している場合は、循環的複雑度に注意する必要があります。循環的複雑度が3の場合、少なくとも有効なテストケースを作成する必要があります。次の表は、アプリケーションのタイプを示しています。循環的複雑度は1〜10になります通常のアプリケーションと見なされます循環的複雑度は11〜20になります中程度のアプリケーション循環的複雑度は21〜50になります危険なアプリケーション循環的複雑度は50以上になります不安定なアプリケーション「&&」などの論理演算子に加えて、「|| 」循環的複雑度にも追加されます。次のようなプログラムを作成している場合If(name.equals(name1)|| name。equals(name2)|| name.equals(name3)&& age!= 23){何かをする}ここで循環的複雑度は次のように計算できます。決定点の数+論理演算子の数+1これはIf +に等しい|| + || + && + 1 = 5アプリケーションのパフォーマンスに影響を与えることも事実です。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、それぞれのケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。equals(name3)&& age!= 23){何かをする}ここで循環的複雑度は次のように計算できます。決定点の数+論理演算子の数+1これはIf +に等しい|| + || + && + 1 = 5 Itまた、アプリケーションのパフォーマンスに影響を与えることも事実です。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、各ケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。equals(name3)&& age!= 23){dosomething}ここで循環的複雑度は次のように計算できます。決定点の数+論理演算子の数+1これはIf +に等しい|| + || + && + 1 = 5 Itまた、アプリケーションのパフォーマンスに影響を与えることも事実です。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、それぞれのケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。= 23){何かをする}ここで循環的複雑度は次のように計算できます。決定点の数+論理演算子の数+1これはIf +に等しい|| + || + && + 1 = 5次のようになることも事実です。アプリケーションのパフォーマンスへの影響。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、各ケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。= 23){何かをする}ここで循環的複雑度は次のように計算できます。決定点の数+論理演算子の数+1これはIf +に等しい|| + || + && + 1 = 5次のようになることも事実です。アプリケーションのパフォーマンスへの影響。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、それぞれのケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。+1 = 5アプリケーションのパフォーマンスに影響を与えることも事実です。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、各ケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。+1 = 5アプリケーションのパフォーマンスに影響を与えることも事実です。ただし、特定の設計で見られる場合がありますが、いくつかのケースがあり、それぞれのケースを完全に異なる方法で処理する必要があります。一部の開発者は、ファクトリ設計を使用して記述します。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。その工場設計では、スイッチケースまたはいくつかの条件が存在する可能性があります。例を挙げましょう。入力に基づいて完全に異なる処理を行うハンドラーについて考えてみましょう。ケースが「A」の場合は特定の方法で処理する必要があり、ケース「B」の場合は別の方法で処理する必要があります。次のコードを調べてみましょう。

 Interface Handler package com.core.cc.handler; /** * @author Debadatta Mishra(PIKU) * */ public interface Handler { public void handle(); } 
クラスAHandler
 package com.core.cc.handler; /**This class implements Handler * @author Debadatta Mishra(PIKU) * */ public class AHandler implements Handler { public void handle() { System.out.println("A handler"); } } 
クラスBHandler
 package com.core.cc.handler; /**This class implements Handler Interface * @author Debadatta Mishra(PIKU) * */ public class BHandler implements Handler { public void handle() { System.out.println("B handler"); } } 
クラスAbstractHandler
 package com.core.cc.handler; /**This class is used as a Factory class. * @author Debadatta Mishra(PIKU) * */ public class AbstractHandler { /**This is a very traditional method, you * can obtain the dynamic object by using * several if conditions. * @param handlerName * @return an object of type {@link Handler} */ public static Handler getHandler( String handlerName ) { Handler handler = null; try { if( handlerName.equals("A")) handler = new AHandler(); if( handlerName.equals("B") ) handler = new BHandler(); } catch( Exception e ) { System.out.println("There is no specific handler"); } return handler; } } 
クラスTestDynamicHandler
 import com.core.cc.handler.AbstractHandler; import com.core.cc.handler.Handler; /**This is a testharness class. * @author Debadatta Mishra(PIKU) * */ public class TestDynamicHandler { public static void main(String[] args) { Handler handler = AbstractHandler.getHandler("B"); handler.handle(); } } 

上記の例では、このコードを記述しても問題はありませんが、ケースが増えるとコンパイラーに時間がかかる場合があります。新しいケースごとに、新しいクラスを作成する必要があり、クラス「AbstractHandler」に1つ以上のif句を追加する必要があります。次の方法でクラス「AbstractHandler」を変更して、非常に洗練された外観にすることができます。これにより、クラス「AbstractHandler」を更新する必要がなくなります。

 package com.core.cc.handler; /**This class is used as a Factory class. * @author Debadatta Mishra(PIKU) * */ public class AbstractHandler { /**This method is used to obtain the dynamic * object of the type Handler * @param handlerName * @return an object of type {@link Handler} */ public static Handler getHandler( String handlerName ) { Handler handler = null; try { handler = (Handler) Class.forName( "com.core.cc.handler." + handlerName + "Handler") .newInstance(); } catch( Exception e ) { System.out.println("There is no specific handler"); } return handler; } } 

上記のコードはプログラミングを簡素化し、大きな変更を加えることなくケースを追加する柔軟性を提供します。結局のところ、これがJavaファクトリデザインの美しさです。この点で、パフォーマンスの観点からリフレクションは遅いという議論をすることができます。多くのif…else節と比較して速くなると言えます。ただし、循環的複雑度を回避するために美しいコードを作成する方法はいくつかあります。

結論

私の記事を楽しんでいただければ幸いです。問題やエラーを見つけた場合は、アドレスにメールを送ってください

[email protected]

。この記事は、Java開発に不慣れな人のみを対象としています。この記事は商業的な意味を持ちません。この記事に関するフィードバックをお寄せください。

このストーリー「Javaコードの循環的複雑度の処理」は、もともとJavaWorldによって公開されました。