ユーニックス総合研究所

  • home
  • archives
  • programming-wrapper

プログラミングのラッパー(Wrapper)とは?

ラッパー(Wrapper)とは?

プログラミングでよく聞く「ラッパー(Wrapper)」とはなんなのでしょうか?
ラッパーとは

🐭 < Hey Yo! チェキ!

のラッパーではなく関数やクラス、ライブラリなどをつつむクッションのことです。
このクッションを作ることでプログラミングにおける設計がしやすくなります。

私は個人Web開発者として毎日プログラミングしていますが、このラッパーを使う時はとても多いです。
とても使える考え方なので、プログラミングをされている人は押さえておきましょう。

🦝 < ではくわしく説明していきます

具体的には↓を見ていきます。

  • ラッパーのおおまかな説明
  • ラッパーは仕様変更に強い
  • ラッパーは関数などを使いやすくする
  • ラッパーはどんな時に作るのか?
  • ラッパーの作成コストを考える

ラッパーのおおまかな説明

ラッパー(Wrapper)とはさきほども書いた通り、関数などのクッションになるものです。
プログラミングではどのようにしてこのラッパーを作るのでしょうか。

ここでは関数で説明したいと思います。
関数のラッパーは、関数で作られることが多いです。
関数をつつみこむ外側の関数を1つ作って、中に入っている関数を隠します。

そうしてクッションのように関数の中に関数を隠すことを、関数をラップ(Wrap)すると言います。
関数を関数でラップすることで、その関数の外側にクッションを1つ作り、設計をしやすくします。

🦝 < おまんじゅうのアンコと皮みたいなものです

しかし、そのように関数を関数でラップして、本当に設計がしやすくなるのでしょうか?
それがなるんです。

具体的には、ラッパーを作ると「仕様変更に強い」設計になります。
ラッパーを作る目的のほとんどはこれです。
仕様変更に強くしたいからラッパーを作るんですね。

あとは元の関数の使い方を変えたい時などにも作ります。
自分好みの関数にラップしちゃうんですね。

たとえば引数が多くて複雑な関数があります。
そのまま使うにはめんどくさいです。
そういう時にラッパーとなる関数を1つ作って、そのめんどくさい関数をラップします。
そうすることで、そのめんどくさい関数を使いやすくするわけですね。

🐭 < 代理人みたいなものですね

これがラッパーの主な目的です。

ここでは関数を使って説明しましたが、もちろんラッパーはクラスにも使えます。
クラス全体をおおうラッパーとなるクラスを作って、そのクラスを包みます。
そうしてメソッドなどもラップして、自分好みのクラスに変えちゃうわけですね。

これは抽象化を一段階、深めるようなものです。
抽象化を行うことで、そのクラスの抽象度を上げ、全体の設計にプラスに働くようにするわけです。

ラッパーは仕様変更に強い

繰り返しになりますが、ラッパーは関数などのクッションとなるものです。
ラッパーで包んだ関数は仕様変更に強くなります。
これは詳しく見るとどういうことでしょうか?

たとえば関数ネコ太郎があるとします。
この関数ネコ太朗は引数を1つ取る関数です。

ネコ太朗(ご飯) {  
    ここに何か処理  
}  

この関数ネコ太郎はプロジェクトの色々なところで使われる便利関数です。
とても人気があり、たくさん使われます。
プロジェクトにはいたるところにこの関数ネコ太朗が散らばっています。

ある日、上司のツルの一声でこの関数ネコ太朗の仕様を変更することになりました。
具体的には引数を1つ増やします。

ネコ太朗(ご飯, 昼寝) {  
    ここに何か処理  
}  

そうすると、関数ネコ太朗の仕様が変わってしまったわけなので、この関数を使っている所のコードも修正が必要になってきます。

🦝 < ゲェー! コ〇す気か!

🦊 < さっさとやるんだよぉ!

大変ですよね。
修正にゲンナリしますよね。

しかし関数ネコ太朗をラッパー関数デブネコ次郎でラップしていたらどうでしょうか?
たとえば↓のようにです。

デブネコ次郎() {  
    ネコ太郎(ご飯)  
}  

↑の状態で関数ネコ太朗の仕様が変わったとします。
しかし、プロジェクトで使われているのは関数デブネコ次郎のほうです。
そのため関数ネコ太朗の仕様が変わったとしても、プロジェクトに散らばっているデブネコ次郎は修正しないで済みます。
修正するのはデブネコ次郎の中で使われているネコ太朗だけです。

このようにラッパーは関数などを仕様変更に強くすることが出来ます。

ラッパーは関数などを使いやすくする

ラッパーには他にも効果があります。
その1つが「関数などを使いやすくする」という効果です。

たとえばバード・ファクトリーというライブラリがあったとします。
このライブラリは関数の引数が多くて有名です。
正直、あまり使いやすいライブラリではありません。

🦝 < いやなライブラリだな

しかし会社の一声であなたはこのライブラリを使うことになりました。
さっそくこのライブラリの関数を使ってみますが、使いにくくてしょうがありません

その関数の1つが↓のような関数です。

バードウォッチ(天気, 場所, 双眼鏡, 靴, 服装, 髪型, メガネ) {  
    ここに何か処理  
}  

🦝 < 引数多いな!

しかしこの関数は使う時が多いです。
なにかの処理を書くときはこの関数を使わないといけません。
しかしあなたは引数が多くていちいちコードを書くのもダルいです。

