2. Who am I ?
• Yoshitaka Fujii
• @yoshiyoshifujii
• Joined MOTEX in April, 2014
• Web Application Engineer
• Scala (7 months)
Java, Python
自己紹介。エムオーテックス株式会社。Scala歴7ヶ月。
5. We are looking for
a Scala of Engineers !!
Scalaエンジニア募集中!!
23. Point of Layered Architecture
1. To clarify the responsibilities of the layer
2. Depends only on the lower layer
3. Isolating the Domain
レイヤーの責務を明確にすること。下位レイヤーだけに依存す
ること。ドメインを隔離すること。
24. User Interface Layer
• Showing information to the user.
• Interpreting the user’s commands.
• The external actor might sometimes be
another computer system rather than a
human user.
ユーザに情報を表示する。ユーザからのコマンドを解釈する。
外部アクタは別のコンピュータシステムのこともある。
25. Application Layer
• Defines the jobs the software.
• Directs the expressive domain objects to work
our problems.
• This layer is kept thin.
• It does not contain business rules or
knowledge.
ソフトウェアの仕事を定義、ドメインオブジェクの問題解決を
導く。薄く保つ。ビジネスルールや知識を含まない。
26. Domain Layer
• Concepts of the business.
• Information about the business solution.
• Business rules.
• This layer is the beat of business software.
ビジネスの概念。ビジネスが置かれた状況に関する情報。ビジ
ネスルール。ビジネスソフトウェアの核心。
27. Infrastructure Layer
• Provides generic technical capabilities that
support the higher layers.
• Message sending for the application.
• Persistence for the domain.
• Drawing widgets for the UI
上位レイヤを支える技術的機能を提供。Applicationのための
メッセージ送信。Domainのための永続化。UIの描画。
34. ViewModel
• Synonymous with the MVVM pattern
• Holding a state for drawing a view.
• Form => Application => Domain
MVVMパターンのViewModelと同義。Viewを描画するための
状態の保持。UI=>Application=>Domainと受け渡す。
35. case class XxxForm(email: String, name: String)
case class XxxViewModel(email: String, name: String)
def convertForm2ViewModel(form: XxxForm):
XxxViewModel =
XxxViewModel(
form.email,
form.name)
36. User Interface Application Domain Infrastructure
ViewModelForm Entity
Record
SQL
JSON Entity
Result Set
ViewModel
37. User Interface Application Domain Infrastructure
ViewModelForm Entity
Record
SQL
JSON Entity
Result Set
ViewModel
Form =>
ViewModel
ViewModel
=> Entity
Entity => SQL
38. User Interface Application Domain Infrastructure
ViewModelForm Entity
Record
SQL
JSON Entity
Result Set
ViewModel
Form =>
ViewModel
ViewModel
=> Entity
Entity => SQL
ResultSet =>
Record
Record =>
Entity
Entity =>
ViewModel
ViewModel
=> JSON
62. Responsibility of Service
• Once, approach to Application Service.
• Temporarily forgive the outflow of Domain
logic.
• Repeat to consider refactoring.
Application Serviceに寄せる。Domainロジックの流出を一時
的に許容。Refactoringを繰り返し検討。
80. CQRS
• CQRS stands for
Command Query Responsibility Segregation
• First proposed by Greg Young
• Martin Fowler
http://martinfowler.com/bliki/CQRS.html
Greg Youngが提唱したのをMartin Fowlerがブログで紹介し
た。
81. About CQRS
• CQS (Command query separation)
• It states that every method should either be a
command that performs an action
• or a query that returns data to the caller
• but not both
あらゆるメソッドは、「コマンド」もしくは「クエリ」のいず
れか一方で、その両方はダメ。
89. User Interface Application Domain Infrastructure
ViewModelForm
Record
SQL
JSON
Result SetForm =>
ViewModel
ViewModel
=> SQL
ResultSet =>
Record
QueryModel
=> JSON
Record =>
QueryModel
QueryModel
90. Query Model
• Query Model into the Infrastructure Layer
• Application Layer direct connection to
Infrastructure Layer
• Result Set => Record => Query Model
• Query Model is returned to User Interface
Layer
Infrastructure層にQuery Modelを作る。 Application層から直接
Infrastructure層。 Query ModelはUser Interface層まで持ち込みOK!!
95. Command tends to be
smaller than Query
Command Modelがシステムの占める割合は少なめ
96. Summary of CQRS
• Simple retrieval process is separated into
queries.
• Direct connection to the Infrastructure Layer.
• Simple things made simply.
単純な取得処理はクエリとして分離。直接インフラ層にアクセ
ス。シンプルなものはシンプルに作る。
111. trait RootEntity {
val id: Option[Long]
val name: String
}
case class Sub1(
id: Option[Long], name: String)
extends RootEntity
case class Sub2(
id: Option[Long], name: String)
extends RootEntity
123. Summary of is-a Root Entity
• Service specifying the children
• To clarify the hierarchy
• It eliminates redundant processing
Serviceが子を知っているパターンを採用
133. Option
• Some or None. Why None ?
• None is Exception
• Exception is Exception
SomeかNoneで、なぜNoneか分からない。Noneがそもそも
異常なこともある。その場合は例外にしたい。
134. Either
• Left or Right. Left is error message.
• Monad (salaz)
• Single message only
Left or RightでLeftにメッセージが詰められる。Monadなコ
ーディング可能。ただしメッセージは1つ。
135. Try
• Define the type of Exception
• Simple error handling
• Throw to the higher layer
例外の型を定義。throw形式でエラー時の制御が容易。処理を
中断し上位のレイヤーまで到達可能。
136. Validation (Scalaz)
• Return the stack error
• But not Monad
• not be used in for-yield
• Applicative
エラーを詰めて返すことが可能。Monadではない。for式で使
えない。Applicative。
142. sealed abstract class Validation[+E, +A]
final case class Success[A](a: A)
extends Validation[Nothing, A]
final case class Failure[E](e: E)
extends Validation[E, Nothing]
143. def ap[EE >: E, B](x: => Validation[EE, A => B])
(implicit E: Semigroup[EE]): Validation[EE, B] = (this, x)
match {
case (Success(a), Success(f)) => Success(f(a))
case (e @ Failure(_), Success(_)) => e
case (Success(f), e @ Failure(_)) => e
case (Failure(e1), Failure(e2)) => Failure(E.append(e2, e1))
}
144. case class Person(name: String, age: Int)
def validateName(name: String) =
if (name.length > 1) name.successNel
else "invalid name".failureNel
def validateAge(age: Int) =
if (age >= 0) age.successNel
else "invalid age".failureNel
146. Summary of Message
• Unrecoverable exception
• Domain Layer return a message to screen
• Validation or Try or Either
復旧不可能な例外もあるが、ドメイン層から何らかのメッセー
ジを返したいとき、ValidationとTry(or Either)を使い分け。