eyecatch
Thu, Feb 23, 2017

Hibernateはどのようにして私のキャリアを破滅寸前にしたか

このエントリでは、Grzegorz Gajosによる記事、How Hibernate Almost Ruined My Careerを紹介する。 (Grzegorzから和訳と転載の許可は得た。) 以下はその全文の和訳だが、意訳超訳が混じっているので、もとのニュアンスを知りたければ元記事を読んでもいいし、読まなくてもいい。 (adsbygoogle = window.adsbygoogle || []).push({}); 想像してくれ。 君はJava開発者で、次のビッグプロジェクトを開始しようとしているところだ。 君は、そのプロジェクト全体に影響する根本的な決断をする必要がある。 君の柔軟なデータモデルをオブジェクト指向で抽象化するベストな方法を選択したい。生のSQLを扱いたくはないからね。 どんな種類のデータもサポートしたいし、理想では全種のデータベースをサポートしたい。 すぐに思いつくのは、単にHibernateを使うという解だ。そうだろ? Javaディベロッパの90%は君に同意するだろう。 しかし、それって正しい決断になっているだろうか? Hibernateが一般に受け入れられているスタンダードだからといって盲目的に採用してしまうと、どんな問題が発生するかを見てみよう。 モニカというJava開発者がいるとしよう。 モニカは最近出世してアーキテクトの役職に就き、会社の新製品のための技術スタックを選定する責任者になった。 彼女は、Javaの世界にはデータベースとのやり取りを扱うたった一つの適切なツールがあることを知っている。Hibernateだ。 Hibernateは良く知られ支持されているJPAのスタンダードではあるが、プロジェクト開始前に多少のチェックをするのが定跡だ。 幸いにも、同僚のベンが適任者を知っている。 4年前、Hibernateは銀の弾丸かのように見えた ベン: やあモニカ。ジョンを紹介させてくれ。彼はHibernateの達人だ。君の助けになるはずだ。 モニカ: ジョン、時間を取ってくれてありがとう。 今、私たちが次なる目玉製品を開発しようとしてるのは知ってる? 次のFacebookやGoogleになるつもりなの。 忙しくなるわ。巨大なものになる。 本当にすてき! みんなとても興奮してる! 私はアーキテクトの役に就いたから、とりあえず採用する技術スタックを選定しなければいけないの。 ひとつだけまだ欠けてるのが永続化なんだけど… ジョン: Hibernate! モニカ: そう!そのとおり! わたしもそう考えていたの! それならわたしたちにぴったりで上手く行きそうでしょう。 マーケットと豊富な実績に裏付けられた、真の業務問題のための真の業務ソリューション。 とてもたくさんのポジティブな経験談を聞いたことがあるわ。 けど、一つ問題があって、チームメンバのひとりがそれに絶対反対してるの。 アプリケーションとデータベースの間に別のレイヤを加えるのを気にして。 彼はすごく頭がいいから、これが良い決断だと納得させるには本当にしっかりした根拠が必要なの。 助けてくれる? ジョン: もちろん、よろこんで! Hibernateは、実際、すばらしいツールです。 銀行といった、大きな真の業務ソリューションで広く使われています。 それを使って失敗するということはありえません。 永続化ときたらHibernate。 Javaで書いているならそれが完全に正しい選択ですし、さらには他の言語への移植もあります。 どれだけ多くの職務記述書がそれを要求しているか! モニカ: 全く同感! 同じことを感じていたわ。 前のプロジェクトで、ほとんどのところで生のJDBCからSQLを使っていたんだけど、ばかげてた! そうでしょ! けど、実は、ほんとに優秀なSQL屋がチームにいて、Hibernateが生成したSQLを見て神経質になってるの。 きたなくて読みにくいって。 これって将来問題になりそう? ジョン: 気を付けてください。DBA屋ってのは違ったものの見方をします。
eyecatch
Sun, Sep 13, 2015

ORMは不快なアンチパターン

