SSブログ

コンパイル時のワーニング(-Wallと-Werror) [プログラマー現役続行]

プログラマー”まだまだ”現役続行 (技評SE選書)

プログラマー”まだまだ”現役続行 (技評SE選書)

  • 作者: 柴田 芳樹
  • 出版社/メーカー: 技術評論社
  • 発売日: 2010/09/04
  • メディア: 単行本(ソフトカバー)

コンパイル時にワーニングを取り除くことについて、拙著の第10章「コードレビューの勧め」の「コードレビューの準備」(p.208)では、次のように述べています。
 実際に何らかの仕様に従ってコーディングを行った後にコードをレビューするのですが、まず作成者がしなければならない作業は、それがクリーンなソースコードであるかどうかを確認することです。
 クリーンなソースコードとは、以下の両方を達成しているコードを指します。
  • コンパイルエラーがないこと
  • ワーニングが出ないこと
 コンパイルエラーがないことは当然としても、ワーニングが出ないことがなぜ必要なのでしょうか?
 自分で最初から書いたコードをコンパイルした際に、コンパイラがワーニングメッセージを出した場合、そのワーニングメッセージを無視してもよいかどうかを判断することは容易です。なぜなら、自分で書いたコードだからです。
 しかし、他人が書いたコードのバグの修正とか、あるいは機能の追加などの作業を行う場合には、そうはいきません。もともとのコードが、コンパイルしただけでワーニングがたくさん表示される場合、自分が修正したことによって新たにワーニングが追加されていたとしても、両者を区別することは容易ではありません。その結果、ワーニングを無視してしまうようになったりします。
 したがって、将来の保守性を考慮すれば、ワーニングが出ないようにコードを作成しておくべきなのです。それをプロジェクトで徹底させるには、gccやg++などのコンパイルオプションで、-Wallを標準として、-Werrorも標準として使用することです。-Wallですべてのワーニング検出が有効になりますし、-Werrorにより、ワーニングがコンパイルエラー扱いとなり、コンパイルできなくなります。その結果として、ワーニングが出力されないソースコードを作成することを、プロジェクトで徹底することが可能となります。
『プログラマー”まだまだ”現役続行』(p.208)
最後の太字にしている段落部分は、初版では書いておらず、改訂版で追記した部分です。私にとっては、-Wallおよび-Werrorをデフォルトのコンパイルオプションに指定して、ソフトウェア開発を行うのが当然だし、長年そうしてきたプロジェクトに従事していたため、常識的な部分だったと思っていました。しかし、実際はあまり行われていないのではないかと思い追記した部分です。

さらに、最近のコンパイラは、単なる言語上の問題だけでなく、printf関数の書式と引数の型のチェックまで行って警告を出してくれます。そのため、コンパイル時に問題となる可能性の箇所をワーニングとして通知してもらい、その場でコンパイルエラー扱いでコンパイルが終わってしまうことが、後で実際に動作させて不具合が発生してから調査するより、非常に簡単だったりします。

これは、開発しようとしているソフトウェアのアーキテクチャとか開発プロセスとは全く別のソフトウェア開発の側面なのです。しかし、この基本的なことさえきちんとできないようであれば、そのソフトウェア開発は着実に技術的負債を積み上げていくことになります。

技術の伝承と良い習慣の伝承 [プログラマー現役続行]

企業において、若手を育成するため、先輩から後輩への知識を伝達するため、仕事を引き継ぐため、といった理由から「技術の伝承」と称した活動が行われたりします。

技術を伝承するというのは、短期間に簡単にできるもでのはありません。私自身が大学時代から今日まで経験してきたことを、すべて伝承することはできません。それに加えて、スキルを伝承できる能力が必要となります。

伝承が失敗した例として、『アプレンティスシップ・パターン』に次の例が説明されています。

アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得

