ワイ「なに！？ライブラリをラップするやと！？」

## とあるシステム会社にて

ワイ「なあ、ハスケル子ちゃん」
ワイ「いま開発してるWebアプリケーションについて、相談したいことがあるんやけど」

ハスケル子「はい」
ハスケル子「どんな内容ですか？」

ワイ「あのな」
ワイ「色んなページで、配列をソートして表示する必要があるんやけど」
ワイ「そのソート内容がちょっと複雑やねん」
ワイ「なんか**オススメのライブラリ**ある？」

ハスケル子「[LodashのorderBy](https://lodash.com/docs/#orderBy)なんて便利ですよ」

ワイ「マジかいな」
ワイ「さっそく使ってみるわ」

##ライブラリを導入してみる

ワイ「まずは・・・」

```terminal:ターミナル
npm install lodash.orderby
```

ワイ「↑こう、`npm`でインストールして」

```javascript:JavaScript
import lodashOrderBy from 'lodash.orderby'
```

ワイ「↑こう、`import`してやれば使えるな」
ワイ「さて、このライブラリはどんな風に使うんかな？」

ハスケル子「ええと、例えば・・・」

- ユーザーの情報が格納された`userList`という配列をソートする
- **名前の昇順**でソートする
- 同姓同名の場合は、**年齢の降順**でソートする

ハスケル子「・・・なんてことがしたい場合は」

```javascript:JavaScript
const sortedUserList = lodashOrderBy(userList, ['name', 'age'], ['asc', 'desc'])
```

ハスケル子「↑こんな風に書きます」

ワイ「なるほどな」
ワイ「第一引数には、ソートしたい配列を」
ワイ「第二引数には、ソートするプロパティ名を」
ワイ「第三引数には、昇順 or 降順を」
ワイ「それぞれ指定すればええんやな！」

ハスケル子「はい」

ワイ「よっしゃ、この関数、いろんなページで使わしてもらうわ！」

ハスケル子「待ってください、やめ太郎さん」

ワイ「ん、なに？」

ハスケル子「`lodash.orderby`の**ラッパー関数**を作って」
ハスケル子「各ページからは、その**ラッパー関数を呼び出す**ようにした方がいいですよ」

ワイ「ラッパー・・・？」
ワイ「何なんそれ」

ハスケル子「`lodash.orderby`を**ラップした関数**を、自分で書くってことですよ」

ワイ「え、なんで？」

ハスケル子「その方が、保守性が上がります」
ハスケル子「具体的には、将来的にそのライブラリを**別のものに入れ替える場合**とかに」
ハスケル子「だいぶ手間が省けます」

ワイ「（何を言うてるか分からんけど・・・）」
ワイ「**よっしゃ、分かった！やってみるわ！**」

## ライブラリをラップする、とは

ワイ「何をすればええねや・・・？」
ワイ「**ラッパー関数**を書けって言うてたな」
ワイ「・・・ということは・・・」

```javascript:JavaScript
// lodash.orderby を import
import lodashOrderBy from 'lodash.orderby'

// lodash.orderby をラップした関数
export const orderBy = (itemsList, sortKeys, sortOrders) => {
  return lodashOrderBy(itemsList, sortKeys, sortOrders)
} 
```

ワイ「↑こんな感じか・・・？」
ワイ「いや、意味なさすぎるやろ」
ワイ「だって、この`orderBy`関数」
ワイ「受け取った引数を`lodashOrderBy`にそのまま渡してるだけやもん」
ワイ「これは多分ちがうな」
ワイ「ほな**ラッパー関数**って、何のことやろ・・・」
ワイ「ラッパー、ラッパー・・・」

#### ワイ「・・・あっ！！」

## 分かった

ワイ「ハスケル子ちゃん、さっそく**ライブラリをラップ**してみたで！」
ワイ「**聞いて**みてくれや！」

ハスケル子「は、はい」
ハスケル子「（**聞く**とは・・・？）」

ワイ「行くで！」

> 誰かが作った**ライブラリ**
> ラップするだけで**だいぶマシ**
> 入れ替える手間ほぼ**皆無だし**
> マジ教えてくれた**アイツ神**

ワイ「どや？」

ハスケル子「**逆に、どう思います？**」
ハスケル子「これをどうプログラムに組み込むんですか？」

ワイ「そ、それな」

ハスケル子「そうじゃなくて」
ハスケル子「最初に書いてた関数の方で合ってますよ」

ワイ「ファッ！？」

```javascript:JavaScript
// lodash.orderby をラップした関数
export const orderBy = (itemsList, sortKeys, sortOrders) => {
  return lodashOrderBy(itemsList, sortKeys, sortOrders)
} 
```

ワイ「↑これかいな！？」
ワイ「なんでこんな、意味のない`orderBy`関数を作るん？」

ハスケル子「意味ありますよ」
ハスケル子「例えば、ライブラリをラップしないで」
ハスケル子「いろんなページから**直接**`lodashOrderBy`を呼び出している場合だと」
ハスケル子「将来的に**ライブラリを入れ替える場合**とかに面倒じゃないですか」

ワイ「まあ、ちょっとだけ面倒やな」
ワイ「いろんなファイルの`lodashOrderBy`を」
ワイ「`xxxSortLibrary`とかに検索置換せなあかんもんな」
ワイ「でも大した手間やないやん？」

ハスケル子「検索置換だけじゃ済まない場合もありますよ」
ハスケル子「例えば・・・」

```javascript:JavaScript
// 新しく使う xxxSortLibrary というライブラリは
// 引数の渡し方が lodash.orderby と違う
// （オブジェクトとして渡さないといけない）
const sortedUserList = xxxSortLibrary({
  array: userList,
  sortKeys: ['name', 'age'],
  sortOrders: ['asc', 'desc']
})
```

ハスケル子「↑こんな感じで」
ハスケル子「似たようなライブラリでも、**引数の渡し方が結構ちがう**こともあるじゃないですか」

ワイ「ほんまや・・・」
ワイ「こんなん、いろんなページで修正するとなったら、結構めんどくさいで・・・」

ハスケル子「ですよね？」

## ラッパー関数を作っていた場合

ハスケル子「ラッパー関数を作って、それを使っていた場合は」
ハスケル子「**1箇所だけの修正**で済みます」

```javascript:JavaScript
// xxxSortLibrary を import
import xxxSortLibrary from 'xxxSortLibrary'

// xxxSortLibrary をラップした関数
export const orderBy = (itemsList, sortKeys, sortOrders) => {
  return xxxSortLibrary({
    array: itemsList,
    sortKeys,
    sortOrders
  })
} 
```

ハスケル子「↑こんな感じで、ラッパー関数を修正してあげるだけです」

ワイ「なるほどなぁ」
ワイ「自作のラッパー関数が受け取った引数たちを」
ワイ「今まではそのまま渡すだけやったけど」
ワイ「新しいライブラリ関数に合う形式に**変換して**、渡してやればええわけか」

ハスケル子「そうです」
ハスケル子「ラッパー関数が作ってあれば」
ハスケル子「ライブラリを入れ替えた場合でも」
ハスケル子「**各ページからの呼び出し方**は変わりません」

```javascript:JavaScript
// ラッパー関数の引数は変わっていないので
// 各ページからは今まで通り使える
const sortedUserList = orderBy(userList, ['name', 'age'], ['asc', 'desc'])
```

ワイ「おお、ほんまや・・・」
ワイ「呼び出し側はそのままでOKなんやね」

ハスケル子「はい」
ハスケル子「それに、ライブラリを入れ替える場合だけじゃなく」
ハスケル子「ライブラリのバージョンアップによって、インターフェース（使い方）が変わる可能性もありますし」

ワイ「なるほどな」
ワイ「最近のフロントエンド開発では、多数のnpmライブラリを使うし」
ワイ「流行り廃りが激しいから、ライブラリを入れ替えることもあるもんな」
ワイ「メンテナンスコストのことも考えとかんとな」

## まとめ

- ライブラリの関数を**ラップした関数**を作っておくと、あとあと便利
- 逆に、ラップしないで直接呼び出していると、ライブラリの入れ替え時に手間がかかる
- 新旧ライブラリの**インターフェースの違い（使い方の違い）**を、ラッパー関数が吸収してくれる
- 結果的に保守性が上がる
- 関数名を`iLoveHipHop()`にするとか、そういうことではない

ワイ「ってことやな！」

ハスケル子「ですね！」

**〜おしまい〜**

## 新しい記事もよろしくやで
- [**ワイ「TypeScriptなんも分からん」**](https://qiita.com/Yametaro/items/ee69f2f81759b9ac39b7)
- [**ワイ「TypeScriptのエラーが読まれへん」**](https://qiita.com/Yametaro/items/bc592ed712edd329f364)


## スペシャルサンクス

[**ばりとん**](https://mobile.twitter.com/dd0125)さん（考え方を教えてもらったから）
[**きんみ**](https://mobile.twitter.com/_kinmi)さん（[ラップ](https://twitter.com/_kinmi/status/1319456333398040577?s=20)をパクらせてもらったから）

## 追記
ばりとんさんも記事を書いてたから、被りまくってしまった。
ばりとんさん、申し訳ありません・・・！

[わて「なにっ！？韻を踏むだけで保守性があがるやと！？」](https://qiita.com/dd0125/items/d8d4900d9480025cfad3)