このエントリでは、Yegor Bugayenkoによる記事、ORM Is an Offensive Anti-Patternを紹介する。 (Yegorから和訳と転載の許可は得た。) 以下はその全文の和訳だが、意訳超訳が混じっているので、もとのニュアンスを知りたければ元記事を読んでもいいし、読まなくてもいい。 (adsbygoogle = window.adsbygoogle || []).push({}); 結論から言えば、ORMはオブジェクト指向プログラミングの原則の全てに違反するひどいアンチパターンだ。オブジェクトをバラバラに引き裂き、もの言わぬ受身なデータ入れに変えてしまう。 小さいWebアプリケーションから、数千のテーブルをCRUD操作するエンタープライズシステムまで、どんなアプリケーションにもORMが存在することはゆるせない。 代わりになるものは? SQLを話すオブジェクトだ。 ORMの仕組み オブジェクト関係マッピング (Object-relatinal mapping、ORM)は、オブジェクト指向言語(例えばJava)からリレーショナルデータベースにアクセスする技術(またはデザインパターン)だ。 ほとんどの言語で複数のORM実装がある。 例えば、JavaのHibernate、Ruby on RalsのActiveRecord、PHPのDoctrine、PythonのSQLAlchemy。 Javaでは、ORMデザインはJPAとして標準化されてさえいる。 最初に、ORMがどう動くかを見てみよう。JavaとPostgreSQLとHibernateを使い、データベースにpost (訳注: ブログポスト、ブログの記事)という単一のテーブルがあるとする。 +-----+------------+--------------------------+ | id | date | title | +-----+------------+--------------------------+ | 9 | 10/24/2014 | How to cook a sandwich | | 13 | 11/03/2014 | My favorite movies | | 27 | 11/17/2014 | How much I love my job | +-----+------------+--------------------------+ で、このテーブルをJavaアプリケーションからCRUD操作したい。(CRUDはcreate、read、update、deleteの略。) まず、Postクラスを書く。(長くてごめん。けどなるべく短くしたんだ。) @Entity @Table(name = "post") public class Post { private int id; private Date date; private String title; @Id @GeneratedValue public int getId() { return this.id; } @Temporal(TemporalType.TIMESTAMP) public Date getDate() { return this.date; } public Title getTitle() { return this.title; } public void setDate(Date when) { this.date = when; } public void setTitle(String txt) { this.title = txt; } } Hibernateでの処理をする前に、セッションファクトリを作らないといけない。 SessionFactory factory = new AnnotationConfiguration() .configure() .addAnnotatedClass(Post.class) .buildSessionFactory(); このファクトリはPostオブジェクトを操作したいときに「セッション」を作ってくれる。 セッションを使う全ての操作は以下のようなコードブロックで囲わないといけない。 Session session = factory.openSession(); try { Transaction txn = session.beginTransaction(); // your manipulations with the ORM, see below txn.commit(); } catch (HibernateException ex) { txn.rollback(); } finally { session.close(); } セッションが準備できたら、以下のようにしてデータベーステーブルから全てのpostのリストを取得する。 List posts = session.createQuery("FROM Post").list(); for (Post post : (List<Post>) posts){ System.out.println("Title: " + post.getTitle()); } ここで何が起こっているかは明確だと思う。 Hibernateという巨大で強力なエンジンが、データベースへの接続、SQLのSELECTリクエスト発行、及びデータの取得をする。 そして、Postクラスのインスタンスを作り、データをつめる。 そのオブジェクトが我々に渡されるとき、それにはデータが詰まっていて、getterでデータを取り出すことができる。上記getTitle()でやっているように。 逆の処理をしてオブジェクトをデータベースに送りたい場合は、同じことを逆の手順でやればいい。 Postのインスタンスを作り、データを入れ、Hibernateに保存するよう頼む。 Post post = new Post(); post.setDate(new Date()); post.setTitle("How to cook an omelette"); session.save(post); これがほぼ全てのORMの仕組みだ。 基本的な原則はいつも同じで、ORMオブジェクトは無気力なデータの包みだ。 我々はORMフレームワークと話して、ORMフレームワークはデータベースと話す。 オブジェクトは我々のリクエストをORMフレームワークに送り、そのレスポンスを読むのを助けてくれるだけだ。 こうしたオブジェクトは、getterやsetterのほかに何のメソッドも持たない。どのデータベースから来たのかすら知らない。 これがオブジェクト関係マッピングの仕組みだ。 これの何が間違ってるかって?