Slide 1

Slide 1 text

麊欽׾竲ֽגְֻ׋׭ך 4DBMBך剅ֹ倯 2018/11/29ɹscala.rookies#1

Slide 2

Slide 2 text

㣐銮姻䛾 (Tadayuki Onishi) Software Engineer Twitter: @kenchan0130 Blog: kenchan0130.github.io 荈䊹稱➜

Slide 3

Slide 3 text

痥♧珏ꆃ輐㉀ㅷ《䒷噟罏䎃։ 䎃剢ח鏣甧 䖞噟㆞秈せ䎃剢植㖈 ؿؓٔؔIUUQTGPMJPTFDDPNך؟٦ؽأ׾䲿⣘

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

'0-*0דך4DBMB 5ISJGU"1*4FSWFS"QQMJDBUJPO )5513&45"1*4FSWFS "QQMJDBUJPO #BUDI"QQMJDBUJPO 1VC4VC欽%FNPO"QQMJDBUJPO

Slide 6

Slide 6 text

'0-*0דך4DBMB 4DBMB੡ͷϚΠΫϩαʔϏε 䎃剢Ĕ晛ٔٔ٦أ 䎃剢劤ٔٔ٦أ

Slide 7

Slide 7 text

'0-*0דך4DBMB ࣾ಺ϥΠϒϥϦ͸ 20 Ҏ্

Slide 8

Slide 8 text

'0-*0דך4DBMB 圫ղז044ٓ؎ـٓٔח״׏ג 佄ִ׵׸גְ׷

Slide 9

Slide 9 text

'0-*0ה4DBMB؝ىُصذ؍הךꟼ׻׶

Slide 10

Slide 10 text

➙傈鑧ֿׅה '0-*0ד㹋ꥷ麊欽׃ג׫גծ 麊欽את׶ًٝذشٝأ䚍ךぢ♳װغؚך幾㼰׃װְׅ ֮׷玎䏝ך倯ꆙָ鋅ִגֹת׃׋կ ׉ֿד猘⦐➂ה׃גך剅ֹ倯ך倯ꆙ׾稱➜׃גְֹתׅկ

Slide 11

Slide 11 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁ זְ 剅ֹ倯ך倯ꆙ

Slide 12

Slide 12 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁ זְ 剅ֹ倯ך倯ꆙ

Slide 13

Slide 13 text

def hoge(): EitherT[Future, FugaException, Unit] def bar(): OptionT[Future, Entity] ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ def hoge(): Future[Either[FugaException, Unit]] def bar(): Future[Option[Entity]] ྑ͘ͳ͍ͱߟ͍͑ͯΔॻ͖ํ ྑ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 14

Slide 14 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ ٌشسزٓٝأؿؓ٦و٦ָ䗳銲דזְㄎן⳿׃⯋ד׮ꆤ ׵׸ג♶欽䠐חٌشسزٓٝأؿؓ٦و٦ָ⢪׻׸ג׷ 穠卓涸חꟼ侧ꟼ侧׃׋铣׫ב׵ְ؝٦سחז׶ָ׍ 䪔ְָ꬗⦜ד׮♧䏝㢌䳔穠卓׾鵤ׅ ꟼ侧ⰻ鿇דꟗׄג׷ⴓחכ⢪欽׃ג׮圓׻זְ

Slide 15

Slide 15 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁ זְ 剅ֹ倯ך倯ꆙ

Slide 16

Slide 16 text

// val ctx: DataBaseContext // val userId: UserId ctx.transaction { val eitherT = for { repo1Entity <- OptionT (repository1.findEntityBy(userId)).toRight(new RuntimeException("Error")) _ <- EitherT.right(repository2.create(repo1Entity)) } yield () eitherT.run.flatMap { case -\/(_) => Future.exception((new RuntimeException("Error"))) case \/-(a) => Future.value(\/-(a)) } } %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ྑ͘ͳ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 17

Slide 17 text

implicit class OptionToFuture[A](option: Option[A]) { def toFuture(whenNone: => Throwable): Future[A] = option match { case Some(a) => Future.value(a) case None => Future.exception(whenNone) } } ctx.transaction { for { repo1EntityOpt <- repository1.findEntityBy(userId) repo1Entity <- repo1EntityOpt.toFuture(new RuntimeException("Error")) _ <- repository2.create(repo1Entity) } yield () } %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ྑ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 18

Slide 18 text

%#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ 5SBOTBDUJPOך㢳ֻכ⢽㢩׾ك٦أחٗ٦ٕغحָؙ遤 ׻׸׷ֿהָ㢳ְ 稆湫ח⢽㢩׾䫎־׷קֲָ鋅鸐׃ָ״ֻז׷ -FGUך佝縧ח״׷ٗ٦ٕغحؙ׃䘌׸ָ饯ֿ׷〳腉䚍 ׾幾׵ׇ׷

Slide 19

Slide 19 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁ זְ 剅ֹ倯ך倯ꆙ

Slide 20

Slide 20 text

