--- title: Mozilla Hacker's Getting Started Guide slug: Mozilla_Hacker's_Getting_Started_Guide tags: - Developing Mozilla ---

もし、このドキュメントについて、誤りを見つけたとか、更新に貢献したいとか、セクションを追加したいとか、そういうときには Kai Engert までコンタクトを。

Mozilla とは?

Mozillaは オープンソースプロジェクトであり、クロスプラットフォームのインターネットクライアントソフトウェアを開発する組織です。ソースコードごとに定められた (MPL、NPL、GPL、LGPLが混在している) ライセンス に従う必要があるとはいえ、Mozilla がオープンソースであるために、ソースコードは誰にでも利用可能です。

Mozilla.org は、このプロジェクトの開発者を助けるための基盤を提供する組織の名前です。mozilla.org は Mozilla プロジェクトのための中心となる Web サイトのアドレスでもあります。

動機

Mozilla は最大規模のオープンソースプロジェクトの一つです。Mozilla は 何百万行のコードで作られています。そのため、この巨大プロジェクトに参加するのは簡単ではありません。このドキュメントの意図は、Mozilla をハックするために何に気を付けなくてはならないかについての概要を示すことにあります。このドキュメントで Mozilla プロジェクトで使われている多くの異なったテクノロジーの間の橋渡しをしようとしています。

私が Mozilla の内部に目を向け始めたとき、私はこのようなドキュメントがあればと願いました (^^)

対象者

このドキュメントは第一に Mozilla のどの部分かで作業できることを望む開発者のために書かれました。参加希望者は、オブジェクト指向プログラミングについて十分な理解が求められます。そして、特に、このプロジェクトで主にプログラム言語で用いられている C言語と C++ についての経験が求められます。

しかし、もしあなたが、例えば JavaScript と XUL UI (XUL ユーザインタフェース) だけのように、コードの一部でだけ作業することを望んでいるとしても、この文書は参考になるでしょう。

このドキュメントの範囲

このドキュメントは以下の疑問に答えようとしています。

Netscape 社はこのプロジェクトに何をすべきなのか?

Mozilla が創造された時、それは Netscape のものでした。ある時期に、会社としての Netscape は、会社が所有していて、他者の著作権に抵触しないソースコードの部分を公開することにしました。

Mozilla は完成された製品ではありませんでした。なので、Mozilla プロジェクトはたくさんのコードを新たに書かなくてはなりませんでした。それに加えて、多くの部分を書き直しました。他のコンポーネントのいくつかは維持され、拡張されました。これが、このドキュメントや、Mozilla プロジェクトについて議論するときに Netscape という単語を目にする、耳にする機会があるの理由の一つです。

C++ と JavaScript

Mozilla では幅広く使われているため、Mozilla のソースコードで JavaScript と C++ が互いにどう関係しているかを説明するのは意味のあることです。C++ はコンパイル型の言語で、JacaScript はインタプリタ型の言語です。JavaScript は Web サイトをインプリメントするのに使われるテクノロジーとして最も共通のものとして知られています。しかし、Mozilla 開発者は、Mozilla ソースコード自身を両方の言語の混合で成り立たせることを選びました。

Mozilla ブラウザを起動したとき、C言語 と C++ のコンポーネントがまず開始します。しかし、起動処理の速い時点で XPConnect と呼ばれるテクノロジーが実行時にインタプリタ解釈された JavaScript を使用可能に初期化します。実際、Mozilla ブラウザは、コンパイルされた C++ と、コンパイルされない JavaScriptの両方で構成されています。

JavaScript は、OS によって直接に実行できるようにコンパイルすることが出来ないことに注意してください。そのために、われわれは C言語と C++ をプログラムのバックエンドで使用し、JavaScript は Mozilla の内部で動作します。

そして、JavaScript を使用した Web ページをネットサーフするとき、その JavaScript はサンドボックス (隔離された安全地帯) の範囲内で動作し、Mozilla の内部オブジェクトにアクセスすることは出来ないことも覚えておいてください。DOM (ドキュメント・オブジェクト・モデル Document Object Model) によって露出したオブジェクトだけが アクセス可能です。

このドキュメントで JavaScript に言及がある時はいつでも、Mozilla 内部の機能性に寄与するテクノロジーを意味します。JavaScript は、ユーザインタフェースイベント (ユーザの操作によるブラウザの動作) の処理を行うソースコードの部分に最もよく使われています。以下のドキュメントのほとんどは、アプリケーションの C++ 部分の概観について説明します。

NSPR - Netscape ポータブル・ランタイム

