ソースコードの質
近年、ハードウェアの性能向上などにより、IT業界をめぐるインフラは、ようやく市場の要求に耐えうるようになってきた。以前はプラットフォームの陳腐化によって5年と持たなかったソフトウェアの平均寿命は、ここへきて徐々に延びつつある。
このような状況の中でソフトウェアに求められるものは、繰り返し行われる機能追加に耐えうる「拡張性」と、長期に渡って品質を保てる「保守性」だ。これらの課題については、クラウドのような分散コンピューティング技術や、オブジェクト指向デザインのような設計思想といった大きな枠組みの中で数多く議論され、ソフトウェア技術の進歩を押し上げてきた。「実際の現場においてこれらの課題をインプリメントするのは、システム設計者やSEといった上流工程を任された人間の役目である」と一般に言われている。
彼らのアウトプットは、基本的に文書(Document)だ。文書は日本語や図から構成されており、読解の敷居はそれほど高くない(作成の難易度は高い)。特に、顧客や経営者に見せる資料は、専門知識がなくとも理解できるよう分かりやすく書かれていることだろう。彼らのアウトプットは多くの人の目に触れ、議論にさらされやすい。たくさんの批評や支援のもとに経験を積むことで、おのずとその品質や精度は上がっていくだろう。
一方、われわれプログラマの方はどうだろうか。
驚くべきことに、IT業界に携わっている人でさえ、プログラマのアウトプットが「ソフトウェア実行モジュール(実行ファイル)」だと思っている人がいる。もちろん、最終的には実行モジュールを納品するのだから、その見解は間違いではない。しかし、われわれが画面に向かってあくせくとタイプし、ない知恵を振り絞ってひねり出しているものは、プログラミングされたコードの方である。実行モジュールは、ソースコードを実行可能な状態に加工したものにすぎない。
そもそも、読解に多くの前提知識を必要とするソースコードにあれこれ言える人間の数は限られている。実際の現場において、議論の対象となったり吟味・分析されたりする機会は、上流工程のそれに比べて異様に少ない。工数が潤沢にあるプロジェクトであれば、ソースレビューやペアプログラミングなどが実践されているかもしれないが、それでも1つのコード作成にかかわる人数はせいぜい1~2人であり、コードそのものがブラッシュアップされる機会は、残念ながらあまりないのではないだろうか。
これまでは、それでよかった。結果的にソフトウェアが正しく動けば、それで事足りていたからだ。われわれに課せられた一番の課題は、実行モジュールが正常稼働することであり、障害が発生すればそれを修正するだけであった。この時点で、アウトプットの評価はもはやソースコードから離れ、テスト項目の網羅性やテスト結果に基づく品質分析によって行われることとなる。
このように、設計と検査の間にある工程、つまりわれわれが最も苦労するコーディングの作業は、ブラックボックス化される傾向にある。ところが、できあがったソースコードの質は、プログラマの能力によって驚くほどの差が出る。なぜなら、上流工程で作られる設計書は、必要機能や拡張保守性を網羅するための「プログラミング設計指針」にすぎないからだ。
もし、ソフトウェアの設計書が建築物の設計図と同じなのだとすれば、設計図どおり忠実に作りさえすれば、誰が作ってもまったく同じものができあがるはずだ。実行モジュールの動作だけを取って見れば、これは当てはまるだろう。しかし、本当の意味でのアウトプットであるソースコードは、1つとして同じものにはならない。設計書をコードに落とすには、(設計図と比べて)あまりにも情報が足りな過ぎるのだ。
そこには、上流工程で網羅されなかった、粒度の細かい機能仕様や設計が数多く存在する。どこまでを上流で設計するか、プロジェクトによってもその線引きは非常に曖昧(あいまい)だ。プログラマは、絶えず不足分の設計を行いながらプログラミングしており、上流のツケによって払わされたコストは、ブラックボックス化された工程の中にすべて押し込まれ、周りからはまったく見えない。
これに加え、アルゴリズムの組み方やコードの可読性、プログラミング言語の習熟度や上流設計を自ら改善できる能力など、さまざまな要因が関わってくることで、出来上がるコードの実装レベルにおける保守性が大きく変わってくる。特に、ソースコードは最も頻繁にリビジョンアップが行われる納品物であり、常に水準低下の危険性にさらされている。修正方法の質によっては、後々の保守作業に甚大な被害をもたらすかもしれないにもかかわらず、その修正の詳細を把握しているのは、ほぼコード作成者本人だけである。今後、拡張・保守工程の期間が伸びるであろう将来のことを考えると、深刻に受け止めなければならない問題であることに間違いない。そして一番の問題は、このことを知っているのはコードを読解できる限られた人間、プログラマだけであるということだ。
残念ながら、プログラマを除くほとんどの人は、コードが正しいことよりも実行モジュールが正しく動くことの方を優先する。非常に洗練されたコードは、バグのないプログラムに負ける。優秀なプログラマはバグの数によって過小評価され、その素晴らしいプログラミングの思想は日の目を見ることなく、その人だけの暗黙知となる。プログラマは自分のコードについて学習できる機会が極端に少ない。スパゲッティコードを作る人はいつまで経ってもスパゲッティコードを作り続け、よもや自分のコードに多くの改善点があるとは思いもしないだろう。
われわれは実行モジュールを作っているのではない。ソースコードを作っているのだ。
プログラマ自らが、コードの洗練性や進化を渇望せずして、一体誰がそれを望むのか? われわれは一刻も早く、コードの質の向上について議論しなければならない。このままではいつまでたっても他人の書いたプログラムの修正に頭を抱えたり、機能追加にかかる工数を理解してもらえず、ブラックボックス化された工程の中で孤軍奮闘しなければならないだろう。来るべき保守フェイズ長期化時代に向けて、対策を練っておく必要がある。いつまでも海外からの技術革新を待っているだけでは、日本のIT業界は市場に生き残り続ける製品を作ることが難しくなっていくだろう。
では「コードの質の向上」とは一体なんだろうか。「洗練されたコード」とは何であろうか。いくつか論点があると思うが、わたしが最も重要視しているのは「可読性」である。プログラマがコードの可読性にもっと気を使うことで、ソフトウェアの長期保守性が格段に上がると信じている。ここではその詳細は述べないが、機会があればテキスト化する(できる)かもしれない。
プログラミング言語は、構造化やオブジェクト指向プログラミングなどさまざまな進化を遂げてきたが、次の大きな技術革新は「可読性の向上」に焦点を当てたものではないかと、わたしは推測している。ScalaやRubyなど最近の言語は、非常に簡潔なコードが書けるものが多い。言語仕様が徐々に可読性という方向に向かって進歩しつつある兆候なのかもしれない、という考えはいささか勇み足だろうか。
ちなみに、簡潔なコードであれば可読性が高いかというと、必ずしもそうではないと、わたしは思っている。一見冗長ではあるが、分かりやすく書かれたコードというものも存在するだろう。一通りの経験をお持ちの方であれば、この辺の話は容易に理解できるはずだ。では、少し飛躍するが、遠い将来には変数名のスペルミスすらコンパイラがチェックするようになるかもしれない、というとどうだろうか。「さすがにそれはないだろう」と思った方は注意した方がいい。なぜならコンピュータは、いずれ人間の言語を解して動くようになるからだ:P
最新の投稿
コメント
難しい問題ですね。解決には、プログラマが作ったソースコードを顧客やPMが評価できる仕組みを作るしかないのでしょう。私の大胆な持論ですが。仕様書つまり、単なるドキュメントを見てソフトウエアを評価するのは、やはり評価する人、つまりデシジョンメーカであり、所謂『偉い人』にとって一番楽です。そのため、ほっとけば、どうしてもそうなってしまうので、それを強制的に禁止すれば良いのではと思います。つまり、ソフトウエアの評価をソースコードで行うように強制するのです。そのため、評価出来ないような、可読性の低いプログラムを書くプログラマはたとえ、それが旨く動いていたとしても、評価が最低になります。私は.NETしか知りませんが、.NETの世界では、ソフトウエアの技術革新が著しく、コードをぱっとみただけで、詳細ドキュメントに近いレベルの情報量を読み取れる、レベルに近づいています。
ハムレット
色々と考え始めると難しいのですが、ソースコードの可読性を大まかに見るだけなら、最近は様々なソースコードメトリックスツールが出回っているので、それを活用するだけでも随分違うと思います。
メトリックスとして、コード全体並びに関数又はメソッド1つあたりのステートメントの行数と、関数やメソッドの引数の数の部分を見るだけでも、どの辺に問題が有りそうなのかという傾向がつかめると思います。個人的な経験では、大抵の場合、問題となる部分はメソッド又は関数あたりのステートメント行数が500行以上に肥大しており、また引数の数がやたら多いため、書いた本人ですら時間が経てば認識・把握が難しくなる傾向がありました。これにメトリックスとしてコードクローンの指標値(自己相関係数)でも有れば、さらに助かります。
後はDoxygenやJavadoc等ですぐにAPI Referenceを作成できるようにコメント規約を徹底させるとかでしょうか。ソースコードが良く整理・整形されていれば、コメント作成も時間を掛ければ、さほど難しくないように思います。
銀の弾丸は無いと思うのですが、地道な努力を積み重ねれば、それなりの成果は出るように思います。実際にあるプロジェクトでは、コーディング規約にソースの行数制限を入れても、みんな馬鹿言うなと、なかなか言う事を聞いてくれませんでした。
やはり案の上、たちの悪いバグが発生して、デバッグがなかなか終息しなかったのですが、2日程潰して、強引にペアプログラミングを行い、実際にプログラマ本人の目の前でリファクタリングを行い、メソッド当たりの行数を100行以下に、ソースコード全体でも500行以下になるようにファイルを分割した上で、デバッグを行い無事に終息させてみたところ、ようやくソースのコード行数規制に意味が有る事を認識してもらいました。(それでも、努力目標程度にしか思ってくれないんですが。・・)
ソースコードの可読性を客観的に評価することは確かに難しいと思います。
しかし、分野を問わずプログラミングの現場では可読性の低いソースコードにより多くのプログラマが苦しめられているのも事実ではないでしょうか。
極端な話、ソースコードの可読性の悪さがプログラマの生産性を低下させ、ひいてはプロジェクト全体に影響する致命的なトラブルに発展し、その負荷でチームメンバの心身が壊れてしまうこともあるでしょう。
実際自分自身が、前任から引き継いだスパゲティソースコードに苦しめられ、それが一因となりメンタルヘルスを崩して心療内科にお世話になったりしています。
最悪のケースを考えると鬱病→自殺、という流れもあり得ます。
可読性の低いソースコードは、たとえミッションクリティカルな分野でなくとも、現場のプログラマやチームメンバを(最悪の場合)死に追いやる可能性があると自分は考えています。
たとえ客観的な評価が難しくとも、自分の書いたソースコードが原因で同僚や引き継ぎ先のプログラマを苦しめたくない、そういう職業意識といいますかプログラマの誇り、それをベースに、せめて自分だけでも、後々引き継いだ担当や同僚が「誰だこのソースコード書いた馬鹿はぁぁああ!!!???」と叫ばなくて済むような可読性の高いコードを書くことを心がけています。
「Cプログラミング診断室」も今は昔となってしまいましたが、「動けばいいや」で気合いで書かれたソースコードが後々、他人を(あるいは自分を)苦しめるのは今も変わらないみたいっすね・・・。
玄米茶
>yamamotoさん
大胆かつすばらしい持論ですね!
残念ながら私はそこまで踏み込むことができなかったようです。
せめてプログラマ内だけでもコードの質について危機感を持とう、と言ったにすぎないのですから。
.NETは今まで触れる機会がありませんでしたが、非常に興味を持ちました。
少しお勉強してみようと思います。
コメントありがとうございました。
>ハムレットさん
なるほど! メトリクスツールで分析することで、コードの問題点をあぶりだすということですね。
コード分析自体知らなかったので、すごく勉強になりました。ありがとうございます。
ちらっと検索するとツールはいくつか見つかりましたが、分析の手法みたいなのは本でないと載ってなさそうですね。今度さがしてみます。
>坂本昌彦さん
おっしゃること、まるごと同意です。
一番深刻なのは、やはり坂本さんご自身の例にあるところの「前担当者からスパゲッティを引き継いだとき」だと思います。スパゲッティ具合で修正工数にものすごく差が出るにもかかわらず、この辺りってあまり理解してもらえないんですよね。そして自分の苦労がむなしくなってくる。大変危険な状態だと思います。
私の場合、引継いだコードは、処理の理解・把握もかねて自分でわかりやすいようにコーディングしなおします。
結構嫌われます(笑)が、自分の身を守るため「知ったこっちゃない」と開き直ってます。
お体大事になさってください。
コメントありがとうございました。
CMP
蛇足ですが、スペルミス程度ならコンパイラでなくIDEががが(ry)。
簡潔なコード≠可読性ってことがわかるには、それ相応の経験をつまないといけないんですよね。
それに可読性は悪いが処理速度を向上させるのためのコードってのも存在する。それをブラックボックスと取るか、職人の技術力と取るか・・・。
玄米茶
>CMPさん
コメントありがとうございます。
処理速度の向上というと、一昔前までは相当シビアでしたね。関数のコールスタックすら気にしたり、インラインアセンブラ使ったり、とにかく可読性を損なう工夫がいっぱいありました。そうでもしないと要求仕様に耐えられなかったんですね。
現在でも例えば、マルチスレッド(プロセス)化、リソースの排他範囲やトランザクションの範囲、プロトコルやパケットサイズの最適化、メモリ効率といった辺りに細心の注意を払わなければならない分野もあるとは思いますが、ハードウェアの性能やソフトウェア技術の向上により、多くのプログラマがこのようなことを気にせずプログラムが書けるようになりました。要するに性能の問題は、OSやミドルウェアのパラメタチューニング的なものでまぁなんとかなるよ、という分野の方も結構多いのではないでしょうかね。
んで、そういう方々がごくごく小さな処理速度の向上を意識するあまり、コードの可読性を損ねてしまう、なんていうことには私は反対で、要求性能がすでに満たされているのであれば、性能よりも可読性を取るべきでしょうね、と思っています。
なにやら雑談になってしまいましたが、こんなところです。
Error401
総論としては完全に同意しますが、ひとつ気になった点があります。
> 5年と持たなかったソフトウェアの平均寿命は
これ、何かソースはありますか?
私の感覚だと「世の中には遺跡のようなソースがごろごろしてる」という感じです。また、私はCOBOLとは無縁の生活を送ってきましたが、COBOLの世界では、「昔のコード」の昔さ加減が尋常でなく昔ではないかと想像します。
ここから雑談。
> われわれは一刻も早く、コードの質の向上について議論しなければならない。
20年くらい前(あるいはもっと前から)いろんなところで議論されてきましたが、それらの議論は今日のプログラマに影響を与えたのでしょうか。
今はなきCマガジンのPhinloda氏の記事に、コードの美しさに関するものがたまにありました。今でも http://www.st.rim.or.jp/~phinloda/rlist.html や http://www.st.rim.or.jp/~phinloda/phin.html などで、昔の記事が読めます。
2chでもたまに議論が沸騰しますね。if (0 == hoge) {}は是か非かとか。
> 遠い将来には変数名のスペルミスすらコンパイラがチェックするようになるかもしれない
typoやスペルミスは相当恥ずかしい、といった感覚は、今はもう無いのかなぁ。
仲澤@失業者
可読性は重要ですね。
自分もそう考えて、何年か前から、プライベートなソースは
「日本語」で書くようにしてます。英語が苦手なんで(笑)。
最近のC++コンパイラは日本語のソースもコンパイルしてくれるので
うれしいですね。
void メインフレーム::リアルタイム測定()
{
主データ.一括測定();
グラフウインドウ( 0)->表示更新();
ツールバー.測定時間.表示更新();
}
てな感じ、読み取るスピードが格段に違います(笑)。
母国語が英語な人は、こんな感じでソースを見ているのかも
しれませんね。たずねたことはありませんが。
「わけわかな英語のソースを書くんじゃねぇ」と注意するのに
疲れたので、日本語で書けばいいじゃんと思う、今日このごろです。
海外へのアウトソーシングがある場合は別ですけどね(vv;)。
まぁ、そのうちにエディタが自動的に翻訳してくれるようになるでしょう(爆)。
ハムレット
こんばんは
とりあえず、私が過去に試した事のあるツールのうち、フリーで手に入るものについて紹介しておきますね。この手のツールの使い方ですが、要は指標値の意味とその数値の上下がどのように品質に影響するかが判れば、後はソースを読み込んで、ボタン一発だったと思います。まずは計ってみましょう。
*SourceMonitor
URL:http://www.campwoodsw.com/sourcemonitor.html
対象:C++, C, C#, VB.NET, Java, Delphi, Visual Basic (VB6) or HTML.
ステートメントの行数をソースコード、クラス、関数毎に算出してくれます。またソースの複雑差に関する指標値の算出やメソッドの引数チェックもしてくれます。割と手軽に使えると思います。
*CCCC
URL:http://sourceforge.net/projects/cccc/
対象:C++ and Java
元々大学の研究の一環として、開発者たちの提案したコードメトリックスの有用性を実証するために開発されたものだったと思います。あんまりパッとしなかったのですが、バッチ的に大量のソースを解析して、後で結果をみるような使い方をしたいときは便利かもしれません。
*CCFinder
URL: http://www.ccfinder.net/index-j.html
対象:Java, C/C++, COBOL, VB, C#
国産のツールです。元々コードクローンの検出を目的に開発されたものです。
実行にそれなりのスペックのマシンを要求し、使い方も易しくはないですが、コードクローンの分布状態を可視化する部分は、最初に見た際に非常に印象深かった記憶が有ります。コードクローンを真剣に撲滅したい場合にはお勧めです。
あと、ソースコードメトリックスに関する記事で、@ITに有る物を紹介しておきます。
山浦恒央の“くみこみ”な話(24)
人類初のソフトウェア・メトリクスをめぐる熱い論争
http://monoist.atmarkit.co.jp/fembedded/articles/kumikomi/24/kumikomi24.html
ではでは
玄米茶
>Error401さん
すみません。平均寿命のソースはないです。
私もCOBOLとは無縁の生活であんまりわかっていないのですが、COBOLの世界ってメインフレームやミドルウェア上で動く業務アプリがほとんどなんじゃないでしょうか? これらは一旦正常稼動するとリビジョンアップの契機がほとんどないクローズドな……、あ、いや、だからといって除外していいルールなんてありませんでしたね。正確さを欠く文章だったかもしれません。
雑談について。
すごく興味をそそられるコラムです。ご紹介ありがとうございます。一気に読んでしまいそうです。
あとif文の話。
それはひょっとして左辺と右辺のどちらに何を記述すべきかという議論でしょうか。私も以前悩んだ経験があるのですが、こんなこと悩んでるのなんて自分だけだろうな、と思っていたのでかなり衝撃を受けています。もしかすると世間は私が思っているよりも、はるかにコードの質への認識が進んでいるのでしょうか。メトリクスツールのようなコードへのアプローチもあるようですし、井の中の蛙とはほんとうに恐ろしいです。
コメントありがとうございました。
>仲澤@失業者さん
日本語コードというのは思ったよりも読みやすいですね。驚きました。なんというか、ぱっと見た感じのとっつきやすさがいいです。私は可読性って右脳で感じる印象みたいなものも重要ではないかと考えていて、要するにぱっと見た感じで大体の処理の流れがわかるような書き方・段組なども考慮すべきではないかと思ってるんですね。まず全体理解を促すためのもので、おおまかな流れをつかんだ後に精読することで、コードの把握が早まったり理解度が増すと思うのです。
その点で「日本語を使う」というのは、全体把握に適しているかもしれませんね。
コメントありがとうございました。
>ハムレットさん
詳細なご紹介ありがとうございます。
色々ためしてみます。
いくつかツールの紹介が上がっていたので、便乗させてもらいます。
コード探知機「Sonar」でプロジェクトの深海を探れ! (1/4) - @IT
http://www.atmarkit.co.jp/fjava/rensai4/devtool17/devtool17_1.html
というのもあるようです。試してないので無責任かもしれませんが、WinやWeb系のメジャー言語に対応しているようですし、興味があります。
アラファイブ
よく悪い例として挙げられますが、自分は「当たり前で意味のない
コメント」も意味があると思っています。
プログラム本文と比べて行が短めで、しかも開発環境や、いいエディタ
なら緑色などの色が付いて、プログラム内の「かたまり」を区別しやすく
なり、読むリズムが付くからです。
コメント本来の意味からは外れますが、可読性を言う場合、これも
意味があるのではないでしょうか?
玄米茶
>アラファイブさん
あると思います。
「処理のかたまり」の先頭行に必ずコメントをつけるのは、私もよくやります。
右脳による全体把握に適してますよね。
コメントありがとうございました。