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

契約による設計事始め

男爵
February 16, 2020

 契約による設計事始め

Object-Oriented Conferenceの発表資料です。
https://fortee.jp/object-oriented-conference-2020/proposal/1224f293-8624-4448-866f-5d1b991d377f

カンファレンスの感想はこちら。
https://dnskimox.hateblo.jp/entry/2020/02/22/104342

男爵

February 16, 2020
Tweet

More Decks by 男爵

Other Decks in Programming

Transcript

  1. 契約による設計
    事始め
    2020/02/16 Object-Oriented Conference
    @dnskimox

    View Slide

  2. 自己紹介
    男爵
    所属:Alp,Inc. / Scalebase(サブスクリプション管理のSaaS)
    開発言語:Scala、TypeScript
    好きな話題:OOP、DDD、開発プロセス
    Twitter:@dnskimox

    View Slide

  3. 今日は
    契約による設計
    の話をします
    https://en.wikipedia.org/wiki/Design_by_contract

    View Slide

  4. 契約による設計事始め
    ▸ 契約による設計とはなにか?
    ▸ 事前条件と事後条件
    ▸ クラス不変表明
    ▸ 表明と例外の関係
    ▸ バリデーションとの違い
    ▸ 明日から使える実践方法

    View Slide

  5. 1.
    契約による設計とは
    なにか? どこから来た用語で
    何を意味するのか?

    View Slide

  6. View Slide

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

    View Slide


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

    View Slide

  9. 顧客モジュールと供給者モジュール
    ● データを利用
    ● サービスを利用
    要求と責任の詳細な定義 = 契約 が必要

    View Slide


  10. 顧客モジュールと供給者モジュールの
    間の契約は、一方にとっての利益はもう
    一方の義務となる。効果的かつ信頼性
    の高いソフトウェアを作るということは、
    顧客と供給考の間で適切なコミュニケー
    ションを重ねた末、ベストな妥協案にあ
    たる契約を作成することである。

    View Slide

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

    View Slide

  12. 様々な種類の表明
    事前条件
    ルーチンを利用する際に求め
    られる要求
    事後条件
    ルーチンの終了時に保証さ
    れる特性
    クラス不変表明
    クラスインスタンスを特徴付
    け、その生存中にずっと保持
    される特性
    ループ不変表明
    説明省略
    ループ変化表明
    説明省略
    check命令
    説明省略

    View Slide

  13. 2.
    事前条件と
    事後条件 このエラーを
    出したのは誰だ!

    View Slide

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

    View Slide

  15. ScalaのCase classの特徴
    ● 基本的に全てのプロパティが不変
    ● 全てのプロパティのgetterを持つ
    ● プロパティの一部を変更したコピーを返すメソッドがある

    View Slide

  16. Statsを持つCharacterを作る

    View Slide

  17. 供給者側の隠された意図
    ● 回復するメソッドでHPを減らせてしまう
    ● ダメージを与えるはずがHPが増えている?
    クラスの作者の想定と異なる使われ方

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. 供給者の意図に則した呼び出しなのに何かが
    おかしい?

    View Slide

  22. メソッドに事後条件を仕込む

    View Slide

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

    View Slide

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

    View Slide


  25. ルーチンの事前条件と事後条件を定義
    するということは、とりもなおさず、ルー
    チンとそれを呼び出すものの間で契約
    (contract)を結んだということである。

    View Slide

  26. 事前条件
    顧客は供給者のメソッ
    ドを呼び出す際、事前
    条件を満たす義務を負
    う。
    契約によって生じる義務
    事後条件
    供給者は事前条件を
    満たして呼び出された
    メソッドを抜ける際、事
    後条件を満たす義務を
    負う。

    View Slide

  27. 事前条件
    供給者は想定外の状
    況でメソッドを呼び出さ
    れないことが保証され
    るという利益を得る。
    契約によって生じる利益
    事後条件
    顧客は事前条件を守っ
    てメソッドを呼び出す限
    り、結果が定義された
    特性を満たすという利
    益を得る。
    どちらのモジュールも想定すべき事項が減る

    View Slide

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

    View Slide

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

    View Slide

  30. 3.
    クラス不変表明 オブジェクトにとって
    正しい状態とはなにか?

    View Slide


  31. 事前条件と事後条件は個々のルーチン
    の特性を記述する。このほかに、全ての
    ルーチンで維持されなければならない、
    クラスに共通する全体的な特性を表す
    必要がある。

    View Slide

  32. Statsクラスにクラス不変表明を記
    述する
    ● インスタンス化の際にチェックされる
    ● copyの呼び出し時にも毎回チェックされる
    ● オブジェクトの生成から破棄まで守られ続ける

    View Slide

  33. 表明違反は即刻エラーになる Diagram featured by
    http://slidemodel.com

    View Slide

  34. クラス不変表明(不変条件)
    あるクラスのオブジェクトは、生成されてから破棄さ
    れるまでクラス不変表明を満たし続ける義務を負
    う。
    契約によって生じる義務

    View Slide

  35. クラス不変表明(不変条件)
    コードベース全体において、あるクラスのオブジェク
    トがクラス不変表明に違反するという想定をしなくて
    良くなるという利益を得る。
    契約によって生じる利益

    View Slide

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

    View Slide

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

    View Slide

  38. 4.
    表明と例外の関係 契約による設計なら
    例外は必要なくなる?

    View Slide

  39. 事前条件
    供給者は想定外の状
    況でメソッドを呼び出さ
    れないことが保証され
    るという利益を得る。
    契約によって生じる利益
    事後条件
    顧客は事前条件を守っ
    てメソッドを呼び出す限
    り、結果が定義された
    特性を満たすという利
    益を得る。
    事後条件を守ることを常に保証できるか?

    View Slide

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

    View Slide


  41. ルーチンが契約を満たす状態で実行を終
    えた場合、そのルーチンコールは成功で
    ある。成功しなければ失敗である。(中略)
    何らかの特別なイベントがルーチンの実
    行を中断させたときルーチンは失敗する。
    そのようなイベントを「例外」という。

    View Slide

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

    View Slide

  43. 5.
    バリデーションとの
    違い 要するに入力
    チェックでは?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49. 5.
    明日からできる実践
    方法 で、結局何から
    始めればいいの?

    View Slide

  50. 使っている言語の表明機構を調べる
    事前条件 事後条件 クラス不変表明
    Scala require ensuring assert
    PHP assert assert ×
    Ruby raise if/unless raise if/unless ×
    なければ表明を組み込むライブラリを探す

    View Slide

  51. 事前条件を書く
    シグネチャで表現しきれない引数の制約はなにか?
    バグを修正する
    発生からの経過時間が短いほど原因調査は簡単
    表明違反を通知する
    開発環境や本番環境からプログラマへのアラート

    View Slide

  52. 表明違反は
    例外なくバグ
    オブジェクトの状態が異常、バリデーションの不
    足、事前条件が強すぎる、etc...

    View Slide

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

    View Slide

  54. 表明を使ってシンプルで正
    しいコードを!
    ご清聴ありがとうございました
    You can find me at @dnskimox & https://dnskimox.hateblo.jp/

    View Slide

  55. 参考文献
    ▸ オブジェクト指向入門 第二版 概念・コンセプト
    ▹ 11章 契約による設計:信頼性の高いソフトウェアを構築する
    ▹ 12章 契約が破られるとき:例外処理
    ▸ https://en.wikipedia.org/wiki/Design_by_contract
    ▸ https://speakerdeck.com/twada/php-conference-2016-revised
    ▸ https://qiita.com/kawachi/items/c3cf53e0602fb53e78e9
    ▸ https://stackoverflow.com/questions/147969/is-it-idiomatic-ruby-to-add-an-asse
    rt-method-to-rubys-kernel-class

    View Slide