ソフトウェアエンジニアリングシンポジウム 2013

null 返り値が保守作業に与える悪影響の調査
木村 秀平1

堀田 圭佑1

肥後 芳樹1

井垣 宏1

楠本 真二1

概要：オブジェクト指向言語を用いたプログラミングでは，メソッドの返り値として null 参照が用いられることがある (null 返り値)．null 返り値は，メソッド中の処理でプログラムが満たすべき条件が満たされなかったことを知らせるために広く利用されている．一方で，null を返す可能性のあるメソッドを呼び出す場合，呼び出し元で返り値が null か否かを判定する必要があり (null チェック)，保守作業を困難にしていることが知られている．しかし，ソフトウェア開発の中で，null 返り値がどのように保守作業に悪影響を与えるかは明らかにされていない．そこで本研究では，ソースコード中の null 返り値と null チェックを調査することで，それらがどのように保守作業に悪影響を与えているかについて調査を行った．本研究では，14 のオープンソースプロジェクトを対象として分析を行った．分析の結果，null 返り値および null
チェックが，規模や作業工程の種別に関係なく頻繁に修正されることを確認した．修正頻度が高いということは，バグを含みやすくなると考えられるため，null 返り値および null チェックが保守作業に悪影響を及ぼしていることを示している．さらに，全分析対象のプロジェクトにおいて，null チェックは 100 行に

1 つから 4 つの割合で存在することが判明した．
キーワード：null 返り値，null 値参照，プログラム保守，リポジトリマイニング

Investigation into Negative Eﬀects of Return Null on Software
Maintenance
Shuhei Kimura1

Keisuke Hotta1

Yoshiki Higo1

Hiroshi Igaki1

Shinji Kusumoto1

Abstract: Developers often use null references for returned values of methods (return-null) in object-oriented
languages. Although return-null is widely used to indicate that a program does not satisfy some necessary
conditions, it is generally said that return-null makes software maintenance more diﬃcult. One of the factors
is: when a method receives a value returned from a method invocation whose code includes return-null, it isnecessary to check whether the returned value is null or not (null-check). However, how return-null aﬀects
software maintenance during software evolution has not been revealed yet. This paper reveals the influencesof return-null by investigating return-null and null-check in evolution of source code. The experiment on 14
open source projects showed that developers modified return-null and null-check more frequently than thestatements that did not include null. This result indicates that return-null makes software maintenance morediﬃcult. On the other hand, the size and the development phase of projects have no eﬀect on modification
probabilities of return-null and null-check. In addition, we revealed that null-check appeared from one tofour times in 100 lines.
Keywords: Return Null, Null Dereference, Program Maintenance, Repository Mining

1. はじめにJava や C++といったオブジェクト指向プログラミング

言語では，null 参照が存在する．変数の初期化時や番兵としての利用など，null は多くの場面で用いられている．中でも，メソッド内で満たすべき条件を満たさなかった際にnull を返す記述が多数存在する (null 返り値)．エラー定数
1

Graduate School of Information Science and Technology, Osaka University©2013 Information Processing Society of Japan

や例外処理を用いる場合に比べ，null 返り値を用いる利点

1

ソフトウェアエンジニアリングシンポジウム 2013

は以下のとおりである．

研究の背景となる関連研究について述べ， 3 章では研究課• null は特殊な値であるため，プログラムが満たすべき

題の定義と，実験の設定について述べる． 4 章では実験結条件を満たさなかったことが一目でわかること．

果と，結果を分析することにより得られた研究課題に対す• 満たさなかった条件に合わせたエラーメッセージを考る回答を述べ， 5 章で null 返り値および null チェックがえる必要がないこと．

• 例外処理などに比べ，簡易な記述が行えること．
null 返り値はこのように開発者の助けとなる一方で，バグを発生させる原因として知られている [1]．null 返り値

与える影響について議論する． 6 章では本研究における妥当性の脅威について述べ， 7 章で本論文をまとめる．

2. 研究の動機に関連する主なバグとして，null 値参照*1 が挙げられる．

Java や C++ といったオブジェクト指向言語において，null 値参照とは，null 参照が代入された変数を参照してしnull 値参照は頻繁に発生するバグとして知られている．そまうバグである．null を返す可能性のあるメソッドを呼びのため，null 値参照を検出するための手法が多数研究さ出した場合，呼び出し元で null が返ってきたかどうかの判れており [2–8]，FindBugs [9]，SALSA [6]，JLint，ESC/-

定 (null チェック) が必要となる．そのため，null を返す

Java [10] など，null 値参照を自動的に検出するツールが数可能性のあるメソッドが追加された場合，そのメソッドを多く公開されている [11]．しかし，これらの研究において，呼び出す全ての箇所で null チェックを追加するか否かを判