Mozilla プロジェクトでのソフトウェア開発のために第一に必要なのは、例えば、特定の OS に制限されてはいけないなどのように、クロスプラットフォームであることです。

C++ がポータブルな言語を意図している一方、そのポータブル性の概観は、一般的なプログラミングロジックとデータ構造に限られます。もし、特定の OS のためのソフトウェアを書きたいならば、その OS の特有の機能を使う必要があります。しばしば、すべての OS 上で同じ機能を使いたくなりますが、それをするためにはプラットフォーム毎に特有のコードを書かなくてはなりません。

NSPR の意図するところは、OS と Mozilla ソースコードの間に、Mozilla ソースコードの他のエリアのコードをシンプルにしやすくするためのレイヤー (層) を提供することです。C言語のライブラリ関数を利用しようとするとき、まずはクロスプラットフォームなインプリメントのものが NSPR により提供されていないかチェックすることが必要です。

スレッド

Mozilla はマルチスレッドアプリケーションです。Mozilla のコードにトライするまえに、それが何を意味するかを知る必要があります。

NSPR はマルチスレッドプログラムのための OS 非依存の機能を提供しています。例えば、すべてのネットワークデータ転送はデータ転送をしている間にも、ユーザインタフェースが応答可能なままとするために、スレッドごとに行われます。

C++ コードのために必要なことの一つは、マルチスレッド対応 (スレッドセーフ) であることです。

オブジェクト指向プログラミング & モジュール化

Mozilla の C++ ソースコードは、OOP (オブジェクト指向プログラミング) のルールに従うことを意図しています。そのルールには、モジュール化コンポーネント設計も含まれており、そこでは、あなたのクラスの public なインターフェースを使用した場合のみ、内部データ (変数) に対するアクセスが許可される、あるいは可能になります。

たいていのシンプルな C++ プロジェクトにおいて、これはそれだけの意味です。クラスを適切に public/protected/private を使い分けるのには注意深くデザインするというだけの意味です。しかし、すべてのソースコードはどこでも利用可能な状態のままです。例えば、いつでも、クラスのコンポーネントを private から public へ変更することが出来ます。そうすると、それはプロジェクトの中の他の箇所から利用可能となります。これは、Mozilla には当てはまりません。Mozilla では、よりモジュール化することが望まれます。

Mozilla のソースコードは分離されたコンポーネントで組織されています。一つのコンポーネントの中に限れば、前段落に記した単純なプロジェクトのように、すべてが自由ですが、複数のコンポーネント間においては、同じレベルの柔軟性はありません。

コンポーネント同士が通信するとき、コンポーネント・オブジェクト・モデル (COM component object model) を使ったうまく定義されたインタフェースだけを使って行います。

インタフェース

インタフェースのコンセプトは、CORBA テクノロジーで使われているもののようなものです。例えば、CORBA も Mozilla もインタフェースを記述するのに XPIDL (IDL とはインタフェース定義言語を意味します Interface Definition Language) という同様の言語を用いています。

CORBA 環境を使用する事は、制限が多く難しいものです。なぜならば、Mozilla では頻繁には用いないようなプロセス間、ネットワーク間通信を伴うためです。正式に流通している CORBA 環境ではインタフェースのコンポーネントを変更するのは同時にしばしば実行しているシステムすべてを入れ替えることが出来ないために困難です。何か変更を加えたいとき、新しいバージョンのインタフェースを定義しなくてはなりません。しかし、前のバージョンのサポートも続けることが求められます。

Mozilla は本稿執筆時点において正式に流通しているアプリケーションではないので、現在のところ多くのインタフェースは開発プロセスの必要に応じて変更することが可能です。しかし、Mozilla ブラウザはいくつかの環境に埋め込まれて実行されるので、それらの環境は確定したインタフェースを信頼できなくてはなりません。したがって、インタフェースは凍結されることができます。この状況は、しばしば、インターフェースが定義されている状態で表されます。時間の経過とともに Mozilla が安定化する、または、魔法のパージョン番号 1.0 に近づくにつれ、凍結されていないインタフェースに対する凍結されているものの割合は増えるでしょう。

Mozilla ビルドする一つのステップは、インタフェース定義ファイルを自動的に C言語 /C++ ヘッダファイルに翻訳することです。これは Mozilla の持つ IDL コンパイラである xipdl の仕事です。

メソッドとメンバデータに加えて、インタフェースは追加の属性を持っています。インタフェースは UUID というインタフェースごとに唯一に識別可能な番号を持っています。インタフェースはスクリプト記述可能な属性を持つことが出来ます。これは、インタフェースに JavaScript のコードからもアクセス可能であるということです。スクリプト記述可能なインタフェースは JavaScript ランタイムの範囲内で有効なパラメータのためのデータタイプを使うためだけに限定されています。

