最初は「良いコード」を書くための知識や心構えから話そうか
「良いコード」! いろいろ想像しちゃいます。芸術的なコード、1バイトの無駄もないコード……
いや、チーム開発という前提のもとでは、必ずしもそういうものがいいとは限らないんだ。わかりやすい基準だと、私はたとえばこういうコードが一般的に「良いコード」だと思うよ
- プロジェクトに参加したばかりの人でも、無理なく理解できる
- 長期的にメンテナンスしやすい(変更を加えたり、バグを修正したりしやすい)
えっ、そんなことでいいんですか?
そんなこと、が大事なんだ。これができてないコードばっかりじゃあ、チームとして一緒に作業できないよ? これができてようやく、スタートラインってところだね。じゃあさっそく、コードの見た目の問題から見ていこうか
コーディングスタイルとは
プログラムのアルゴリズムやロジックとは無関係に、書きかたが分かれる場面があります。たとえば、よく知られたところでは次のような項目があります。
- インデント(字下げ)の幅
- 半角スペース2文字分でインデントする
- 半角スペース4文字分でインデントする
- 半角スペース8文字分でインデントする
- インデントのしかた
- タブ文字でインデントする(ハードタブ)
- インデントの幅に相当する数の半角スペースで行う(ソフトタブ)
- スペースの空けかた
function ( arg1, arg2 )
のようにスペースを空ける
function(arg1,arg2)
のようにスペースを詰める
- 複数単語が連なる識別子[1]の書きかた
- 小文字の単語とアンダースコアで
variable_name
のように書く[2]
- 先頭の単語はすべて小文字、2つ目以降の単語は先頭文字を大文字にして
variableName
のように書く[3]
- 単語の先頭文字を大文字にして
VariableName
のように書く[4]
- 改行の位置
- 関数の宣言では型名のあとで改行するのか、しないのか
- 関数の宣言やif文では波括弧の前で改行するのか、しないのか
このような違いはコーディングスタイルと言われます。コーディングスタイルはコーディング規約の一部としてプロジェクトごとに定められている場合があり、プログラミング言語やOSS(Open Source Software)のプロジェクトによってどのようなコーディング規約が定められているかをまとめたWikipediaの記事もあります。
スタイルがバラバラのコードは読みづらい
次のような理由から、1つのプログラムの中でも場所によってコーディングスタイルがそろっていないことがあります。
- 複数人で開発する際に、コーディング規約が決まっていなかった
- 別のプロジェクトからコードを引用した
- その場しのぎで適当に直したものがそのまま残った
- 前任者からの引き継ぎが不十分だった
文法エラーになるような致命的な間違いと異なり、コーディングスタイルの違いは見た目の差だけでプログラムの動作に影響がない場合が多い[5]ため、あまり注意が払われないこともあります。そのため、コーディングスタイルがファイルごとに異なっていたり、それどころかリスト1のように同じファイルの中で異なっている場合すらあったりします。
しかし、このようにコーディングスタイルが統一されていないコードは、読みづらく、コードを理解するのに時間がかかります。また、精神的に疲れるために、間違ったり間違いを見落としたりしやすく、コードを誤読したりバグを埋め込んでしまったりしてしまう可能性が高まります。
スタイルの違いがバグを生む
コーディングスタイルの違いがバグの原因になることもあります。もとのコードがリスト2のようなとき、(a)でも(b)でもfailed
が真であればdo_fallback()
が実行されます。そこで仕様の追加があって、do_fallback()
のあとにfinalize()
も実行することになったとしましょう。しかしリスト3のようにまったく同じ形で修正を施すと、(b)では常にfinalize()
が実行されるというバグが埋め込まれてしまいます。これはJavaScriptやC言語などでたまに見かけるバグです。
プロジェクト全体で「if文では必ず波括弧を付ける」というスタイルが徹底されていればこのバグは発生しませんし、「if文で実行する処理が1つだけのときだけは波括弧を付けない」スタイルが徹底されている場合も、このような変更には注意が向けられるためバグの発生を防ぎやすいでしょう。
しかしコーディングスタイルが統一されていないと、たまたま波括弧が付いていた個所だけを見て前者のスタイルと早合点してしまい、波括弧の追加が必要な個所を見落としてしまいかねません。
つまり、コーディングスタイルを統一していないとバグ発生のリスクが高まるということが言えます。括弧の付けかた一つでバグを埋め込む可能性が減るのであれば、コーディングスタイルを統一することには大きな意義があります。
ツールの助けを借りて統一しよう
コーディングスタイルを統一するためには、テキストエディタ[6]の力を借りることができます。
プログラミング向けのテキストエディタには、次のような機能があります。もちろんEclipseやVisual StudioのようなIDE(Integrated Development Environment、統合開発環境)に組み込まれたエディタにもそのような機能があります。
- ソースコードを読みやすく色付け表示する
- 自動的にインデントをそろえる
- 長い名前を自動的に補完する
- リファクタリング[7]を支援する
テキストエディタを適切に設定すれば、統一したコーディングスタイルでコードを書くことができます。
また、言語によってはコーディングスタイルを確認したり統一したりするためのツールが提供されていることもあります[8]。「コーディング規約チェックツール」といったキーワードで検索してみてください。
既存のコードは少しずつスタイルを統一しよう
現在、手元にコーディングスタイルがそろっていないコードがあるときにはどうすればよいでしょう。一度にすべて修正してしまいますか? それとも諦めてしまいますか?
コーディングスタイルがばらばらのコードのスタイルを統一するためには、ツールを使って改行位置やインデント幅を揃えたり、正規表現を使って一括置換したりといった方法が考えられます。しかし、「プロジェクトでの名前づけはスネークケースだが、使っているライブラリの名前づけがキャメルケースである」「内部の名前づけはキャメルケースだが、公開しているAPIはスネークケースである」などのように、複数のスタイルが混在せざるを得ない場合もあります。このような物まで一度にすべて修正してしまうと機能が壊れてしまいますので、スタイルの修正は慎重に進める必要があります。変更個所をカバーした自動テストがあれば一度にすべて修正しても問題がないことを確認できますが、残念ながら、「自動テストが整備されているのにコーディングスタイルは統一されていない」プロジェクトというのは筆者は見たことがありません。
こんなとき、筆者は次のようなやりかたを取っています。少しずつ着実に進められると同時に、無用なリスクを冒さないやりかたなので、みなさんも参考にしてください。
- まずコーディングスタイルを決める
- 新しく書くコードは新しいコーディングスタイルで統一する
- 既存のコードを変更するときは、まずファイル単位で新しいコーディングスタイルに移行する。コーディングスタイルの修正が完了してから、バグ修正や機能追加をする
- 完全を求めない
- 設計の変更を伴うようなリファクタリングは控える
コーディングスタイルを決める
コーディングスタイルを決めるときは、インターネットで公開されていてよく使われているものから自分たちに合うものを選ぶとよいでしょう。前出のWikipediaの記事などを参考にしてください。
また、公開されているコーディングスタイルをそのまま使うのではなく、自分たちの現実に合うようにアレンジすることも必要です。たとえば、Linux Kernelのコーディング規約では次のように書かれています。
if文で実行する内容が1ステートメントの場合は波括弧を省略せよ、というルールです。しかし自分たちのプロジェクトではif節の波括弧は省略しないほうがよいという意見であれば、「Linux Kernelのコーディング規約には基本的に従うが、if節の波括弧は省略しない」というふうにアレンジしてもかまいません。
コーディングスタイルを統一してから変更する
新しく書くコードはもちろん決めたコーディングスタイルに統一して書きますが、問題になるのは既存のコードです。
既存のコードを変更するときは、まず変更する個所が含まれているファイル単位で新しいコーディングスタイルに移行し、そのあとでもともとやろうとしていた修正や機能追加などの変更を行いましょう。これは、変更によって問題が発生したときに、問題の原因となった変更個所を特定しやすくするためです。
また、コーディングスタイルを統一する際は、ルールを1つ適用するごとにコミットを分けることも大切です。たとえばインデントのルールと名前付けのルールの両方が統一されていない場合でも、「インデントの修正」と「名前付けの修正」というふうにルールを1つ適用するごとにコミットしましょう。これも、問題の原因となった変更の特定を容易にするためには大事なことです[9]。
完全を求めない
コーディングスタイルの統一が重要だと書いておきながら矛盾するようですが、完全であることを求めないのも重要です。
既存のコードを修正するとき、完全にコーディングスタイルを統一しようとすると、とても大変です。インデントや括弧の付けかたの統一は問題なく適用できる場合が多いですが、名前の付けかたなどのようにコードの字面を変更するルールを完全に適用しようとすると、ツールのサポートがあっても非常に手間がかかります。ですので、そのような変更については重要度を決めて、重要なものから順に適用していくのがよいでしょう。
大規模なリファクタリングは控える
最後に、コーディングスタイルの修正はコーディングスタイルの修正のみにとどめて、それ以外の大規模なリファクタリングは控えるのも大切です。
コーディングスタイルが統一されていない状態から統一された状態になってくると、コーディングスタイル以外の粗に気づくかもしれません。しかし、設計の変更を伴うようなリファクタリングは修正範囲が広くなることが多く、ときには複数モジュールに渡る大規模な変更となる場合すらあります。また、変更時の見落としが原因で正常に動作しなくなってしまう可能性もあります。そうなってくるとリファクタリングだけに時間を取られて、本来したかった変更にいつまでも着手できないということにもなりかねません。リファクタリングに着手する際は、よく検討してから行うようにしましょう。
スタイルが統一されているコードは読みやすいし、書くときも迷わなくて済むから、気持ち良く開発できるんだ。開発や修正といった本来の目的に集中できるようになるから、ミスも減るし、いいことずくめだね
基準がわかりやすいから、僕でも手始めに実践しやすそうですね。さっそく、自分のコードでやってみようと思います!