Help us understand the problem. What is going on with this article?

Domaの開発で大切にしている10のこと

Domaの開発で大切にしている10のこと

by nakamura-to
1 / 41

自己紹介


Domaとは?


Domaの歴史

  • 2009/05: 開発開始
  • 2009/02: v1.0.0リリース
  • 2014/07: v2.0.0リリース (Java 8対応)
  • 2016/06: v2.11.0リリース(最新版)

1. 動かさないとわからないを減らす

  • コンパイル時にできるだけチェック

  • Javaコードに対して
    • 例:アノテーションの存在チェック

apt_error_1.png


  • SQLファイルに対して
    • 例:パラメータの存在チェック

apt_error_2.png

select * from EMP where ID = /*identity*/100

  • SQL内の式コメントに対して
    • 例: 型チェック
select * from EMP where ID = /*id.hoge*/100
  • コンパイル時に idInteger 型だとわかる
    • hoge への参照はコンパイルエラー

2. コードの信頼性を高める

  • SQLテンプレートでSQLインジェクションを防ぐ
select * from emp whrere name = /* name */'taro'
  • PreparedStatementへ変換して実行するので安全
select * from emp whrere name = ?

  • リソース(Connectionとか)を自動で解放する
// トランザクション内で検索と更新をするコード
tm.required(() -> {
    Employee employee = dao.selectById(1);
    employee.setName("hoge");
    employee.setJobType(JobType.PRESIDENT);
    dao.update(employee);
});

3. シンプルさを重視する

  • 例えばCriteria APIは提供しない
  • Criteria APIはシンプルさを損なう
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
TypedQuery<Pet> q = em.createQuery(cq);
List<Pet> allPets = q.getResultList();

  • 利点
    • 型安全で組み立てられる
      • 文字列のタイポが発生しない
  • 欠点
    • 学習コストが高い
    • いつCriteria APIを使うべきかで迷う
      • 迷う ≒ シンプルさの欠如

4. SQLの発行場所とタイミングを明確にする

  • SQLの発行はDAOインタフェースの呼び出しで
    • 遅延ロードはサポートしない
// ここでSQLを発行するならOK
Dept dept = dao.selectById(1);

// ここでSQLを発行するのはNG!
List<Employee> employees = dept.getEmployees(); 

  • キャッシュはしない
    • いつも必ずSQLを発行
    • 必要ならアプリレイヤで
// SQL発行
Dept dept = dao.selectById(1);
// SQL発行
Dept dept = dao.selectById(1);

5. SQLの完全性を重視する

  • SQLの断片化を促進させる機能は持たない
-- こんな機能はありません!
select /*%include common_select_list.sql*/ 
from employee
where /*%include common_search_condition.sql*/
  • 過剰な共通化は見通しを悪くする

6. JDBCでできることを制限しない

  • 例えばストアドプロシージャーの呼び出し
@Procedure
void execute(@In Integer id, @InOut Reference<BigDecimal> salary);

  • 結果セットを複数個返すようなストアドプロシージャー
@Procedure
void execute(
  @ResultSet List<Employee> employees,
  @ResultSet List<Department> departments,
  @In Integer employee_id,
  @In Integer department_id);

7. 逃げ道を用意する

  • いざという時にJDBCを自由に使えるのが重要
    • かつ呼び出し元に影響を与えないものポイント
@Dao
public interface EmpDao {
  default Emp select() {
    Config config = Config.get(this);
    DataSource ds = config.getDataSource();
    ... // 自由にJDBCの機能が使える
  }
}

  • Domaを捨てる場合にも使える
    • 他のDBアクセスライブラリへの移行する場合
  • Javaのインタフェースを使っていることの利点

8. 様々な環境で長期的に使えるようにする

  • JDK/JRE以外には依存しない
    • 依存ライブラリがJavaのバージョンに追随しないリスクを避ける
    • 依存ライブラリが他のライブラリと競合するリスクを避ける

  • 実行環境に依存しがちなところはインタフェースで実装を差し替えられるように
    • 例えば、クラスローディング周り
      • Play Framework v1
      • Spring Boot DevTools

  • バイトコードをハックしない
    • 同じ注釈処理をするライブラリでもLombokとは違うところ
    • Domaは将来のJavaでもほぼそのまま動作するはず