null 値参照がどのように保守作業に悪影響を与えるかにつ断する必要がある．null チェックを記述し忘れた場合，実いては言及されていない．

行時例外を発生させるバグ (null 値参照) の原因となる．まnull 値参照を発生させる原因は，その値が null かどうか

た，null という値は，型やメッセージなどでエラー情報をを判定せずに参照をしてしまうこと (null チェック不足) で保持する仕組みを持った例外とは異なり，エラー情報を含ある．null チェック不足の原因として，呼び出したメソッ

まない．そのため，null を受け取った呼び出し元ではどのドが null 返り値を含むにも関わらず，呼び出し元で null

ようなエラーが生じたかを判別しにくい場合がある．他にチェックを書き忘れてしまうことが挙げられる．図 1(b)も，返り値が null であった場合に，さらに null を返す，とは，JGit 中に存在したコードである．4 行目に記述されていった null が伝搬するコードでは，エラーの原因を特定すいる command.call() は，図 1(a) に示したメソッドを呼びることが困難となってしまう．結果として，null 返り値は出している．このメソッドは，9 行目に記述されているとお保守作業を困難にしていると考えられる．

り，null を返す可能性がある．図 1(b) において，4 行目でしかし，null 返り値が保守作業に悪影響を与えているこ

定義されている変数 ref は，command.call() で初期化を行とを示した研究はない．そこで，本論文では null 返り値がなっているため，null が代入される可能性がある．そのた保守作業に与える悪影響の調査を行った．本研究では，14

め，5 行目の ref.getName() は null 値参照を発生させうる．

のプロジェクトに対しリポジトリマイニングを行い，null

図 1(c) は，この null 値参照に対するバグ修正である．+ が返り値および null チェックに対して行われた修正を抽出し行頭にあるものが，このバグ修正によって追加された記述

た．抽出した修正回数および修正の内容から，null 返り値

である．これは，5 行目の null チェックを追加することにおよび null チェックが保守作業にどのように悪影響を与えより，null 値参照を発生させないようにしている．コミッているのかを結論付けた．
結果として，null 返り値および null チェックは保守作業を困難にし，以下の特徴を持っていることが判明した．

トメッセージは「Do not fail when checking out HEAD」
であり，このことからも null 値参照に対する修正であることを示している．このように，null 返り値，null チェック，• null 返り値および null チェックは，それぞれ null を含

null 値参照は密接な関係にある．そのため，null 返り値おまない return 文，条件式と比較して修正頻度が高い．

よび null チェックが与える影響を調査することで，どの程• プロジェクトの規模と null 返り値および null チェッ

度 null 値参照が悪影響を及ぼしているかも調査することがクの修正頻度には相関が無い．

• プロジェクトの作業工程は null 返り値および null
チェックの修正頻度に影響を及ぼさない．

• プロジェクトの進行に伴ってソースコード中に占める
null チェックの割合が増加するとはいえない．
• null チェックは，どのプロジェクトにおいても 100 行に 1 つから 4 つの割合で存在する．

できると考えられる．
本研究では，null 返り値および null チェックを対象として保守作業に与える悪影響を調査した．-1 などのエラー定
数も null 返り値および null チェックと同様の意味で用いられることが多い．しかし，特に Java では，null はどのオブジェクトにも代入可能であり，エラー定数より保守作業に悪影響を及ぼす可能性が高いと考えられる．そこで，本研以降，本論文は次のように構成されている． 2 章では本

究では null 返り値および null チェックのみを対象とした．

null dereference

合，保守作業へ悪影響を及ぼす可能性が高いと判断する．

なお，本研究では，「修正が加えられることが多い」場*1©2013 Information Processing Society of Japan2

ソフトウェアエンジニアリングシンポジウム 2013

1

2
3
4
5
6
7
8
9
10
11

