1 . 次のコードは、設定値への依存の仕方があまりよくありません。結合度の観点から適切な改善はどれでしょうか?
function connectDb() {
const client = new DbClient({
host: 'db.example.internal',
port: 5432,
user: 'app_user',
password: 'secret'
});
return client;
}
A.
DbClient のクラス名を短くする
B.
host や user などの設定値を、直接コードにベタ書きするのではなく設定オブジェクトや環境変数から受け取る
C.
port を 3306 に変更する
D.
password を空文字にする
解説: DB接続情報を関数内にベタ書きすると、接続先が変わるたびにコード修正が必要になり、設定との結合度が非常に高くなります。設定オブジェクトや環境変数などに外だしし、呼び出し側から渡すことで、コードと環境設定の結合度を下げつつ、再利用性とテストのしやすさを高めることができます。
2 . 次の2つの関数は、どちらもログイン状態に依存する処理です。結合度/凝集度の観点から、どのような改善が望ましいでしょうか?
function showMyPage() {
if (!window.currentUser) {
throw new Error('ログインしていません');
}
// 画面描画
}
function showSettings() {
if (!window.currentUser) {
throw new Error('ログインしていません');
}
// 設定画面描画
}
A.
currentUser を null にする
B.
window.currentUser を使うのをやめ、ログインチェックを共通のガード関数やミドルウェアにまとめる
C.
エラーを投げるのをやめる
D.
関数名を変える
解説: 両方の関数がグローバル変数 `window.currentUser` に依存し、同じログインチェックロジックを重複して持っています。これは強結合かつ低凝集な状態です。認証ミドルウェアや共通のガード関数にログインチェックをまとめ、画面側は「認証済みユーザー」を前提に描画するようにすると、責務が整理されます。
3 . 次のクラスは、リポジトリとサービスが分かれていません。結合度/凝集度の観点から、改善ポイントはどこでしょうか?
class UserManager {
constructor(db) {
this.db = db;
}
async findById(id) {
return this.db.query('SELECT * FROM users WHERE id = ?', [id]);
}
async changeEmail(id, newEmail) {
const user = await this.findById(id);
// ドメインルールのチェック(省略)
await this.db.execute('UPDATE users SET email = ? WHERE id = ?', [newEmail, id]);
}
}
A.
SQLを使っていること
B.
db をコンストラクタで受け取っていること
C.
データアクセス(リポジトリ)とドメインルール適用(サービス)が同じクラスに混在していること
D.
async/await を使っていること
解説: UserManager が「DBへの問い合わせ」と「ドメインルールの適用」の両方を担当しています。リポジトリ(データアクセス)とサービス(ビジネスルール)は役割を分けておくと、各モジュールの凝集度が高まり、テスト・変更・再利用がしやすくなります。
4 . 次のコードは、法則的には「デメテルの法則(LoD)」に違反しやすいパターンです。結合度の観点から、最も問題になりやすい点はどれでしょうか?
function getCustomerCity(order) {
return order.customer.address.city;
}
A.
return を使っていること
B.
city を使っていること
C.
order → customer → address → city とオブジェクトチェーンをたどりすぎて、内部構造に依存していること
D.
関数名が get から始まっていること
解説: `order.customer.address.city` のようにオブジェクトチェーンを深くたどると、「order の中身がどう実装されているか」に強く依存することになります。これはデメテルの法則に反し、結合度を高めてしまいます。`order.getCustomerCity()` のようなメソッドを用意するなど、問合せ先をなるべく直接の隣人に留めることで、変更に強い設計にできます。
5 . 次の関数は、1つのパラメータオブジェクトに大量の値を詰め込んでいます。凝集度の観点から、何が問題になりやすいでしょうか?
function createReport(params) {
// params = {
// userId, userName, userAge,
// projectId, projectName,
// startDate, endDate,
// includePrivate, includeDeleted,
// ...
// }
// 複雑なレポート生成処理
}
A.
オブジェクトリテラルを使っていること
B.
パラメータが1つだけであること
C.
関係の薄い情報が1つの「なんでも詰め込み」オブジェクトに集められていて、関係性のまとまり(凝集)が見えにくいこと
D.
コメントを書いていること
解説: 「params」という1つの入れ物に、ユーザー情報・プロジェクト情報・期間・フラグなどの異なる関心ごとが詰め込まれており、何がまとまりなのか分かりづらくなっています。レポート条件・ユーザー条件・プロジェクト条件など、意味のまとまりごとに型やオブジェクトを分けることで、情報の凝集度を高め、理解しやすく変更しやすい設計になります。
6 . 次の2つのクラスは、互いにお互いを new しています。結合度の観点から、どのような問題がありますか?
class A {
constructor() {
this.b = new B(this);
}
}
class B {
constructor(a) {
this.a = a;
}
}
A.
クラス名が1文字で短すぎる
B.
A と B が循環参照しており、互いに強く結合している
C.
constructor を使っていること
D.
this を保存していること
解説: A が B を new し、B が A を引数で受け取る形になっており、循環依存・強結合の状態です。片方を変更するともう片方にも影響しやすく、テストや差し替えが困難になります。インターフェースを導入して依存方向を一方通行にする、ファクトリを挟むなどして、循環依存を避ける設計が望ましいです。
7 . 次の2つの関数は、一見別の目的に見えますが、結合度/凝集度の観点からどのような改善が望ましいでしょうか?
function formatUserAddress(user) {
return `${user.postalCode} ${user.pref} ${user.city} ${user.street}`;
}
function formatShippingLabel(order) {
const user = order.user;
return `${user.postalCode} ${user.pref} ${user.city} ${user.street}`;
}
A.
住所情報を user ではなく order にまとめる
B.
住所フォーマット処理を共通のヘルパーとして切り出し、両方の関数から利用する
C.
city を表示しないようにする
D.
order.user をグローバル変数にする
解説: 同じ住所フォーマット処理が2つの関数に重複しており、DRY違反でもありますが、「住所のフォーマット」という関心ごとが分散していて凝集度も低くなっています。住所フォーマットを1つの関数に集約することで、そのモジュールが住所表現の責務を持つ「高凝集」な形になり、修正も1か所で済みます。
8 . 次のクラスは、ログ出力と業務ロジックが混ざっています。凝集度/結合度の観点から、どのような改善が望ましいでしょうか?
class PaymentService {
constructor(http) {
this.http = http;
}
async pay(order) {
console.log('PAYMENT START', new Date(), order.id);
const result = await this.http.post('/payments', { orderId: order.id });
console.log('PAYMENT END', new Date(), order.id, result.status);
return result;
}
}
A.
console.log を減らし、1か所だけにする
B.
ログ出力を別のロガーに委譲し、PaymentService は「支払い処理」に集中させる
C.
result を返さないようにする
D.
this.http をグローバル変数にする
解説: 支払い処理とログ出力が同じメソッド内に混在しており、責務が増えて凝集度が下がっています。ログはロガーインターフェースに委譲し、PaymentService は支払いのドメインロジックに集中させることで高凝集になります。ロガーは引数やDIで渡すことで、結合度も下げられます。
9 . 次の関数は、複数のオブジェクトにまたがって状態を更新しています。結合度/凝集度の観点から、どのような設計リスクがありますか?
function completeTask(task, user, project) {
task.completed = true;
task.completedAt = new Date();
user.completedTaskCount++;
project.lastActivityAt = new Date();
}
A.
Date コンストラクタを2回呼んでいること
B.
task, user, project の3つの集約にまたがる更新ロジックを1つの関数にまとめており、複数のものと強く結合している
C.
completed フラグを true にしていること
D.
project に lastActivityAt を持たせていること
解説: 1つの関数が、task・user・project の3つの異なるオブジェクトに対する状態更新を一度に行っており、多くのものと結合した「何でも屋」になっています。どれか1つの仕様が変わるたびにこの関数も影響を受けるため、結合度が高すぎます。更新の責任をどの集約が持つべきかを見直し、モジュールごとに責務を整理する必要があります。
10 . 次のコードは、内部データ構造に強く依存した取り方をしています。結合度の観点から、最も問題となる点はどれでしょうか?
function getFirstItemPrice(cart) {
return cart.items[0].price;
}
A.
price プロパティ名を使っていること
B.
items 配列のインデックス0に直接アクセスしていること
C.
cart を引数で受け取っていること
D.
関数名の先頭が get になっていること
解説: `cart.items[0]` のように内部構造(配列で先頭要素が必ず存在する前提)にベッタリ依存しているため、cart の実装が変わるとすぐ壊れる強い結合になっています。`getFirstItem()` のようなメソッドや、合計金額を取得する専用APIなど、もう一段抽象化されたインターフェース越しにやり取りすることで結合度を下げられます。