IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

ゼロから歩くPythonの道

CTC 教育サービス

 [IT研修]注目キーワード   Python  Power Platform  最新技術動向  生成AI  Docker  Kubernetes 

第63回 Pythonプログラムでエラーを出す前に確認したいこと ~コメントアウト・デッドコード・スタブ編~ (菱沼佑香) 2025年3月

こんにちは、吉政創成 菱沼です。
今回も「きれいなPythonプログラミング(マイナビ出版)」という書籍を利用して学習します。

現在学習中の5章「怪しいコード臭」では、バグを未然に防ぐために、どういった点に注意した方が良いのか、対処するか否かの判断について学んでいます。今回はコメントアウトされたコードとデッドコード、スタブの使い方についてです。

コメントアウトは混乱の元

自分で書いたプログラムを使っているうちに、ココをこうしてみたらもっと良くなるかなと試してみたり、同じような業務に流用したりすることはよくあります。
そうした時にコピーしてやったり、バージョン管理システムを使ったりすればいいところを、プログラムが置かれている場所の事情やズボラさによってはそのまま編集して、改変前の部分をコメントアウトして残しておくということが私の場合はよくあります。

それはさておき、そんな一時的にコードを改変しようかなという時、コメントアウトでその部分が動かなくなるようにしますが、訳あってそのままにしてしばらく触らずにいると、アレ、これなんだっけ?なんていうこともきっとよくあるはずです。これに関して、本当はよくないことは重々承知しております。
今回はそんなコメントアウトによる問題についてです。

---------------------------------------------------------------
P.78
コメントアウトされたコードがそのまま残っていると、なぜそのコードが削除されたのか、またどのような状況でそのコードが必要になるのか全くわからなくなります。次のような例を考えてみましょう。


doSomething()
#doAnotherThing()
doSomeImportantTask()
doAnotherThing()

(中略)
なぜdoAnotherThing()がコメントアウトされたのか?今後コメントを解除して、この部分をコードに含めることはあるのか?2つ目のdoAnotherThing()の呼び出しはなぜコメントアウトされなかったのか?doAnotherThing()の呼び出しは元々2回だったのか、それとも元々1回だけ呼びだすものがdoSomeImportantTask()の後に移動しただけなのか?コメントアウトされたコードを削除してはいけない理由があるのか?これらの疑問に対する答えは、すぐにはわかりません。
---------------------------------------------------------------

そうですよね。基本的に書いた人にしか、その意図はわかりませんし、過去の自分のことをあっさり忘れることがあるのもまた人間です。うっかりに定評のある私もしょっちゅう忘れます。
なので、コメントアウトせず削除するのが一番でしょうし、どうしても残しておきたいという場合にはコメントを残しておくのが良いのだろうと思います。

デッドコードは誤解の元

さて次に問題となるのがデッドコードです。
デッドコードとは、「到達できない、あるいは論理的に実行できないコード」のことだそうで、つまるところ、プログラムを実行する上で要らない部分だということのようです。

---------------------------------------------------------------
P.78、79
例えば、関数内でreturn文の後に書かれたコード、常に条件式がFalseであるif文ブロック内のコード、決して呼び出されない関数内のコードなどはすべてデッドコードです。このことを実際に確認するためには、インタラクティブシェルに次のように入力します。


import random
def coinflip():
    if random.randint(0, 1):
        return 'Heads!'
    else:
        return 'Tails!'
    return 'The coin landed on its edge!'
print(coinflip())

Tails!

return 'The coin landed on its edge!'の行はデッドコードです。なぜなら、ifブロックとelseブロック内のコードは、実行がこの行に到達する前にリターンするからです。デッドコードは、コメントアウトされたコードと実質的には同じであるにもかかわらず、それを読んだプログラマーはプログラムのアクティブな部分であると思い込んでしまうため、誤解を招く恐れがあります。
---------------------------------------------------------------

このサンプルの場合、if文は必ずTrueかFalseになるので、returnはどちらかで必ず実行されるからということですね。
このサンプルではランダムな数字は0か1しか出されないので、3つ目の条件はそもそも設定する必要がありませんでした。もし、3つ目の選択肢として入れたいのなら、ランダムな数字の範囲を(0, 2)にして、if文に比較演算子にいる判定と、elifを使って条件分岐を増やしてあげればよかったという事になります。

スタブは一時的な措置で使う

さて、次にスタブという文字がテキストに出てきました。スタブ...また知らない言葉が出てきました。

スタブとは
(stub)
スタブとは、大規模なシステム開発の際に、完成済みのプログラムの動作を検証するための、完成していないプログラムの代用となるプログラムのことである。または、外部プログラムとの細かなインターフェース制御を引き受けるプログラムのことである。
by  ZDNET 用語辞典(スタブ)

では...と、実際の現場でのスタブについてある方に聞いてみたところ、スタブは開発している中で、本来この機能を作りたいけれど作り切っていない時や将来的にこういったものがあった方が良いよねという時に、関数やメソッドの枠組みだけを先に作っておく手法だそうです。オープンソース系のような複数人で開発するプログラムを開発する時には、後で機能を追加しやすくするようによく利用されるとのこと。ただ、お客様から依頼されたプログラム開発の場合には、開発スピードやコストなども考慮しなければならないため、不要なスタブを作らないよう避けますが、将来的に必要な機能なのであれば作ることもあるということでした。
そんな一時的な措置であるスタブの使い方です。

---------------------------------------------------------------
P.79
スタブには、実際のコードの代わりに何もしないpass文が書かれています。pass文は構文上で何らかのコードを書く必要がある場所にスタブを作成するためのものです。


def exampleFunction():
    pass

この関数が呼ばれても何もしませんが、いずれコードが追加されることを示します。
また、誤って未実装の関数を呼び出してしまわないように、raise NotImplementedError文でスタブ化することもできます。これにより、その関数がまだ呼べる状態ではないことがすぐにわかります。


def exampleFunction():
    raise NotImplementedError

example Function() (エラーメッセージ詳細略)NotImplementedError

NotImplementedErrorを発生させると、プログラムが誤ってスタブ関数やメソッドを呼び出したときに警告が表示されます。
---------------------------------------------------------------

より詳細な使い方についても聞いてみました。
NotImplementedErrorは、特にオープンソース系での開発によく利用され、未実装な機能であることを明確に示すための例外だそうです。NotImplementedErrorが返ってくれば、「この機能はまだ作ってないのだ」と判断がつくため、開発者にとってわかりやすくなります。

また、passは将来的に必要になる機能のために空の関数を定義する場合や、if 文やループの中で何も処理をしない場合に使用されるそうです。特にテストファースト開発では関数がないとテストを書くことができないため、passを使って関数だけを仮の関数を定義しておくことがあるということでした。また、Pythonは、インデントが必須な言語のため、if文などで何も処理を書かない場合でも、ブロックは作らなければならないため、passを利用するそうです。

それでは今回はこちらで終了です。今回もお付き合いいただきありがとうございました。

 

 [IT研修]注目キーワード   Python  Power Platform  最新技術動向  生成AI  Docker  Kubernetes