public Ref call() throws GitAPIException,
RefAlreadyExistsException,
RefNotFoundException, InvalidRefNameException, CheckoutConflictException {checkCallable();processOptions();try {if (checkoutAllPaths || !paths.isEmpty()) {checkoutPaths();
status = new CheckoutResult(Status.OK, paths);
setCallable(false);
return null;}...

(a) null 返り値を含むメソッド
1
2
3
4
5
6
7
8

...
try {
String oldBranch = db.getBranch();Ref ref = command.call();if (Repository.shortenRefName(ref.getName()).
equals(oldBranch)) {outw.println(MessageFormat.format(
CLIText.get().alreadyOnBranch,...

(b) (a) のメソッドを呼び出すコード
1
2
3
4
5
6
7
8
9
10

...
try {
String oldBranch = db.getBranch();Ref ref = command.call();+ if (ref == null)+
return;if (Repository.shortenRefName(ref.getName()).
equals(oldBranch)) {outw.println(MessageFormat.format(
CLIText.get().alreadyOnBranch,...

RQ1 returnnull および condnull は，returnnot およびcondnot と比べて修正される頻度が高いか？
RQ2 プロジェクトの規模は，returnnull および condnullの修正頻度に影響を与えるか？

RQ3 あるバージョンをリリースするにあたり，その開発の前期と後期で，returnnull および condnull の修正頻度に差はあるか？

RQ4 ソースコード中に占める condnull の割合はプロジェ
クトの進行に伴って増加するか？

3.2 実験対象対象としたプロジェクトを表 2 に掲載する．これらは，Java 言語で記載され，git で管理されている，一定以上の規模を持つプロジェクトである．

3.3 実験手法
本実験では，各実験対象から以下の情報を得る．

• ∀r ∈ R について，Returnrnull ，Returnrnot ，Condrnull ，Condrnot ，locr , mocr
• ∀c ∈ C に つ い て ，∆Returncnull ，∆Returncnot ，∆Condcnull ，∆Condcnot
3.3.1 手順の詳細
これらの情報を取得するため，リポジトリに対し以下の手順を行う．なお図 2 は実験手順を図示したものである．

Step1 各 リ ビ ジ ョ ン で ，メ ソ ッ ド ご と に returnnull ，returnnot ，condnull ，condnot の個数を計測する．
Step2 Step1 で算出した個数を用いて，次のリビジョンで新たに追加された，または，前のリビジョンで存在して(c) null チェック追加後のコード

表 1: 実験で用いる略称

図 1: null 返り値と null 値参照，null チェックの例
Fig. 1 An example code fragments of return-null, null dereference, null-check

3. 実験の設定

Table 1 Abbreviations
略称

その説明

returnnull

オペランドが null である return 文

returnnot

オペランドが null でない return 文

condnullnull との比較を行なっている条件式

condnot

null 以外と比較を行なっている条件式
リビジョン r における，returnnull の集合のために行った実験について説明する．なお，以降では，表 1

Returnrnull
ReturnrnotrReturnに示した略称を用いる．また，|S| を集合 S の要素数とする．

Returnrnull ∪ Returnrnot

Condrnull

リビジョン r における，condnull の集合

さらに，c をリビジョン r と r + 1 の間のコミットとし，c でCondrnotr

リビジョン r における，condnot の集合

Cond

Condrnull ∪ Condrnot

Descrnull
Descrnotr

Returnrnull ∪ Condrnull

この章では，null 返り値および null チェックに対する調査

追加・削除された returnnull ，returnnot ，condnull ，condnotの集合をそれぞれ ∆Returncnull ，∆Returncnot ，∆Condcnull ，∆Condcnot とする．

Desc

リビジョン r における，returnnot の集合

Returnrnot ∪ Condrnot
Descrnull ∪ Descrnot

C

実験対象の指定範囲におけるコミットの集合

R

実験対象の指定範囲におけるリビジョンの集合

本実験の目的は，以下の研究課題に対して回答を行うこ

locr

リビジョン r における，ソースコードの行数とにより，null 返り値および null チェックが保守作業に与mocr

リビジョン r における，メソッド数える悪影響を調査することである．

latest

指定範囲内で最新のリビジョン

3.1 実験の目的©2013 Information Processing Society of Japan3


 Vol.0
1–8
情報処理学会論文誌
No.0(??? 1959) 


   









!



 
   returnnull ，returnnot ，condnull ，condnot である．な
ぜなら，機能の追加・削除によって個数が変化した場
合，バグ修正のためにそれらの数が変化したのではな
いためである．この実験では，メソッドそのものが追加・削除された場合は，それらを機能の追加・削除と 

みなし，除外した．これにより，機能の追加・削除のみでなく，Move Method リファクタリングなどによっ

て，メソッドそのものが移動した場合に伴って発生した returnnull ，returnnot ，condnull ，condnot の追加・

 

削除についても除外することができる．
 

このようなフィルタリングを行い，残った追加・削除

を，研究課題への回答に必要な情報として記録する．
図 2 の例では，個数が「0 から 1」「2 から 1」
「1 から 



0」へと変化した場合のみを記録する．個数が変化し     

なかった場合，メソッドごと消滅した場合，または新

図 2: 修正回数の算出方法

しくメソッドが出現した場合はそれに伴って発生した

Fig. 2 The overview of the steps

returnnull ，returnnot ，condnull ，condnot の追加・削除は記録しない．

いたが削除された returnnull ，returnnot ，condnull ，condnot を 特 定 す る ．メ ソ ッ ド ご と に returnnull ，3.3.2 修正頻度の算出
研究課題への回答を行うために，returnnull ，returnnot ，

returnnot ，condnull ，condnot の個数を直前のリビジョ

condnull ，condnot そ れ ぞ れ の 修 正 頻 度 を 比 較 す る 必ンと比較し，個数が変化していれば追加・削除があっ

要 が あ る ．本 研 究 に お い て ，returnnull ，returnnot ，たとみなす．個数を用いているため，直前のリビジョ

condnull ，condnot の修正頻度 freturnnull (C)，freturnnot (C)，ンで存在している returnnull ，returnnot ，condnull ，fcondnull (C)，fcondnot (C) は，全コミットを通して修正さ

condnot の (メソッド内での) 位置が変更された場合や，れた回数を合計し，その値を最新リビジョンにおけるそれメソッド内で追加された同数削除された場合には，特ぞれの個数で割った値とする．最新リビジョンでの個数で定されない．

割ることにより，個数の差による影響を軽減することがで

Step3 Step2 で特定した，個数の変化が生じた returnnull ，きる．これを式で表すと，以下のとおりとなる．

returnnot ，condnull ，condnot から，本実験で不要なものを除外する．本実験で不要な追加・削除とは，機能を追加・削除したことに伴って追加・削除された

freturnnull (C) =c∈Cfreturnnot (C) =c∈Cfcondnull (C) =c∈Cfcondnot (C) =c∈C

表 2: 対象としたプロジェクトとその規模
Table 2 Target projects and their size
Project

loc

latest|R|

ant

131,265

12,783commons-io

25,031

1,526

1,155,484

19,140jdt.core
egit

92,305

3,126

jEdit

115,842

6,221

jboss-as551,426

10,764|Returnlatest
null |
|ΔReturncnot ||Returnlatest
not |
|ΔCondcnull ||Condlatest
null |
|ΔCondcnot ||Condlatest
not |

(1)

(2)

(3)

(4)

jetty

207,517

6,082

例えば，式 (1) では，全コミットで追加・削除された

JGit

124,662

2,321

log4j

30,0103,226

returnnull の個数を，最新リビジョンにおける returnnull

lucene-solr

537,150

8,026の個数で割っている．そのため，freturnnull (C) は 1 つのmaven

72,201

9,312

returnnull が変更される頻度を示す．

cdt

1,029,497

21,157

hudson.core

81,876

1,008

tomcat240,086

9,172

本研究では，メソッドの呼び出し関係を用いて，returnnull

Total

4,394,352

122,116が加わった際に呼び出し元で condnull がどのように変更さ

c 1959 Information Processing Society of Japan


|ΔReturncnull |     

3.4 解析単位

4ࢯࣇࢺ࢙࢘࢔࢚ࣥࢪࢽ࢔ࣜࣥࢢࢩ࣏ࣥࢪ࣒࢘

 


 


n

n

k
2

 

n k

n k

l
2

 

n k l

4. 研究課題に対する回答

                                   

4.1 回答を行うために用いるデータ

図 3: バージョン間分割の例

ΔReturncnot ，ΔCondcnull ，ΔCondcnot を算出した．

Fig. 3 The overview of the division

14 のプロジェクト全体に対して実験を行い，returnnull ，returnnot ，condnull ，condnot ，お よ び ΔReturncnull ，各プロジェクトに対する freturnnull (C) と freturnnot (C)，fcondnull (C) と fcondnot (C) の比較を図 4 に示す．黒く塗れたかを取得している．そのため，returnnull ，returnnot ，

condnull ，condnot に対して追加・削除が行われた個数もメ
ソッド単位での計測を行った．

3.5 作業工程の分割
実験対象がオープンソースソフトウェアであるため，明られた棒は Descnull を示し，灰色に塗られた棒は Descnotを示す．なお，この図では，全プロジェクトでの比較を行
いやすくするため，個数ではなく割合で表示している．例
えば，freturnnull (C) の占める割合は，下記の式により表され，freturnnot (C)，fcondnull (C)，fcondnot (C) それぞれの占める割合に関しても同様に求めることができる．

究では，あるメジャーバージョンのリリースから次のメ

freturnnull (C)freturnnull (C) + freturnnot (C)ジャーバージョンのリリースまでの期間を 1 つのソフト

また，実験対象プロジェクトには，109 のメジャーバー

ウェア開発期間として想定し，その期間を前半と後半に分ジョンが格納されていた．メジャーバージョン間を二分割割した．図 3 では，バージョン 1.0.0 とバージョン 1.1.0 のし，分割された 218 の期間それぞれに対して freturnnull (C)

期間を分割し，さらに，バージョン 1.1.0 からバージョン

および fcondnull (C) を取得した．結果を箱ひげ図として表

1.2.0 の期間を分割した例を示している．前半では主に機した図を図 5 に示す．

確に作業工程を分けることはできない．そのため，本研(5)

能追加による修正が，後半では主にバグに関する修正が行われると想定した．このような分割を行い，前半と後半それぞれに対して修正頻度を求めた．
作業工程の分割および検定は，tomcat，jdt.core を除く

12 プロジェクトに対して行った．この 2 つのプロジェクト

4.2 RQ1 に対する回答
returnnull および condnull が，それぞれ returnnot および condnot に比べ頻繁に修正されるかを確かめるため，検定を行った．

は，リポジトリにメジャーバージョンのタグが付けられてfreturnnull (C) と freturnnot (C) 間に差があるか否かを判おらず，開発の区切りが明らかでなかったため除外した．

定するため，ウィルコクソンの符号順位検定により p 値を求めたところ，p = 1.22 × 10−4 となった．これは，n = 14

3.6 検定方法
研究課題に回答するためには，二群間に差があるか否か，の場合の，ウィルコクソンの符合順位検定で示される最小値である．すなわち，freturnnull (C) − freturnnot (C) は全て

また，二群間に相関があるか否かを検定する必要がある．

のプロジェクトで正の値を示した．p ≤ 0.01 であるため，検定方法は，ノンパラメトリック検定の中で，この分野でreturnnull は returnnot に比べ頻繁に修正されるといえる．

よく用いられる方法を採用した．

同様に，fcondnull (C) と fcondnot (C) に対する検定において

まず，二群間に差があるか否かは，ウィルコクソンの符も，p = 1.22 × 10−4 となった．これは，p ≤ 0.01 であるた

号順位検定 [12] を行い判定した．検定によって求められため，condnull は condnot に比べ頻繁に修正されるといえる．

p 値が低ければ，差が無いことが偶然である可能性が低い

これらの結論により，RQ1 への回答は，returnnull およことを表している．本実験では，有意水準を 1% と定め，

び condnull は returnnot および condnot と比べて頻繁に修p ≤ 0.01 であれば二群間に有意な差があり，0.01 < p であ正される，となった．

れば有意な差は無い，とした．二群間に相関があるか否か
は，スピアマンの順位相関係数 ρ を求め，それに対する有4.3 RQ2 に対する回答

意性検定を行い p 値を求めて判定した．相関係数 ρ が正のプロジェクトの規模と修正頻度に相関があるか否かを確

値では正の相関を持ち，ρ が負の値では負の相関を持つ．p

かめるため，loclatest がプロジェクトの規模を反映してい値に対する棄却域の設定は，ウィルコクソンの符合順位検ると仮定し，検定を行った． 4.1 章の結果を，loclatest を定と同様である．また，相関の強さは，|ρ| < 0.5 では相関x 軸に，freturnnull (C) および fcondnull (C) を y 軸に取り，が無く，0.5 ≤ |ρ| の場合，相関があると定めた．

散布図に表した図を図 6 に示す．また，スピアマンの順位
相関係数 ρ を算出し，それに対する p 値を求めた．

ª Information Processing Society of Japan5

ソフトウェアエンジニアリングシンポジウム2013

f
:b
lack
,f
:g
ra
y
re
tu
rn
re
tu
rn
nu
l
l
no
t

f
:b
lack
,f
ra
y
condnucondnot:g
l
l

an
t

an
t

commons−
io

commons−
io

jd
t
.
co
re

jd
t
.co
re

eg
i
t

eg
i
t

jEd
i
t

jEd
i
t

jbo
s
s−a
s

jboss−as

je
t
t
y

je
t
ty

jg
i
t

jg
i
t

log4
j

log4
j

lu
cene−
so
l
r

lucene−so
l
r

ma
ven

ma
ven

cd
t

cd
t

hud
son
.
co
re

hudson
.co
re

tom
ca
t

tomca
t
0

20

40

60

80

100

0

(
a
)f
C)と f
C)の比較
re
turnnull (returnnot (

20

40

60

80

100

(b
)f
C)と f
C)の比較
condnull (condnot (

図4
:f
C)
(
黒)と f
C)
(
灰)の割合比較
Descnull (Descnot (

l

l

l
l

ρ =0
.169
p=0
.563

0
.10

●
●

l
l
l
l

(
a
)f
C)
re
turnnull (

l

an
te
r
io
rha
l
fpos
te
r
io
rha
l
f

(b
)f
C)
condnull (図5:バージョンの前半と後半で算出した fC)とreturnnull (fC)の分布
condnull (Fig. 5 Th
e box
-p
lo
t tha
t ind
i
ca
t
e
s freturnnull (C) andfcondnull (
C)o
fth
ean
t
e
r
io
rha
l
fandth
epo
s
t
e
r
io
ron
e

l

l

l

l
l

l

0 200

600

l
l
l
l
l

l

l
l

0
.0

0
.00

an
te
r
io
rha
l
fpo
s
te
r
io
rha
l
f

1
.0

l

l

l

f
cond
nu
l
l

●
●

l

0
.6

●
●
●

l
l
l

0
.2

●
●

l
l

f
re
tu
rn
nu
l
l

●

f
condnu
l
l

●
●
●
●
●
●

1
.0

●

●

0
.20

l
●

0
.00

ρ =−0
.0330
p=0
.916

l
l

1
.4

3
.0

l

2
.0

●

●
●

●
●

0
.20

0
.30

●

0
.10

0
.30

F
ig
.4 Compa
r
i
sonbe
tw
e
en fDescnull (
C)
(b
la
ck
)andfDescnot (
C)
(g
ray
)

1000

LOC(1
,000
)

(a
)f
C)
re
turnnull (

l

l

l
l
l

0 200

600

1000

LOC(1
,000
)

(b
)f
C)
condnull (

C)
，f
C)と，
図6
:各プロジェクトでの freturnnull (condnull (プロジェクトの規模との相関
la
tes
t
F
ig
.6 S
ca
t
t
e
rg
ram
so
flo
c
andfreturnnull (C),fcondnull (C)

この値は 0.
0
1<pであるため，前半と後半の fC)returnnull (プロジェクトの規模と f
C)
(
図6
(
a
)
)に対して．
returnnull (

ρ= −0
.
0
3
3
0
,p=0.
9
1
6が得られた．これは，0.
01<pであるため，相関は無いと判定できる値である．また，プロジェクトの規模と f
C)
(
図6
(b
)
)に対しては，condnull (

ρ=0.
1
6
9
,p=0.
5
6
3が得られた．同様に，0.
01<p であるため，相関は無いと判定できる値である．
以 上 よ り ，RQ
2 に 対 す る 回 答 は ，r
e
tu
rn
nu
l
l および

c
ond
nu
l
l の修正頻度は，プロジェクトの規模による影響を受けない，といえる．

4.4 RQ3に対する回答
図 5に示した前半と後半それぞれの修正頻度を用いに有意な差は存在しなかった．また，c
ond
図5
(b
)
)に
nu
l
l(

3
8
3となり，0.
0
1<p であるため対する検定では，p=0.
同様に有意な差は存在しなかった．
以上より，RQ
3に対する回答は，r
e
tu
rn
ond
nu
l
lと c
nu
l
l
は開発の前期と後期で修正頻度に差は無い，となった．

4.5 RQ4に対する回答
対象プロジェクトの各リビジョン rに対して，1行に存

ond
en
s
i
t
ycondnull (r)を，以下の在する cnull の数を表す d式を用いて算出した．

|
Condr
nu
l
l|
d
en
s
i
t
ycondnull (
r
)=
r
lo
c

(
6
)

て，プロジェクト開発の前期と後期で fC)とreturnnull (プ ロ ジ ェ ク ト ご と に ，リ ビ ジ ョ ン 番 号 r とfC)の修正頻度に差は無いか否か検定を行った．
condnull (

d
en
s
i
t
ycondnull (r)との間に正の相関があるか否か，に対しウィルコクソンの符合順位検定を行ったところ，て検定を行った．リビジョン番号 rと densitycondnull (
r
)

r
e
tu
rn
図5
(
a
)
)に対する検定では，p=0.
126となった．
null(が正の相関を持つということは，プロジェクトの進行に

©
2
0
1
3 In
fo
rma
t
ionP
roce
s
s
ing SocietyofJapan6

ソフトウェアエンジニアリングシンポジウム 2013

伴って condnull の密度が増加してゆくことを示す．検定を行った結果を表 3 に表す．ρ は相関の強さを表し，p は統計的に有意な差があるか否かを表している．

ぼす要因となるといえる．
結果として，null 返り値および null チェックは，プログ
ラム保守の観点から置き換えるべきであると判断できる．

結果として，4 つのプロジェクトは有意な正の相関を示

なお，null 返り値および null チェックの置き換えは，null

し，5 つのプロジェクトは有意な負の相関を示し，3 つの値参照を検出する研究と密接な関係がある．なぜなら，null

プロジェクトは相関が無いことが示された．なお，2 つの値参照を検出することは，null の伝搬および null となりう

プロジェクトは，p > 0.01 であるため統計的に有意な相関る変数を検出することであり，これらの情報は，null 返りが示されなかった．このように，正の相関を持つか負の相値および null チェックを他の記述に置き換える際に非常に関を持つかはプロジェクトによってまちまちであり，共通有用であるためである．そのため，null 値参照を検出する

して有意な正の相関を持つことは無かった．

研究の動機として，「null 値参照は数多く発生するバグでこれにより，RQ4 への回答は，コード中に占める condnull

あり，そのバグを検出し修正することは有用」という既存の割合はプロジェクトの進行に伴って増加するとはいえなの動機に加え，「保守作業に影響を与える null 返り値およい，となった．

び null チェックを，他の記述に置き換えることの支援」という動機を加えることができるといえる．

5. 議論
5.1 RQ の結果に対する考察

5.2 condnull の占める割合に関する考察

RQ1 に対する回答から，returnnull および condnull はRQ4 では，表 3 に示したとおり，多くのプロジェクトは

returnnot および condnot と比べて頻繁に修正されること修正頻度とリビジョン番号の間に有意な相関を持っているがわかった．すなわち，returnnull および condnull を多くことを示した．相関があるということは，開発が進んだ際含むコードは修正されやすくなるため，結果として保守に，今までと同じ増加・減少・変化なしの傾向が現れる可

作業に悪影響を及ぼす可能性があるといえる．RQ2，RQ3

能性が高いことを表す．また，各プロジェクトが持つ相関に対する回答から，プロジェクトの規模および開発の時の正負は異なっており，プロジェクト間で共通する傾向は

期は，returnnull および condnull の修正頻度に影響を及ぼ見いだせなかった．

さないことがわかった．このことは，様々なプロジェクト

図 7 は ，全 プ ロ ジ ェ ク ト の r ∈ R に お い て ，の様々な時期において，returnnull および condnull の修正

densitycondnull (r) を図示したものである．x 軸は，リビが行われることを示している．RQ1 の結果と合わせると，

ジョン r がそのプロジェクトの全リビジョン番号で占める

returnnull および condnull は，常に保守作業に悪影響を及割合，y 軸は densitycondnull (r) を表している．また，薄い点は各プロジェクトの値を，濃い点は全プロジェクトの中央値を示している．このグラフから，ほぼ全てのプロジェ

表 3:

対象プロジェクトのリビジョン番号 r とdensitycondnull (r) に対するスピアマンの順位相関係数 ρ，および ρ に対する有意性判定値 p

クトにおいて densitycondnull (r) は 0.01 から 0.04 の間に収束しており，また，中央値はプロジェクトの進行に関わらずほぼ一定の値となっていることがわかる．このことから，

Table 3 Spearman’s rank correlation coeﬃcient (ρ value) andp value for a revision number r and densitycondnull (r)condnull は 100 行に 1 つから 4 つ程度の割合で存在し，将来的にもこの割合が保たれると考えられる．

Softwareρ valuep value

ant

0.432

under 2.2 × 10−16 *2

commons-io

0.733

under 2.2 × 10−16

jdt.core-0.974

under 2.2 × 10−16

本実験では，計測要素の個数をメソッド単位で計測して

egit

0.223

under 2.2 × 10−16いる．この手法は，計測要素がメソッドに含まれない場合

jEdit

0.668

under 2.2 × 10−16に情報が取得できないという問題点がある．しかし，個数

jboss-as-0.765under 2.2 × 10−16-0.992

under 2.2 × 10−16を取得する対象は return 文と条件式であるため，メソッ

jetty
jgit

0.598

under 2.2 × 10−16

log4j

0.006

0.740

6. 妥当性への脅威

ド外に配置されることは少ない．そのため，本実験ではメソッド外に存在する計測要素は考慮しないものとした．

lucene-solr-0.947

under 2.2 × 10−16

returnnull に対する修正として，追加および削除によって

maven

0.934

under 2.2 × 10−16

個数が変化する場合のみ検出している．そのため，condnull

cdt

0.156

under 2.2 × 10−16において，null との比較を行う変数が修正された場合など

hudson.core-0.1512.898 × 10−4

-0.986

under 2.2 × 10−16は計測していない．また，本実験手法では計測要素の移動

tomcatを検知できないため，Extract Method などのリファクタ

小さすぎて正確な値を表せないことを示す

リングによる移動も計測要素の修正と認識してしまう．こ©2013 Information Processing Society of Japan

7*2

ソフトウェアエンジニアリングシンポジウム 2013

返り値および null チェックの修正されやすさは，プロジェ
クトの成熟度や，開発の段階に影響を受けない事を確かめた．加えて，null チェックがコード中に占める割合は，実験対象の全プロジェクトで 100 行に 1 つから 4 つ程度であることがわかった．
これらの分析により，様々なプロジェクトにおいて，null
返り値および null チェックが保守作業に悪影響を与えていることがわかった．そのため，開発者は null 返り値を安易に記述してしまう前に，他の記述で置き換える事ができないかを考えるべき，といえる．具体的には，例外処理を用いる方法，null の代わりに適切なオブジェクト（空の配列，特殊なクラスなど）を返す，などが挙げられる．ただし，null 返り値および null チェックに対する置き換えは自動化されておらず，開発者の負担は増大してしまう．そ図 7: 全プロジェクトの r ∈ R における，densitycondnull (r)のため，今後の研究として，null 返り値の置き換えを支援の推移 (各プロジェクトごとに，左端が最初のリビジョン，する手法を研究する予定である．また，null 返り値および右端が最新のリビジョンを表す)

null チェックがどのような状況で用いられることが多いの

Fig. 7density(Condrnull ) of ∀r ∈ Revisions in all projects

か，また，null 返り値の置き換えにより，保守作業にどのような影響が生じるのかについて調査を行う予定である．

のようなリファクタリングは，機能追加の場合と同様に修正回数から取り除くべきである．しかし，本実験では，こ謝辞

本研究は，MEXT/JSPS KAKENHI 25220003，

24650011，および 24680002 の助成を得た．

のような移動の占める割合は少ないものとして，考慮せず実験を行った．
本実験では，returnnull として計上されるものは，return

参考文献
[1]

文のオペランドに直接 null が記述された場合のみである．
変数に null が代入され，その変数を return している場合[2]など，null が return される可能性のある文は数に加えていない．condnull に関しても同様である．このことによ[3]

り，本実験で計上した個数は，実際の returnnull 数および

[4]

condnull 数と乖離してしまう恐れがある．
作業工程の比較を行う際，メジャーバージョン間を二等分し，その 2 つの間で差があるかどうかの比較を行った．

[5]

しかし，これはリビジョン数のみを利用した分割であり，正確に作業工程に基づいた分割を行っているわけではな[6]

い．そのため，正しい作業工程で分割を行った場合と異なる結果となる恐れがある．
本研究は，対象とするプロジェクトによって結果が変動[7]する可能性がある．プロジェクトによる差分を吸収するため，より多くのプロジェクトを用意することによって，さ[8]らに一般的な結果が得られると考えられる．

7. まとめ
本論文では，null 返り値が保守作業に悪影響を与えてい

[9]
[10]

るのかを調査するため，null 返り値と null チェックに焦点を当て分析を行った．14 プロジェクトのリポジトリから[11]null 返り値および null チェックに対する修正を抽出した結果，null 返り値および null チェックは，null を含まない記述と比べて頻繁に修正されることが示された．また，null©2013 Information Processing Society of Japan[12]

Hoare, T.: Historically Bad Ideas: ”Null References:
The Billion Dollar Mistake, QCon (2009).
Nanda, M. G. and Sinha, S.: Accurate Interprocedural Null-Dereference Analysis for Java, ICSE, pp. 16–24(2009).
Ayewah, N. and Pugh, W.: Null Dereference Analysis in
Practice, PASTE, pp. 65–72 (2010).
Bush, W. R., Pincus, J. D. and Sielaﬀ, D. J.: A static
analyzer for finding dynamic programming errors, Software: Practice and Experience, Vol. 30, No. 7, pp. 775–
802 (2000).
Hovemeyer, D., Spacco, J. and Pugh, W.: Evaluating
and Tuning a Static Analysis to Find Null Pointer Bugs,
PASTE, pp. 13–19 (2005).
Loginov, A., Yahav, E., Chandra, S., Fink, S., Rinetzky, N. and Nanda, M.: Verifying Dereference Safety via
Expanding-Scope Analysis, ISSTA, pp. 213–224 (2008).
Hovemeyer, D. and Pugh, W.: Finding More Null
Pointer Bugs, But Not Too Many, PASTE, pp. 9–14
(2007).
Loginov, A., Yahav, E., Chandra, S., Fink, S., Rinetzky, N. and Nanda, M.: Verifying Dereference Safety via
Expanding-Scope Analysis, ISSTA, pp. 213–224 (2008).
Hovemeyer, D. and Pugh, W.: Finding Bugs is Easy,
OOPSLA, pp. 24–28 (2004).
Flanagan, C., Leino, K. R. M., Lillibridge, M., Nelson,
G., Saxe, J. B. and Stata, R.: Extended Static Checking
for Java, PLDI, pp. 17–19 (2002).
Nanda, M. G., Gupta, M., Sinha, S., Chandra, S.,
Schmidt, D. and Balachandran, P.: Making DefectFinding Tools Work for You, ICSE, pp. 99–108 (2010).
Hollander, M. and Wolfe, D. A.: Nonparametric Statistical Methods, 2nd Edition, Wiley-Interscience (1999).

8