$30 off During Our Annual Pro Sale. View Details »

契約による設計の紹介

 契約による設計の紹介

hakobe (Yohei Fushii)

August 25, 2016
Tweet

More Decks by hakobe (Yohei Fushii)

Other Decks in Programming

Transcript

  1. ܖ໿ʹΑΔઃܭͷ঺հ
    hakobe932

    View Slide

  2. ࿩୊: ؔ਺ͷೖྗ΍ग़ྗͷ
    νΣοΫͲ͏ͯ͠·͔͢?

    View Slide

  3. ؔ਺ͷ࢓༷: 

    τʔΫϯΛड͚औΓHTTPϦΫΤετͯ͠

    ಘΒΕͨ಺༰Λฦ͢
    sub retrieve_content_by_token_1 {
    my ($token) = @_;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return $res->content;
    }
    ↑ ԿͷΤϥʔνΣοΫ΋ͳ͍
    ۭจࣈྻͩͬͨΒ
    ϦΫΤετࣦഊͯͨ͠Β

    View Slide

  4. sub retrieve_content_by_token_return {
    my ($token) = @_;
    return unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return if $res->is_error;
    return $res->content;
    }
    Կ͔͓͔͠ͳ͜ͱ͕ىͬͨ͜ΒِʹͳΔ஋Λฦ͢
    ͓͔͔ͬͨ͠ΒSFUVSO
    ͬͪ͜΋
    ྑ͘ͳ͍͜ͱ͕ىͬͨ͜Βِ஋

    View Slide

  5. sub retrieve_content_by_token_3 {
    my ($token) = @_;
    $token //= 'DEFAULT_TOKEN';
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return Failure->new($res->code)
    if $res->is_error;
    return Success->new($res->content);
    }
    ͱʹ͔͘ݺͼग़ͤΔ/݁Ռͷදݱ͸2छྨ
    ࣦഊͨ͠Β'BJMVSFΦϒδΣΫτ
    ੒ޭͨ͠Β4VDDFTTΦϒδΣΫτ
    ͳΔ΂͘Ժศʹࡁ·͢
    ೖྗ͕͓͔͔ͬͨ͠ΒσϑΥϧτ஋

    View Slide

  6. sub retrieve_content_by_token_die {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    die 'request error: ' . $res->content
    if $res->is_error;
    return $res->content;
    }
    ॲཧ͕ࣦഊͨ͠Βྫ֎Λൃੜͤ͞Δ
    ෆਖ਼ͳೖྗ͸ڐ͞ͳ͍
    ྫ֎ͰͳΜͱ͔͢Δ

    View Slide

  7. Ͳͷೖྗݕࠪॲཧ͕ྑ͍Ͱ͠ΐ͏?
    ❖ ྑ͘ͳ͍͜ͱ͕ىͬͨ͜Βِ஋
    ❖ ͳΔ΂͘Ժศʹࡁ·͢
    ❖ ྫ֎ͰͳΜͱ͔͢Δ

    View Slide

  8. ਖ਼ղ: Θͨ͠͸޷͖ʹͨ͠
    ͲͷΑ͏ʹߟ͑Δ΂͖͔ͷࢦ਑͸͋Δ
    ܅Β΋޷͖ʹ͠Ζ

    View Slide

  9. ߟ͑Δ΂͖͜ͱ:
    ؔ਺ͷ࢓༷

    View Slide

  10. έʔεελσΟʹ͓͚Δؔ਺ͷ࢓༷
    •τʔΫϯΛड͚औΓ
    •HTTPϦΫΤετͯ͠
    •ಘΒΕͨ಺༰Λฦ͢
    ←ਖ਼͍͠ೖྗ͕ಘΒΕͨ࣌
    ←Կ͔࢓ࣄΛͯ͠

    ←ظ଴͞ΕΔ݁ՌΛฦ͢

    View Slide

  11. έʔεελσΟʹ͓͚Δؔ਺ͷ࢓༷ (Cont.
    •τʔΫϯΛड͚औΓ
    •HTTPϦΫΤετͯ͠
    •ಘΒΕͨ಺༰Λฦ͢
    ←ࣄલ৚݅Λຬͨͤ͹
    ←Կ͔࢓ࣄΛͯ͠

    ←ࣄޙ৚݅Λຬͨ͢
    ؔ਺ͷར༻ऀ͕
    ؔ਺͸

    View Slide

  12. Q: ΋͠৚͕݅ຬͨͤͳ͍ͱͲ͏ͳΔ?
    ❖ ࣄલ৚͕݅ຬͨͤͳ͍
    • ex.τʔΫϯ͕౉͞Εͳ͔ͬͨ
    • HTTPϦΫΤετΛ͢ΔͨΊͷURL͕ߏஙͰ͖ͳ͍
    ❖ ࣄޙ৚͕݅ຬͨͤͳ͍
    • ex. HTTPϦΫΤετ͕ࣦഊͨ͠
    • ฦ͢΂͖ίϯςϯπ͕࡞Εͳ͍
    A: ؔ਺͸໨తΛՌͨͤͳ͍
    ؔ਺Λ࣮ߦͨ݁͠ՌɺԿ͕ى͜Δ͔͸ෆఆ

    View Slide

  13. ࣄલ৚݅ͱࣄޙ৚݅ͷද໌
    ❖ ؔ਺Λਖ਼͘͠ಈ͘ͷʹඞཁͳ৚݅Λද໌͢Δ
    # 事前条件: $token は必ず渡される必要がある
    # 事後条件: 取得したコンテンツは必ず返却される
    sub retrieve_content {
    my ($token) = @_;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return $res->content;
    }

    View Slide

  14. use Carp::Assert;
    sub retrieve_content_assert {
    my ($token) = @_;
    assert($token);
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    assert($res->is_success && $res->content);
    return $res->content;
    }
    ίʔυͰදݱ͢Δͱ࣮ߦ࣌ʹνΣοΫͰ͖Δ
    ίʔυʹΑΔද໌ͷදݱ(Carp::Assert)
    τʔΫϯΛ͏͚ͱ͍ͬͯΔ͜ͱͷද໌
    ίϯςϯπΛ༻ҙͰ͖ͨ͜ͱͷද໌

    View Slide

  15. sub retrieve_content_by_token_die {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    die 'request error: ' . $res->content
    if $res->is_error;
    return $res->content;
    }
    PerlͰ͸ૉ๿ʹྫ֎ʹΑΓදݱ͢Δ͘Β͍͕Ұൠత
    ίʔυʹΑΔද໌ͷදݱ(ྫ֎ )
    τʔΫϯΛ͏͚ͱ͍ͬͯΔ͜ͱͷද໌
    ίϯςϯπΛ༻ҙͰ͖ͨ͜ͱͷද໌

    View Slide

  16. sub retrieve_content_by_token_die {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    die 'request error: ' . $res->content
    if $res->is_error;
    return $res->content;
    }
    ؔ਺ͷ࢓༷ʹج͍࣮ͮͨ૷
    τʔΫϯΛड͚औΓHTTPϦΫΤετͯ͠ಘΒΕͨ
    ಺༰Λฦ͢

    View Slide

  17. ܖ໿ʹΑΔઃܭ (Design by Contract)
    ❖ ࣄલ৚݅ͱࣄޙ৚݅ͱ͍͏એݴతͳੑ࣭ʹج͍ͮͯ

    ؔ਺Λઃܭ͢Δ
    ❖ ؔ਺ͱͦͷར༻ऀͷؒʹ͸ˢͷΑ͏ͳܖ໿͕͋Δͱ

    ଊ͑Δ
    ʮ΋ͦͪ͠Β͕ࣄલ৚݅Λຬͨͨ͠ঢ়ଶͰࢲΛ
    ݺͿͱ໿ଋͯ͠Լ͞ΔͳΒ͹ɺ

    ͓ฦ͠ʹࣄޙ৚݅Λຬͨ͢ঢ়ଶΛ࠷ऴతʹ࣮ݱ
    ͢Δ͜ͱΛ͓໿ଋ͠·͢ʯ

    View Slide

  18. ܖ໿ʹΑΔઃܭͷར఺
    ❖ ਖ਼͍͠ίʔυΛॻ͘ॿ͚ʹͳΔ
    • ਖ਼͍ؔ͠਺ͷ࢖͍ํ͕໌֬ʹͳΔ
    • ·͕͍ͪʹૣ͘ؾ͚ͮΔ
    • → ιϑτ΢ΣΞͷ৴པੑ͕޲্͢Δ
    ❖ ؔ਺ͷੑ࣭Λ෼ੳ͢Δνϟϯε͕ಘΒΕΔ
    ❖ ؔ਺ͷੑ࣭Λදݱ͢ΔυΩϡϝϯτʹͳΔ

    View Slide

  19. Q:Τϥʔ͸ͳΜͰ΋ྫ֎ʹ͢Δ࿩?
    ❖ ΋͏͢͜͠ৄ͘͠
    • ؔ਺ͷ࢓༷Λਖ਼͘͠ఆٛ͠Α͏
    • ཁٻܕͷؔ਺/อޢܕͷؔ਺
    • ৴པͰ͖ͳ͍ೖྗ͸༧ΊνΣοΫ͠Α͏
    A: ͦ͏Ͱ͸ͳ͍

    View Slide

  20. sub retrieve_content_by_token_die {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    die 'request error: ' . $res->content
    if $res->is_error;
    return $res->content;
    }
    ؔ਺ͷ࢓༷ʹج͍࣮ͮͨ૷(࠶ܝ)
    τʔΫϯΛड͚औΓHTTPϦΫΤετͯ͠ಘΒΕͨ
    ಺༰Λฦ͢
    Τϥʔͷ಺༰ʹԠͯ͡

    ॲཧΛ੾Γସ͍͑ͨ

    View Slide

  21. ؔ਺ͷ࢓༷Λద੾ʹఆٛ͠Α͏
    τʔΫϯΛड͚औΓHTTPϦΫΤετͯ͠ಘΒΕͨ
    ಺༰Λฦ͢
    τʔΫϯΛड͚औΓHTTPϦΫΤετͯ͠
    ੒ޭ͢Ε͹ಘΒΕͨ಺༰Λฦ͢
    ࣦഊ͢Ε͹ΤϥʔͷछྨΛฦ͢
    ؔ਺ͱͷద੾ͳܖ໿ؔ܎Λߟ͑Δ → ઃܭ

    View Slide

  22. sub retrieve_content_by_token_2 {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return Failure->new($res->code)
    if $res->is_error;
    return Success->new($res->content);
    }
    ࣄલ৚݅Λຬͨͯ͠ͳ͍ͷͰྫ֎
    ੒ޭͨ͠Β4VDDFTTΦϒδΣΫτ
    ৽͍ؔ͠਺ͷ࢓༷ʹج͍࣮ͨ૷
    ࣦഊͨ͠Β'BJMVSFΦϒδΣΫτ
    τʔΫϯΛड͚औΓ

    HTTPϦΫΤετͯ͠
    ੒ޭ͢Ε͹ಘΒΕͨ಺༰Λฦ͢/ࣦഊ͢Ε͹ΤϥʔͷछྨΛฦ͢

    View Slide

  23. sub retrieve_content_by_token_3 {
    my ($token) = @_;
    $token //= 'DEFAULT_TOKEN';
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return Failure->new($res->code)
    if $res->is_error;
    return Success->new($res->content);
    }
    τʔΫϯͳ͚Ε͹σϑΥϧτ஋
    ੒ޭͨ͠Β4VDDFTTΦϒδΣΫτ
    ͞Βʹࣄલ৚݅ΛΏΔΊΔ͜ͱ΋Ͱ͖Δ
    ࣦഊͨ͠Β'BJMVSFΦϒδΣΫτ
    τʔΫϯΛड͚औΔ͕ɺͳ͚Ε͹σϑΥϧτ஋Λ࢖͍

    HTTPϦΫΤετͯ͠
    ੒ޭ͢Ε͹ಘΒΕͨ಺༰Λฦ͢/ࣦഊ͢Ε͹ΤϥʔͷछྨΛฦ͢

    View Slide

  24. ཁٻܕͷؔ਺ͱอޢܕͷؔ਺
    ❖ ཁٻܕͷؔ਺
    • ݺͼग़͠ଆ͕ࣄલ৚݅Λຬͨ͢͜ͱΛཁٻ͢Δؔ਺
    • ex. ͢΂ͯͷ৔ॴͰྫ֎Λ࢖͍ͬͯͨύλʔϯ
    ❖ อޢܕͷؔ਺
    • ͲΜͳೖྗͰ΋ͳΜͱͯ͠ॲཧ͢Δؔ਺
    • ex. Ұ൪৚݅ΛΏΔΊͨύλʔϯ
    ͲͪΒ͕ྑ͍͔͸ɺ࣌ͱ৔߹ɺ޷ΈʹΑΔ

    View Slide

  25. ཁٻܕ͕͓͢͢Ί(υϝΠϯϩδοΫͰ͸)
    ❖ ࢖͏ଆʹڧ͍৚݅Λ՝͢͜ͱͰؔ਺͕ਖ਼͘͠ಈ࡞͢Δ
    ͜ͱΛڧ੍Ͱ͖Δ
    ❖ ҟৗͳೖྗΛॲཧ͢Δίʔυ͕ͳ͘ͳΓίΞϩδοΫ
    ʹूதͨ͠γϯϓϧͳίʔυʹͳΔ
    ❖ ҟৗͳೖྗΛͲͷΑ͏ʹ੍ޚ͢Δ͔͸࢖͏ଆͷΈͰ

    ܾΊΔͷͰ੹೚ͷॴࡏ͕໌Β͔

    View Slide

  26. sub retrieve_content_by_token_3 {
    my ($token) = @_;
    $token //= 'DEFAULT_TOKEN';
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    return Failure->new($res->code)
    if $res->is_error;
    return Success->new($res->content);
    }
    Ҿ਺Λ౉͠Θ͢Εͯͯ΋ಈ͘
    อޢܕͷؔ਺ͷ৔߹
    ຊ࣭తͰͳ͍ॲཧ͕૿͑Δ
    ೖྗ஋ݕࠪͷ੹೚͕ᐆດʹ

    View Slide

  27. sub retrieve_content_by_token_die {
    my ($token) = @_;
    die 'no token' unless $token;
    my $url = 'http://www.example.com/api?token=' . $token;
    my $res = request($url);
    die 'request error: ' . $res->content
    if $res->is_error;
    return $res->content;
    }
    ཁٻܕͷؔ਺ͷ৔߹
    ෆਖ਼ͳݺͼग़͠͸Τϥʔ
    ࢓༷ʹԊ͏ݕࠪͷΈΛߦ͏
    ೖྗ஋ݕࠪͷ੹೚͸ݺͼग़͠ଆ

    View Slide

  28. my $input_token = ;
    if (!$input_token) {
    print "Please input token";
    exit 1;
    }
    my $content = retrieve_content_by_token_die($token);
    ࣄલ৚݅ΛνΣοΫͯ͠ݺͼग़͢
    ࣄલ৚݅Λຬͨ͢͜ͱͷνΣοΫ
    ҆৺ͯ͠ݺͼग़͢
    Ϟσϧͷ

    ϩδοΫ
    Ϣʔβೖྗ
    ϑΟϧλ

    View Slide

  29. ؔ਺ͷ࢓༷͸Ͳ͏΍ܾͬͯΊΔͷ͔?
    ❖ ؔ਺ʹͲͷΑ͏ͳ੹೚Λ༩͑Δͷ͔͸

    ؔ਺ͷଐ͢ΔΫϥε΍Ϟδϡʔϧʹґଘ͢Δ
    ❖ Ϋϥε΍Ϟδϡʔϧͷ੹೚͸

    ιϑτ΢ΣΞͷΞʔΩςΫνϟʹґଘ͢Δ
    ࡉ෦ͷઃܭ͸શମͷઃܭʹجͮ͘

    View Slide

  30. ϨΠϠͷ͋ΔΞʔΩςΫνϟͷ৔߹
    Ϣʔβೖྗ
    • ೖྗͷνΣοΫ
    • νΣοΫOK

    → ϩδοΫݺͿ
    • νΣοΫNG

    → ΤϥʔΛฦ͢
    • ೖྗΛ৴པͯ͠

    υϝΠϯϩδοΫ

    Λ࣮ߦ
    อޢܕͷϝιου ཁٻܕͷϝιου
    ΠϯλʔϑΣʔε υϝΠϯϩδοΫ
    ݺͼग़͠
    ϨΠϠͷ੹೚ʹରԠ͢Δ

    View Slide

  31. ܖ໿ʹΑΔઃܭ͸ؔ਺ʹݶΒͳ͍
    ❖ ؔ਺͸୅දత͚ͩͲଞͷ෦෼ʹ΋ద༻Ͱ͖Δ
    • Ϋϥε: ΦϒδΣΫτͷෆม৚݅
    • ϧʔϓ: ϧʔϓෆม৚݅
    ίϯϙʔωϯτͷཁٻΛຬͨ͢͜ͱͰརӹΛಘΔ

    View Slide

  32. ৄ͘͠͸ΦϒδΣΫτࢦ޲ೖ໳Λಡ΋͏
    ❖ ιϑτ΢ΣΞઃܭͷຊ
    ❖ ιϑτ΢ΣΞ඼࣭ͷఆٛ΍
    ྺ࢙ΛͨͲֶͬͯ΂Δ
    ❖ ༗ӹ͚ͩͲྔ͕͓͓͍
    • 1800ϖʔδ͘Β͍
    • ͕Μ͹Ζ͏

    View Slide

  33. ιϑτ΢ΣΞΞʔΩςΫνϟ͕ؾʹͳΔਓ޲͚
    https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
    Clean Architecture

    View Slide

  34. ·ͱΊ
    ❖ ʮܖ໿ʹΑΔઃܭʯ͸ਖ਼͍͠ίʔυͷͨΊͷςΫχοΫ
    • ؔ਺ͷ࢓༷Λࣄલ৚݅ͱࣄޙ৚͔݅ΒͳΔܖ໿ͱଊ͑Α͏
    • ܖ໿ʹج͍ͮͯίʔυΛ࣮૷͠Α͏
    ❖ ؔ਺ͱͷܖ໿͸ιϑτ΢ΣΞΞʔΩςΫνϟΛݩʹ

    ߟ͑Α͏
    • Ϋϥε΍ϨΠϠͷ੹೚Λ෼ੳͯ͠ରԠͨ͠੹೚Λ༩͑Α͏
    • ཁٻܕͱอޢܕΛҙࣝͯ͠࢖͍Θ͚Α͏

    View Slide

  35. ๷ޚతϓϩάϥϛϯά͸Ͳ͜΁?
    ❖ Կ͕ى͜Δ͔Θ͔Βͳ͍ͷͰݸʑͷؔ਺͸ͳΔ΂͘

    ͋ΒΏΔೖྗνΣοΫ
    ❖ ؔ਺ͷఆٛͱݺͼग़͠͸ܖ໿ͱ͍͏ܗͰ੔ཧ͞Ε͍ͯ
    Ε͹γϯϓϧͳίʔυͱ໌͕֬͞ҡ࣋͞ΕΔ

    View Slide