新しいライブラリを導入するときの考え方

この記事は[2019新卒 エンジニア Advent Calendar 2019](https://qiita.com/advent-calendar/2019/2019-graduates)の17日目の記事になりました。

# TL;DR
- ライブラリ無しで解決できないか確認しよう
- 解決できない場合、まずは導入しているライブラリの中から探そう
  - 検索で出てきたライブラリを即導入するのは割と悪手かもしれない
- 導入するなら基準を持ってライブラリを選ぼう

# 前書き
自分は2018年10月1日より社員としてエンジニアをはじめました。
扱いとしてはギリギリ19卒の人間なので、このアドベントカレンダーに投稿させて頂こうと思います。

この記事では、1年強の間開発する中で得た「新しいライブラリを導入するときの考え方」についてまとめます。

なるべく一般的な内容を目指しますが、言語は`Java`/`Kotlin`(= `JVM`系)で、`Intellij`系`IDE`を用い、何かしらのフレームワーク（e.g. `SpringBoot`）を用いる前提で書きます。

また、この記事はあくまで自分の経験から出した結論であるため、意見など有れば是非コメントを下さい。

# 探す必要があるか考える
まず、他人の実装を探すか、手で書くかの判断についてです。
自分は以下の3点に引っかかっている場合は他人の実装を探すようにしています。

- 簡単かつその実装がプロジェクト内で大量に登場しうる（= 誰かしら`Util`を作っていると予想できる）
- やりたい処理にかっちりした規格が定まっている（= ライブラリが作り易い）
- 自分で書くのがめんどくさい（= ~~働きたくないでござる~~）

# ライブラリを導入する必要が有るか確認する
他人の実装を探すと判断した場合は、次にライブラリを導入する必要が有るか確認するようにしています。

## 言語に付随する機能の中に無いか確認する
言語に付随する機能（スタンダードライブラリ）の中は一番最初に探すべきです。

言語に付随する機能は安定性・信頼性共に非常に高く、それが使えなくなる状況は殆ど有りません。
また、特に`Java`では、`java`パッケージ配下に様々な機能が定義されているため、使える場面は多く有ります。

ただし、状況を考えて「ライブラリを導入しなくてもできるが、敢えて導入する」というような判断は適切に行う必要があるでしょう（e.g. 「`Java8 -> Java11`では消えるパッケージが有るため、ライブラリを用いることでアップデートを容易にする」など）。

## 導入しているライブラリから探す
言語に付随する機能の中には無いという結論に至った場合、次は導入しているライブラリから機能を探すのが良いと思います。
理由は以下の3点です。

1. プロジェクトは最小構成に近い状態の方が望ましい
2. ライブラリ自身や、それが用いる依存は信頼度が高いと考えられる（特にフレームワークが依存しているライブラリ）
3. 有用なライブラリであっても検索して出てくるとは限らない

1は、依存同士の相性によって何か変になるという状況を自分が経験したので、そのような深いトラブルを避けるためにも、なるべく新しい何かは導入せず、最小構成に近い方が状態で済ませた方が良いという考えからです。

2は、フレームワークは多くの機能を持っているため、ある場面ではそれを使い回すことができたり、フレームワークが依存するライブラリに有用なものが含まれる場合があることからです。
また、フレームワークを変える可能性は小さく、フレームワークが依存するライブラリが変わる可能性も小さいため、その中に含まれる機能を使うのは安全度が高いと考えられます。

3に関しては、検索しても出てくる情報が古かったり、最善とは言えなかったりと、後から後悔する場面がちょくちょくあったので、まずは自分のプロジェクトの中を探した方がよい結果になりやすいという考えからです。
極端な例では、「超有名フレームワークに採用されていて実際有用なライブラリなのに用途で検索しても出てこない。Qiitaには4記事しか上がっていない」というような場面が有りました。

### 探し方
「使える場合が有る」と言っても、ソースコードを全文読んだり、依存しているパッケージを全て見て探すようなことは非効率であるため、`IDE`の検索機能を使うことをオススメします。

例として、`Intellij`系`IDE`では`Shift`を2回押すことで、プロジェクト全体からの曖昧検索ができます。
この時`include non-project items`をチェックすることで、依存しているパッケージからも検索ができます。

画像は適当な単語で実際に曖昧検索をやってみた結果です。
様々なパッケージの内容が抽出できていることが分かります。

![スクリーンショット 2019-12-15 17.09.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/e79974f2-2ea1-8efe-e90a-b133e898e5f7.png)

もし見つからなかった場合、ググってみて出てきた語彙を導入して検索してみるのもおすすめです。

### どの依存からライブラリを導入するのが適切か
「探してみると、複数のライブラリで同等の実装が有った」という場面も有ります。
そのような場合、自分は以下の優先順位で選ぶことにしています。

1. フレームワーク本体に含まれている
2. フレームワークの依存に関係が有る
3. そのライブラリを捨てる可能性が小さい

# ライブラリを探す・選ぶ
ここまでやって見つからなかった場合は新しいライブラリの導入を検討します。

大体の場合は検索時点で使えそうなライブラリが見つかっていることでしょう。
しかし、そのライブラリを導入するかは慎重に判断した方がいいと考えています。

自分は、`Maven Central`等で公開されていることを確認した上で、少なくとも以下の3点[^doc]を確認してからライブラリを導入しています。

- ライセンス
- 利用状況
- メンテナンス状況

[^doc]: ドキュメントが充実しているかも重要な要素かもしれませんが、検索で見つかるなら他にも多分ドキュメントは有るだろうということで無視しています。加えて、自分の場合は大体`idea`の検索と自力でコードを読めばなんとかなっているので、ドキュメントが無くて困ったことがあまり無いというのも有ります。

## ライセンス
まずライブラリのライセンスについてです。

ライセンスによっては、そのライブラリを用いたソフトウェアのソースコードの公開を義務付けています。
その義務を把握し受け入れていた場合はともかく、商用ソフトウェアが不意にソースコード全体の公開を求められるというのはよろしく有りません。

そういった無用のリスクを避けるためにも、ライセンスはまず真っ先に確認しておくべきでしょう。

### 参考にさせて頂いた記事
- [公開ライセンスの話 \- Qiita](https://qiita.com/lovee/items/484ae3fc038314a64ee2)

## 利用状況
次に、そのライブラリの利用状況についてです。

いくら便利そうに見えるライブラリであっても、そのライブラリがあまり使われていなかったり、歴史が浅かったりする場合には、バグが出たり、いきなりドラスティックな変更が起こったりということが予想されます。
そのため、安定を求める場合には確かな利用状況を確認できないライブラリは利用すべきでないでしょう。

### 確認方法
例として、`Maven`のライブラリページからの確認方法を示します。

`Date`からそのライブラリの歴史を、`Usages`からそのプロジェクトがどのくらい使われているか、どのプロジェクトから使われているかを確認できます。
画像は`unbescape`というライブラリに関する結果です。
長い歴史があり`Thymeleaf`のような有名フレームワークから利用されていることが分かります。

![スクリーンショット 2019-12-16 17.00.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/1914d33a-aebb-50fc-d967-0c5a34ba5086.png)
![スクリーンショット 2019-12-16 17.03.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/55c2f990-7435-a0c2-cc4b-f2c8f3f71211.png)

## メンテナンス状況
ライブラリによっては現在メンテナンスされていない場合があります。
そのようなライブラリを用いる場合、バグが修正されなかったり、脆弱性が放置される危険性が有るため、避けた方が良いでしょう。

また、個人で開発されているようなライブラリは、いつ更新が止まるか分からない、アップデートでいきなりドラスティックな変更が起るなどの危険性が有るため、これも避けた方が無難です。

### 脆弱性
ライブラリには度々脆弱性が生えるもので、物によっては2, 3ヶ月の間に重大な脆弱性がいくつも出る場合もあります（e.g. `Jackson`）。
仮に使っているライブラリに深刻な脆弱性が認められ、その修正が容易でないとなった場合には、どこかで多大な労力をかけてそのライブラリを捨てる必要が出てきます。

このような状況に陥らないためにも、メンテナンス状況の良いライブラリを選ぶべきだと自分は考えています。

## （オマケ）おすすめのライブラリ
`JVM`限定ですが、ここまでの基準をクリアできるライブラリが見つからなかったり、複数見つけて迷ったりした場合には、`apache`系のライブラリをオススメします。
`apache commons`を筆頭に様々なライブラリが有り、今まで紹介した項目は全て満たしています。

# まとめ
この記事では新しいライブラリを導入するときの考え方についてまとめました。

ごちゃごちゃと書きましたが、要約すると「後から『アレ変えたいコレ変えたい』という事態が発生する確率の低い所から探して行こう」ということです。

大げさかもしれませんが、新しい何かを導入した場合、それが3年4年のスパンで生き残っていそうかという所まで判断できるに越したことは有りません。
重要度が高く代替が難しいものほど、そのリスクは慎重に判断するべきでしょう。

取り留めがなくなった感も有りますが、この記事が何かのお役に立てば幸いです。