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

似非サービスクラスの殺し方 / #ginzarb

似非サービスクラスの殺し方 / #ginzarb

ぎんざRuby会議LT資料

Tomohiro Hashidate

August 05, 2017
Tweet

More Decks by Tomohiro Hashidate

Other Decks in Technology

Transcript

  1. 似非サー
    ビスクラスの殺し方
    @ joker1007

    View Slide

  2. self.inspect
    @joker1007
    R
    epr
    o inc. CTO
    R
    u
    by/R
    ails
    flu
    ent
    d/embu
    lk
    D
    ocker/ECS
    B
    igqu
    ery/EMR
    /H
    iv
    e/P
    r
    est
    o
    クレカで40万ぐらい不正使用され、T
    hinkp
    adがぶっ壊れて修理に出し
    たら31万かかると言われて、
    マジお金が無くて辛い。

    View Slide

  3. なんちゃら
    R
    uby会議歴
    東京
    R
    u
    by
    会議スピー
    カー
    関西
    R
    u
    by
    会議スピー
    カー x3
    T
    okyuR
    u
    by
    会議
    L
    T

    R
    u
    byK
    aigi日本酒スー
    パー
    バイザー
    東京
    R
    u
    by
    会議日本酒仕入れ
    R
    u
    byK
    aigi
    L
    T
    x3
    名古屋
    R
    u
    by
    会議スピー
    カー
    大江戸
    R
    u
    by
    会議
    N
    inja
    ぎんざ
    R
    u
    by
    会議
    L
    T
    (NEW
    !!)

    View Slide

  4. 今一度、
    サー
    ビスクラスについて語ろう
    そして、
    こういうのをちくちく直してコー
    ドを読める様にする
    不毛な仕事が無くなります様に……。

    View Slide

  5. この話におけるサー
    ビスクラスとは
    いわゆるドメインサー
    ビス
    ユー
    ザー
    が利用する機能そのものを表現するクラス
    アプリが提供している業務の名前で呼ばれる
    ユー
    ザー
    を作る機能 ‑> C
    r
    eat
    e
    U
    s
    erS
    erv
    ice
    領収書を登録する機能 ‑> R
    egist
    erR
    eceiptS
    erv
    ice
    ~~
    するに明確な名前を付けたもの

    View Slide

  6. サー
    ビスクラスという名前のややこしさ
    アプリケー
    ションサー
    ビスとドメインサー
    ビス
    前者はビジネスロジック自体の外側にあるもの
    後者はビジネスロジックの機能の一表現
    R
    ailsは
    DDD
    に余り親和性が無いため、DDD
    のパター

    を取り込むことが難しいのもややこしさを助長する
    R
    ailsにおいては複数のモデルに跨るトランザクション管
    理のためのクラスと考えておけば概ね大丈夫

    View Slide

  7. サー
    ビスクラスにおいて最も重要なこと
    それは適切な名前が付けられるかどうか
    機能名が付けられない様なものはサー
    ビスで
    はない

    View Slide

  8. おかしな名前の例
    <モデル名>::S
    erv
    ice (何をするのか分からん)
    <モデル名>S
    t
    or
    age
    S
    erv
    ice (何をするのか分からん)
    A
    ccessB
    u
    ilder (サー
    ビスではないし、B
    u
    ilder
    パター
    ンですらない)
    全体的に一連の手続きを表わすものでも何でもないが、
    app/s
    erv
    ices

    下にある。
    こんなの無いだろと思うかもしれませんが、
    実際にあったんだから
    仕方がない。

    View Slide

  9. 名前が曖昧 ≒
    仕様が曖昧
    適切な名前が付いていないものは、
    書いている本人も何
    をやりたいか良く分かっていない
    もしくは、
    仕様に対して真剣に向き合っていない
    結果、
    責任が不明確なクラスが生産され、
    メンテしづら
    いコー
    ドがはびこる
    ‑> 似非サー
    ビスクラス

    View Slide

  10. 似非サー
    ビスクラスの問題点
    ややこしい処理をただ押し込めただけ
    強烈に分岐があり、
    テスタビリティが悪い
    一つのクラスで色々
    やり過ぎ
    app/models
    を読めばいいのか、
    app/s
    erv
    ices
    を読めばいいのかさ
    っぱり分からない
    特にapp/s
    erv
    ices
    に <
    動詞>
    S
    e
    r
    v
    i
    c
    e
    以外のクラスを置いている人は、
    本気で反省した方が良い。
    R
    ails
    が何のために a
    p
    p
    以下のディレクトリを区切っていると思ってい
    るのか。
    どこにどういう性質のものがあるかすぐ分かるための規約である。

    View Slide

  11. 延々
    キレ続けたおかげで、
    最近はこういうの
    が新しく増えることはほぼ無くなった

    View Slide

  12. あるべきサー
    ビスクラスの形
    T
    railblazerの
    O
    perationクラスに学ぶ
    仕事はフロー
    コントロー
    ルとエラー
    ハンドリングだけ
    コンテキストを順番に受け渡し、
    結果を返す
    結果は成功か失敗かが分かる様になっている

    View Slide

  13. サンプルコー
    ドで示すサー
    ビスクラス
    c
    l
    a
    s
    s R
    e
    g
    i
    s
    t
    e
    r
    H
    o
    g
    e
    h
    o
    g
    e
    S
    e
    r
    v
    i
    c
    e
    d
    e
    f i
    n
    i
    t
    i
    a
    l
    i
    z
    e
    (
    m
    o
    d
    e
    l
    A
    , m
    o
    d
    e
    l
    B
    , m
    o
    d
    e
    l
    C
    )
    d
    e
    f e
    x
    e
    c
    u
    t
    e #
    起動以外のp
    u
    b
    l
    i
    c
    メソッドは持たせない
    A
    c
    t
    i
    v
    e
    R
    e
    c
    o
    r
    d
    :
    :
    B
    a
    s
    e
    .
    t
    r
    a
    n
    s
    a
    c
    t
    i
    o
    n d
    o
    r
    e
    s
    u
    l
    t
    A = m
    o
    d
    e
    l
    A
    .
    d
    o
    _
    s
    o
    m
    e
    s
    h
    i
    n
    g
    A
    r
    e
    s
    u
    l
    t
    B = m
    o
    d
    e
    l
    B
    .
    d
    o
    _
    s
    o
    m
    e
    t
    h
    i
    n
    g
    B
    (
    r
    e
    s
    u
    l
    t
    A
    )
    m
    o
    d
    e
    l
    C
    .
    d
    o
    _
    s
    o
    m
    e
    t
    h
    i
    n
    g
    C
    (
    r
    e
    s
    u
    l
    t
    B
    )
    e
    n
    d
    r
    e
    s
    c
    u
    e
    n
    i
    l
    e
    n
    d
    e
    n
    d
    可読性のために一時的な状態やメソッド抽出をプライベー
    トメソッドで
    行える様にインスタンスメソッドレイヤー
    に処理を定義する方が良い。
    特にクラスレイヤー
    で色々
    やるとマルチスレッド時に危険。
    ex
    ecut
    e以外で持ってよいメソッドはエラー
    ハンドルぐらい。

    View Slide

  14. 良くないサー
    ビスクラスのシー
    ケンス図
    問い合わせの嵐により、
    とてもテストしづらい。

    View Slide

  15. 目指すべき形
    目指すは大きな
    V

    問い合わせずに命じる
    責任範囲の集約境界を意識する

    View Slide

  16. 主要な処理は
    AR
    モデルか、
    もしくは入れ子に
    した別のクラスに移譲する
    似非サー
    ビスクラスの処理はとにかく
    AR
    のモ
    デルに戻していくのが早道
    特にエンティティモデルに対して状態を確認
    しにいってる処理はエンティティ側が持って
    るべき処理であることがほとんど
    行き場が無ければ、T
    railblazerの様に子サー
    ビスを作っても良い

    View Slide

  17. ここまで理解した上で、
    サー
    ビスクラスが必
    要な時には作ってもいい
    しかし、
    ここまでの話に実感を伴っていない
    場合、
    余計なことはせずに
    AR
    モデルに処理を
    書いておく方が安全
    そして、
    名前がちゃんと付かないものを絶対
    にサー
    ビスクラスにしないこと!!

    View Slide

  18. サー
    ビスクラスをより良く使うために
    最低でもこれぐらいは読んでおくこと
    エリック・
    エヴァンスのドメイン駆動設計 (定番であり入口)
    オブジェクト指向設計実践ガイド
    特に単一責任の原則、
    デメテルの法則をしっかり守ること
    リー
    ダブルコー

    名前付けの重要さや、
    処理フロー
    の抽象化レベルを揃えること
    について

    View Slide

  19. 良いコー
    ドと共にあらんことを

    View Slide