9. 変化(トレンド)に追随する

  • Java 8対応
    • Stream
    • Optional
    • JSR310 Date & Time API

  • Kotlin対応(実験的)
@Entity(immutable = true)
data class Person(
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  val id: Int? = null,
  val name: String,
  val age: Int,
  @Version
  val version: Int = -1)

10. 利用者の声を聞く

  • 自分が考えた機能は2010年時点でほぼ実装完了
    • それ以降の機能追加は利用者の意見が中心

http://d.hatena.ne.jp/taedium/20101002/p2


  • 利用者の声は宝の山
    • そんな使い方があったとは!という良い意味での発見が多い
    • 7年も続けられている理由の1つ

Twitterのつぶやき


Twitterでメンション


Gitterへの書き込み

https://gitter.im/domaframework/doma?at=56dd0db91263673835717662


もちろんPull Requestも

https://github.com/domaframework/doma/pull/71


疑問や要望はいつでもWelcome

  • できるだけ応えたい
  • 面白いアイデアに発展するかも?

ぜひ使ってみてください


Domaの開発で大切にしている10のこと

  1. 動かさないとわからないを減らす
  2. コードの信頼性を高める
  3. シンプルさを重視する
  4. SQLの発行場所とタイミングを明確にする
  5. SQLの完全性を重視する
  6. JDBCでできることを制限しない
  7. 逃げ道を用意する
  8. 様々な環境で長期的に使えるようにする
  9. 変化(トレンド)に追随する
  10. 利用者の声を聞く

追記(2020年5月30日)

このスライドの中で「例えばCriteria APIは提供しない」と書きましたが、2020年5月、Doma 2にCriteria APIを導入することにしました(2.35.0で正式リリース)。

ひと言で言えば当時と状況が変わったからということになりますが、細かい理由は次のようなものです。


Criteria API導入の理由 1

  • SQLファイル内の大部分が条件分岐だらけになっているようなプロジェクトを度々見かけるが、非効率かつ保守性に難がある。そのようなケースではJavaでSQLを組み立てた方が適切である。

Criteria API導入の理由 2

  • Javaの複数のORMを併用する事例を見かけるが、個人的にはオーバーヘッドだと思うのでできるだけ1つのORMで済むようにしたい(Domaが機能不足であれば補いたい)

Criteria API導入の理由 3

  • GraalVMを使ってNative Imageにするためにはリフレクションに制約がかかるケースがある。SQLファイル内の式コメントはリフレクションに頼っているが、リフレクションを使わないで動的SQLを組み立てる手段を提供したい。

Criteria API導入の理由 4

  • コンパイル時(Annotation Processingの最中)にファイルを読むのは環境(ビルドツールやIDE)依存の部分がありハマりポイントになっている。できればこのハマりポイントを回避したい。Criteria APIが主流になればファイルを読むのは実行時だけにしてコンパイル時に読むのは止めてもいい(オプションにするなど)と思っている。

Criteria API導入の理由 5

  • Doma 1を作り始めた当時はJava 6がリリースされたばかりであり言語の制約上使いやすいCriteria APIを作ることができなかった。しかしJava 8で導入されたラムダ式を使えば使いやすいAPIを構築可能に思われた。

Criteria API導入の理由 6

  • Domaが関連をサポートしていないので使えないとか古いなどと言われるのがちょっと癪なので :smile:

参考情報

nakamura-to
プログラミング言語の特徴を生かしてデータベースアクセスを簡単にするためのライブラリを書くのが好き。これまで、Java、Kotlin、C#、F#、JavaScriptなどで実装経験がある。
isid
電通国際情報サービス(Information Services International-Dentsu, Ltd. 通称ISID)は、アメリカのGE社と電通の合弁会社として創業しました。 2000年に東証一部上場し、現在は単体で社員数約1,500人の会社です。ISIDにおける先端技術を活用した挑戦と事例、 検証した技術などを紹介します。
https://www.isid.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away