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

Scalaで始める表明プログラミング

男爵
March 04, 2022

 Scalaで始める表明プログラミング

『SaaSプロダクト開発のScala活用事例』の発表資料です。
https://alp.connpass.com/event/239935/

男爵

March 04, 2022
Tweet

More Decks by 男爵

Other Decks in Programming

Transcript

  1. Scalaで始める
    表明プログラミング
    2022/03/04 SaaSプロダクト開発のScala活用事例
    @dnskimox

    View full-size slide

  2. 自己紹介
    男爵
    所属:Alp, Inc. / Scalebase
    開発言語:Scala、Apex/LWC(Salesfore)
    好きな話題:OOP、DDD、アジャイル開発
    Twitter:@dnskimox

    View full-size slide

  3. Scalaで始める表明プログラミング
    ▸ 契約による設計と表明
    ▸ 事前条件と事後条件
    ▸ 不変条件の実装方法
    ▸ Eitherと組み合わせる
    ▸ まとめ

    View full-size slide

  4. 1.
    契約による設計と表明

    View full-size slide

  5. バートランド・メイヤー著
    『オブジェクト指向入門 第二版』
    開放/閉鎖の原則、コマンドとクエリの
    分離原則、統一形式アクセスの原則、
    契約による設計、単一責任選択の原
    則、etc...
    https://en.wikipedia.org/wiki/Bertrand_Meyer

    View full-size slide


  6. キーコンセプトは契約による設計(Design by
    Contract)である。クラスと顧客の間の関係は、お
    互いの権利と義務を表した正式な同意と見なすこ
    とができる。すべてのモジ ュールのそのような要
    求と責任の詳細な定義があって、はじめて信頼性
    の高い大規模システムが実現できるのである。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide

  7. 顧客モジュールと供給者モジュール
    ● データを利用
    ● サービスを利用
    お互いの権利と義務を表した正式な同意 = 契約

    View full-size slide


  8. 顧客モジュールと供給者モジュールの間の契約
    は、一方にとっての利益はもう一方の義務とな
    る。効果的かつ信頼性の高いソフトウェアを作る
    ということは、顧客と供給者の間で適切なコミュ
    ニケーションを重ねた末、ベストな妥協案にあた
    る契約を作成することである。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide

  9. 意図明白なインターフェースのこと?

    View full-size slide

  10. それもある。が、それだけではない

    View full-size slide


  11. 我々に必要なのは、内部を徹底的に調べなくて
    も、設計要素の意味と操作の実行結果を理解で
    きるようにする方法である。(中略)「契約による
    設計」学派は次の段階に進み、クラスとメソッドに
    ついて、開発者によって保証される「表明」を作
    成する。
    『エリック・エヴァンスのドメイン駆動設計 』

    View full-size slide

  12. 契約の形を
    表明する道具
    事前条件、事後条件、クラス不変表明、ループ
    不変表明、etc...

    View full-size slide

  13. 2.
    事前条件と事後条件

    View full-size slide

  14. メソッドの
    コード本体を
    表明で挟む
    事前条件
    コード本体
    事後条件

    View full-size slide

  15. BankAccount(銀行口座)

    View full-size slide

  16. deposit(預け入れ)を実装

    View full-size slide

  17. withdraw(引き出し)を実装

    View full-size slide

  18. 顧客側のメソッド呼び出し

    View full-size slide

  19. 供給者側の隠された意図
    ● 預け入れで残高を減らせてしまう
    ● 「0円を引き出す」という操作ができてしまう
    クラス設計者の想定と異なる使われ方をしている

    View full-size slide

  20. メソッドに但し書きをつける?

    View full-size slide

  21. メソッドに事前条件を仕込む

    View full-size slide

  22. 供給者の意図に反した呼び出しが
    できなくなる

    View full-size slide

  23. 表明は
    動くドキュメント
    コードの書き手の想定、クラスの責務の範囲、オブジェク
    トの「正しい状態」の定義

    View full-size slide

  24. 供給者の意図に則した呼び出しなのに何かが
    おかしい?
    口座残高がマイナスに。それをクラス設計者は想定しているのか?

    View full-size slide

  25. メソッドに事後条件を仕込む
    ensuring: 確実にする、 保証する、 確保する

    View full-size slide

  26. 事後条件に違反していることが判明!

    View full-size slide

  27. 事後条件を守るようにコードを修正

    View full-size slide


  28. ルーチンの事前条件と事後条件を定義するとい
    うことは、とりもなおさず、ルーチンとそれを呼び
    出すものの間で契約(contract)を結んだという
    ことである。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide


  29. 顧客モジュールと供給者モジュールの間の契約
    は、一方にとっての利益はもう一方の義務となる。
    効果的かつ信頼性の高いソフトウェアを作るという
    ことは、顧客と供給者の間で適切なコミュニケー
    ションを重ねた末、ベストな妥協案にあたる契約を
    作成することである。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide

  30. 義務
    顧客は供給者のメソッ
    ドを正当な方法で呼び
    出さなければならない。
    事前条件によって生じる契約
    利益
    供給者はメソッドが呼
    び出された際、特定の
    仮説が満たされると保
    証される。

    View full-size slide

  31. 義務
    供給者はメソッドを抜け
    る際、定義された状態
    を満たしていなければ
    ならない。
    事後条件によって生じる契約
    利益
    顧客はメソッドの呼び
    出し後に、特定の性質
    が得られることを保証
    される。
    どちらのモジュールも想定すべきパターンが減る

    View full-size slide

  32. コードがシンプルになる
    起こり得ない分岐を書かなくて良い、デッドコードの抑
    制、「但し書き」のコメント不要、etc...

    View full-size slide

  33. 責任の所在が明らかに
    事前条件違反なら顧客側が悪い、事後条件違反なら供
    給者側が悪い。修正すべきコードは明白。

    View full-size slide

  34. 3.
    不変条件の実装方法

    View full-size slide


  35. 事前条件と事後条件は個々のルーチンの特性
    を記述する。このほかに、全てのルーチンで維持
    されなければならない、クラスに共通する全体的
    な特性を表す必要がある。
    『オブジェクト指向入門 第2版 原則・コンセプト 』
    不変条件(クラス不変表明)

    View full-size slide


  36. クラス不変条件は、あらゆる操作が終わった時
    のオブジェクトの状態に関する表明となる。不変
    条件は、集約全体に対しても宣言することがで
    き、整合性に関するルールを厳密に定義する。
    『エリック・エヴァンスのドメイン駆動設計 』

    View full-size slide

  37. Scalaには不変条件を定義する構文がない

    View full-size slide

  38. ScalaにはCase Classがある

    View full-size slide

  39. BankAccountクラスに不変条件を
    記述する
    ● インスタンス化の際にチェックされる
    ● copyの呼び出し時に毎回チェックされる
    ● オブジェクトの生成から破棄まで守られ続ける
    *ただしイミュータブルな場合に限る

    View full-size slide

  40. 不変条件違反は即座にエラーになる

    View full-size slide

  41. 義務
    全てのクラスのオブ
    ジェクトは、生成されて
    から破棄されるまで不
    変条件を満たし続けな
    ければならない。
    不変条件によって生じる契約
    利益
    コードベース全体にお
    いて、いかなるときもオ
    ブジェクトが定義された
    性質を満たしていると
    保証される。

    View full-size slide

  42. コードがシンプルになる
    起こり得ない分岐を書かなくて良い、デッドコードの抑
    制、「但し書き」のコメント不要、etc...

    View full-size slide

  43. 責任の所在が明らかに
    不変条件違反はクラス内部のコードに問題がある。事前
    条件かメソッドの本体を見直すべし。

    View full-size slide

  44. ところで、表明エラーは副作用なのでは?

    View full-size slide


  45. もう一つのよくある誤解は、表明を制御構造(す
    なわち、特殊なケースを取り扱う技術)と考えるこ
    とである。(中略)sqrtが事前条件を持つ場合、x
    < 0での呼び出しは特殊なケースではない。単純
    明快、それはバグである。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide

  46. 表明エラーが起きたら
    コードを修正すべし
    オブジェクトの状態が異常、バリデーションの不
    足、事前条件が強すぎる、etc...

    View full-size slide

  47. 表明違反の修正は簡単
    問題あるのコードのすぐ近くでエラーが起きる、データが破損
    する前に処理が停止する、責任の所在が明白

    View full-size slide

  48. 副作用の局所化とは分けて考えよう

    View full-size slide

  49. 4.
    Eitherと組み合わせる

    View full-size slide

  50. 義務
    供給者はメソッドを抜け
    る際、定義された状態
    を満たしていなければ
    ならない。
    事後条件によって生じる契約
    利益
    顧客はメソッドの呼び
    出し後に、特定の性質
    が得られることを保証
    される。
    事後条件を守ることを常に保証できるか?

    View full-size slide

  51. コードの正しさだけでは抑制できな
    い実行時エラー
    ファイルアクセスエラー
    存在しないパス、パーミッショ
    ンの不一致、ディスクの物理
    的な呼称
    メモリエラー
    メモリ割り当ての失敗、メモリ
    の物理的な故障
    OSからのシグナル
    入力デバイスからの割り込
    み、中断命令、Kill
    データベースエラー
    接続失敗、コネクション数の
    超過、ロック待ち時間の超
    過、SQLのシンタックスエラー
    ネットワークエラー
    コネクション確立の失敗、コネ
    クションの中断
    外部サービスのエラー
    認証失敗、外部サービス側の
    バリデーション、メンテナンス

    View full-size slide


  52. ルーチンが契約を満たす状態で実行を終えた場
    合、そのルーチンコールは成功である。成功しな
    ければ失敗である。(中略)何らかの特別なイベン
    トがルーチンの実行を中断させたときルーチンは
    失敗する。そのようなイベントを「例外」という。
    『オブジェクト指向入門 第2版 原則・コンセプト 』

    View full-size slide

  53. 例外は契約の
    履行失敗を表す
    データベースエラー、ファイルへのアクセスエ
    ラー、メモリ確保の失敗、etc...

    View full-size slide

  54. Eitherを使って契約の履行失敗を表す
    パターン

    View full-size slide

  55. バリデーションとは何が違うの?

    View full-size slide

  56. バリデーションはシステム境界の外から
    の入力を検証する仕組み

    View full-size slide

  57. 表明はシステム境界内のモジュール同
    士のやり取りを定めた契約
    常に真

    View full-size slide

  58. 外からのいかなる入力に対しても表明違反
    を起こさないようプログラミングする
    常に真

    View full-size slide

  59. 表明とバリデーションは存在目的の異なる道
    具である
    バリデーション 表明
    誰のためのもの? システムを使う人 コードを書く人
    違反が起きた時、
    どうする?
    入力内容を改める コードを修正する
    本番稼働時に必要? 必要 必ずしも必要ではない

    View full-size slide

  60. BankAccountオブジェクトを作る
    際のバリデーション

    View full-size slide

  61. 表明を使ってモジュール間の
    契約を定義する
    表明エラーが起きたときは
    コードを修正する
    不変条件でデータの破損を
    未然に防ぐ

    View full-size slide

  62. 表明を使ってシンプルで堅
    牢なコードを書こう!
    ご清聴ありがとうございました
    You can find me at @dnskimox & https://dnskimox.hateblo.jp/
    👦👧👨👶
    😸

    View full-size slide

  63. 参考文献
    ▸ オブジェクト指向入門 第二版 概念・コンセプト
    ▹ 11章 契約による設計:信頼性の高いソフトウェアを構築する
    ▹ 12章 契約が破られるとき:例外処理
    ▸ エリック・エヴァンスのドメイン駆動設計
    ▸ https://en.wikipedia.org/wiki/Design_by_contract
    ▸ https://speakerdeck.com/twada/php-conference-2016-revised
    ▸ https://qiita.com/kawachi/items/c3cf53e0602fb53e78e9

    View full-size slide