OSSプロジェクト開発を始めるときに設計しておきたいことリスト

ウチの会社が提供している[Unipos](https://unipos.me/ja/)というサービスのアプリではReactNativeを使って開発しています。
そのアプリの画面遷移でははじめ今は亡き組み込みのルーティングAPIを使っていましたが、次に[react-navigation](https://reactnavigation.org/)を使うことになり、最近では自前のルーティングライブラリを開発し、それを組み込んだものをもう少しでリリースできそう、という状況です。

自社サービスに適用すると同時に、このライブラリをforkしたものをオープンソース化して公開する、というチャレンジも視野に入れていました。
このライブラリはサンプル、ドキュメント、ライセンスあたりを整理してから年明けくらいに公開しようと思っています。(公開後にはリンクを貼るようにします)

今回は、そんなOSSプロジェクト開発を始めるときに **「こういうことを考えて整理しておくと、開発しながらブレずにやっていけるのでは？」** ということを備忘録的にリスト化してみたいと思います。

# どんなものを作るのか？
作るもののコンセプト/実現したいこと/解決したい課題を言語化(+メンテナンス)しておきます。
そして、作っていく過程で「そもそもなんでコレを作っているのか」「どこに向かうのか」がわからなくなったときのために、コレを立ち返る場所とします。
下記はRNルーティングライブラリでの例です。

(以下スニペット内はルーティングライブラリでの具体例とします)

- コンセプト

```
・ヘッダー/画面タイトル/戻るボタン/タブボタンのような表示要素を一切持たず、遷移の機能だけを提供する。ミニマルであることにこだわる
・Router/Screen/Contentという要素を設定する。この概念は内容が間違っていない限りは変更しない。
```


チームメンバーが利用者になるので、コンセプトをできるだけ捉えやすくするためにイメージも用意したりしました。
<img width="398" alt="zen-router1.png" src="https://qiita-image-store.s3.amazonaws.com/0/39330/509d40be-58c5-1014-9b27-0b020619c504.png">

<img width="598" alt="zen-router2.png" src="https://qiita-image-store.s3.amazonaws.com/0/39330/6bccc2fe-a0ad-794b-d308-8c3fb0c0c23a.png">

<img width="414" alt="zen-router3.png" src="https://qiita-image-store.s3.amazonaws.com/0/39330/2aeb88ee-33aa-436f-5e52-e56f875174cc.png">

<img width="393" alt="zen-router4.png" src="https://qiita-image-store.s3.amazonaws.com/0/39330/f97115b6-5071-81ad-0639-67c7c2a2de83.png">


- 実現したいこと/解決したい課題

```
・reduxに乗せても機能するものにする
・react-navigationを使っていて出来なかったこと/しんどいことを解決する
　・同じタブを持つ画面間の遷移において、タブを固定したまま遷移できるようにする
　・Android/iOSともにタブ遷移操作をスワイプでできるようにする
　・高速連続タップで複数回遷移が起きてしまうのを、ライブラリの中で制御できるようにする
　・バージョンアップでインターフェースが大きく変更されることが多く、追従が大変。型定義もなかったり。(自前化することで自動的に解決)
```


# やらないことは何なのか？
作っているうちに、アレもやりたい、コレも出来たほうが、こんなアプリでは使えないかも、といった思いが膨らんでいきキリが無くなってしまいがちです。
前に進みにくくなったり、ゴールが遠のいてしまうことを防ぐために、(いったん)やらないことも言語化しておきました。

```
今回は、プロダクト(Unipos)に組み込むことを最初のゴールとし、最低限必要な機能を提供することに集中する。
そこに登場しない機能は、明らかに後々必要になりそうなものを除き実装しない。
```

# 型システムへの対応はどこまでやるか？
TypeScript/FlowType、昨今型システムも広く使われるようになり、理想を言えばどちらにも対応させたいところです。
使える時間や学習コストなんかも考えつつ、「段階的に、あとでやる」という選択をとるのも大事かなと思ったりします。

```
自分(と会社)の話で言えば、使い慣れているのはTypeScriptなので、TypeScriptを優先させ、
より多くの人に使ってもらいたいフェーズにはFlowTypeも対応させる、という優先順位をつける。
```

# どんなモジュール/APIが良いのか？
細部の構成に関しては最初から決めて貫くのが難しいところなので、後から改善していく前提で、ざっくりとしたコンセプトだけを作るようにしました。
はじめは下記のようなざっくりしたイメージだけ決めておきました。

```
・メソッドの引数が３つを超えたら、何番目の引数が何を表しているかわからなくなりがちなので、引数はオブジェクトを受け取ることにする。
・画面を重ねる、外す、差し替える操作は、全コンポーネントにrouterオブジェクトを流し込み、メソッドを叩けるようにする。
・タブの切替、タブ切替時のコールバック登録はタブ画面に対応するオブジェクトを流し込み、メソッドを叩けるようにする。
```

# どんなプロジェクト構成にするのか？
githubやnpm/bowerなどのリポジトリにスムーズに対応させること。
複数人でのライブラリ開発もやりやすいこと。
といったプロジェクト構成やポリシを早めに作っておくと後々の細かい作業が楽になっていくので、意外と重要なところではないでしょうか。

exampleプロジェクトの配置や、ドキュメント、テストなんかのディレクトリも必要かなと思いますが、
それらはnpmダウンロードして使う利用者にとっては不要なりソースだったりして、使ってくれる人のプロジェクトが重くなるのは嫌だなーと思っていたので下記のようにしてみました。

```
- router-devプロジェクト -> github
  - examples/
  - docs/
  - tests/
  - routerプロジェクト -> npm/bower
```

router-devプロジェクトを上位に置き、これは開発用リソースとしてgithubで管理します。その中にrouterプロジェクトを内部に作り、こちらはnpm/bowerに公開し、ダウンロードして使ってもらいたいリソースのみを配置することにしました。


# 残しておきたい思考ログ
最後に、やらずに後悔していることを挙げておきます。
よくある話ですが、のちのちコードを読んだだけではその時々の判断意図がわからなくなってしまうことがあります。
コメントやコミットログをみっちり書いていっても良かったのですが、中途半端にOSSを意識して英語コメントを書いていったため、「あのときなんでこうしたのか？」を振り返るのが結構大変になってしまいました。
振り返ることを目的として日記のような形で、今日悩んだこと、どう解決したか、どんなコードを書いたか、などを残し続けていけば良かったなぁ、と今にしてみると思います。
いったん実装に入ると早く前に進みたい気持ちが先行してしまうので、なかなか気持ちを制御するのが大変なところではありますが、あとでそれに見合う価値は返ってくるんじゃないかという気がしています。