アプレンティスシップ・パターン ―徒弟制度に学ぶ熟練技術者の技と心得

  • 作者: Dave H. Hoover
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2010/07/08
  • メディア: 単行本(ソフトカバー)
 17 世紀と18 世紀のアントニオ・ストラディバリ(Antonio Stradivari)の工房で作られたバイオリンとチェロは、歴史に残る名作です。それらは、定期的に数億円で売られ、過去300 年間に、それらを再現しようと多くの挑戦が行われてきました。しかし、The Craftsman(p.75)に書かれているように、「アントニオ・ストラディバリやグァルネリ・デル・ジェス(Guarneri del Gesu)のような熟練職人の秘密は、実際、彼らと一緒に消えていきました。膨大なお金を費やして、数知れず行われた実験は、それらの熟練職人の秘密を探り出すのに失敗してきました。彼らの工房の性質の何かが、知識の伝達を抑制していたに違いありません」。ストラディバリが歳を取り、弟子のアプレンティスのように日々活動的でなくなるにつれて、彼の工房での楽器の質は落ちました。彼の工房は「1 人のたぐいまれな才能のもとに発展し」、そして、ストラディバリは自分の才能をアプレンティスに受け継がせることができなかったため、彼の工房は彼と共に死を迎えました(The Craftsman、p.76)。
 ストラディバリのアプレンティスには、彼の2 人の息子も含まれていました。そして、息子達に対して何かを隠すつもりはありませんでした。私達が知る限り、彼は息子達に知っていることすべてを教えました。いや、むしろ、息子達にとって知るのが重要だと彼が考えたすべてを、息子達に教えたのです。しかし、彼は、まさに失敗しました。なぜなら、彼が認識していなかった暗黙知のすべてが、彼のスキルセットの一部だったからです。当時彼が重要には思えなかったために記録しなかったすべての微妙な知識の関連と、彼がアプレンティスと取り組んだ些細な仕事で彼が適用したすべての暗黙知の中に、彼の工房の破綻は深く根付いていたのです。
『アプレンティスシップ・パターン』(p.151)
技術の伝承は容易ではありませんが、伝承するための努力を組織は行い続ける必要があります。その場合、特定の技術を教えるというのではなく、良い習慣を伝承させて、スキルを伝承できる能力を伸ばしていくことが必要となってきます。

たとえば、勉強会を継続的に主催したり、勉強会へ参加するという習慣を継続して行えばその勉強会で学んでいる技術的な事柄だけでなく、参加者の経験談や失敗談を伝えることで伝承していくことになります。

継続的インテグレーションにしても、その環境に対して日々どのような開発を行うかが重要です。たとえば、コミットする前に自分のマシンでコンパイルからテストまでが成功するのを確認してコミットするのか、コンパイルできただけでコミットするのかは、良い習慣で開発しているのか、悪い習慣で開発しているのかという差になっていきます。この場合でも、良い習慣の開発を伝承していく必要があります。

防御的プログラミングを行うとしても、それを、コードレビューできちんと指摘するというのを習慣にしている人には当たり前ですが、いい加減なコードレビューしかしていない組織では防御的プログラミングさえ行われなかったりするかもしれません。知識だけでなく、実際の開発で実践することで、防御的プログラミンを伝承しかなければなりません。

結果として、一時的なノウハウ(技術)の伝承よりは、ソフトウェア開発全体に対する良い習慣を若い人たちに伝承することが組織としては重要になってきます。そして、その習慣を通して、ソフトウェア開発に関する技術の伝承をできる人材が育っていく必要があります。しかし、その前に良い習慣を持った組織を作り上げなければならないので、ニワトリが先か卵が先かになってしまいがちです。

現実的には、良い習慣を持たない既存の大きな組織を良い習慣を持つ組織に変えることは非常に困難です。むしろ、良い習慣を持った小さな組織に、毎年若手を入れて年々拡大していくということで大きな組織にしていくのが、遠回りのようで近道だったりします。

継続した学習と勉強会 [プログラマー現役続行]

会社で始業時間前に行う非業務の勉強会を始めたのが富士ゼロックス情報システム(FXIS)に勤務していた1999年の初め(「勉強会一覧」)です。現在でも平日の始業前に、私が主催している勉強会が2つ、参加している勉強会が1つあります。

勉強会を開催して始める頃には、参加者も多いのですが、途中で少なくなっていって、参加メンバーが固定されていきます。自主的な参加の勉強会ですので、途中で参加しなくなってしまう人が出てくるのは仕方ないことかもしれません。ただ、新卒新人の場合には、強制的に参加させる必要がある場合もあります。

FXIS勤務時代は、フレックス勤務でしたし私自身が部門長でしたので、コアタイム前に勉強会を開催して、新卒新人は強制参加で業務扱いにし、先輩は非業務扱いの自主参加にして開催する勉強会もありました。新卒新人には半年から一年間はとにかく継続的に強制参加させていました。その参加を通して、継続して学習する習慣を身につけるだけでなく、非業務でありながら参加している先輩と一緒に学習することで、学習を継続するのが当たり前だという認識を持ってもらう訳です。

