静的解析ツールというと「違反が大量にレポートされる」、「違反が多すぎて見ていられない」といった話をよく聞きます。たしかに、すでにリリースしているプロジェクトのソースコードに静的解析ツールを実行すると大量に違反が出る場合があります。原因は以下の様な事が考えられます。
- 開発時は静的解析ツールを使っていなかったため、静的解析ツールに合わない実装が多く検出される
- 開発時にコーディング規約が遵守されていなかった
- 複数ベンダーが開発しており、それぞれコーディング規約が違う
では、静的解析ツールは新規の開発にしか利用できないのでしょうか?そんなことはありません。Parasoft Jtest(Jtest)とレポーティングツールであるParasoft DTP(DTP)の場合、変更された違反を表示する機能でその問題を解決できます。
変更された違反の表示とは?
ある時点をベースラインとして設定し、それ以降の解析でベースラインの違反と比較して変更された違反を表示する機能です。この機能を使うと、ベースライン以降のソースコード修正に伴って発生した静的解析違反だけを表示することができます。新しく発生した静的解析違反だけを表示するため、大量に違反がレポートされる問題を回避できます。
特に保守開発などすでに稼働している製品がある場合、現状稼働しているソースコードに不具合は含まれない、静的解析の違反は修正しないと決めます。一方で、ツールの導入以降に追加、修正されたソースコードによって発生した違反は必ず修正し品質を担保しよう、という考え方です。
具体的な運用例
store-allプロジェクトという架空のプロジェクトでJtestを導入したとして、具体的な手順、運用の仕方をご紹介します。このstore-allプロジェクトは書籍の購入システムです。今回の改修で国際化対応のため顧客ごとに通貨を設定し、通貨ごとに料金の計算を行う処理を追加します。ただし、すでに安定稼働しているシステムのため、現在稼働しているソースコードで静的解析の違反が発生しても修正したくありません。
そのため、変更された違反の表示機能を使ってソースコードの修正にともなって発生した静的解析違反だけ修正する、という運用を行います。
手順
- 解析のベースラインを決める
ソースコード修正前にベースラインを作成するための解析を行います。ここで行った解析をもとに、以降に新しく発生した静的解析違反だけを確認します。今回の例では現状のソースコードに解析を実施すると以下のように、違反の合計に129件の静的解析違反がレポートされました。
- ソースコードを修正する
ベースラインを決める解析ができたのでソースコードを修正します。今回の修正では以下の2つのメソッドを追加します。calculatePriceWithCurrencyメソッドでmemberIDに紐づく顧客の国ごとに該当する通貨で金額の計算を行います。private Currency getCurrency( String countryCode ) { switch( countryCode ) { case "US": case "GB": return Currency.generateCurrencyWithCents(countryCode); case "JP": case "ISK": return Currency.generateCurrencyWithNoCents(countryCode); } return null; } public void calculatePriceWithCurrency( int memberID, BigDecimal price ) { Customer customer = customerStore.getCustomerByID( memberID ); Currency currency = getCurrency( customer.getCountryCode() ); currency.calculatePrice( price ); … … … … }
実装を見ると、calculatePriceWithCurrencyからgetCurrencyを呼び出しています(14行目)。getCurrencyは処理の中でswitchの条件全てにマッチしない場合nullを返します(10行目)。しかし、14行目で戻り値を受け取ったあとに戻り値を評価せずに使用している(16行目)ため、NullPointerExceptionが発生する可能性があります。
- 修正後のソースコードに静的解析実施
ソースコード修正後に再度解析を実施します。
実行後のレポートが以下です。違反の合計は129件と同じ数字なのですが、「違反 - 変更済み」の内容が変わっています。
小さいので拡大して見てみます。ベースラインと修正後の解析を比較すると、「新規」「修正済み」「既存」の件数が異なっています。
それぞれ何を表しているのかは、以下のとおりです。- 新規 … ベースライン設定後に新しく検出された静的違反の数
- 修正済み … ベースラインで検出された違反の中で、修正された違反
- 既存 … ベースラインの違反
つまり、ベースライン設定後は「新規」のみ対応することで、修正したソースコードの影響で発生した違反のみ確認できます。「既存」で検出されている127件は別のリファクタリングのタイミングで修正するなどの対応を検討できます。
新規2つの違反の詳細を確認すると、ひとつは「2」で説明したNullPointerExceptionの可能性がレポートされています。開発者はこのレポートを確認し、対応方針を検討、再度修正後解析を実行する、といったサイクルを新規の違反がなくなるまで繰り返します。
もう一つは、switch文にdefaultラベルがない、という違反がレポートされています。これは解析時のルールに含まれているためであり、不要であればルールを使用しない事もできます。
まとめ
いかがでしょうか?「静的解析は大量に違反が出るから使えない」という問題は、ソースコードの修正に伴って発生した違反だけを確認することで回避できます。
JtestとレポーティングツールDTPを使えば、特に何もしなくても自動で差分を検出します。JenkinsなどCIツールを使って静的解析を自動化すれば解析ごとに毎回差分だけを確認できるので、開発途中のプロジェクトや既存システムの改修案件でも手間を掛けずに新しいツールの導入を行えます。
Jtestでは体験版やお客様のソースコードを使った無償アセスメントもご利用いただけます。ぜひ一度お試しください。
Parasoft Jtestについて
Java対応静的解析・単体テストツール Parasoft Jtest
Jtestは、テスト工数の大幅削減とセキュアで高品質なJavaシステムの開発を強力にサポートするJava対応テストツールです。2,000個以上のコーディング規約をもとにソースコードを静的に解析し、プログラムの問題点や処理フローに潜む検出困難なエラーを検出します。さらに、JUnitを用いた単体テストについて、作成、実行、テストカバレッジ分析、テスト資産の管理といった単体テストに係る作業をサポートし、単体テストの効率化を促進します。