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

エンジニアとして高みを目指す、 利益を生み出す設計の考え方 / design-for-profit

Avatar for MinoDriven MinoDriven
September 24, 2025

エンジニアとして高みを目指す、 利益を生み出す設計の考え方 / design-for-profit

こちらのイベントの登壇資料です。

エンジニアとして高みを目指す、 利益を生み出す設計の考え方
https://hireroo.connpass.com/event/365195/

Avatar for MinoDriven

MinoDriven

September 24, 2025
Tweet

More Decks by MinoDriven

Other Decks in Programming

Transcript

  1. © DMM 自己紹介 ミノ駆動 ( @MinoDriven ) 合同会社DMM.com プラットフォーム開発本部 第3開発部

    DeveloperProductivityGroup DMMプラットフォームの設計を改善し 開発生産性向上を図るのがミッション 2
  2. © DMM あなたが経営者なら誰に高給を支払いますか? 1. 利益向上を狙ったシステム要件を策定し、実績を出し続けている人 2. 実績はないけどIT資格を沢山持っている人 3. 開発効率を高めるシステム構造を設計したり、 不具合等による損失を抑制する構成や構造を設計できる人

    4. 「私はReact使いたいから、とにかくReact使える開発にアサインして ほしい」と言い続けている人 私なら1と3の人に高給を支払います。 利益に寄与していることが明確だからです。 21
  3. © DMM こんなケース、身に覚えがありませんか • せっかく新機能を開発したのにあまり使われないケース • 顧客の要望通りのものを作ったはずなのに 「求めていたのはこんな機能じゃないんだが」と失望されるケース • コードが複雑すぎて実装がなかなか進まず、

    いつまで経っても新機能をリリースできないケース • リリースしても不具合が続出し、顧客離れを起こしているケース このような利益創出困難なケースは枚挙に暇がありません 利益はソフトウェア開発のすぐ隣にいます 24
  4. © DMM 定義が不適切だと目的達成困難 34 【目的】 ダイエットしたい 【目標】 ・体重40kg以下にすること 【手段】 ・絶食

    ・ダイエット番組を見るだけ 身長170cmの人が40kgまで体重を 落とすと明らかに健康に害があります 絶食は健康を害したり、 リバウンドの原因になります ダイエット番組見ただけでは 絶対に痩せません!
  5. © DMM 目的、目標、手段は、 私たちが開発するソフトウェアでも同じことが言えます。 顧客の要求(目的)をかなえるための手段として、 私たちはソフトウェアを開発しているのです。 35 目的 手段 商品を売買したい

    ショッピングサイト 動画を視聴したい 動画投稿サイト 遊びたい ゲームソフト 効率良く勉強したい 学習サイト 私たちは「手段」を開発している
  6. © DMM 「目標」は要件や仕様に相当する 36 【目的】 注文数を正しく表現したい 【目標】 注文数は1〜200であること 【手段】 目的を満たすソースコード

    システムを不具合なく的確に機能させるには、仕 様を決める必要があります。 例えば注文数は負数だと不具合になりますし、 5000兆個といった非現実的な数量も問題があ ります。 出荷業務の都合などを考慮し仕様を決めます。 こうした要件や仕様が目標に相当します。 目標を満たすようにコードを実施します。
  7. © DMM 目的、目標、手段は、ソフトウェア開発では次の位置付けと言えます 37 一般的な定義 ソフトウェア開発における位置付け 目的 目指すべき状態、 行動のねらい (顧客の)要求

    目標 目的達成の具体条件 機能要件、仕様、制約 手段 目的達成に用いる 方法や道具 ソースコード そしてソフトウェア開発の成功と利益向上のためにも 目的、目標、手段の適切な定義が重要です
  8. © DMM 45 // 注文明細クラス class OrderItem { int orderItemId;

    int orderId; int productId; int unitPrice; int quantity; // 注文数 } たとえばショッピングサイトにおける「注文」を考えてみます。 注文明細クラスを次のように実装したとします。 quantityは注文数です。
  9. © DMM 47 class Validator { boolean isValidQuantity(OrderItem orderItem) {

    return 1 <= orderItem.quantity && orderItem.quantity <= 200; } } 正しい注文数だけを受け付けられるよう、 次のようなバリデーションをどこかに実装するかもしれません。 しかしこの実装では、以下のような問題が生じる可能性があります。 • バリデーションを呼び忘れるとバグになる • 別の箇所に重複したコードが実装される可能性 • 注文数の仕様変更時、あちこち探し回らなければならない
  10. © DMM 48 【目的】 注文数を正しく表現したい 【目標】 注文数は1〜200であること 【手段】 OrderItem.quantity 【手段】

    Validator.isValidQuantityメソッド 目的に対して手段がバラバラになっているのが原因 家電に例えるとドライヤーがバラバラに提供されているような状態
  11. © DMM 50 class Quantity { private static final int

    MIN = 1; private static final int MAX = 200; final int value; Quantity(final int value) { if (value < MIN || MAX < value) { throw new IllegalArgumentException("注文数は1以上200以下で指定してください"); } this.value = value; } Quantity add(final Quantity other) { return new Quantity(value + other.value); } } カプセル化とはデータとそのデータを操作するロジックをひとま とめにすること。これで正しい注文数を確実に表現できる。
  12. © DMM 51 class YearlyPointBonus { int value; YearlyPointBonus(PurchaseHistory purchaseHistory,

    boolean isGoldMember) { value = (int)(purchaseHistory.yearlyAmount() * 0.01); if (isGoldMember) { value += 10000; } } } 会員ランク 年間ポイントボーナス仕様 一般会員 年間購入費の1% ゴールド会員 年間購入費の1% + 10000ポイント ショッピングサイトにおけるポイントボーナスを考えてみます。 この仕様を下記のように実装したとします。
  13. © DMM 52 class YearlyPointBonus { int value; YearlyPointBonus(PurchaseHistory purchaseHistory,

    boolean isGoldMember) { value = (int)(purchaseHistory.yearlyAmount() * 0.02); if (isGoldMember) { value += 10000; } } } 会員ランク 年間ポイントボーナス仕様 一般会員 年間購入費の1% ゴールド会員 年間購入費の2% + 10000ポイント ゴールド会員側の仕様が2%に変わり、0.02に実装修正すると、 一般会員側が正しく計算できなくなります。バグになります!
  14. © DMM 53 【目的】 一般会員の年間ポイントボーナスを 計算したい 【目標】 年間購入費の1% 【手段】 YearlyPointBonusクラス

    【目的】 ゴールド会員年間ポイントボーナスを 計算したい 【目標】 年間購入費1% + 10000ポイント 手段であるYearlyPointBonusが 異なる目的に使い回されているのが原因
  15. © DMM 54 【目的】 一般会員の年間ポイントボーナスを 計算したい 【目標】 年間購入費の1% 【手段】 RegularYearlyPointBonusクラス

    【目的】 ゴールド会員年間ポイントボーナスを 計算したい 【目標】 年間購入費1% + 10000ポイント 目的それぞれで手段を分ける これが関心の分離 【手段】 GoldYearlyPointBonusクラス
  16. © DMM 55 class RegularYearlyPointBonus { private static final double

    POINT_RATE = 0.01; final int value; RegularYearlyPointBonus(final PurchaseHistory purchaseHistory) { value = (int)(purchaseHistory.yearlyAmount() * POINT_RATE); } } class GoldYearlyPointBonus { private static final double POINT_RATE = 0.01; private static final int FIXED_POINT_BONUS = 10000; final int value; GoldYearlyPointBonus(final PurchaseHistory purchaseHistory) { value = (int)(purchaseHistory.yearlyAmount() * POINT_RATE) + FIXED_POINT_BONUS; } } このように目的ごとに分離することで コード変更影響が生じなくなります。変更に強くなります。
  17. © DMM 56 ボールペン のり 付箋 はさみ ホッチキス 修正液 予約注文

    クラス 抽選注文 クラス サブスク注文 クラス 普通注文 クラス 別に難しいことを言ってるわけではあ りません。 みなさん、普段道具を目的ごとに収納 していますよね。 同様にクラスも目的ごとに分 けましょうということです。 目的ごとに取り扱うデータや ロジックが違います。
  18. © DMM 58 【目標(仕様)】 年間購入費の1% 【手段】 YearlyPointBonusクラス 【目標(仕様)】 年間購入費1% +

    10000ポイント 目的は認知困難です。 仕様書だけ眺めていても目的は分かりません。 「何のため(目的)の仕様なのか」を考えることが大事です。
  19. © DMM まとめ • 私たちは利益を上げるためにソフトウェアを開発しています。 • より高いキャリアを目指すには、利益を意識しましょう。 利益を生み出すことを意図して開発したり、 ITスキルを活用できるようになりましょう。 •

    利益向上の基本は、目的達成です。 目的達成には、目的−目標−手段の関係性の整理が必須です。 • 目的−目標−手段の関係は、ソフトウェアの機能や 開発力を高めるためのモジュール構造の設計を大きく左右します。 目的を意識して機能要件を策定したり、 構造設計できるようになりましょう。 59