完全な自主参加の勉強会の場合には、様々な理由から脱落していく人が増えてきます。
  • 業務が忙しいので業務を優先したい
  • もともと朝早く起きるのが苦手
  • 他の勉強を優先させたい
これらは、自主参加の勉強会の場合には、本人にとってはもっともらしい正当な不参加理由に思えるかもしれません。しかし、このような理由で途中から参加しなくなった人が、本当に一人で学習を継続していることはまれです。

たとえ、週1時間であっても、一ヶ月に4時間か5時間、一年で50時間以上になります。50時間としてもそれだけ時間をかければ技術書によっては読み終えるかもしれません。技術書を読み終えるという経験を積み重ねるには、一人で学習するよりは、勉強会への参加の方が良かったりします。

API設計の基礎(仮題)(4) [API設計の基礎]

第1章を書き終えた段階で、執筆作業が止まっていましたが、今年は何とか残りの章も執筆したいと思っています。とりあえず、リスト1-3にバグがあったので修正したものです。


(「API設計の基礎(仮題)(3)」「API設計の基礎(仮題)(2)」「API設計の基礎(仮題)」)

書籍『Coders at Work プログラミングの技をめぐる探求 』 [プログラマー現役続行]

Coders at Work プログラミングの技をめぐる探求

Coders at Work プログラミングの技をめぐる探求

  • 作者: Peter Seibel
  • 出版社/メーカー: オーム社
  • 発売日: 2011/05/25
  • メディア: 単行本(ソフトカバー)
著名なプログラマーに対するインタビューを集めた書籍です。まもなく、翻訳本が出ます。

以前、何度かブログで紹介しています。
もう一度、日本語版で読み返すのを楽しみにしています。

リーダはコードに関心を持つ(3) [プログラマー現役続行]

リーダがコードに関心を持たないような組織においては、継続的インテグレーション環境を導入してビルドやテスト実行だけでなく、FindBugsを含む様々な静的解析ツールを実行させても、それらの結果に関心を持たなかったりします。
  • ビルドの失敗に関しては、どのような原因で失敗しているのかログを見ることで、現場の開発者がどのような開発をしているのかが分かる場合があります。たとえば、単純なコンパイルエラーが発生していたりすると、開発者がローカルでコンパイルもせずにコミットしている可能性があります。
  • FindBugsの警告の内容を確認することで、どのようなコードが書かれているのかも理解することができます。そして、警告が何日も放置されているようなら対処するように指示する必要があります。
  • カバレッジの結果を見て、テストが十分に行われているか、特に、C2カバレッジまで測定できている環境であれば、テストで条件漏れがないかを確認することができます。
  • ビルド結果の履歴を見て、(マルチスレッド系のテストで起きやすいですが)ビルドが時々失敗していることに気づくことがあったりします。それに対して、何も対処されずに放置されているならば調査を指示したりする必要があります。
継続的インテグレーション環境というのは、単にサーバが自動で行ってくれるというだけでないのです。その結果にリーダが関心を持ち、必要な指示を日々行うことで、ソフトウェア開発組織としてのより健全な運営のための情報を提供してくれます。

しかし、リーダが関心を持たないということは、日々の指導も行われないことになり、結果として現場の開発者もビルドが成功するかどうかしか関心を持たなくなってしまい、技術者としても成長しません。さらに、開発組織そのものも成長しなくなる可能性が高くなります。

デバッグを支える知識 [プログラマー現役続行]

ソフトウェアのデバッグでは、不具合の現象を観察し、ソースコードを調べたり、デバッガーを使用したりして原因に対する仮説を立てます。仮説を立てて、それを証明していくことになります。証明といっても、仮説通りの動きをしているかを確認するためのデバッグ文であったりします。

仮説を立てるには知識が必要です。自分が持っている知識の範囲内でしか仮説を立てることはできません。

たとえば、C言語のコードで、 int型へのポインターptrを通して、*ptr としてポインタの指す先を参照したとします。この参照がx86系のCPUでは動作して、他の種類のCPUでは動作しない場合があります。ptrの指す先のアドレスが4バイト境界を指していない場合には、CPUによっては正しく動作しないという知識を持っている人は、それが原因であるという仮説を立てることになります。そして、それを証明するためにデバッグ文を入れてアドレスを確認する訳です。そして、4バイト境界を指していないと分かったら適切な修正を行います。一方、CPUに関する知識がない人は、デバッグ文を入れてアドレスを表示させることは行うかもしれませんが、そのアドレスを見ても何が悪いのかは分かりません。そして、試行錯誤を行うことになります。

