SlideShare una empresa de Scribd logo
1 de 65
Descargar para leer sin conexión
Scala with DDD
かとじゅん(@j5ik2o)
Scalaで実践的な設計の話
自己紹介
•

DDD/Scala/Finagle

•

http://git.io/trinity

•

Haskell/MH4
Scalaで実践的な設計の話
 じゃなくてMH4の話…。
設計には様々な正解があります。
DDDの実践例のひとつだと
思ってください。
ところで
ウェブアプリケーション
を作るときに、
何を重視して設計するか?
テーブル?
UI?
DDDでは(ドメイン)モデル
なんで?
詳しくはこちら?
というのは、
冗談です
モデルオブジェクト(=オ
ブジェクト指向)を使っ
て、問題を解決したいか
らです。
複雑な問題は
モデルを使って
解決する
I/F

Domain
Model
問題の領域=
ドメイン
ボクらのハンタードメイン
Hunter

Item

Monster

Sword

Armor
ハンター世界の
一つのシナリオを
考えてみよう
落とし物を拾うシーン
HUNTER_LOST_MATTER
テーブルに
外部キーの関連を追加する
HUNTER

1

0..*

HUNTER_LOST_MATTER 1

1 LOST_MATTER
これは間違いではない。
しかし実装の用語であって
ドメインの知識を
表していない
ハンターが落とし物を拾い、
アイテムとして所持する。
Hunter

1

0..*

LostMatter

trait	
  Item	
  
trait	
  LostMatter	
  extends	
  Item	
  
trait	
  Hunter	
  {	
  
	
  	
  val	
  items:	
  Seq[Item]	
  
	
  	
  def	
  take(lostMatter:	
  LostMatter):	
  Try[Hunter]	
  
}
ドメインの語彙=
ユビキタス言語
シナリオ

実装

モデル
他にもシナリオがある
•

モデル間の関係がどうなるのか考える
•

乗り攻撃のシーン

•

しっぽを切り落とすシーン
DDDによるレイヤー化
UI

Controller
Form

Dto(ViewModel)

Validator
JavaScript

HMTL/CSS

アプリケーション層
Factory

Entity

ドメインの概念

ValueObject

ドメイン層

Repository

Service

Module

Aggregate

インフラストラクチャ層
Configuration

RPC

ORM

DataAccess
モデルと実装
モデルの種類
エンティティ
値オブジェクト
サービス

モジュール
エンティティ

•

見分けることができる

•

不変の識別子を持つ
trait	
  Entity[ID	
  <:	
  Identity[_]]	
  {	
  
!

	
  	
  /**	
  エンティティの識別子。	
  */	
  
	
  	
  val	
  identity:	
  ID	
  
!

	
  	
  override	
  final	
  def	
  hashCode:	
  Int	
  =	
  
	
  	
  	
  	
  31	
  *	
  identity.##	
  
!

	
  	
  override	
  final	
  def	
  equals(obj:	
  Any):	
  Boolean	
  =	
  	
  
	
  	
  	
  	
  obj	
  match	
  {	
  
	
  	
  	
  	
  	
  	
  case	
  that:	
  Entity[_]	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  identity	
  ==	
  that.identity	
  
	
  	
  	
  	
  case	
  _	
  =>	
  false	
  
	
  	
  }	
  
!

}
trait	
  Identity[+A]	
  extends	
  Serializable	
  {	
  
!

	
  	
  def	
  value:	
  A	
  
!

}	
  
!

object	
  EmptyIdentity	
  
	
  	
  extends	
  Identity[Nothing]	
  {	
  
!

	
  	
  def	
  value	
  =	
  throw	
  EmptyIdentityException()	
  
!

	
  	
  override	
  def	
  equals(obj:	
  Any):	
  Boolean	
  =	
  
	
  	
  	
  	
  EmptyIdentity	
  eq	
  obj	
  
!

	
  	
  override	
  def	
  hashCode():	
  Int	
  =	
  31	
  *	
  1	
  
!

	
  	
  override	
  def	
  toString	
  =	
  "EmptyIdentity"	
  
}
case	
  class	
  User(id:	
  Int,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  firstName:	
  String,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  lastName:	
  String)	
  
!