XPCOM / nsISupports / nsCOMPtr

XPCOM は Mozilla 自身の COM (コンポーネント・オブジェクト・モデル component object model) のインプリメンテーションです。名前の頭につく XP は、それがクロスプラットフォームであることを意味します (この XP がつくということを、特定の OS 製品のためのように見えるので、XP のつくこの名前で混乱しないこと)。実際のところ、クロスプラットフォームであるので、XPCOM は、他の形の COM より、用途は広いです。

最終的には、mozilla.org にある紹介ドキュメント XPCOM を読むべきでしょう。ハックを始めるためには、XPCOM は COM のコンセプトを働かすエンジンだということができます。これは、オブジェクト仲介人の役割を演じることも含まれています。

一般に、インタフェースはジョブを行うために使われることのできるオブジェクトを記述します。もし、しなければならないジョブがあるなら、インタフェースで提供される インプリメントをリクエストする必要があります。そのインプリメントは他のコンポーネントの範囲内に属することが出来ます。あなたの望む特定のインプリメントに決定するために、テキストベースの識別子である規約 ID を利用しています。規約 ID は、細部まで定義されたインターフェースを使用することで利用しやすくなる、インプリメントの動作上の契約です。XPCOM ランタイムシステムは、どのクラスが規約 ID でインプリメントされているか、どのコンポーネントがそれを提供しているかを知っています。

たとえ、あなたのコードが単独のコンポーネント内だけのものであり、COM の使用が必要条件ではないとしても、COM はいずれにせよとてもしばしば使われます。一つの理由は柔軟さにあります。他の理由として、JavaScript を利用してインプリメントされた Mozilla のロジックのある部分と機能を共有することを許すためです。Mozilla は実行時にインタプリタ言語の JavaScript と コンパイル言語の C++ の間でコミュニケーション可能とする XPConnect と呼ばれる技術を提供しています。

実行時に COM オブジェクトのインスタンスが必要なときにはいつでも、クラスオブジェクトは作成され、インタフェースのポインタが与えられます。いくつかの理由でこれらのインスタンスが参照をカウントされることが決められました。一つの理由は効率です。そのために、オブジェクトの不要なコピーは省かれるべきです。他の理由は、データオブジェクトはスレッド間で渡されるべきですが、すべてがメモリ上の同じデータオブジェクトに対するポインタを維持するためです。だからです。最後に、同じデータオブジェクトは多数のコンポーネントに参照されたり、多数のリストに貯えられたりすべきだからです。

参照の生存期間は異なるため、どのくらいしばしば現在何かに参照されているという状態であるか覚えておくためには、それぞれのオブジェクトが参照のカウントを保持するのが最も簡単な方法です。オブジェクトから参照されたとき (XPCOM エンジンによる直接参照もしくは、関数呼び出しによって)、リファレンスのカウントのケアを確実にする必要があります。オブジェクトへの参照を維持するかどうかや、参照を終えられるかどうかを教え、参照を削除しなくてはなりません。そのように、オブジェクトはそれがまだ必要とされているかどうかを自分自身で判断することが出来ます。オブジェクトがもう不要なら、自分自身でメモリから削除します。

この一般的な機能を満たすために、インタフェースをインプリメントする Mozilla のすべてのクラスは参照カウント機能と自動破棄機能を備えた nsISupports という共通基礎クラスを共有しています。このような共通基礎クラスは、どんな COM のインプリメントにも存在します。

あなたが割り当てたものは、あなたが掃除 (削除) しなければならない、という一般的なルールがあります。例えば、参照を追加したいとき、もう不要となったときすぐさま参照を解放することを強く促します。そうしなければメモリリークといった問題を引き起こすことになるでしょう。

C++ では、nsISupports 基本クラスのメソッドの明白なメソッド呼び出しによって行われます。しかし、それらのメソッド呼び出しは、忘れやすいだけでなく、コードの可読性も低下させます。特に多くの関数やメソッドは複数の出口を持っているからです (例:return 文など)。

関数やメソッドの出口毎にすべてのオブジェクトへの参照を解放することを確実にしなければなりません。これを楽にするために、解放の呼び出しを繰り返さなくて良いために、一般的な補助クラスは nsCOMPtr という名前の COM オブジェクトへのポインタを扱うために提供されています。これは XPCOM の特徴の一つで、COM コーディングをより楽にします。これは、特定のオペレータのオーバーライドを通してポインタをシミュレートします。いくつかの例外的ケースがありうるにも関わらず、このような一般的なルールはほとんどすべてのコードで守られています。:ポインタ変数 "interface*" をインタフェースをインプリメントしたオブジェクトとして使うつもりがあるときにはいつでもローカル "nsCOMPtr<interface>" 変数をかわりに使う。このポインタが "スコープ範囲外" となったらすぐに、可能ならデストラクタが自動的に参照カウントを減らします。