別の例としては、Javaで特定のクラスのインスタンスをnewで生成するコードが戻ってこなく、どうもコンストラクタの処理の中で止まっているように見える場合があります。①本当に止まっている場合と、②実は、RuntimeExceptionがスローされて誰もそれをキャッチしていない上に、そのスレッドを動作させているThreadGroupがキャッチされなかった例外を表示しないようにもみ消すようなシステムが作られている場合があります。後者の場合、キャッチされなかった例がどのように処理されるのかという知識がないと仮説として立てることもできなかったりします。

残念ながらこのような知識は、バグに直面して一人でデバッグしている時に得られるものではありません。運良く、相談できる経験のある人が居れば解決できるかもしれません。そうでなければ、一時間で解決することが、数時間や数日かかってしまうことがあります。

ソフトウェアエンジニアとしては、継続した学習を通して、知識も増やしながら、ソフトウェア開発を実践していく必要があります。そして、各人の自己学習だけでなく、仲間同士による勉強会や、強制的に学習を強いられる私が行っているような「プログラミング言語Java」教育などが必要となってきます。

リーダはコードに関心を持つ(2) [プログラマー現役続行]

実際に書かれているコードの品質を確認できない、しないリーダであれば、単にスケジュール管理だけになりがちです。そのため、品質優先ではなく納期優先の管理となったりします。遅れが発生した場合に、何が原因かということに対して現状把握を行い対策を打つことをせずに、担当者に「納期に間に合うように対策を考えて再スケジュールしなさい」という指示だけだったりします。

しかし、遅れの原因は、仕事の難易度が高かったり、あるいは、担当者のスキルレベルが低かったりすることがあります。その場合、コードを書いている担当者は、遅れを挽回する対策を考えることは無理かもしれません。しかし、リーダは、コードを見ることもないので、再スケジュールしなさいとか、早く不具合を修正しなさいとしか言えなかったりします。

リーダがコードを読んで品質を確認できることは、仕事の難易度と技術者のスキルレベルを把握して、適切な仕事の割り当てを行い、プロジェクトを健全に推進するために必要なことです(「技術者のレベルとソフトウェア開発の難易度(6)」)。

リーダはコードに関心を持つ [プログラマー現役続行]

ソフトウェア開発組織において、開発のリーダが現場で書かれたコードに関心を持たない場合、実際に書かれているコードの質を知ることはできません。

関心を持つということは、実際に自分でコーディングしなくても、以下のことを行ったりすることだったりします。
  • コードレビューにレビューアとして参加する
  • レビューに参加しなかったとしても、(Subversionなどの)ソースコードコントロールからソースコードを取り出して、実際に書かれたコードを見たりして、問題があれば担当者に指摘する。
  • ソースコードのコミット状況を調べて、怪しげなコミットがされていたら、その内容を調べてみて、問題がないか確認する。
この場合のリーダは、単なるチームリーダやグループリーダだけでなく、いわゆる組織長である部門長ぐらいまでを指します。当然、部門長であれば対応方法も異なります(つまり、きちんとコードを書かせるにはどうすべきかということを検討して指示したりとか)。

要は、ソフトウェア開発組織全体が書かれたコードの品質に関心を持っているというメッセージが、日々の活動の中で多かれ少なかれ実際にコードを見て品質を確認することで、伝達されていることが重要です。

『Android Developer's Cookbook』の翻訳作業終了 [プログラマー現役続行]

The Android Developer's Cookbook: Building Applications with the Android SDK (Developer's Library)

The Android Developer's Cookbook: Building Applications with the Android SDK (Developer's Library)

  • 作者: James Steele
  • 出版社/メーカー: Addison-Wesley Professional
  • 発売日: 2010/10/27
  • メディア: ペーパーバック

昨年末から開始したこの本の翻訳作業がほぼ終わりました。翻訳本としては、私にとってはちょうど10冊目になります。印刷されて発売されるまでには、もうしばらくかかります。

全部で12章から構成されます。
第1章 Android の概要
第2章 アプリケーションの基本:アクティビティとインテント
第3章 スレッド、サービス、レシーバ、アラート
第4章 ユーザインタフェースのレイアウト
第5章 ユーザインタフェースのイベント
第6章 マルチメディア技法
第7章 ハードウェア・インタフェース
第8章 ネットワーキング
第9章 データストレージ技法
第10章 位置情報に基づくサービス
第11章 高度なAndroid 開発
第12章 デバッグ