val	
  l	
  =	
  List(	
  
	
  	
  User(1,	
  "Yutaka",	
  “Yamashiro"),	
  
	
  	
  User(2,	
  "Junchi",	
  “Kato")	
  
)	
  
l.exists(_	
  ==	
  User(1,	
  "Yutaka",	
  "Yamashiro"))	
  //	
  true
//	
  値表現としての山城さんが改名されてしまったら見分けられない	
  
val	
  l	
  =	
  List(	
  
	
  	
  User(1,	
  "Yutaka",	
  “Yamashiro").	
  
	
  	
  	
  	
  copy(lastName	
  =	
  “Hogeshiro"),	
  
	
  	
  User(2,	
  "Junchi",	
  "Kato"))	
  
l.exists(_	
  ==	
  User(1,	
  "Yutaka",	
  "Yamashiro"))	
  //	
  false	
  
!

//	
  この操作は危険。オブジェクトを取り違える可能性。	
  
User(1,	
  "Yutaka",	
  "Yamashiro").copy(id	
  =	
  2)
class	
  User(val	
  id:	
  Int,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  val	
  firstName:	
  String,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  val	
  lastName:	
  String)	
  {	
  
	
  	
  	
  override	
  def	
  equals(obj:	
  Any):	
  Boolean	
  =	
  obj	
  match	
  {	
  
	
  	
  	
  	
  	
  case	
  that:	
  User	
  =>	
  id	
  ==	
  that.id	
  
	
  	
  	
  	
  	
  case	
  _	
  =>	
  false	
  
	
  	
  	
  }	
  
	
  	
  	
  override	
  def	
  hashCode	
  =	
  31	
  *	
  id.##	
  
	
  	
  	
  //	
  識別子は更新できない	
  
	
  	
  	
  def	
  copy(firstName:	
  String	
  =	
  this.firstName,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  lastName:	
  String	
  =	
  this.lastName)	
  =	
  	
  
	
  	
  	
  	
  	
  new	
  User(firstName,	
  lastName)	
  
}	
  
object	
  User	
  {	
  
	
  	
  def	
  apply(…):	
  User	
  =	
  …	
  	
  
}
//	
  	
  見つけられる	
  
val	
  l	
  =	
  List(	
  
	
  	
  User(1,	
  "Yutaka",	
  "Hogeshiro"),	
  
	
  	
  User(2,	
  "Junchi",	
  "Kato"))	
  
l.exists(_	
  ==	
  User(1,	
  "Yutaka",	
  "Yamashiro"))	
  //	
  true
case	
  class	
  HunterId(value:	
  UUID)	
  
	
  	
  extends	
  Identity[UUID]	
  
!

class	
  Hunter(	
  
	
  	
  val	
  identity:	
  HunterId,	
  
	
  	
  val	
  name:	
  String,	
  
	
  	
  val	
  rank:	
  Int,	
  
	
  	
  //	
  ...	
  
)	
  extends	
  Entity[HunterId]	
  {	
  
	
  	
  //	
  ...	
  
}
値オブジェクト
•

識別はしない。

•

値の説明が目的。

•

原則的に不変オブジェクト。

•

Identityは値オブジェクト。
sealed	
  trait	
  Item	
  {	
  
	
  	
  val	
  name:	
  String	
  
	
  	
  def	
  beUsedBy(hunter:	
  Hunter):	
  Try[Hunter]	
  
}	
  
case	
  class	
  Analepticum()	
  extends	
  Item	
  {	
  
	
  	
  val	
  name	
  =	
  "analepticum"	
  
	
  	
  def	
  beUsedBy(hunter:	
  Hunter):	
  Try[Hunter]	
  =	
  {	
  
	
  	
  	
  	
  //	
  hunterを回復させる	
  
	
  	
  }	
  
}	
  
case	
  class	
  Antidote()	
  extends	
  Item	
  {	
  
	
  	
  val	
  name	
  =	
  "antidote"	
  
	
  	
  def	
  beUsedBy(hunter:	
  Hunter):	
  Try[Hunter]	
  =	
  {	
  
	
  	
  	
  	
  //	
  hunterを解毒させる	
  
	
  	
  }	
  
}
class	
  Hunter(	
  
	
  	
  val	
  identity:	
  HunterId,	
  
	
  	
  val	
  name:	
  String,	
  
	
  	
  val	
  rank:	
  Int,	
  
	
  	
  val	
  items:	
  Set[Item]	
  
)	
  extends	
  Entity[HunterId]	
  {	
  
!

	
  	
  def	
  use(item:	
  Item):	
  Try[Hunter]	
  =	
  {	
  
	
  	
  	
  	
  	
  require(items.exists(_	
  ==	
  item))	
  
	
  	
  	
  	
  	
  item.beUsedBy(hunter)	
  
	
  	
  }	
  
!

}
ドメインモデルはユビキ
タス言語と対応づくこと
(クラス名, 属性, 振舞い)
指定席と自由席
•

座席予約システムの場合
•

座席と参加者はエンティティ。各
チケットに座席番号が紐づくから

•

イベント自体が自由席でチケット
を持っていればどこでもよいなら
エンティティである必要はない。
個数だけ把握できればいいので、
値オブジェクトとなる。
ライフサイクルの管理
ライフサイクル管理
ファクトリ

リポジトリ
集約
リポジトリ
•

エンティティをリポジトリに
保存したり、識別子からエン
ティティを取得できる。

•

ドメインの知識は表現しない
で、I/Oだけを担当する。

•

内部で何をしていても、外部
からはコレクションのように
見える。
よくある勘違い
•

DDDにおいては、User#saveはドメイン
モデルの責務じゃない。ユビキタス言語
に対応する言葉がないから。これはリポ
ジトリの責務。

•

ARのようなモデルはドメインモデルとせ
ずに、インフラストラクチャ層のモデル
と定義した方が現実的。
Repository

DAO

Repository

on Memory on Memcached

on DB

DAO

on API
どんなI/Fがあるか
def	
  resolve(identity:	
  ID)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Future[E]	
  
!

def	
  store(entity:	
  E)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Future[(R,	
  E)]	
  
!

def	
  delete(identity:	
  ID)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Future[(R,	
  E)]	
  
!

def	
  resolveChunk(index:	
  Int,	
  maxEntities:	
  Int)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Future[EntitiesChunk[ID,	
  E]]	
  
!

//	
  toList,	
  toSetは	
  メモリ版の実装のみ。	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
def	
  toList:	
  Future[List[E]]	
  
def	
  toSet:	
  Future[Set[E]]
Cache Management
Repository
Decorator

on Memcached

on DB
!

	
  	
  protected	
  val	
  storage:	
  AsyncRepository[ID,	
  E]	
  
!

	
  	
  protected	
  val	
  cache:	
  AsyncRepository[ID,	
  E]	
  
!

	
  	
  def	
  resolve(identity:	
  ID)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):

	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Future[E]	
  =	
  {	
  
	
  	
  	
  	
  implicit	
  val	
  executor	
  =	
  getExecutionContext(ctx)	
  
	
  	
  	
  	
  cache.resolve(identity).recoverWith	
  {	
  
	
  	
  	
  	
  	
  	
  case	
  ex:	
  EntityNotFoundException	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  for	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entity	
  <-­‐	
  storage.resolve(identity)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (_,	
  result)	
  <-­‐	
  cache.store(entity)	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  yield	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  result	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
	
  	
  }
def	
  filterByPredicate(predicate:	
  E	
  =>	
  Boolean,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  index:	
  Option[Int]	
  =	
  None,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  maxEntities:	
  Option[Int]	
  =	
  None)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Future[EntitiesChunk[ID,	
  E]]	
  
!

def	
  filterByCriteria(criteria:	
  Criteria,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  index:	
  Option[Int]	
  =	
  None,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  maxEntities:	
  Option[Int]	
  =	
  None)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Future[EntitiesChunk[ID,	
  E]]	
  
!

trait	
  CriteriaValue[A]	
  {	
  
	
  	
  val	
  name:	
  String	
  
	
  	
  val	
  operator:	
  OperatorType.Value	
  
	
  	
  val	
  value:	
  A	
  
	
  	
  def	
  asString:	
  String	
  
}	
  
!

trait	
  Criteria	
  {	
  
	
  	
  protected	
  val	
  criteriaValues:	
  List[CriteriaValue[_]]	
  
	
  	
  def	
  asString:	
  String	
  
}
val	
  repository:	
  HunterRepository	
  =	
  
HunterRepository(RepositoryType.Memory)	
  
//	
  or	
  RepositoryType.Memcached	
  
!

val	
  hunter	
  =	
  new	
  Hunter(EmptyIdentity,	
  ...)	
  
!

val	
  updateTime	
  =	
  for	
  {	
  
	
  	
  (newRepos,	
  newEntity)	
  <-­‐	
  repository.store(hunter)	
  
//	
  def	
  store(entity:	
  E):	
  Try[(R,	
  E)]	
  
	
  	
  hunter	
  <-­‐	
  newRepos.resolve(newEntity.identity)	
  
//	
  def	
  resolve(identity:	
  ID):	
  Try[E]	
  
}	
  yield	
  {	
  
	
  	
  hunter.updateTime	
  
}
val	
  repository:	
  HunterRepository	
  =	
  	
  
	
  	
  HunterRepository(RepositoryType.JDBC)	
  
!

val	
  hunter	
  =	
  new	
  Hunter(EmptyIdentity,	
  ...)	
  
!

//	
  def	
  withTransaction[T](f:	
  (DBSession)	
  =>	
  T):	
  T	
  
val	
  updateTime	
  =	
  UnitOfWork.withTransaction	
  {	
  
	
  	
  tx	
  =>	
  
	
  	
  	
  	
  implicit	
  ctx	
  =	
  EntityIOContext(tx)	
  
	
  	
  	
  	
  for	
  {	
  
	
  	
  	
  	
  	
  	
  (newRepos,	
  newEntity)	
  <-­‐	
  repository.store(hunter)	
  
//	
  def	
  store(entity:	
  E)	
  
//	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Try[(R,	
  E)]	
  
	
  	
  	
  	
  	
  	
  hunter	
  <-­‐	
  newRepos.resolve(newEntity.identity)	
  
//	
  def	
  resolve(identity:	
  ID)	
  
//	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Try[E]	
  
	
  	
  	
  	
  }	
  yield	
  {	
  
	
  	
  	
  	
  	
  	
  hunter.updateTime	
  
	
  	
  	
  	
  }	
  
}
ScalikeJDBCで
UnitOfWorkを実装
val	
  repository:	
  HunterRepository	
  =	
  	
  
	
  	
  HunterRepository(RepositoryType.JDBC)	
  
!

val	
  hunter	
  =	
  new	
  Hunter(EmptyIdentity,	
  ...)	
  
!

//	
  def	
  withTransaction[T](f:	
  (DBSession)	
  =>	
  Future[T]):	
  Future[T]	
  
val	
  updateTime	
  =	
  UnitOfWork.withTransaction	
  {	
  
	
  	
  tx	
  =>	
  
	
  	
  	
  	
  implicit	
  ctx	
  =	
  EntityIOContext(tx)	
  
	
  	
  	
  	
  for	
  {	
  
	
  	
  	
  	
  	
  	
  (newRepos,	
  newEntity)	
  <-­‐	
  repository.store(hunter)	
  
//	
  def	
  store(entity:	
  E)	
  
//	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Future[(R,	
  E)]	
  
	
  	
  	
  	
  	
  	
  hunter	
  <-­‐	
  newRepos.resolve(newEntity.identity)	
  
//	
  def	
  resolve(identity:	
  ID)	
  
//	
  	
  	
  	
  	
  (implicit	
  ctx:	
  EntityIOContext):	
  Future[E]	
  
	
  	
  	
  	
  }	
  yield	
  {	
  
	
  	
  	
  	
  	
  	
  hunter.updateTime	
  
	
  	
  	
  	
  }	
  
}
 	
  def	
  withTransaction[A](op:	
  (DBSession)	
  =>	
  Future[A])	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (implicit	
  executor:	
  ExecutionContext):	
  Future[A]	
  =	
  {	
  
	
  	
  	
  	
  Future(ConnectionPool.borrow()).flatMap	
  {	
  
	
  	
  	
  	
  	
  	
  connection	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  val	
  db	
  =	
  DB(connection)	
  
	
  	
  	
  	
  	
  	
  	
  	
  Future(db.newTx).flatMap	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  tx	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Future(tx.begin()).flatMap	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  op(db.withinTxSession(tx))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }.andThen	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  Success(_)	
  =>	
  tx.commit()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  Failure(_)	
  =>	
  tx.rollback()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }.andThen	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  _	
  =>	
  connection.close()	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
	
  	
  }
