Upgrade to Pro — share decks privately, control downloads, hide ads and more …

サマーインターンシップ2019で学生とDDDなScala開発に取り組んだ / Working on DDD and Scala development with students at Summer Internship 2019

yoshiyoshifujii
September 16, 2019

サマーインターンシップ2019で学生とDDDなScala開発に取り組んだ / Working on DDD and Scala development with students at Summer Internship 2019

yoshiyoshifujii

September 16, 2019
Tweet

More Decks by yoshiyoshifujii

Other Decks in Programming

Transcript

  1. サマーインターンシップ
    2019

    学生と
    DDD

    Scala
    開発に取り組んだ
    Scala
    秋祭り
    @yoshiyoshifujii
    1 / 50

    View Slide

  2. タイトルですが、正確には…
    Chatwork
    では、サマーインターンシップを
    今年
    (2019

    )
    、初めて開催しまして、その中
    で、学生の皆さんと、とある
    Web
    アプリケー
    ションを、ドメイン駆動設計 して
    Scala

    開発することに取り組みました。
    になります。
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 2 / 50

    View Slide

  3. その過程で改めて
    ドメイン駆動設計 と
    Scala

    Unlearn (
    学びほぐし
    )
    する機会となりました
    そのあたりをご紹介できればと思います
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 3 / 50

    View Slide

  4. 「まなびほぐし(アンラーン unlearn
    )」というのは、「まなび(learn
    )」のやり直しである。しか
    し、「やり直し」と言っても、これまで学んできた知識や技能を「帳消しにする」などということが
    できるわけはない。「一たす一は二である」という知識を、あえて「なかったことにする」わけには
    いかない。ここはやはり、これまでの「まなび」。通して身に付けてしまっている「型」としての
    「まなびの身体技法(まなび方)」について、それをあらためて問い直し、「解体」して、組み替え
    るということを意味しているのであろう。(『まなびを学ぶ』62
    頁)
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 4 / 50

    View Slide

  5. Yoshitaka Fujii @yoshiyoshifujii
    Chatwork
    株式会社(13
    ヶ月目)
    Scala
    関西 Summit
    スタッフ(4
    年目)
    登壇
    ScalaMatsuri2016
    Scala
    でドメイン駆動設計に真正面から取り組んだ話
    ScalaMatsuri2017
    Serverless Architecture
    をScala
    で構築するぞ
    ScalaMatsuri2019
    実践 Clean Architecture

    自己紹介
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 5 / 50

    View Slide

  6. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 6 / 50

    View Slide

  7. https://2019.scala­kansai.org
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 6 / 50

    View Slide

  8. あじぇんだ
    どんなことしたの?
    Scala
    の教育
    DDD
    とScala
    で開発
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 7 / 50

    View Slide

  9. どんなことしたの
    ?
    講義パート : 1
    週間
    業務パート : 2
    週間
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 8 / 50

    View Slide

  10. 講義パートの目的
    業務パートを過ごすうえで、最低限必要となる知識を伝える
    業務パートを過ごすうえで、初めて聞く単語を、限りなく少くしたい
    「あ、これ、あそこで習った(
    聞いた)
    ことやから、そこから調べれば何とかなる」状態を目指す
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 9 / 50

    View Slide

  11. 講義パートの概要
    ソフトウェア開発の全体像
    要件定義
    設計
    開発・テスト
    配置
    運用
    インフラ
    チーム開発
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 10 / 50

    View Slide

  12. 講義パートの概要
    +
    観点
    ソフトウェア開発の全体像 ←Chatwork
    の開発の全体の流れ
    要件定義 ← RDRA
    をベースとした、かとじゅんによる講義、みっちり2
    時間。贅沢。
    設計 ← DDD
    をベースとした、かとじゅんによる講義、みっちり4
    時間。贅沢。
    開発・テスト ←
    後程、詳細に
    配置 ← Chatwork
    のCI/CD
    を中心に
    運用 ← Chatwork
    の運用を中心に一般的な座学
    インフラ ← Chatwork
    で使うインフラを中心に紹介
    チーム開発 ← Scrum/
    カンバン/
    モブの座学とワークショップ
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 11 / 50

    View Slide

  13. 業務パート
    とあるWeb
    アプリケーションの開発業務
    Scrum /
    カンバン /
    モブワーク などを取り入れたモダンなチーム開発を実践する
    Scrum
    チームの一員となる
    Dev
    チーム (
    インターン生)
    Product Owner (
    社員)
    Scrum Master (
    社員)
    ステークホルダーに、Product Manager (
    社員)
    PM
    が作成した PRD (Product Requirements Document)
    の簡易版をインプットする
    Scrum
    チームで、要件定義、設計、開発、テスト、配置 を目指す
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 12 / 50

    View Slide

  14. Scala
    の教育
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 13 / 50

    View Slide

  15. Scala
    の教育
    ­
    前提
    インターン生は、Scala
    の経験が、 無い
    関数型経験者はいる (OCaml
    、Rust
    、Elm
    など)
    サーバサイドに興味がある
    チーム開発をしてみたい
    Scala
    を業務でどう取り組んでいるのか知りたい
    これを機会にScala
    はじめたいという方々…
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 14 / 50

    View Slide

  16. インターンが始まるまでに1
    ヶ月弱
    何か、事前に学んできていただく必要がある
    実践Scala
    入門をプレゼント
    可能な限り読んできてね!分からないところあったら聞いてね!
    Using Akka HTTP
    https://doc.akka.io/docs/akka­
    http/10.1.9/introduction.html#using­akka­http
    分からないところあったら聞いてね!
    Scala
    の教育
    ­
    事前
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 15 / 50

    View Slide

  17. インターンが始まるまでに1
    ヶ月弱
    何か、事前に学んできていただく必要がある
    実践Scala
    入門をプレゼント
    可能な限り読んできてね!分からないところあったら聞いてね!
    Using Akka HTTP
    https://doc.akka.io/docs/akka­
    http/10.1.9/introduction.html#using­akka­http
    分からないところあったら聞いてね!
    ノーリアクションで…
    不安…
    Scala
    の教育
    ­
    事前
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 16 / 50

    View Slide

  18. Scala
    の教育
    ­
    講義
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 17 / 50

    View Slide

  19. Scala
    の教育
    ­
    講義
    目的
    実践Scala
    入門 と 業務パートで必要となる知識の間を埋める
    業務パートで使う技術スタックを説明
    実際に開発してもらうプロジェクトのScala
    コードを解説
    ハンズオン形式で実際にScala
    のコードを書いてもらう
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 17 / 50

    View Slide

  20. Scala
    の教育
    ­
    講義
    Scala
    による開発
    実践Scala
    入門は、あくまでScala
    という言語全般についての幅広い知識を得るもの
    実際の現場では、より実践的であることが求められる
    コードの読みやすさ
    コードの保守性
    非機能要件とのトレードオフ
    Scala
    は色々な書き方ができてしまうので、機能要件と非機能要件を満たす範囲で、出来るだけ読み
    やすく(
    理解しやすく)
    、保守性の高いコードにする
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 18 / 50

    View Slide

  21. Scala
    の教育
    ­
    講義
    Scala
    を実践的に使う
    チーム開発を意識したコード
    型を意識したコード
    既存のライブラリを上手に利用する
    case class
    を上手に利用する
    汎用的な型を特化した型にするため、型に対するパターンマッチ
    タプルを上手に利用する
    値の変換の過程で、可読性を損なわない範囲で
    trait
    を上手に利用する
    インターフェースの観点、再利用の観点、責務の分離の観点
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 19 / 50

    View Slide

  22. DDD

    Scala
    で開発
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 20 / 50

    View Slide

  23. DDD

    Scala
    で開発
    ドメインモデリングからのUnlearn
    Scala
    に関する指摘事項からのUnlearn
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 21 / 50

    View Slide

  24. ドメインモデリング
    ユースケースを定義し、内容に齟齬が無いか、PM
    と議論し、合意形成
    ユースケースの内容を議論するなかで、ユビキタス言語の正しい表現に着目
    ドメインモデルに採用するユビキタス言語をPM
    と合意
    ユビキタス言語をドメインモデルとして定義するにあたり既存のドメインモデルとの関連を検討
    検討したドメインモデルの関連について社員がレビュー
    ドメインモデルの関連にいたった根拠やユースケースをP­R
    に記載
    そこから歴戦の猛者である先輩社員たちによる思考のトレースと可能性の模索
    Dev
    チーム(
    インターン生)
    は、その考察から自分たちで落とし所を探しドメインモデルを確定
    ドメインモデルをコードに落としてレビュー
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 22 / 50

    View Slide

  25. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 23 / 50

    View Slide

  26. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 24 / 50

    View Slide

  27. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 25 / 50

    View Slide

  28. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 26 / 50

    View Slide

  29. ユースケースを見てみる
    利用者はサインインしたUserAccount
    を使ってMessage
    をBookmark
    のリストに1
    件追加する
    利用者はサインインしたUserAccount
    を使ってBookmark
    のリストを表示する
    利用者はサインインしたUserAccount
    を使ってBookmark
    のリストの表示順を変更できる
    利用者は、Bookmark
    のリストを表示したとき、サインインしたUserAccount
    を使ってMessage

    Bookmark
    のリストから削除する
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 27 / 50

    View Slide

  30. ユースケースを見てみる
    利用者はサインインしたUserAccount
    を使ってMessage
    を Bookmark
    のリスト に1
    件追加する
    利用者はサインインしたUserAccount
    を使って Bookmark
    のリスト を表示する
    利用者はサインインしたUserAccount
    を使って Bookmark
    のリスト の表示順を変更できる
    利用者は、 Bookmark
    のリスト を表示したとき、サインインしたUserAccount
    を使ってMessage

    Bookmark
    のリスト から削除する
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 28 / 50

    View Slide

  31. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 29 / 50

    View Slide

  32. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 30 / 50

    View Slide

  33. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 31 / 50

    View Slide

  34. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 32 / 50

    View Slide

  35. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 33 / 50

    View Slide

  36. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 34 / 50

    View Slide

  37. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 35 / 50

    View Slide

  38. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 36 / 50

    View Slide

  39. ドメインモデリングからの
    Unlearn
    ユースケースの文脈から、「Bookmark
    のリスト」が読み取れたため、永続化を意識せずにモデリン
    グすると、 BookmarkList
    を定義したい
    ドメインモデリングにおいては、永続化層を意識せずに実施する
    その後、どのように永続化するか、クエリの要求も踏まえて永続化層の設計をする
    永続化層の検討では、データの制限の有無、データストアの種類など、様々な制約を考慮する
    最終的には、ドメイン層以外のフィードバックもドメインモデリングに影響を与える
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 37 / 50

    View Slide

  40. CQRS+ES
    を使うと、後半の
    永続化層の様々な制約をある
    程度考慮せずにドメインモデ
    リングが可能
    ちなみに

    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 38 / 50

    View Slide

  41. Scala
    に関する指摘事項から
    Unlearn
    Future
    関連
    生成ロジックとするか事後条件とするか
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 39 / 50

    View Slide

  42. lazy val bookmark = Bookmark(
    id = bookmarkId,
    status = BookmarkStatus.Active,
    messageId = command.messageId,
    userAccountId = command.userAccountId,
    createdAt = now
    )
    val result = for {
    message case e: AggregateNotFoundException => Future.failed(new MessageNotFoundException(e))
    }
    thread case e: AggregateNotFoundException => Future.failed(new ThreadNotFoundException(e))
    }
    _ if (!thread.hasMember(command.userAccountId)) throw new AddBookmarkForbiddenException("You are not a m
    }
    _ } yield {
    AddBookmarkSuccess(bookmarkId)
    }
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 40 / 50

    View Slide

  43. Future
    関連
    ­
    指摘事項
    Future.apply
    は並行処理としてスケジューリングされてしまいますが、ここは大した計算処理ではな
    いのでスレッド実行せずに同期処理でよい
    Future#successful, failed
    でよい
    Future
    の中で明示的に例外をthrow
    しないようにしましょう。Future.failed
    を使う
    if
    式は必ずelse
    句書く。if
    は式なので必ず値を返す必要がある。命令型プログラミングとしてelse
    句を
    書かない場合もあるが、本来の使い方としては値を返すべき
    _ if (!thread.hasMember(command.userAccountId)) throw new AddBookmarkForbiddenException("You are not a m
    }
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 41 / 50

    View Slide

  44. Future
    関連
    ­
    コードで提案
    before
    after
    _ Future.failed(new AddBookmarkForbiddenException("You are not a member!"))
    else
    Future.succcessful(())
    _ if (!thread.hasMember(command.userAccountId)) throw new AddBookmarkForbiddenException("You are not a m
    }
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 42 / 50

    View Slide

  45. 正常系をベースに書く
    _ Future.succcessful(())
    else
    Future.failed(new AddBookmarkForbiddenException("You are not a member!"))
    正常系を先に書く
    Thread
    が Member
    を持っているなら、正常。それ以外は、異常。
    否定の !
    は、「持っている」の否定なので「持っていない」になるな、と脳内変換が必要
    「読みやすさ」を重視するなら、否定とか無いほうが良い
    どうしても異常を先に検査するなら、 thread.hasNotMember
    とかにする
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 43 / 50

    View Slide

  46. 生成ロジックとするか事後条件とするか
    lazy val bookmark = Bookmark(
    id = bookmarkId,
    status = BookmarkStatus.Active,
    messageId = command.messageId,
    userAccountId = command.userAccountId,
    createdAt = now
    )
    val result = for {
    message case e: AggregateNotFoundException => Future.failed(new MessageNotFoundException(e))
    }
    thread case e: AggregateNotFoundException => Future.failed(new ThreadNotFoundException(e))
    }
    _ else Future.failed(new AddBookmarkForbiddenException("You are not a member!"))
    _ } yield AddBookmarkSuccess(bookmarkId)
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 44 / 50

    View Slide

  47. 生成ロジックとするか事後条件とするか
    _ else Future.failed(new AddBookmarkForbiddenException("You are not a member!"))
    上記の処理は、Bookmark
    の生成ロジックと言えそう
    こんな感じで、生成処理をFactory Method
    としてドメインに持っていくのが良いかなーと思いま
    す。
    object Bookmark {
    def generate(thread: Thread, messageId: MessageId, userAccountId: UserAccountId): Either[DomainError, Bookma
    if (thread.hasMember(userAccountId)) {
    ...
    }
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 45 / 50

    View Slide

  48. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 46 / 50

    View Slide

  49. サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 47 / 50

    View Slide

  50. Scala
    に関する指摘事項から
    Unlearn
    Future
    の並行処理を適切に使おう
    Future
    で明示的な例外をthrow
    しない
    if
    は式なので、else
    書く
    生成ロジックを暗黙知にせず、ファクトリメソッドに明示する
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 48 / 50

    View Slide

  51. まとめ
    サマーインターンシップを通して、社内でも暗黙知となっている部分をUnlearn
    することができた
    改めて学び直すこと、言語化することを通して、色々な気付きがあるのは良いですね
    引き続き、このような機会を創出していくことを、社内やコミュニティで実現できると良いですね
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 49 / 50

    View Slide

  52. 一緒に働くエンジニアを募集しています!
    https://corp.chatwork.com/ja/recruit/
    サマーインターンシップ2019
    で学生とDDD
    なScala
    開発に取り組んだ
    Scala
    秋祭り 50 / 50

    View Slide