インタプリタ言語の JavaScript では、これはコード上で簡単に行えます。それは、ガベージコレクションのためです。可能なときに参照を自動的に減少させる魔法があるのです。しかし、この魔法は循環参照しないことを必要とします。例えば、もし、二つのオブジェクトがあり、お互いへの参照を含んでいても、他のオブジェクトがそれらを参照していないとき、それらのオブジェクトは検出されません。それらのオブジェクトはプログラム実行の残りの間メモリに存在しつづけます。

例外 / nsresult

コード実行が実行時に失敗することもあります。失敗を扱うプログラミングメカニズムが例外 (エクセプション) を用いることです。Mozilla では JavaScript 部分で例外を使っており、C++ 部分では使っていません。以前やったことがスタックの中にあるため、例外はいつでもポータブルというわけではないというのが、そのいくつかの理由のうちの一つです。Mozilla の C++ のコードは戻り値で例外を真似ています。つまり、JavaScript の中では、tyr-catch のブロックを使うことが出来、C++ の中では、インタフェースのメソッドを使う場合はいつでも戻り値を見なくてはなりません。その戻り値は nsresult 型です。このため、IDL ファイルで定義されている論理的な戻り値型は、C++ コードの中の追加のメソッドのパラメータにマッピングされています。

nsresult 型は、失敗理由の付加情報も運ぶことを意図しています。成功か失敗かという単純なレポートの代わりに、整数型を使い、多くの異なったエラーコードを定義することを許しています。

いくつかの戻り値があります。例えば、NS_OK は、何事もうまくいっていて、そのままプログラムを続けることが出来るという場合に使われ、NS_ERROR_FAILURE は、何か異常が発生しているけれども、今のところそれ以上の詳細は必要ないといった場合に使われます。

それに加え、互いのコンポーネントはアプリケーションの他のエリアで使用していない失敗コードを上書きしないエラーコードの定義をするために、独自の範囲の整数をリクエストすることが出来ます。詳細な情報は mozilla/xpcom/base/nsError.h を参照のこと。

C++ における文字列

多くのアプリケーションやクラスライブラリでは、単なる簡単な string (文字列) クラスを使用することを決めている中で、Mozilla 開発者は、文字列により強力な機能を求めました。実行時の動的な振る舞いを異なったシチュエーションのために最適化することを許すために、いくつかの文字列クラス階層をインプリメントしました。時には文字列のサイズを変更するだけでしょうし、時には、自動的にサイズが大きくなる文字列が必要でしょう。そのため、たとえば、ただの平坦な文字列ではなく、断片化された文字列型も使用可能です。

さらなる要求としては、Mozilla は完全な多言語対応をしなくてはならないということです。ユーザにみせる情報を扱う文字列は、そのためにマルチバイトな Unicode 文字列を使っています。

文字列型はテンプレートに基づき、可変型のような文字列型を伴い、通常文字列と Unicode 文字列を使うのを同じロジックで扱えるようにしています。

多くの文字列クラスを持つというアプローチは多くの柔軟性を意味する一方、欠点としてMozilla の文字列クラスを学ぶのが易しい作業ではなくなる、ということがあります

GUI (グラフィカル・ユーザ・インタフェース) / XUL

たいていの OS では、GUI を開発するための独自の方法を定義していて、それぞれたいてい異なっています。

Mozilla のようなクロスプラットフォームアプリケーションにとっては、アプリケーションのロジックから OS 依存のロジックを隠すテクノロジーをもつということは、重大なことです。

今までに、多くの C 言語と C++ のライブラリはクロスプラットフォームに書かれてきました。私の知るところによると、それらは Mozilla には使われていません。またしても、独自のグラフィックシステムを作りました。

GUI のレイアウトを定義するとき、二つの可能性のいずれかを共にするかを選ぶことが出来ます。まず、表示させたいそれぞれの UI (ユーザ・インタフェース: user interface) 要素の絶対位置を定義する方法があります。この方法は、実際に多くの GUI ライブラリで選ばれています。しかし、これには欠点があります。エレメントが加わってレイアウトが変わったとき、十分な柔軟性がないことです。それは、すべての要素を新しい位置に計算し直す必要があるからです。それは、どのエレメントが重なっているかなどのフィードバックをいちはやく得るために、よりグラフィカルにしなくてはなりません。しかし、いまだ、UI は異なるメトリクスをもつフォントが使われなくてはならないとき、意図したように見えないかもしれません。このことは、UI が使い物にならないと判断させます。