REST APIで
ドメインの利用例
class	
  HunterController(hunterRepository:	
  HunterRepository)	
  	
  
	
  	
  extends	
  ControllerSupport	
  {	
  
	
  	
  def	
  createHunter	
  =	
  SimpleAction	
  {	
  
	
  	
  	
  	
  request	
  =>	
  
	
  	
  	
  	
  	
  	
  val	
  params	
  =	
  parseJson(request)	
  
	
  	
  	
  	
  	
  	
  val	
  formValidation	
  =	
  CreateForm.validate(params)	
  
	
  	
  	
  	
  	
  	
  formValidation.fold(validationErrorHandler,	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  case	
  form	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  UnitOfWork.withSession	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  implicit	
  session	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  hunterRepository.	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  store(form.asEntity).flatMap	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  (_,	
  entity)	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  responseBuilder.	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  withJValue(entity.asJValue).toFuture	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  })	
  
	
  	
  }	
  
}
class	
  HunterController(hunterRepository:	
  HunterRepository)	
  	
  
	
  	
  extends	
  ControllerSupport	
  {	
  
	
  	
  def	
  transferItems(from:	
  HunterId,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  to:	
  HunterId,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  itmes:	
  Seq[Item])	
  =	
  SimpleAction	
  {	
  
	
  	
  	
  	
  request	
  =>	
  
	
  	
  	
  	
  	
  	
  UnitOfWork.withSession	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  implicit	
  session	
  =>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  toHunter	
  <-­‐	
  hunterRepository.resolve(to)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  fromHunter	
  <-­‐	
  hunterRepository.resolve(from)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _	
  <-­‐	
  fromHunter.transerItems(items,	
  toHunter)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  yield	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  createResponse()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  }	
  
	
  	
  }	
  
}
やってみて思ったこと
DDDでは
フルスタックF/Wが
使いにくい
Play2 with DDD
Controller