sealed abstract class DbError(val msg: String, e: Throwable) extends RuntimeException(msg, e) case class ConnctionError(cause: Throwable) extends DbException("Connection Error", cause) case class TimeoutError(cause: Throwable) extends DbException("Timeout Error", cause) case class TimeoutError(cause: Throwable) extends DbException("Duplicated Entry Error", cause) @Singleton class ExecuteImpl { def execute(): Future[SchemeModel] = { // It is possible the execute method raise some exceptions of DbCtxError. ctx.execute().map(Right.apply).rescue { case e: DbCtxCancelConnection => Left(ConnctionError(e)) case e: DbCtxTimeout => Left(TimeoutError(e)) case e: DbCtxDuplicatedEntry => Left(TimeoutError(e)) } } } ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ ྑ͘ͳ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 21

Slide 21 text

ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ @Singleton class ExecuteImpl { def execute(): Future[SchemeModel] = ctx.execute() } @Singleton class ExecuteApiController @Inject()(executeImpl: ExecuteImpl) { // It is possible the execute method raise some exceptions of DbCtxError. def run(): Future[Unit] = executeImpl.execute().map(_ => ()) } @Singleton class Endpoint @Inject()(controller: ExecuteApiController) { override val executeApi(): Future[Unit] = { controller.run().rescue { case e: DbCtxError => Future.exception(e) } } } ྑ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 22

Slide 22 text

ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ וֲ׃ג׮3VOUJNFד饯ֿ׏ג׃תֲ׮ךָ֮׷ %#ך״ֲח帾ְٖ؎َ٦ד饯ֿ׷⢽㢩ך㜥さכ㾴׾ת׋ּ䏝ח وحؾָؚٝ䗳銲חז׶撕꧟חז׷ ،فٔ؛٦ءّٝדعٝسٕ׃׋ְ׮ךח穾׶ծ䖓כ㣐劤ךㄎן⳿ ׃⩎דٍؗحثׅ׷הأحׅؗٔ׷ את׶ծ،فٔ؛٦ءّٝך㹋鄲ח꧊⚥דֹ׷

Slide 23

Slide 23 text

ٌشسزٓٝأؿؓ٦و٦׾ז׷ץֻ㢩鿇ח⳿ׁזְ %#זוךزٓٝؠؙءّٝⳢ椚דכ琎噰涸ח⢽㢩׾ちֻ ⶰ⡲欽׾搀椚ח㘗ד邌植׃זְ %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁ זְ 剅ֹ倯ך倯ꆙ

Slide 24

Slide 24 text

// Auto Generated Code case class User(id: Int, name: String) case class UserDetail(phone: String, birthdate: String, sex: Int) // Auto Generated Code @Singleton class UserInternalApiClient { // Auto Generated Code def getUser(): Future[User] = { /** compiled code **/ } def getUserDetail(userId: Int): Future[UserDetail] = { /** compiled code **/ } } @Singleton class ReturningUserDetailUserCase @Inject()(client: UserInternalApiClient) { def run(): Future[UserDetail] = { for { user <- clinet.getUser() userDetail <- client.getUserDetail(user.id) } yield userDetail } } %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁזְ ྑ͘ͳ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 25

Slide 25 text

// Auto Generated Code case class User(id: Int, name: String) case class UserDetail(birthdate: String, sex: Int) // Auto Generated Code @Singleton class UserInternalApiClient { // Auto Generated Code def getUser(): Future[User] = { /** compiled code **/ } def getUserDetail(userId: Int): Future[UserDetail] = { /** compiled code **/ } } %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁזְ ྑ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 26

Slide 26 text

case class MyUser(id: UserId, name: Name, birthdate: Birthdate, sex: Sex) @Singleton class UserInternalApiClientAntiCorruption @Inject()(clinet: UserInternalApiClient) { def getUser(): Future[MyUser] = for { user <- clinet.getUser() detail <- client.getUserDetail(Random.shuffle(idList).head) } yield MyUser( UserId(user.id), Name(user.name), Birthdate(detail.birthdate), Sex(detail.sex) ) } @Singleton class ReturningUserDetailUserCase @Inject()(antiCorruption: UserInternalApiClientAntiCorruption) { def run(): Future[MyUser] = { antiCorruption.getUser() } } %#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁזְ ྑ͍ͱߟ͍͑ͯΔॻ͖ํ

Slide 27

Slide 27 text

%#װ"1*ؙٓ؎،ٝزך鵤⽱⦼ך㘗׾׉ךתת⢪ְ㔐ׁזְ ⢪ֲ䩛岀ח״׏גכ鵤⽱⦼ָ荈⹛欰䧭ׁ׸ג⤑ⵃ׌ָծ%#װ"1*ؙٓ ؎،ٝزזוכ׋׌ךر٦ةا٦أזךדծ䧮ղָ⡲׶׋ְ،فٔ ؛٦ءّٝהכⴽ暟 臰侁꣇姺㾴זו׾䮠׫ծ䧮ղך،فٔ؛٦ءָّٝ欽䠐ׅ׷㘗ח㢌䳔 ׅ׷ֿהד%#װ"1*ך➬圫㢌刿ח䓼ֻז׷ 侧ָ㢳ְהوحؾָؚٝ꬗⦜׌ָծ㛙暕ז،فٔ؛٦ءّٝח鵚בֻ

Slide 28

Slide 28 text

'0-*0ה4DBMBךꟼ׻׶׾稱➜ '0-*0דך麊欽ח״׷濼鋅ַ׵ծ⦐➂涸ח葺ְה 罋ִ׷倯ꆙ׾稱➜ תה׭

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

➰ꐮ

Slide 31

Slide 31 text

ؙٔ٦ٝ،٦ؗذؙثٍך䱰欽 ⣛㶷זוךⵖ秈ָ㟓ִծ㹋鄲ָ侔׵ל׵׆ծ䕵ⶴָ僇然חדֹ׷ ،فٔ؛٦ءّٝךسً؎ٝ׾ؾُ،חדֹ׷ 稢ְַ㹋鄲כ䖓ח׃גِ٦أ؛٦أ׾鎸鶢דֹ׷ ⡲噟ⴓ䬐ָ֮׷玎䏝דֹ׷ سً؎ٝ椚鍑ך׋׭ךٙ٦ؙءّحف׾ث٦يדꟚ⪵ ׉ך➭