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

オブジェクト指向でなぜ作るのか振り返り

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 オブジェクト指向でなぜ作るのか振り返り

Avatar for junhat6

junhat6

May 07, 2026

More Decks by junhat6

Other Decks in Programming

Transcript

  1. 3. コアコンセプト①:クラス まとめる・隠す・たくさん作る 前提:そもそもクラスは現実世界の写しではなく、データと処理を整理するためのプログラミングの仕組み 役割 内容 まとめる 関連する変数とメソッドを集める 隠す 内部状態を外から直接触らせない

    たくさん作る 同じ構造のインスタンスを複数作る 自分の理解 クラスは、データと処理を責任ごとに整理するための仕組み 例: Cart クラスが商品追加・削除・合計金額計算を担当する 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 4
  2. 具体例①:ショッピングカートで見る「クラスの3役割」 クラスを使わない実装 $cart_items = [] def add_item(item) $cart_items << item

    end def total $cart_items.sum(&:price) end どこからでも $cart_items を直接書き換えられ る(隠せていない) データと関数がバラバラ(まとまっていない) ユーザー用・ゲスト用の2つは作れない(たくさ ん作れない) Cart クラスにまとめる class Cart def initialize @items = [] # 隠す(インスタンス変数) end def add(item) # まとめる @items << item end def total @items.sum(&:price) end end user_cart = Cart.new # たくさん作る guest_cart = Cart.new ポイント: 「まとめる・隠す・たくさん作る」が揃って初めて、データの整合性をクラス自身が守れる 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 5
  3. 具体例①(モデリング):業務をクラスとして洗い出す 要件: 「会員が商品を選んで注文するECサイト」 機能だけ羅列する ユーザー登録機能 商品検索機能 カート機能 注文機能 決済機能 「誰が何を持つか」

    「誰が何をするか」が曖昧 → 後から仕様の漏れ・矛盾が頻出 (例:会員ランクで送料変わる仕様忘れる) 登場人物(クラス)として整理する クラス 持つもの できること User email, name login Product title, price - Cart items add, total Order items, status confirm, cancel データと振る舞いが組になり、 業務の構造がそのまま設計図になる ポイント:要件定義の段階から「まとめる」発想を持つと、ヒアリングの抜け漏れに気づきやすい(コードを書く 前から効く) 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 6
  4. 4. コアコンセプト②:ポリモーフィズム 呼び出し側を、相手の種類から切り離す 項目 内容 概念名 ポリモーフィズム(多態性) 一言で 同じメッセージで、相手によって違う振る舞いをさせる 自分の言葉

    呼び出す側は、相手が誰かを気にせず同じ呼び方ができる なぜ重要か if で種類ごとに分岐するコードを減らし、変更に強くなる 具体例 payment.pay(amount) で クレカ / PayPay / 銀行振込 が違う処理を行う 本書での位置づけ OOPの三大要素のうち、もっとも"設計の効果"が出る部分 共通のインターフェースに揃えることで、呼び出し側を一切変えずに種類を増やせる 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 7
  5. 具体例②:決済処理で見る「ポリモーフィズム」 case 文で種類ごとに分岐 def pay(method, amount) case method when :credit

    # クレカ処理 when :paypay # PayPay処理 when :bank # 銀行振込処理 end end 支払い方法が増えるたび pay を 修正 呼び出し側が 種類を全部知っている テストも条件分岐の考慮が必要だったりする 同じ pay メソッドで揃える class CreditCard def pay(amount) # クレカ処理 end end class PayPay def pay(amount) # PayPay処理 end end # BankTransfer も同様 def checkout(payment, amount) payment.pay(amount) # 中身を知らずに呼べる end 新しい決済を追加しても checkout は変えない ポイント:呼び出す側は「お会計お願いします」と頼むだけで、相手がクレカかPayPayかを気にしない。新しい 決済方法を増やしても checkout 側は一切変えずに済む。 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 8
  6. 具体例②(モデリング):業務フローを共通の窓口に揃える 要件: 「会員はクレカ/PayPay/銀行振込で決済できる」 決済方法ごとに別フロー設計 クレカ用の画面遷移 PayPay用の画面遷移 銀行振込用の画面遷移 を それぞれ独立に 設計する

    新しい決済が増えるたびにフロー設計をゼロから QAも全パターン分試験 共通仕様(例:確認画面)の変更が 3か所に波及 「お会計する」共通フローに揃える 共通フロー:商品確認 → 決済方法選択 → 確定 → 完了 その中で 差分だけ 決済方法ごとに定義: 決済方法 差分(決済方法選択の中身) クレカ カード番号入力 PayPay QR読み取り 銀行振込 振込先表示・確認 → 共通フローは 常に1本 ポイント: 「お会計お願いします」という1つの業務行為に揃えれば、業務フロー自体がシンプルになり、新しい 決済が増えても 共通フローは変えずに済む 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 9
  7. 5. コアコンセプト③:継承 共通点をまとめ、差分だけサブクラスに書く 項目 内容 概念名 継承(インヘリタンス) 一言で 共通の構造・振る舞いを親クラスにまとめ、子クラスは差分に集中する 自分の言葉

    「同じ部分」を一箇所にまとめ、 「違う部分」だけ書く仕組み なぜ重要か 重複コードが減り、共通仕様の変更が一箇所で済む 具体例 Product を親に、 Book / CD が共通属性を引き継ぐ 注意点(一般的に言われていること) 「Book は Product の一種である」のように "Is a 関係" "〜の一種である" 関係が成立するときに使う 親クラスを変えると子クラスすべてに波及するため、多段継承は変更コストが跳ね上がる 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 10
  8. 具体例③:商品クラスで見る「継承」 継承を使わない(重複だらけ) class Book def initialize(title, price, author) @title =

    title @price = price @author = author end def display_info puts "#{@title}: ¥#{@price}" end end class CD def initialize(title, price, artist) @title = title @price = price @artist = artist end def display_info puts "#{@title}: ¥#{@price}" end end title price display_info が クラスごとに重複 共通部分を Product に集約 class Product def initialize(title, price) @title = title @price = price end def display_info puts "#{@title}: ¥#{@price}" end end class Book < Product def initialize(title, price, author) super(title, price) @author = author end end # CD < Product も同様 共通仕様の変更は Product 1箇所で済む 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 11
  9. 具体例③(モデリング):業務での "〜の一種である" 関係 を見つける 要件: 「商品は書籍/CD/ダウンロード商品。表示や送料計算が違う」 種別ごとに独立した概念で整理 種別 持つ情報 書籍

    タイトル, 価格, 表示, 送料計算, 著者 CD タイトル, 価格, 表示, 送料計算, アーテ ィスト ダウンロー ド タイトル, 価格, 表示, 送料計算, 配信 URL 共通仕様(タイトル・価格・表示)が 3か所に重複 「カートに入れる」のような業務ルールも 3回定 義 共通仕様の変更が 3か所に波及 共通の親概念「商品」を見つける 商品(共通):タイトル, 価格, 表示, 送料計算, カートに入 る その一種として: 書籍 = 商品 + 著者 CD = 商品 + アーティスト ダウンロード = 商品 + 配信URL → 共通仕様の変更は 「商品」 1か所 で済む → 新しい商品種別が増えても 差分だけ を定義 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 12
  10. 6. 実務との接続 開発プロセスで使われそうな場面 要件定義・業務分析:登場人物・データ・ルールを整理し、どんなクラスが必要かを描く 設計:責任の置き場所/継承で表せる関係か/ポリモーフィズムで揃えられるか を判断する コードレビュー:UMLや図で設計意図を共有する/"このクラス太りすぎ" を指摘し合う 保守・改修:呼び出し側を変えずに種類を増やせるなど、変更に強い構造を作る 現場で聞きそうな言葉

    「このクラス、責任持ちすぎじゃない?」 → 単一責任原則 「この継承、本当に "〜の一種である" 関係になってる?」 「ここ if だらけだから、ポリモーフィズムにできない?」 「このModel、責任持ちすぎだから別クラスに分割しない?」 (Rails文脈) 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 13
  11. 7. 理解度の自己評価 区分 内容 理解できた点 OOPは文法ではなく、ソフトウェアを整理するための考え方である 理解できた点 クラス・ポリモーフィズム・継承の三大要素を、本書+ネットで補完しながら掴めた 理解できた点 UML(クラス図・シーケンス図)は普段Mermaidで書く機会があるので使える

    曖昧な点 OOPの考え方が 実務のどの場面で具体的に生きているか の感覚 曖昧な点 コーディングではなく "設計" の部分(責任の分け方/継承を採用する判断) わからなかった点 Ruby の モジュール (mix-in) や委譲 — 概念として未着手、これから調べたい わからなかった点 関数型プログラミングHaskellとかElixirとか使ってみたい、何作ろう 実務で確認したいこと UML を仕様書に書く文化があるのか/コードベースで読み合う運用なのか 『オブジェクト指向でなぜつくるのか』中間アウトプット 服部潤一 14