Batch or ???

Entity
VO

Domain
Repository

Service

ScalikeJDBC

Anorm

Play2
まとめ
•

コストがかかる。複雑でない問題には使わない。

•

CoCを前提にするF/Wとは相性が悪い。F/Wとけん
かしない方法を選ぶべき。

•

OOPよりデータと手続きの方が高速。とはいえ、オ
ブジェクトを使いますよね。高速化必須な場合は局所
的に手続き型にする。
ありがとございました。

Más contenido relacionado

La actualidad más candente

20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swiftnecocen
 
Monadicプログラミング マニアックス
Monadicプログラミング マニアックスMonadicプログラミング マニアックス
Monadicプログラミング マニアックスTomoharu ASAMI
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lensNaoki Aoyama
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語るAkira Takahashi
 
Javaデザインパターン入門【第3回】
Javaデザインパターン入門【第3回】Javaデザインパターン入門【第3回】
Javaデザインパターン入門【第3回】Yukiko Kato
 
JastAdd & JastAddJ クリックチュートリアル
JastAdd & JastAddJ クリックチュートリアルJastAdd & JastAddJ クリックチュートリアル
JastAdd & JastAddJ クリックチュートリアルFuminobu Takeyama
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタートShumpei Shiraishi
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~Fujio Kojima
 
怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01nagachika t
 
Chapter 6: Computing on the language (R Language Definition)
Chapter 6: Computing on the language (R Language Definition)Chapter 6: Computing on the language (R Language Definition)
Chapter 6: Computing on the language (R Language Definition)Nagi Teramo
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?Kenji Nakamura
 
What Dotty fixes @ Scala関西サミット
What Dotty fixes @ Scala関西サミットWhat Dotty fixes @ Scala関西サミット
What Dotty fixes @ Scala関西サミットTaisuke Oe
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説JPCERT Coordination Center
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎Kenji Otsuka
 
Active Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorActive Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorMichio Koyama
 

La actualidad más candente (20)

20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift
 
Monadicプログラミング マニアックス
Monadicプログラミング マニアックスMonadicプログラミング マニアックス
Monadicプログラミング マニアックス
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lens
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語る
 
Javaデザインパターン入門【第3回】
Javaデザインパターン入門【第3回】Javaデザインパターン入門【第3回】
Javaデザインパターン入門【第3回】
 
JastAdd & JastAddJ クリックチュートリアル
JastAdd & JastAddJ クリックチュートリアルJastAdd & JastAddJ クリックチュートリアル
JastAdd & JastAddJ クリックチュートリアル
 
講座Java入門
講座Java入門講座Java入門
講座Java入門
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタート
 
