学生時代にOSS活動に参加することのすゝめ

# はじめに

開発と言ってもいろんな種類の開発が世の中にはあるものです。
そして、それらの開発はOSSに支えられていることは少なくありません。
今回はそのOSS自体に参加し、OSSの文化に触れながら、自分の視野を広げていくための足掛かりになるような記事を書こうと思いました。

# 目次

| index | タイトル                                     |
| ----- | -------------------------------------------- |
| 1     | [OSSに貢献するメリットがわからない](#1-ossに貢献するメリットがわからない)|
| 2     | [そもそもどんなものに貢献していいかわからない](#2-そもそもどんなものに貢献したらいいかわからない) |
| 3     | [貢献したいけど、怖くて貢献できていない](#3-貢献したいけど怖くて貢献できていない)|

#1. OSSに貢献するメリットがわからない

- GitHubが豊かになる
- ソフトウェアに対して、視野が広くなる
- ソフトウェアのメンテナンスを体験できる
- 自分の好きな機能を取り込ませることができる


## GitHubが豊かになります。

OSS活動を始める前の自分のstatusと始めたあとのstatusを比較したいと思います。

### OSS活動前

![スクリーンショット 2020-11-15 23.54.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/652bb44e-3360-17bf-7dfe-f833ea38b33b.png)


### OSS活動を初めて1年半くらい経った状態

![スクリーンショット 2020-11-15 23.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/111c2a5c-62c6-ac22-24e7-235ce9039f8d.png)

見違えるように情報が多くなりました。また、Pull Requestのグラフの割合が上昇しているのがわかります。GitHubを豊かにすることはモチベーション向上にも繋がりますし、他にもいろいろなメリットがあると思います。

## ソフトウェアに対して、視野が広くなる

貢献したことで視野が広くなったと思った、自分が体験した具体的な例を以下に示します。

自分は[vaffle.vim](https://github.com/cocopon/vaffle.vim)というVimのファイラプラグインを愛用していましたが、これにアイコンが表示できたら便利だよなぁと思い、以下のようなパッチを書いたことがあります。
これは、[vim-devicons](https://ryanoasis/vim-devicons)という別のプラグインが提供している、アイコンフォントを返すAPIを利用することで、ファイラにアイコンフォントをレンダリングできるようにしたパッチになります。（言語はVim scriptです）

```diff
function! vaffle#renderer#render_item(item) abort
-  return printf('%s %s',
-        \ a:item.selected ? '*' : ' ',
-        \ a:item.basename . (a:item.is_dir ? '/' : ''))
+  if exists('*WebDevIconsGetFileTypeSymbol')
+    return printf('%s %s %s',
+         \ WebDevIconsGetFileTypeSymbol(a:item.basename, a:item.is_dir),
+         \ a:item.selected ? '*' : ' ',
+         \ a:item.basename . (a:item.is_dir ? '/' : ''))
+  else
+    return printf('%s %s',
+        \ a:item.selected ? '*' : ' ',
+        \ a:item.basename . (a:item.is_dir ? '/' : ''))
endfunction
```

パッチ適用前（アイコンフォントがレンダリングされていない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/1bae829a-411f-c275-af13-67445a31fabc.png)

パッチ適用後（アイコンフォントがレンダリングされている）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/e383ea98-c574-5fe9-d24d-44e2c6cc270e.png)

図を見てわかるように、ディレクトリに当たる部分にはフォルダのアイコンが、markdownに当たる部分にはmarkdownのアイコンがレンダリングされているのがわかります。

しかし、このパッチはあまり良くないと、[vaffle.vim](https://github.com/cocopon/vaffle.vim)のメンテナからレビューを受けました。

### 良くない点

- アイコンのレンダリング部分が、vim-deviconsに依存している
- 他に、同様にアイコンをレンダリングできるプラグインが合っても、柔軟に対応できない。
- [vim-devicons](https://github.com/ryanoasis/vim-devicons)のバグなのに、[vaffle.vim](https://github.com/cocopon/vaffle.vim)にissue報告が来てしまう場合がある（問題の切り分けがしにくくなる）
- プラグイン自体の保守コストが上がる（[vim-devicons](https://github.com/ryanoasis/vim-devicons)のAPIの仕様や名前などが変わったら、それに柔軟に対応しないといけない）

などが挙げられます。

- 上のパッチのフロー

![スクリーンショット 2020-11-26 3.17.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/e34e5b93-bd1c-4175-68f4-7a8581acc195.png)

- 理想のフロー

![スクリーンショット 2020-11-26 3.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278618/8c808aeb-f2a5-2086-1da7-2b9c9319f1d5.png)



### 解決策

[vaffle.vim](https://github.com/cocopon/vaffle.vim)が提供するのは、アイコンフォントを返す骨格だけで、具体的な実装は、ユーザごとのvimrcに提供してはどうだ？と提案を受けたので、その提案にしたがいパッチを書き直しました。

- パッチ

```diff
function! vaffle#renderer#render_item(item) abort
-  return printf('%s %s',
-        \ a:item.selected ? '*' : ' ',
-        \ a:item.basename . (a:item.is_dir ? '/' : ''))
+  if get(g:, 'vaffle_render_custom_icon', '') !=# ''
+    return printf('%s %s %s',
+        \ a:item.selected ? '*' : ' ',
+        \ call(g:vaffle_render_custom_icon, [a:item]),
+        \ a:item.basename . (a:item.is_dir ? '/' : ''))
+  else
+    return printf('%s %s',
+        \ a:item.selected ? '*' : ' ',
+        \ a:item.basename . (a:item.is_dir ? '/' : ''))
endfunction
```

- vimrc（例）

```vim
function! RenderMyFavoriteIcon(item)
  return WebDevIconsGetFileTypeSymbol(a:item.basename, a:item.is_dir)
endfunction

let g:vaffle_render_custom_icon = 'RenderMyFavoriteIcon'
```

このパッチは、ユーザのvimrcにアイコンフォントを返す関数を定義します。
そのアイコンフォントを返す関数を `g:vaffle_render_custom_icon`というグローバル変数に指定することで、vaffleは、vimrcに実装された方法でアイコンフォントをレンダリングしようとします。
これにより、[vim-devicons](https://github.com/ryanoasis/vim-devicons)に依存しない形でアイコンフォントを提供できるようになりました

こういった問題解決方法を、他の人からレビューを受けながら体系的に身につけることができるのはOSS活動をする上で一つのメリットだと思います。

実際のPRの様子

> https://github.com/cocopon/vaffle.vim/pull/43

## ソフトウェアのメンテナンスを体験できる

ある程度開発が進んでいるOSSであるならば、メンテナンスを体験できます。Issueが来たり、自分が実装したパッチに対してフィードバックが来たりと、ユーザから様々なレスポンスが来ることがありますが、それらに対して対応する力が身につきます。ユーザからのfeature requestにすべて同意していると、機能が膨らんで、メンテナンスが大変になってしまったりすることもあります。そういった体験をすることで、様々な考え方や、issueを取捨選択する能力が身につくと思います。

#2. そもそもどんなものに貢献したらいいかわからない

個人的には、**普段から使用しているソフトウェアの中から見つける**、がとてもおすすめです。

理由としては

- 普段から使っていれば、ある程度の動作を知ることができる。
- 貢献するモチベーションが上がる
- 普段から使っていないと、1からそのソフトウェアについて調べないといけない。

等があると思います。

特にモチベーションを維持することがOSS活動を始める、ないしOSS活動を続ける上で重要な要素になってくると思います。
自分は普段からVimを使っていることから、Vimに関係したOSSに貢献していました。

## Vim関係のOSS（例）

- Vimのドキュメントの翻訳プロジェクト
  - https://github.com/vim-jp/vimdoc-ja-working
- Vimプラグイン
- Vim scriptのテスティングフレームワーク
  - https://github.com/thinca/vim-themis
  - https://github.com/junegunn/vader.vim
  - https://github.com/kana/vim-vspec
- Vim scriptのparser
  - https://github.com/vim-jp/vim-vimlparser
- Vim本体
  - https://github.com/vim/vim
- Vim scriptの静的解析ツール
  - https://github.com/Vimjas/vint

特に自分は、ドキュメントの翻訳プロジェクトとプラグインに貢献していました。


## 自分の好きな機能を取り込ませることができる

時々あんな機能があれば便利なのになぁって思ったりすることもあるでしょう。
それがOSSであれば、自らその便利機能を実装してしまうことだって夢ではありません。

例えば、上に示した[vaffle.vim](https://github.com/cocopon/vaffle.vim)にアイコンフォントをレンダリングするパッチも、僕がアイコンフォントを表示させたいと思ったから書きました。

誰でも、平等に意見交換や実装できる場所がOSSです。

# 3. 貢献したいけど、怖くて貢献できていない

これは本当によくある話です。しかし、実際のところは、多くのOSSではPRを歓迎しています。
たった数行のコードを修正しただけで、多くの人が踏んだバグを修正することだって夢ではありません。


## 3-1. 問題を見つけてissueを発行し、報告する
OSSに貢献するとなると、パッチを送る印象が強いですが、普段使っているツールの問題を発見した場合、それを報告する事自体貢献になります。

しかし、これには注意が必要で、メンテナにわかりやすく伝わるように、情報を整理して書かないといけません。

- どんな環境で再現したか
- 使っているソフトウェアのバージョンは何か
- どんな動作を想像していて、実際はどんな動作をしたか
- その問題が再現する最小構成

主にこの4つが必要だと思います。

特に、最後の **その問題が再現する最小構成**をしっかり書かないと、動作確認をするときに問題の切り分けができないので注意が必要です。

なので、ISSUE_TEMPLETEがある場合はそれに従い、ない場合は、過去のissueを参考に、一番わかりやすく書いているissueを参考にして書くといいかもしれないです。

## 3-2. ドキュメントに貢献する

Pull Requestを送るという行為を**コード本体に貢献する**と想像してしまう人が多いですが、コード本体に貢献することだけがOSS貢献ではありません。
初めての貢献であったり、なれていない場合は、ドキュメントに貢献することをオススメします。
理由としては

- コミュニティの温度感や作法、ルールなどをドキュメント貢献を通して学ぶことができる。

- Ruby
    - https://github.com/rurema/doctree

- Vim
    - https://github.com/vim-jp/vimdoc-ja-working


## 3-3. コードに貢献する

### issueに上がっているバグを直す

一番やりがいがある貢献であると思います。

issueに書いてある、バグの再現手順をもとに、バグの発生を確認し、それを修正することが目標になります。

ここで重要なのは、慣れていないときほど、全部のコードを理解しようとしないことです。
はっきり言って、全部のコードを理解しようとするとめちゃくちゃ時間がかかります。

そこで意識するのが、ディレクトリ構成の把握です。ディレクトリ構成を把握し、どこに何があるのか、なんとなくで当たりをつけることで、一つのバグを潰すために読まなければならないコードの量を減らすことができます。ファイル名や、ディレクトリ名を見たり、フレームワークが使われているのであれば、そのフレームワークが作るディレクトリ構成などを把握することが重要です。

ある程度当たりをつけたら、定義ジャンプやgit grep、デバッカなどを駆使して、どこまで実行されたか
であったり、どこで怪しい挙動になっているかであったりに当たりをつけて、範囲を狭めていきます。
泥臭いかもしれませんが、この繰り返しで僕はバグを潰してきました。

### 落ちているテストを修正する

OSSの中には、CIなどを用いて、自動テストを導入しているケースも少なくありません。
中には、自動テストの一部が失敗してしまっているケースもあります。
そういったテストを修正することもできるでしょう。

### CIを更新する

最近だと、travis-ci.orgが2020年で終了すると行った情報が出ています。
しかし、現状は多くのOSSはtravis-ciを使っているところが多いです。
そこで、github-actionsに移行するPull Requestを送ったらmergeしてもらえる可能性は高いと思います。本体コードに貢献するわけではないですが、重要な貢献になることは間違いないです。

また、特定のバージョンでしかCIが実行されていないCIも存在します。それらに、様々なバージョンで実行してくれるようなパッチをかけば、それがMergeされる可能性は高いです。また、CI自体の品質が向上します。

以下に例を示します。

これは、[vim-airline](https://github.com/vim-airline/vim-airline)の、`travis-ci`による単体テストを更新した例です。

- 更新前

```yml
language: ruby
before_install:
  - curl -f -L "https://raw.githubusercontent.com/vim-airline/vim-airline-themes/master/autoload/airline/themes/simple.vim" -o autoload/airline/themes/simple.vim
  - curl -f -L "https://raw.githubusercontent.com/vim-airline/vim-airline-themes/master/autoload/airline/themes/molokai.vim" -o autoload/airline/themes/molokai.vim
  - mkdir colors && curl -f -L 'https://raw.githubusercontent.com/tomasr/molokai/master/colors/molokai.vim' -o colors/molokai.vim
    #rvm:
    #  - 1.9.3
script: rake ci
```

- 更新後

```yml
# This config is based on lightline.vim <https://github.com/itchyny/lightline.vim/blob/master/.travis.yml>

language: ruby
before_install:
  - curl -f -L "https://raw.githubusercontent.com/vim-airline/vim-airline-themes/master/autoload/airline/themes/simple.vim" -o autoload/airline/themes/simple.vim
  - curl -f -L "https://raw.githubusercontent.com/vim-airline/vim-airline-themes/master/autoload/airline/themes/molokai.vim" -o autoload/airline/themes/molokai.vim
  - mkdir colors && curl -f -L 'https://raw.githubusercontent.com/tomasr/molokai/master/colors/molokai.vim' -o colors/molokai.vim
  - (if ! test -d $HOME/vim-$VIM_VERSION/bin; then
       git clone https://github.com/vim/vim $HOME/vim &&
       cd $HOME/vim &&
       git checkout v$VIM_VERSION &&
       ./configure --prefix=$HOME/vim-$VIM_VERSION &&
       make &&
       make install;
     fi)
    #rvm:
    #  - 1.9.3
cache:
  directories:
    - $HOME/vim-$VIM_VERSION

env:
  - VIM_VERSION=8.2.0000
  - VIM_VERSION=8.1.0000
  - VIM_VERSION=8.0.0000
  - VIM_VERSION=7.4

script:
  - export PATH=$HOME/vim-$VIM_VERSION/bin:$PATH
  - cd $TRAVIS_BUILD_DIR
  - rake ci

```

`更新前`では単純に rake ciを実行して、テストを実行しています。
これでは、標準でCIにインストールされているVimでしかテストされません。

`更新後`では、実際にVimを7.4から8.2までそれぞれのversionを並列でビルドしています。
これにより、指定した、様々なVimのバージョンをインストールして、テストを実行できるため、テストの品質が向上します。

#### 実際のPR

> https://github.com/vim-airline/vim-airline/pull/2034

### テストを導入する

中には全くテストのないOSSもあります。そこに単体テストを導入すれば、メンテナンス性が向上します。単体テストを導入するパッチを書くのもありでしょう。


# 終わりに

ここまで読んでいただき、ありがとうございます。
OSS貢献も様々な貢献があります。
この記事を読んだあなたが、OSSに貢献しようと思ったのであれば、とても嬉しいです。

この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをお願いします！
また [DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい！
<a href="https://twitter.com/DeNAxTech?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-size="large" data-lang="ja" data-show-count="false">Follow @DeNAxTech</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>