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

  • 79
    いいね
  • 0
    コメント

自己紹介


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. 利用者の声を聞く