Mozilla の開発者は、より柔軟性のあるものを求めました。Mozilla はクロスプラットフォームなので、フォントにより注意を払う柔軟性を備えることが必要です。

Mozilla 開発者は、論理的なもので UI のコンテンツがデザインされたところというアプローチを使うことを選びました。現在は UI エディタを使っていません。UI がどうみえるべきかを指示するファイルを書きました。実行時にレイアウトエンジンはどのフォントが利用可能か決定し、UI 詳細に定義されたすべての要求を考慮し、実際の UI を動的に生成します。これは、Web ブラウザが Web ページをどのように表示するかと似ています。

Web は大部分がテキストベースのシステムから多くのプログラムのようなユーザインタフェースをもつとてもグラフィカルで裕福な環境へ移り変わってきました。そのため、Web ブラウザにとって、独自のユーザインタフェースを定義するために Web 言語を使うことはもっとも自然なことです。XUL(extensible user-interface language 拡張ユーザインタフェース言語) と呼ばれる UI 内容の記述のための XML ベースの文法を選びました (XUL についての良いリファレンスとして XULPlanet が利用できます)。

XUL ファイルは、どの要素が UI を構成しているか、どこに要素が現れているかを記述します。XUL 言語は制御に反応してどういう働きがあるかをプログラマが定義することを許す属性を定義します。動的なアプリケーションのふるまいを定義するために、ある場合には特定のユーザインタフェースイベントが発生したときに呼ばれる JavaScript 関数を定義することが出来ます。それらの JavaScript 関数の中では、直接アプリケーションのふるまいを記述するか C++ で定義されたロジックを含む COM オブジェクトの利用可能な他のアプリケーションロジックを呼び出すかすることが出来ます。

UI の論理的表現に加え、人々は UI のかわいらしい見た目を望んだりもします。UI の詳細な特徴を定義するために、例えば特定の UI 要素を表示するのに使われる画像を定義する CSS を使うこともあります。これは、"テーマ"や"スキン"を参照するアプリケーションのための追加の"ルックス"の定義を柔軟にします。Mozilla には、現在 Mozilla 開発者によって活発にメンテナンスされている「クラシック」と「モダン」という2つの「テーマ」が定義されています。Mozilla のための追加のテーマが存在するということは、それだけのバージョンの Mozilla が存在するということです。UI に毎日起こるすべての変化に同期をとりつづけることは、「テーマ」のデザイナにとって大きな仕事です。

ビルドシステムとツリー

現在、Mozilla は主に実行時に必要に応じて動的にロードされた多くの共有ライブラリの集まりのように使われています。COM システムによって、ソースコードの複数の場所を変更した場合でも、再コンパイルする必要があるのはアプリケーションの一部だけで良い場合が多い、という開発環境が可能となっています。これは、とても便利な開発環境です。しかし、これは実行の速度低下を意味します。一方、内部コンポーネントの大部分を静的にリンクした Mozilla バイナリを作ることも可能です。アプリケーションのサイズのため、このリンクステップには多くの時間がかかります。ディストリビューション向けのパッケージを準備するときに、この意味が良くわかるでしょう。

それぞれのコンポーネントはその独自のディレクトリを Mozilla のルートディレクトリの中に持ちます。それはまた、呼び出したモジュールの範囲内でサブのコンポーネントを持つということです。Mozilla をどのようにビルドするか教えるツリーの全体にわたるメイクファイル (Make File) があります。

プラットフォーム依存のコードのほとんどは、ツリーの少しの場所にだけ含まれます。OS と Mozilla の他のコードの間にあるレイヤーはこのコードによってインプリメントされたインタフェースです。ビルドが発生するものの中のプラットフォームを準備するプラットフォーム依存のコードだけがビルドされます。

OS からのメッセージはプラットフォーム依存のコードによって集められています。そして、同じ方法でプラットフォームに独立したコードへ送られます。

Mozilla プロジェクトに関する部品はプラットフォーム依存のレンダリング技術を使って書かれた OS 独立の部品です。

ツリーの範囲内で、public と名づけられたディレクトリはたいていインタフェースのヘッダを含み、src と名づけられたディレクトリはたいていインタフェースのインプリメントやインタフェースのヘッダでないものを含みます。