Introduction Xtend
Introduction XtendIntroduction Xtend
Introduction Xtend
 
C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~C# LINQ ~深く知って、使いまくろう~
C# LINQ ~深く知って、使いまくろう~
 
怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01怠惰なRubyistへの道 fukuoka rubykaigi01
怠惰なRubyistへの道 fukuoka rubykaigi01
 
Chapter 6: Computing on the language (R Language Definition)
Chapter 6: Computing on the language (R Language Definition)Chapter 6: Computing on the language (R Language Definition)
Chapter 6: Computing on the language (R Language Definition)
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?
 
What Dotty fixes @ Scala関西サミット
What Dotty fixes @ Scala関西サミットWhat Dotty fixes @ Scala関西サミット
What Dotty fixes @ Scala関西サミット
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎
 
Active Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorActive Directoryデータの Security Descriptor
Active Directoryデータの Security Descriptor
 

Similar a Scala with DDD

C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~Fujio Kojima
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
Active Directoryデータのプロパティ出力(Output Properties)
Active Directoryデータのプロパティ出力(Output Properties)Active Directoryデータのプロパティ出力(Output Properties)
Active Directoryデータのプロパティ出力(Output Properties)Michio Koyama
 
J qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているかJ qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているかHisashi Aruji
 
Java x Groovy: improve your java development life
Java x Groovy: improve your java development lifeJava x Groovy: improve your java development life
Java x Groovy: improve your java development lifeUehara Junji
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swiftYuki Asai
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swiftYuki Asai
 
Active Directoryデータの "大きい整数"
Active Directoryデータの "大きい整数"Active Directoryデータの "大きい整数"
Active Directoryデータの "大きい整数"Michio Koyama
 
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」fukuoka.ex
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.specKent Ohashi
 
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミングJavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミングKent Ohashi
 
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングkunihikokaneko1
 
PHPerのためのSwift入門
PHPerのためのSwift入門PHPerのためのSwift入門
PHPerのためのSwift入門Tomoki Hasegawa
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書くHideyuki Tanaka
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと Haruka Ozaki
 

Similar a Scala with DDD (20)

C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
Active Directoryデータのプロパティ出力(Output Properties)
Active Directoryデータのプロパティ出力(Output Properties)Active Directoryデータのプロパティ出力(Output Properties)
Active Directoryデータのプロパティ出力(Output Properties)
 
J qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているかJ qmobiはjqueryから軽量化しているか
J qmobiはjqueryから軽量化しているか
 
Java x Groovy: improve your java development life
Java x Groovy: improve your java development lifeJava x Groovy: improve your java development life
Java x Groovy: improve your java development life
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
 
Active Directoryデータの "大きい整数"
Active Directoryデータの "大きい整数"Active Directoryデータの "大きい整数"
Active Directoryデータの "大きい整数"
 
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
 
Teclab3
Teclab3Teclab3
Teclab3
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
boost tour 1.48.0 all
boost tour 1.48.0 allboost tour 1.48.0 all
boost tour 1.48.0 all
 
OSC京都2011
OSC京都2011OSC京都2011
OSC京都2011
 
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミングJavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
JavaからScala、そしてClojureへ: 実務で活きる関数型プログラミング
 
Swiftおさらい
SwiftおさらいSwiftおさらい
Swiftおさらい
 
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
 
PHPerのためのSwift入門
PHPerのためのSwift入門PHPerのためのSwift入門
PHPerのためのSwift入門
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書く
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
 

Último

【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 

Último (9)

【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 

Scala with DDD