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

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

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

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