このプログラムのビルドはこのように大きなプロジェクトに慣れない人をひるませるかもしれません。ビルドには、パワフルなワークステーションで 20 分、古い PC なら 2 時間はかかるでしょう。まず、ソースを入手しなくてはなりません。そして、ビルド資料 に含まれるルールを使ってそれをビルドします。ビルドしている間、ヘッダファイルのディレクトリを特に指定する必要がないように、すべてのヘッダファイルは dist/include ディレクトリに移動するでしょう。(集合としては chrome と呼ばれる) XUL 、画像、JavaScript ファイルもすべて chrome ディレクトリ (Mozilla のバイナリを含むディレクトリの子ディレクトリ) にコピーされるでしょう。これらは jar.mn と呼ばれるファイルの中で定義される chrome:// という URL にマッピングされます。Mozilla のリリースバージョンでは、chrome ディレクトリは、.jar ファイルだけが含まれるでしょう。

Mozilla をビルドするというのは、プロセスの一部に過ぎません。もし、開発したければ、CVS と呼ばれるプログラムを使ったツリーのメンテナンスをしなくてはなりません。ビルドに失敗した時には、あなたのツリーの中のファイルとレポジトリの中のファイルとの結合が失敗した際に生じた競合を解消しなくてはなりません。また、ツリーをハックするとき、修正したツリーの部分をビルドしなくてはなりません。時折、depending と呼ばれるプロセスを使ってツリー全体を再ビルドしなくてはならないでしょう。ソースファイル間の依存を決定しなくてはならないからです。また、時折、ツリーを再ビルドするでしょう。たいていは、これをしている間、ツリーへの自身の行った変更をメンテナンスしていて、他人の変更と同期をとろうとしているでしょう。

アプリケーションの開始

Mozilla の COM システムは、タイプライブラリと、実行可能なコンポーネントの内部レジストリと、インタフェースに頼っています。アプリケーションを開始している間、レジストリが今も最新のものかのチェックが行われます。もし、変更されたライブラリを検知したとき、レジストリは更新されます。それぞれのコンポーネントはそのレジストレーションフェーズの間に初期化を行うことが許されます。もし、変更されたライブラリを検知したとき、それらはロードされ、初期化ロジックが実行されます。変更ライブラリに加え、それらのアプリケーションコンポーネントだけが必要とされたようにロードされます。

内部通知システム

このセクションでは Mozilla 内部で利用可能な機構について記述します。めったにこれは必要になりません。しかし、特定のイベントに対処する必要のある時には、このシステムを知ることが助けとなるでしょう。OOP (オブジェクト指向プログラミング) の考え方は、各々が各々自身の役割を果たすことというものです。しかし、それはしばしば他のコンポーネントがコンポーネント B で起きたあるアクションの引き金を引くとき、コンポーネント A がそれに対応しなくてはなりません。しかし、コードは部分で分離されているほうが好ましいため、B はそれを起こすのに何が必要かの詳細を知るべきではないのです。ここで必要なのは、次のような事です。もし、他のコンポーネントが B のアクションに反応する必要があるのであれば、B はそのアクションに対する引き金が引かれたら通知を送信するように拡張されるべきです。それに加え、B は誰が通知されるのを待っているか覚えているリストを実行時に動的に保持します。実行時に、A が初期化されたとき、A は B に通知リストの対象に加えてほしいと告知します。

これをより一般化するため、中央観察サービス (central observer service) を使うことを決めました。コンポーネント B がアクションの引き金を引いたとき、観察サービスにすぐに通知し、記述的にイベントの名前を明確にします。A のようなコンポーネントは観察サービスに観察したいイベントの名前をもらえるよう申請します。その原則を使用し、観察サービスだけがイベントを見るコンポーネントのリストを扱わなくてはなりません。観察サービスはイベントの通知を受けると、その通知を、そのイベントへのすべてのコンポーネントリストに引き渡します。詳細は nsIObserver を参照のこと。

ローカライゼーション

Mozilla は人間の言語からコードを分離するデザインがされています。ユーザに見せる必要があるためにテキスト文字列が必要なときはいつでも JavaScript や C++ ファイルの中に直接文字列を保存することは許されません。かわりに、C++ や JavaScript のコードで使われるテキストのために記述的識別子を定義します。その識別子をキーとして使い、実際のテキストを取り出すための文字列集合インタフェースのメンバーを呼び出します。テキスト自身はテキストだけ格納された分離されたファイルに格納されます。Mozilla はモジュールの集合であるため、多くのファイルがあり、分離されたモジュールにそれぞれ所属します。その分離にともなって、翻訳者がテキストファイルの言語別バージョンを作るのが簡単なのです。

UI を定義するとき、2 種類の文字列があります。ある文字列は、入力フィールドのテキストやヘルプの中にだけ出てくるテキストのようにアプリケーションがコンパイルされ、パッケージ化されたその時に知られるもので、またある文字列は、実行時に動的に組み立てられます。

