30
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ウルトラ今更な「なんでSpringのServiceにはInterfaceが要るのか」

Last updated at Posted at 2018-05-24

この記事は、Springは使っているけど、中身どうやっているのか知らなくて、でも表題のようなことを疑問には思う、そんな人向けです。
もっと言えば、**こんなものを書くなんて、俺はどうかしているんじゃないか?**と思ってしまった人向けです。

……というか、今日思いっきりコケて調べて「そういうことだったのか!」となったので書きました
どういう風に実装してるか調べないとどこかで落とし穴に落ちますね(這い上がりながら)。


世の中にはたくさんのServiceがあります。あ、サービスじゃなくて、Service。

Serviceがどこからきて本来どういう意味なのかというのはひとまず置いておくとして1、Spring絡みの作例では、Serviceを作る際、その多くが Interface + Implement class の構成を取ります。
何故でしょうか?

TL; DR

Springが介入するスキを作るためです

えっ!?

実際のところ、結構な部分において、Interface抜きのServiceは期待通りに機能します
しかし、特定の一部パターンにおいて死にます。
具体的には、トランザクション制御や非同期処理が絡むと、いきなりインジェクションに失敗することになるのです

これにはSpringの実装が絡んでいます。といっても、難しい話ではありません。

SAStrutsを使っていた頃、JavaVMのバージョン違いで起動せずにうがー!となることがよくありました。
私があれを使っていたのはEOLも間近だったので、更新がバージョンに追いついていなかったのです。
私の認識が正しければ、アレの動作書き換えはJavassistを利用したバイトコードレベルでの書き換えに依存していたはずです。
(気づくまでずいぶん手こずりましたが、Javassistを入れ替えると動くということはそういうことでしょう)

Springの場合、少なくともAOPやトランザクション制御や非同期処理のためには、バイトコード変換を使っていません2
ではどうやっているのかといえば、Interfaceを実装しているのです。
予め用意された、SpringのInterfaceではありません。

あなたの用意したInterfaceを、Springが、動的に、実装しているのです

これが答えです。
Springは、あなたの用意したInterfaceを実装して、あなたの用意したServiceへ動作を委譲するようなクラスを作ることで、自らの機能を果たすのです。
あなたの用意したInterfaceこそ、Springが己の機能を発揮する最大の手助けなのです!3

脱線 - 何故「Interface + Implement class」構成を疑うのか

Javaという言語はオブジェクト指向ですが、その中でもインターフェイス指向に分類されます。
つまり、インターフェイスを全面に押し出している言語です。
「ということは、そもそもとりあえずインターフェイスを作っておけばいいじゃないか?なんでそれを疑うんだ?」
これは非常に尤もな話です。

ところで皆さん。
ぶっちゃけインターフェイス作るのめんどくさくないですか
もちろん、インターフェイスが非常に有効な場合は死ぬほどあります。
そういう時、作るのは何の苦もありません。むしろ楽しいものです。
我々は、何故あんなものを強いられているのでしょう

JavaBeansというものがあります。
「JavaにGetter/Setterの呪いをかけたクソ」と呼ばれることもあれば、「現在の自動実装プロパティ類に続く重大な発明」と呼ばれることもある、アレです。
ともあれ共通しているのは、「何もしないGetter/Setterをむやみに量産することは無価値であり、害悪であり、(場合によっては)オブジェクト指向に反する」という認識です。

これに歯向かった(?)のが少々前まで活躍していた4フレームワーク、SAStrutsでした。
あれの特徴はやっぱり「もうpublicでいいじゃん」という割り切りというか、開き直りだったように思います。
事実、privateフィールド+何もしないGetter/Setterはpublicフィールドとほぼ同義です。
そしてpublicフィールドとGetter/Setterに両対応したSAStrutsは、事実非常に「書きやすい」部類のフレームワークでした。
本当に必要なの?」という問いは、重要なのです。

ServiceのInterfaceはどうでしょう。
大抵実装クラス1つしかないゴミ(のように見える)インターフェイスもどきになりませんか?
そんなものが山程できる状態は耐え難くないですか?
もういっそ全部吹き飛ばしてやろうとか思いませんか?

まとめ

我々が「書かされて」来た、無数の "実装が一つしか無い、ユニットテスト以外で役立たずのように見える" Interfaceは、決して役立たずではなかったのです!
だから、自信を持ってください。
……あと、むやみに省略すると死ぬこともあると覚えておきましょう。特に、Springのような、頭を使ってお行儀よくきれいに書いてくれているコード相手には。

  1. エリック・エヴァンス氏の「ドメイン駆動設計」読んできてください

  2. 10年前の記事ですが、パッと出てきたものを。 http://d.hatena.ne.jp/minghai/20070924/p1

  3. 大げさすぎやしないかって? いやいや、「契約を守る」ことこそ最大の手助けというのは、契約による設計を考えるとむしろ当然でしょう。……そういうことにしてください。「俺たちが書いてきたのはゴミじゃないんだ!」というだけで、我々の精神状態はいくらかよくなるはずです。

  4. 既にEOLを迎えています。終末期でしたが、私もお世話になったものです。S2JDBCとか未だに最高のO/Rマッパの一つだとおも……あれ?

30
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?