【翻訳】Clojureにコントリビュートするには

この記事はClojure開発コアメンバーのひとりであるAlex Millerさんが先日書かれた記事「[Contributing to Clojure](http://insideclojure.org/2015/05/01/contributing-clojure/)」を本人の許可を得て翻訳したものです。

翻訳の誤り等のご報告は @athos0220 までお願いします。

# Clojureにコントリビュートするには

[「法案はどうやって法律になるのか」](https://www.youtube.com/watch?v=Otbml6WIQPo)の精神にならって、Clojureの[JIRA](http://dev.clojure.org/jira/browse/CLJ)チケットがどうやって[Clojureコード](https://github.com/clojure/clojure)にコミットされるのかをお教えしたいと思います。

## チケットはどこからやってくるの？

Clojure(と関連するコントリビューションプロジェクト)のチケットは課題管理システムの[JIRA](http://dev.clojure.org/jira/browse/CLJ)で管理されています。このシステムは[Contegix](http://contegix.com/)社の厚意によって専用のマシンでホスティングされています。Contegix社のOSSプロジェクトへの支援には非常に感謝しています。現時点では、比較的古いバージョンのJIRAが動いていますが、ゆくゆくはアップデートされるでしょう。

誰でもJIRAでアカウントを作って、課題を新しく報告することができます(訳注：この文章では「チケット(ticket)」と「課題(issue)」がしばしば区別なく使われます)。[サインアップページ](http://dev.clojure.org/jira/secure/Signup!default.jspa) に行ってアカウントを作り、ログインして右上の"Create Issue"ボタンを押します。

    注意：アカウントを作ると、チケットの作成とチケットへのコメントや投票ができるようになります。ただし、チケット作成後にそれらのフィールドを編集することはできません。このデフォルト権限でおおむね問題にはなりませんが、コントリビュータになることで自動的に追加の権限も与えられます(後述)。自分自身で作ったチケットの編集権限が欲しい場合は、Clojureのメーリングリストで聞いて下さい。

課題には3種類あります。不具合(defect: 既存のコード中のバグ)、機能向上(enhancement: 既存のコードに対する新しいフィーチャーや機能)、そしてタスク(ほとんど使われることはありません)の3つです。

新しいチケットを作るには、たくさんのフィールドを埋める必要があります。

- **サマリー**(Summary) - 問題の簡潔な説明
- **優先度**(Priority) - デフォルトでは「メジャー」に設定されますが、通常は開発チームが実際の優先度を設定しています(深刻度ではありません)。優先度はチケットのライフサイクルの間に変化することもありますが、あまり気にする必要はありません。
- **影響するバージョン**(Affects Versions) - 問題がどのバージョンで発見されたかを特定することは重要です。問題の起こる可能性があるすべてのバージョンを確認する必要はありません。どのバージョンで問題が見つかったのかさえ分かれば十分です。新機能を提案するチケットを作る場合には、単に最新の安定バージョンを書いて下さい。
- **環境**(Environment) - 使っているJavaのバージョンやOS等の詳細な内容が重要な場合はここに書きます。
- **説明**(Description) - 実際の状況をここで説明します。これについては後でもうちょっと詳しく説明します。
- **添付ファイル, パッチ**(Attachment, Patch) - 通常、チケット作成時にはファイルを添付する必要はありません。
- **ラベル**(Labels) - ここは、私たち開発チームが標準的なラベルをつけるので、空欄のままでかまいません。もし、自分でラベルをつける場合には`reader`や`printing`などの主なコンポーネントを書いて下さい。「バグ」や「機能向上」「パッチ」などその他のフィールドから分かるものは書かないで下さい。

いいチケットを作るにはもちろん、説明をしっかり書くことが肝心です。これについては [チケットの作り方](http://dev.clojure.org/display/community/Creating+Tickets) により詳しく書かれています。不具合についてのチケットでは、一般的に次のような内容を含む説明が好まれます。

- **問題の記述**(Statement of the problem)
- **再現方法**(Example demonstration) - 正しくない挙動を提示し、明らかでなければ期待する挙動も示します。99%の場合、これはREPLでのデモで示すべきです。GitHubリポジトリやGist、その他へのリンクを載せるべきではありません。

すでに問題の解決に取り組んでいる場合は、問題の説明に以下を含むべきです。

- **原因**(Cause) - 特定した問題の原因
- **アプローチ**(Approach) - どのようにして特定した原因を修正すべきかということと、選択しなかった他のアプローチとその理由についての議論
- **パッチ**(Patch) - 「現在」のパッチの名前(たまに追いかけるのが難しくなるので(訳注：添付されたパッチが多くなると、最新のパッチがどれか分かりにくくなるため、ここでその名前を指示します))

新しく作られたチケットにはこれらのセクションはないこともよくあります。その場合には、これらのセクションはチケットに取り組む人が後で追加します。

ここで、チケットの説明がどういう感じになるかを例で見てみましょう(当然ですが、これは実際のバグではありません)。

> 奇数同士の足し算が正しく機能していない。

> user> (+ 2 2) user> (+ 1 3) ClassCastException

> 原因：奇数の足し算はコンパイラで実装されていない！FooExprの抜けている分岐を参照のこと。

> アプローチ：奇数同士の場合の分岐を抜け漏れなく、偶数の場合と同様に実装。足し算を全部取り除くことも考えたが、使う人もいると思う。

> パッチ：add-odd-3.patch

一般的に、これらすべてのセクションを出来る限り最小限に留めるように心掛けましょう。そうすることで、後々新しい人が来てチケットを見たときに、詳細を正確に把握し、実際の振る舞いや期待される挙動、そしてそれがどう修正されているのかを理解できるような有益なチケットになります。もし、そのチケットの背景をさらに詳しく説明する必要がある場合には、付加的な情報をコメントとして残してもいいでしょう。

## コントリビュータになるには

もし、チケットに対するパッチを提供したり、もっと突っ込んだ取り組みをしたいと思ったらClojureコントリビュータになる必要があるでしょう。Clojureにコントリビュートする人は、Clojureの作者であるRich Hickeyを自分のコードの共同著作権者として認める必要があります(訳注：法律用語に明るくないのでこのあたりきちんと理解できてません。[ここ](http://clojure.org/contributing) の説明を見ると、元の著作権は放棄せずにRich Hickeyにも権利を認める、ということのようです)。プロジェクト全体に渡る著作権者が一人いることで、プロジェクトを法的な異議申立てから守ることができます。また、今後個々のコントリビュータから追加で許可を得ることなくライセンスを変更することができるようになります。詳細についてもっと知りたければ、[コントリビュータページ](http://clojure.org/contributing) あるいは [コントリビューティングFAQ](http://dev.clojure.org/display/community/Contributing+FAQ)、もしくは [OCA FAQ](http://oss.oracle.com/oca-faq.pdf) (訳注：OCAはOracle Contributor Agreementの略。以降のCAも同様の略語で、各ライセンスにしたがったコントリビューションをするための合意書を指す)を参照して下さい(Clojure CAはSun CAをベースにしています。Sun CAは後のOracle CAです…ヒュー)。

コントリビュータになるには、Clojureコントリビュータ合意書(Clojure Contributor Agreement)のフォームに署名をする必要があります。数日以内にはコントリビュータページにコントリビュータとして追加され、[clojure-dev](https://groups.google.com/forum/#!forum/clojure-dev)メーリングリストに投稿できるようになるはずです。また、JIRAやConfluence(訳注：JIRA以前にClojureの課題管理システムとして使われていた)の権限も新たに追加されます。このプロセスにはたまに問題が生じるので、もし何か問題があればメーリングリストで確認をとって下さい。

コントリビュータ合意書なしでJIRAに送られたパッチは **レビューされません** 。私たちはそれを受理することはできませんし、パッチを一から書き直さなければいけないということも起こりうるためです。

パッチについて触れておくと、ClojureとコントリビューションプロジェクトはJIRAのチケットに添付されたパッチ経由でしか変更を受けつけていません。これらのプロジェクトはGitHubのイシューを使っていませんし、プルリクエストも受けつけていません。他のオープンソースプロジェクトでのコントリビューションに慣れている開発者の中には、これを煩わしいと感じる人がいることは十分承知しています。

プルリクエストモデルはコントリビューションのしやすさに最適化されています。しかしRichはむしろ、自身の好むワークフローがパッチをより効率よく捌けるように、プロセスの管理面や評価面に対して最適化がなされるべきだと過去に[主張しています](https://groups.google.com/forum/#!msg/clojure/jWMaop_eVaQ/3M4gddaXDZoJ)。

とはいえ、このような判断がなされてからもプルリクエストの機能は様々な面で改善されてきているため、将来的に状況が変わる可能性はあるでしょう。しかし、さしあたり今はパッチだけに限られています。以降にその基本を説明します。

## チケットワークフロー

チケットには、[ワークフローページ](http://dev.clojure.org/display/community/JIRA+workflow) に掲載されている次の図に示されるように、ワークフローを規定する多くの「状態」があります。

![Ticket workflow](http://dev.clojure.org/download/attachments/1572892/workflow.png)

コントリビュータとして関係があるのは主に、パッチが開発されるオレンジ色の四角の部分です。

チケットは一般的に以下のようなプロセス(色付きの四角形)をたどります。チケットは状態(角丸の四角形)の間を移動します。ほとんどのプロセスでは、個人あるいは複数人のグループによって判断(菱型の部分)がなされます。

- **優先度付け**(Triage) - チケットが新しく作られると、スクリーナー(訳注：後述するスクリーニング等をする開発チームの少数のメンバー)はチケットをレビューし、次の質問について考えます：「これは取り組むべき問題だろうか？」もし質問への答えがイエスなら、チケットの承認(Approval)フィールドは"優先度付済み(Triaged)"としてマークされ、チケットは優先度付済みの状態に移ります。質問への答えがノーなら、チケットは棄却(Declined)されるか、重複したチケットとして処理されます。もし質問への答えがどちらとも言えない場合には、チケットはオープンの状態のままになります。ここで多くの場合スクリーナーは、チケットの記述を単純化したり、チケットにラベルをつけたり、次の処理がしやすくなるようにチケットのクオリティ改善に努めます。
- **審査**(Vetting) - Richが定期的に(数ヶ月のオーダーで)優先度付済みのチケットに目を通し、スクリーナーの仕事をダブルチェックします(おおむね問題になることはありません)。これが済むと、チケットは審査済み(Vetted)の状態になります。
- **リリーススケジューリング**(Release scheduling) - 審査済みのチケットは次に、Richによって評価され、どのリリースに取り入れるかが決められます。だいたいは現在のリリースになりますが、次のリリースになることもあります。このプロセスはよくチケットの審査と一緒に実施されます。

チケットがこれらのプロセスを通過する中で、スクリーナーとRichはチケットが取り上げる問題が取り組むべきものだったかについて合意し、その修正がいつ取り入れられるべきかを決定します。ここを過ぎると、焦点はチケットのためのパッチを作ることに移っていきます。最初にチケットが作られたときにパッチが添付されていることもありますが、ほとんどの場合そのままの形で適用されることはありません。

[パッチの作り方](http://dev.clojure.org/display/community/Developing+Patches) についてまとめたページもありますが、ここでかいつまんで説明しましょう。パッチ作りに取り組みたいと思ったら、ClojureのGitHubリポジトリをクローンなりフォークなりして、自分で取り組むチケット用のブランチを新しく作ります。

    git clone git@github.com:clojure/clojure.git
    cd clojure
    git co -b clj-9999

それから、チケットの問題を解決する変更をします。その際、`mvn clean test`で全テストスイートを実行できます。また、`mvn install`でClojureの新しいバージョンをローカル環境のMavenリポジトリにインストールすることもできます。一度インストールをしておけば、スナップショットバージョンとしてローカル環境でビルドした他のライブラリ等から使うことができるようになります。詳細についてもっと知りたければ、[パッチの作り方](http://dev.clojure.org/display/community/Developing+Patches) のページを参照して下さい。

準備が整ったら、次のようにしてパッチを作ることができます。

    git format-patch master --stdout > clj-9999.patch

そうしたら、作業中のチケットにパッチを添付します。既存のパッチに手を加えるとき、私の場合はよく、新しいブランチを切ってから元のパッチを`git apply`し、そこから修正を始めるようにしています。

チケット開発のプロセスは以下のとおりです。

- **開発**(Development) - 上記のプロセスでコントリビュータがチケットにパッチを追加するところです。
- **スクリーニング**(Screening) - スクリーナーがパッチをレビューし、チケットの問題に対する解決策がいいものかどうかを判断します。もしそうであれば、チケットは「スクリーニング済み(Screened)」とマークされます。そうでなければ、どういう修正をするべきかについてのコメントとともに「保留(Incomplete)」としてマークされます。

ここまででRichがチケットとパッチをレビューできる状態になります。Richは定期的に(多くは金曜日に)、スクリーニングされたすべてのチケットをレビューします。パッチに問題なければ「OK」とマークされます。さらに修正が必要な場合には「保留(Incomplete)」とマークされ、開発に差し戻されます。「OK」がついたチケットは、Stuart Hallowayが最後にひと通り目を通してからパッチをClojureのコードベースに適用し、クローズされます。

## その他のリンク

Clojureのコントリビューションプロセスに関する実質的にすべての情報(この記事で記載しているすべてのリンクも含む)はコミュニティWikiの [コントリビューションページ](http://dev.clojure.org/display/community/JIRA+workflow) にカテゴリー分けされてリンクをたどれるようになっています。何か分からないことがあれば、まずはこれらの情報を出発点として使ってみて下さい。

## 初心者向けのチケット

先ほどのコントリビューションプロセスのページには、上で述べたライフサイクルのフェーズ毎にまとめたJIRAのレポートページやその他の役に立つレポートページへのリンクもあります。そのなかでも、[「初心者向け(newbie)」](http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&requestId=10617)というタグのついたチケットの一覧には興味のある方もいるでしょう。これらは、取り組むべきだと私が思うチケットのうち、まだパッチがなく、しかしそれなりにアプローチしやすそうなものの一覧です。パッチは比較的すぐに誰かから提供されるので、一般的にこういったチケットはいつの時点でも数はそんなに多くありません。

## 投票

チケットのプロセスに参加するもう1つの方法は既存の課題に対する投票です。コアチームはどの課題を優先的に進めるべきかを、投票の結果からうかがえる課題に対する関心や影響の大きさ等も考慮して決定します。JIRAシステムは「投票」と「ウォッチ(訳注：特定のチケットに対する更新を通知してもらえるように登録する機能)」の2つの機能を備えているので、私たちはこれらを両方ともチェックすることで関心の大きさを測っています。

チケットの検索結果に得票数のカラムを表示させたり、得票数でソートしたりすることもできます(私はデフォルトでそうやって表示されるように設定して使っています)。また、Andy Fingerhutが[加重投票制](http://jafingerhut.github.io/clj-ticket-status/CLJ-top-tickets-by-weighted-vote.html)での集計を定期的に行なうプロセスも作っています。各自一票ずつ割り当てられ、それを投票したすべての課題の件数で割った数が各課題への票としてカウントされます。つまり、たくさんの課題に投票すればするほど、投票したそれぞれの課題への自分の票は割合的に少なくなっていきます。

これら2つの投票アルゴリズムはどちらにもメリットがあり、実際私はこの両方のメトリクスをチェックしています。次のリリースに移行するときはどれを取り込むべきかを決めるのにこれらのメトリクスを見直す時期なので、今は投票をする絶好のタイミングですよ！

## お礼として

Clojureのリリースには毎回数百の課題に取り組んで下さるたくさんのコントリビュータがいます。コントリビュータの皆さんの活動すべてに感謝しています！！

もし何か分からないことがあれば、Clojureの [メーリングリスト](https://groups.google.com/forum/#!forum/clojure) に投稿して下さい。喜んでお答えします。