実行時にアクセスされる必要のないテキストを定義するときはいつでも、DTD ファイルの中に定義してください。XUL ファイルの中でそのテキストを直接参照することが出来ます。

実行時にテキストを伴った動作が必要なとき、例えばテキストが実行時に入力される必要のあるユーザ名のための代替文字列を含むとき、properties ファイルにテキストを定義してください。

コーディングとレビューのルール

Mozilla ダウンロード、コードの変更、独自の変更を含むバージョンでの作業などがフリーで行えます。

しかし、Mozilla で使われているオープンソースの背後にある一つの考え方に次のようなものがあります。ソースをフリーで入手できるかわりに、ソースに変更を加えたら、コミュニティに何がしかの還元を考えるべきです。そうすることにより、貢献者となるのです。

しかし、Mozilla コミュニティは公開の中央 Mozilla コードに組み込まれるという変更をただ受け入れることは出来ないと決定しました。自分のコードをその中の一部にしたければ、次のようなルールに従わなければなりません。それは法律のようなものではありません。しかし、基本的に、あなたは、あなたの変更が良いものであると他の人々が認めるよう説得しなければなりません。

この考え方は、Mozilla のコードをより正しい状態にするために作られた多くの効果があります。Mozilla のコードはどのソフトウェアの一部と同様に、完璧からはほど遠く、人々は保守性を低下させるものは何でも取り除こうとし、正しいと思われるコードだけを受け入れます。

これを達成するために、Mozilla コミュニティはすべてのコードは他のすでによく知られた Mozilla ハッカーたちに受け入れられる必要があると決めました。ここに2つの段階のレビューがあります。まず、コード変更希望者は、変更したいコードの部分の所有者から最初のレビュー (r=) を受ける必要があります。要求された修正を行うことが期待されます。そうでなければここで終わりです。もし、最初のレビューが終われば、たいていの場合スーパーレビュー (sr=) と呼ばれるレビューを受ける必要があります。限られたメンバーである " Mozilla 導師 " という、どのコードがよく、どこを変更するべきかについての判断が優れていると認められている人々がいます。一度、両方のレビューを受ければ、ほとんどの場合、コードはチェックインされます。ある特定の事例では、他のレベルのレビューがあり、それは別の場所に記述されます。

多くの人々が Mozilla を変えています。みんなが Mozilla をよりよくしようとする一方、どの変更も思いがけない面への影響というリスクがあります。これは、変更の結果、アプリケーションの機能が動かなくなるといったものから、Mozilla ソースコードがコンパイルできなくなるといった単純な問題にまで及びます。後者は、"ツリーが壊れている、燃え上がっている、赤い"と表現され、ここでツリーとは CVS リポジトリの事です。

ある OS とコンパイラの組み合わせの上でだけ開発をしていて、移植性について (Mozilla.org のドキュメント参照のこと) 注意を払っていないとき、ツリーは簡単に壊れてしまいます。ツリーを壊さないためにベストを尽くす必要があり、レビューを受けることで、願わくば、変更点をチェックインするより早く潜在的な問題を発見したいのです。

ツリーが壊れてしまったとき、Mozilla コミュニティは、ツリーが壊れている間ほかのチェックインを許さないというルールを決定します。これは、この問題を修正する人を助けます。ほかの変更を許すことは、新しいチェックインがあたらしい問題を含んでいるかもしれないために、問題のほんとうの原因を見つけることを難しくします。

マイルストーン

数週間ごとに、Mozilla.org はソースレポジトリの新しいスナップショットを出します。この考え方は、世界の人々が現在のスナップショットを試してみて、彼らの見つけた問題 (バグ) を報告すべきだというものです。しかし、Mozilla.org はそれらのマイルストーンはテスト目的だけのために出されたということを強調したいのです。

より安定したマイルストーンを準備するために、ソースコードレポジトリを変更するためのルールは、新しいマイルストーンを準備する前にはより厳格なものになります。Mozilla.org は、スケジュールを引き、マイルストーン目標日の前の2日間、Mozilla.org の"ドライバ"と呼ばれる人たちに認可されたチェックインだけが許されます。ドライバは、Mozilla レポジトリに関して、最高の権限をもっている人の集団です。ドライバはまた、マイルストーンが準備できているのか、よりマイルストーンを安定させるためにマイルストーンを出すためより多くの修正を許すために日程を遅らせるかどうかも決定します。

Bugzilla

