有名なオープンソースプロジェクトのコーディングスタイルを紹介していくシリーズ。単純にコーディング規約を紹介するのでは無く、プロジェクト特有の癖や文化も交えて紹介していく。第一回目はApple社とも深い関わりのあるWebKitプロジェクトを紹介する。
WebKit
有名なHTMLレンダリングエンジン。Webブラウザの中核を担う技術。C++で作られている。Appleが中心になって開発。AppleのSafariが採用。Google Chrome(Chromium)が活用していたことでも有名(現在はWebKitから分裂したBlinkを採用)。WebKitはレンダリングを担う「WebCore」の他、JavaScriptの実行エンジンである「JavaScriptCore」など複数のコンポーネントを内包している。
なおWebKitはもともとKDEプロジェクトのKHTMLがベースとなっている。WebKitプロジェクトのコーディングスタイルの多くはこのKHTMLのスタイルと類似している。よって「WebKitのコーディングスタイル = Apple社のコーディングスタイル」とはならない点に注意したい。
サンプルコード
WebKitのコーディングスタイルを意識して記述した架空のサンプルコード。プロジェクト特有の規約や癖をコメント内で解説する。
namespace ns {
// 名前空間内では字下げを行わない
template <typename T>
class ClassName { // 機能名はキャメルケース
public:
ClassName()
: m_data() // 改行後カンマと同列に記述
, m_length()
{
switch (0) { // 波括弧は制御文と同一の行に記述
case 0: break; // case文をswitchと同一の列に記述
}
return; // voidを返す際には空白を省略する
}
char value() // 関数定義時、開始括弧の前で改行
{
if (m_length == 0) // 波括弧省略
return '\0'; // then節は開業後に記述
return m_data[m_length - 1]; // 演算処理における適切な空白挿入
}
// document comment ドキュメントコメントはスラッシュ二つで表現
template<class T> int setValue(const T& value, unsigned length) // 仮引数は全て一行で記述
{
const char* data = copy(value);
m_data = data;
if (length != -1
&& length != 0) // 改行後オペレータを先頭に記述
m_length = length; // 複雑な条件式でも波括弧は省略することが多い
else {
m_privateMember = static_cast<int>(strlen(data));
return 1;
}
// 処理毎に適切な改行を用いてコードブロックを表現
return 0;
}
// 空行ではインデントを省略
private:
const char* m_data; // `m_`プレフィックスを利用
unsigned m_length; // `unsigned int`は使わない
int m_privateMember; // キャメルケース
};
} // namespace ns
コーディングスタイルや開発スタイルの特徴
比較的緩いスタイル。厳格さよりも書きやすさや書き手を重視する姿勢が感じられる。クラスのメンバ変数には接頭辞としてm_
を利用している点が特徴的。
またcase文をswitch文と同一の列に記述点も特徴的。ちなみにApple製のIDEであるXcodeではこのcase文のスタイルを強制していないが、Swift言語向けのソースエディタ及びコード整形機能では当スタイルがデフォルトになっている。
カテゴリ | スタイル |
---|---|
開発スタイル | |
インデント | ソフトタブ(4文字幅) |
空行 | インデント無し |
適切な改行 | わりと行う |
波括弧の省略 | あり |
波括弧の改行 | なし(関数定義時のみ改行 - K&Rスタイル) |
if文のインライン化 | なし(then/else節は改行後に記述) |
制御文の空白 | 丸括弧の前後に空白を挿入(`if () {}`) |
一文字変数 | ほとんど見かけない(例外: `i`)。明確な名前を用いる |
アクセサ | ゲッタの接頭辞のみ省略(`value(), setValue()`) |
ドキュメントコメント | `// `を利用 |
コメント整列 | しない(`;`の後空白一文字で統一) |
ヘッダファイル | ソースファイルと同一ディレクトリで管理 |
ヘッダファイル内定義 | あり(メンバ関数) |
設計 | |
演算子オーバロード | 使う |
純粋仮想関数 | 使う(override修飾子必須) |
プログラミング作法 | |
goto文 | あり(頻繁に利用) |
case文 | switch文と同一の列に記述 |
ヨーダ記法 | 無し |
演算処理の空白 | あり |
改行時の演算子 | 前置(改行の後に記述) |
変態技法 | 見かけない |
命名規則 | |
クラス名 | アッパーキャメルケース |
メンバ変数 | ローワーキャメルケース(`m_`メンバプレフィックス使用) |
メンバ関数 | ローワーキャメルケース |
引数 | ローワーキャメルケース |
変数 | ローワーキャメルケース |
略称 | 使わない(一時変数は基本的に代入元のメソッドと同名) |
C++スタイル | |
参照 | 型側に詰める(`int& v;`)※ KHTMLは変数側 |
ポインタ | 型側に詰める(`int* v;`)※ KHTMLは変数側 |
const左辺値参照 | constを型名に対して前置する(`const T&`) |
プライベートメンバ変数 | クラススコープの末尾で宣言 |
コンストラクタ | クラススコープの前方で宣言、ヘッダーファイル側で定義 |
メンバ関数 | 実装ファイル側で定義 |
テンプレート | 空白あり(改行省略時空白なし)、typename/class混在、改行ありなし混在 |
生ポインタ | adoptRef(T*)とT::deref()の独自機構で管理 |
スマートポインタ | 使う(unique_ptr)外部ライブラリで利用(weak_ptr/shared_ptr) |
前置/後置インクリメント | 使う |
列挙体 | enum/enum classの両者を利用 |
C++スタイルキャスト | dynamic_cast以外は良く使う(static_cast, reinterpret_cast) |
using namespace | ユーザ定義の空間をファイルスコープに取り込む(`using namespace WebCore;`) |
イテレータ | `for (; it != end ;)`形式で回す |
仮引数名 | 宣言時に省略する場合がある |
コーディング規約
Code Style Guidelines | WebKit(https://webkit.org/code-style-guidelines/)
ソースコード・リポジトリ
WebKit/webkit(git://git.webkit.org/WebKit.git
, ミラー: https://github.com/WebKit/webkit)