0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

『良いコード/悪いコードで学ぶ設計入門』第9章の輪読会資料まとめ

Last updated at Posted at 2025-09-11

はじめに

社内の輪読会で『良いコード/悪いコードで学ぶ設計入門』の第9章「コレクションーネストを解消する構造化技法ー」を担当しました。本記事では、その際に作成した資料を公開します。
(本書ではJavaのコードが掲載されていますが、本記事ではTypeScriptを用いて解説します)

配列でスマートな処理の書き方を紹介

なぜ?:ループの中に条件分岐がネストしていくと、コードが複雑化し、可読性が低下するため。

ゴール:シンプルで理解しやすいコードを書くための技法を学ぶ。

標準メソッドが無いか確認する

コード例

配列にオレンジがあるかどうか確認する処理

❌️for文

const items = [{ name: 'apple' }, { name: 'orange' }, { name: 'grape' }];

let hasOrange = false;

for (let i = 0; i < items.length; i++) {
  if (items[i].name === 'orange') {
    hasOrange = true;
  }
}

✅️someメソッド

1つでも返り値にtrueがあればtrueを返す

const items = [{ name: 'apple' }, { name: 'orange' }, { name: 'grape' }];

const hasOrange = items.some((item) => item.name === 'orange');

ループ中の条件分岐のネストをしない

早期continueでネストを減らす

コード例

年齢30歳以上、身長160cm以上、体重60kg以上の人物を抽出する処理

❌️for文の例

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

let targetUsers = [];

for (let i = 0; i < users.length; i++) {
  if (users[i].age >= 30) {
    if (users[i].height >= 160) {
      if (users[i].weight >= 60) {
        targetUsers.push(users[i]);
      }
    }
  }
}

✅️早期continue

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

let targetUsers = [];

for (let i = 0; i < users.length; i++) {
  if (users[i].age < 30) {
    continue;
  }

  if (users[i].height < 160) {
    continue;
  }

  if (users[i].weight < 60) {
    continue;
  }

  targetUsers.push(users[i])
}

😇filterメソッド

返り値がtrueの要素を返す

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

const targetUsers = users.filter((user) => {
  return user.age >= 30 && user.height >= 160 && user.weight >= 60;
});

breakでもネスト解消できる

全員がBMIで普通体重かどうか(18.50〜24.99以下)

コード例

❌️ネストしている

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

let isAllHealthy = false;

for (let i = 0; i < users.length; i++) {
  const bmi = users[i].weight * Math.pow(users[i].height, 2);

  if (bmi > 18.5) {
    if (bmi < 25) {
      isAllHealthy = true;
    }
  }
}

✅️breakを使用

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

let isAllHealthy = true;

for (let i = 0; i < users.length; i++) {
  const bmi = users[i].weight * Math.pow(users[i].height, 2);

  if (bmi <= 18.5) {
    isAllHealthy = false;
    break;
  }

  if (bmi > 25) {
    isAllHealthy = false;
  }
}

😇everyメソッドを使用

すべての返り値がtrueならtrueを返す

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
];

const isAllHealthy = users.every((user) => {
  const bmi = user.weight * Math.pow(user.height, 2);

  return bmi <= 18.5 && bmi > 25;
});

処理のカプセル化

配列操作ロジックと、その操作結果を使うロジックを分離する。

コード例

❌️体重の合計を計算する処理が重複している

type User = {
  name: string;
  weight: number;
};

function processReport(users: User[]) {
  let totalWeight = 0;

  for (let i = 0; i < users.length; i++) {
    totalWeight += users[i].weight;
  }

  console.log(`合計体重は ${totalWeight} kg です。`);
  // ... その他のレポート処理
}

function checkHealthStatus(users: User[]) {
  let totalWeight = 0;

  for (let i = 0; i < users.length; i++) {
    totalWeight += users[i].weight;
  }

  if (totalWeight > 200) {
    console.log('グループの合計体重が200kgを超えています。');
  }
}

✅️外部関数を呼び出すことで、体重の合計の計算処理が重複しない

type User = {
  name: string;
  weight: number;
};

// 体重の合計を計算する処理を専用の関数としてカプセル化
function calculateTotalWeight(users: User[]) {
  // reduceで合計を計算
  return users.reduce((total, user) => total + user.weight, 0);
}

function processReport(users: User[]) {
  const totalWeight = calculateTotalWeight(users);

  console.log(`合計体重は ${totalWeight} kg です。`);
  // ... その他のレポート処理
}

function checkHealthStatus(users: User[]) {
  const totalWeight = calculateTotalWeight(users);

  if (totalWeight > 200) {
    console.log('グループの合計体重が200kgを超えています。');
  }
}

まとめ

  • 配列の標準メソッドを知ることが大事
  • 車輪の再発明はしない(学習のためならOK)
  • 処理は(なるべく)共通化する

クイズ

<メソッド> に何のメソッドが入るか考えよう❗️

すべて出来れば君も配列マスターだ❗️

第1問

すべてのユーザーの体重を-3する

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const healthyUsers = users.メソッド((user) => {
  return {
    ...user,
    weight: user.weight - 3,
  };
});
解答
const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const healthyUsers = users.map((user) => {
  return {
    ...user,
    weight: user.weight - 3,
  };
});

第2問

配列の1番目と2番目のユーザーを抽出する(元の配列は変更せずに)

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const targetUsers = users.メソッド(1, 3);
解答
const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const targetUsers = users.slice(1, 3);

第3問

配列の最後から見て最初に年齢が25歳のユーザーを取得する

const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const targetUser = users.メソッド(user => user.age === 25);
解答
const users = [
  { name: 'takeshi', age: 30, height: 172, weight: 70 },
  { name: 'hanako', age: 27, height: 161, weight: 43 },
  { name: 'kenta', age: 25, height: 188, weight: 46 },
  { name: 'satoshi', age: 25, height: 180, weight: 60 },
];

const targetUser = users.findLast(user => user.age === 25);

参考記事

最後に

GoQSystemでは一緒に働いてくれる仲間を募集中です!

ご興味がある方は以下リンクよりご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?