💡

実は普段からやってるだけのこと 契約による設計:事前条件編

2023/03/31に公開

これなに?

契約による設計と防御的プログラミングについての考えをつらつら書いて見ようと思ってます。
それぞれ説明した上で、どういう部分にそれぞれ適用すればいいのかを考えてみようと思います。
今回はそのうちの契約による設計の事前条件についての記事です。

契約による設計って?

一旦Wikiから引用してみます。
https://ja.wikipedia.org/wiki/契約プログラミング

契約プログラミング(けいやくプログラミング、英: Contract programming)または契約による設計(けいやくによるせっけい、英: Design by Contract; DbC)は、ソフトウェアの正確性と頑健性を高めるためのソフトウェア設計の方法論である。DbC はロバート・フロイド、アントニー・ホーア、エドガー・ダイクストラらの形式的検証の仕事を基礎にしている。DbC は(抽象データ型に基づく)オブジェクト指向プログラミングにおける表明の利用や、継承に伴う表明の再定義の原理的規則、例外処理の原理的規則などを提供する。

なーんか難しそうな事書いてますね

事前条件って?

関数の引数が適切であることを保証し、バグや予期しない動作を未然に防ぐために、関数が呼び出される前に守らないといけない条件のこと。

大抵の場合、関数の最初で引数の値を検証する。
ひとことで関数と言っていますが、コンストラクタ(またはそれに該当するもの)で検証することが多い。
で、条件に違反する場合はエラーを返す。

こんなかんじ↓
ブログの記事を生成するコンストラクタのイメージ
検証事項は以下

  • タイトルは必須で50文字以下
  • 本文は必須で1000文字以下
type Post struct {
    Title string
    Body  string
}

func NewPost(title, body string) (*Post, error) {
    // パラメータのバリデーション
    if post.Title == "" || len(post.Title) > 50 {
        return errors.New("Invalid title")
    }
    if post.Body == "" || len(post.Body) > 1000 {
        return errors.New("Invalid body")
    }
    return &Post{age: age}, nil
}

このようにすることによって入力を保証できる。
入力を保証できると、入力の不備による正しくないインスタンスが出来上がってしまうことを未然に防ぐことができる。
次回書こうと思っていますが、事後条件と組み合わせることによって、ドメイン上で定義される正しい状態のインスタンスのみを作れることを保証できる。

おわり

たぶんみなさんが自然とやっていることであり、いまさらなんだって感じかもしれませんが、設計論上契約プログラミングにおける考え方のひとつなんだと理解しなおせると、フレームワーク的に意識できるのでちょっとした品質向上に寄与できるかと思います!

Voicyに雑に話している放送があるので、よかったら合わせてぜひ
https://voicy.jp/channel/1305/490073
https://r.voicy.jp/GZV0lPryVW7

Voicyテックブログ

Discussion