こういう時にラッパーを作ると便利です。
たとえば↑の関数の、特定の用途に限定したラッパーを作ります。

いつものバードウォッチ(天気) {  
    バードウォッチ(天気, 場所, 双眼鏡, 靴, 服装, 髪型, メガネ)  
}  

↑のように「いつものバードウォッチ」という関数を作りました。
この関数は中で例の引数の多いバードウォッチ関数を呼び出していますが、いつものバードウォッチ関数自体の引数は1つだけです。
あとの引数はいつものバードウォッチ関数が適当に決めてバードウォッチ関数を呼び出しています。

このようにすることで、複雑な関数を特定の要件に絞ってラップし、関数を使いやすくするわけですね。

ラッパーはどんな時に作るのか?

ラッパーはどんな時に作ればいいのでしょうか?
これも繰り返しになりますが、多いのは↓の時です。

  • プロジェクトを仕様変更に強くしたいとき
  • ライブラリなどの関数を使いやすくしたいとき

仕様変更に備える

具体的に考えてみます。
まず仕様変更の面です。

たとえばプロジェクトに外部ライブラリを入れることを考えます。
そのライブラリはソフトウェアの中心部分でよく使われます。
つまり、ソフトウェアの大事なところがそのライブラリを使って書かれています。

ライブラリは基本的には信頼できるものです。
頼りになるし、開発者の負担を減らしてくれます。
しかし、ライブラリというのはバージョンが上がります。

バージョンが上がる時に、過去のライブラリの仕様を切り捨てることを「後方互換性がない」と言います。
つまり、昔はこのライブラリはこういう使い方で使えたんだけど、バージョンが上がった今ではもうその使い方は出来ない、ということですね。
このバージョンが上がり切ると、そのライブラリは安定し、いわゆる「枯れた」とか表現されます。
しかし、この枯れた状態になるライブラリと言うのはそれほど多くありません。

🦝 < 「枯れた」っていうのはポジティブな意味ですね

ほとんどのライブラリは、あーでもないこーでもないと言いながら、バージョンを上げて開発されていきます。
そしてその時にライブラリは、昔の仕様を切り捨てることがあります。

ライブラリが昔の仕様を切り捨てるとどうなるのかというと、それはいわゆる仕様変更です。
プロジェクトで使っているライブラリのバージョンを上げてしまうと、そのライブラリを使っている部分のコードが動かなくなります。

悪夢のような話ですが、これはけっこうよく起こります。
有名なのはプログラミング言語のPythonです。
Pythonは2系から3系に切り替わる際、過去の仕様をいっさい切り捨てました。
そのため2系のコードで書かれたプロジェクトは、3系への移行をしなくてはいけなくなりました。

🦊 < ソフトウェアの世界はこわいね

こういう時にラッパーを書かないでいたらどうなるでしょうか?
Pythonの例はかなり極端ですが、ライブラリが関数の仕様をとつぜん変えるというのはよくある話です。
つまりライブラリを使う場合、その仕様変更に備えたいのであれば、ラッパーを作ったほうが良いということになります。

ここではライブラリを例に挙げましたが、複数の人で開発しているプロジェクトで、他の人が作った関数を使う場合も考えてみます。
他の人が作った関数をそのまま使っていたら、その関数を作った人がその関数の仕様を変えてしまった。
その人の関数を使って書かれていたコードは動かなくなってしまいました。

複数人の開発では、そういうことが起こりえます。
ではそうならないようにするにはどうしたらいいのか?
それがラッパーを作ることなんですね。

関数などを使いやすくしたいとき

これは先ほども解説しましたが、関数などを使いやすくしたい時にラッパーを作ります。
基本的に、自分以外の人が作った関数と言うのは使いづらいものです。

これは仕方のないことです。
他人の家の使い勝手がよくわからないのと同じで、他人が作った関数と言うのは基本的には他人の人が使う関数です。
例外はライブラリですが、ふつうはライブラリ・レベルの関数を作るというのはハードルが高いものです。
じっくりと考えて、引数や返り値の設計をする必要があるからですね。

しかしそういったキカンボウな関数などもラッパーを作れば自分にとって使いやすい関数に早変わりです。

ラッパーの作成コストを考える

しかしラッパーが便利なものだとわかっていても、いちいちラッパーを作るというのは大変な話です。
使う関数ぜんぶにラッパーを作るというのは現実的ではありません。
つまり、どれにラッパーを作るか選んでいく必要があります。

まぁぜんぶにラッパーを作っちゃうというのも、それはそれで開発手法としては正しいと思います。
ただ、それは企業などのプロジェクトで、開発が大規模になるケースなど、ラッパーの価値が非常に高いプロジェクトにおいての話です。
個人で使い捨てのツールを作る時にいちいちラッパーを作るというのは、なんか面倒な話ですよね。

ラッパーの作成にはコストがかかるため、このようにプロジェクトの特性を考えて作っていく必要があります。
基本的にはラッパーを作っておいた方が最終的にコストが小さくすみますが、使い捨てのツールでラッパーを作っても仕方のない話です。

おわりに

ラッパーという考え方はプログラミングを非常に簡単にしてくれる考え方です。
この考え方をあなたのプログラミングにも導入して楽をしてみましょう。

🦝 < 楽をするのはいいことだ