Bugzilla は Mozilla.org の Web ベースのバグ追跡システムです。問題に遭遇したときはいつでも、ユーザは新しいバグ (時には問題に切符を切ることとして知られてもいます) を、よく詳細に何が起こったかとともに申し立てるよう依頼されます。バグが公表されるなり、番号を発給するなりします。この番号は問題について話されるときに使われます。開発者は"バグ"について署名し、コメントします。そして、修正方法を知っていればどのように問題の修正方法を提案するかを見せるために、パッチを添付するでしょう。レビューも、このシステムの内部で進みます。

バグという単語はしばしばソフトウェアのエラーという意味にみなされます。しかし、Bugzilla の内部では、バグは追跡されるべきものとなります。これはソフトウェアのエラーから、機能拡張のリクエストに及びます。例えば、このドキュメントの発展は {{ Bug(123230) }} で追跡されています。

もし、C++ の開発者でないなら、Bugzilla で貢献できます。これは、簡単なバグ報告ツールとして出発し、ほかのプロジェクト (例えば Redhat のような) まで多くのユーザに使われる機能的な複雑なシステムにすっかり変わりました。

Webtools / LXR / Bonsai

Webtools は情報を貯えるツールをベースとしたサーバで、その情報を表示されることやときに操作することまで許します。そのシステムには Mozilla のように Web ブラウザを使ってアクセスできます。

Mozilla 開発者は開発を容易にするためにいくつかのツールを作りました。すでにお話した Bugzilla もそうです。

LXR は Mozilla のソースコードのためのハイパーテキスト検索エンジンです。識別子やテキストを調べることが出来、Mozilla の中のどこでそれが使われているかを見られるでしょう。検索結果項目をクリックすることで、直接現在のソースコードが得られます。コードはページに表示され、識別子にはハイパーリンクがはられ、それはクリックすると、その識別子についての LXR 検索結果を得られます。LXR はソースコードを表示し、それを通してすぐにナビゲートするのに使うことが出来ます。これは、Linux プロジェクトの glimpse のエンジンに内部修正を加えたものをベースにしています。

Tinderbox はソースコードレポジトリの現在の状況を表示するツールです。Mozilla.org は、多くの異なった OS のために、繰り返し、絶え間なく中央レポジトリから新しいソースコードを手に入れ (チェックアウトし)、コンパイルを試みるマシンをホストしています。コンパイルが終わったとき、プログラムがまだ正しく動作するかをチェックするためのいくつかの自動テストが実行されます。コンパイルとテストの結果は中央の Tinderbox システムにレポートされます。Tinderbox ページにアクセスすると、ソースコードレポジトリが現在いい状態にあるかどうかこの数時間の間にどんな変化があったのかを見ることが出来ます。Tinderbox は縦軸が時間を示し、横軸が OS ごとの状態を示すグラフを表示します。それぞれのコンパイル・テストフェーズはビルドの要求された時間で定義されたバーで表されます。

バーは色付けられています。緑は Good を示します。黄色はコンパイル中であることを示します。オレンジはコンパイルとビルドが終わったけれども自動テストに失敗したことを示します。赤はソースコードのコンパイルが成功していないことを示します。もしツリーが赤になると、開発を停滞させます。

Tinderbox はとても有用なツールで、ソースコードレポジトリに変更を加える人は誰でも、例えば、自分の変更がなにか問題を起こしていないかのような"ツリーを見る" ことを期待できます。

より援助とするため、追加の情報が Tinderbox ページで利用できます。チェックインしたときに、その人の名前がページに現れます。行われた変更の一覧へのリンクがあります。もし、コンパイルかテストが失敗したとき、ボックスはコンパイル失敗理由を示すコンパイラからのアウトプットへのリンクも含みます。ページのいつかのテキストはパフォーマンス測定の結果も示します。

ほかの Web ツールとして、Bonsai があります。Bonsai はソースコードレポジトリのすべての変更を追跡します。誰かの行ったすべての変更の一覧を取り出すことが出来ます。Bonsai は変更一覧の問い合わせのための強力なインタフェースも提供します。

更なる情報を探す

一般的なプログラミング技術について述べられたものについてもっと知りたければ、Web でフリーのドキュメントを捜し求めることを勧めます。うまくいけば、そのドキュメントでの言及が導いてくれるでしょう。もし、本を読むことをより好むなら、一般的な説明を著者が試みている本であって、いくつかの特定の OS に集中していない本を選ぶことを勧めます。

Mozilla に関するたいていのドキュメントは www.mozilla.org の Web サイトに掲載されています。もし、探しているものがなければ、サーチエンジンを使うことを試してみてください。いくつかのポピュラーなサーチエンジンは、特定の Web サイトに限定して検索することのできる上級 (詳細) 検索オプションを提供しています。

原文書の情報