SuperAPI AI Directory

intent-based-dedup

Coding & development

View repository

Updated 10-16 09:57

About this skill

Intent-Based Commonalization Judgment

Commonalize based on whether the intent (purpose) is the same, rather than whether the literal text is the same.

Core Principles

The simplistic thinking of "if the literal text is the same, commonalize it" is dangerous. Judge with the match of intent and purpose as the top priority.

Even if the code expression is identical, you must not commonalize it if the business logic purpose differs. Conversely, even if the expression differs, you should unify it if the purpose is the same.

Decision Matrix

Literal Text Intent Judgment Action
Same Same Commonalize ◎ Apply the DRY principle and extract into a common function
Different Same Unify ◎ Unify into one of the implementations
Same Different Commonalize ✗ Commonalization strictly prohibited(Most important)
Different Different Commonalize ✗ No consideration needed

Decision Flow

重複コードを発見した
    ↓
2つのコードの「目的」は同じか?
    ├─ YES → 字面は同じか?
    │         ├─ YES → 共通化する(標準的DRY)
    │         └─ NO → 実装方式を統一する
    └─ NO → 字面は同じか?
              ├─ YES → ⚠ 共通化禁止(最も危険なケース)
              └─ NO → 何もしない

Antipattern Detection

If you find the following patterns, they are signs of DRY misapplication:

❌ 異なるドメイン概念に同じユーティリティ関数を使い回す
❌ "たまたま同じ計算式" を共通関数に抽出
❌ 共通化した関数に if (type == A) / else if (type == B) の分岐が増える
❌ 共通関数名が汎用的すぎる(calculate, process, transform等)
❌ 一方の仕様変更時に「もう一方も壊れないか」を心配する
❌ 共通関数のパラメータが増殖し続ける

Details of the 4 Patterns

1. Literal text same × Intent same → Commonalize

The case where the DRY principle is correctly applied.

// ❌ 同じ目的の処理が2箇所に重複
fn report_even_squares(numbers: &[i32]) -> Vec<i32> {
    numbers.iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * x)
        .collect()
}

fn display_even_squares(numbers: &[i32]) -> Vec<i32> {
    numbers.iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * x)
        .collect()
}

// ✅ 共通化: 同じ目的なので1つにまとめる
fn even_squares(numbers: &[i32]) -> Vec<i32> {
    numbers.iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * x)
        .collect()
}

2. Literal text different × Intent same → Unify

The case where the same purpose is written in different implementation styles.

// パターンA: 関数型アプローチ
fn total_a(values: &[i32]) -> i32 {
    values.iter().fold(0, |acc, &x| acc + x)
}

// パターンB: 命令型アプローチ
fn total_b(values: &[i32]) -> i32 {
    let mut sum = 0;
    for &v in values { sum += v; }
    sum
}

// ✅ どちらか一方に統一(チーム規約に従う)
fn total(values: &[i32]) -> i32 {
    values.iter().sum()
}

3. Literal text same × Intent different → Commonalization prohibited (most important)

The most dangerous case. Even if the code is formally the same, the business purpose differs.

// ケース1: 攻撃力計算(地形倍率を適用)
fn adjusted_attack_points(weapon_points: &[i32]) -> Vec<i32> {
    weapon_points.iter()
        .map(|&x| x * 2)
        .filter(|&x| x % 2 == 0)
        .map(|x| x * x)
        .collect()
}

// ケース2: 武器加工費用計算
fn weighted_crafting_costs(amounts: &[i32]) -> Vec<i32> {
    amounts.iter()
        .map(|&x| x * 2)
        .filter(|&x| x % 2 == 0)
        .map(|x| x * x)
        .collect()
}

The literal text is the same, but it must not be commonalized. Reason:

  • A specification change to attack power (e.g., the terrain multiplier changes to 3x) breaks the cost calculation
  • A change to the cost calculation (e.g., applying a tax rate) breaks the attack power calculation
  • Different reasons for change = commonalizing improperly increases coupling
// ❌ 危険な共通化
fn apply_formula(values: &[i32]) -> Vec<i32> { /* ... */ }

let attack = apply_formula(&weapon_points);  // 攻撃力?
let cost = apply_formula(&amounts);          // 費用?
// → 一方を変更すると他方が壊れる

4. Literal text different × Intent different → Do nothing

No consideration needed. Maintain them as independent pieces of code.

Criteria for Judging "Identity of Intent"

Questions for determining whether the purpose is the same:

  1. Reason-for-Change Test: When one specification changes, does the other also change for the same reason?

    • YES → Intent is the same (commonalization allowed)
    • NO → Intent is different (commonalization not allowed)
  2. Naming test: Can you give the shared function a name that makes sense in both contexts?

    • YES → Same intent
    • NO (only a generic name can be given) → Different intent
  3. Domain Test: Do the two pieces of code represent the same domain concept?

    • YES → Same intent
    • NO → Different intent

Application guidelines

Recommended

  • Code reviews where "there is similar code" is reported
  • Situations where you are about to extract a shared function during refactoring
  • When a utility function is reused for multiple domain concepts
  • When the parameters of a shared function start to proliferate

Avoid over-application

  • Boilerplate that is clearly for the same purpose (config initialization, logging, etc.)
  • Utilities provided by frameworks/libraries
  • Mathematically identical operations (trigonometric functions, etc.; pure calculations that do not depend on purpose)

Review perspectives

Checkpoints during code review:

  1. Confirming intent: Do the two pieces of code to be shared have the same "purpose"?
  2. Separating reasons for change: Will a specification change in one affect the other?
  3. Naturalness of naming: Does the shared name make sense in both contexts?
  4. Parameter proliferation: Are conditionals or flags increasing in the shared function?
  5. Domain boundaries: Are you mixing different domain concepts into one function?

Related skills (recommended reading)

When using this skill, also refer to the following skills:

  • domain-building-blocks: The judgment not to share isomorphic code from different domains
  • first-class-collection: The judgment to treat collections with the same structure as different types if their intent differs
  • package-design: The judgment to separate packages if the reason for change differs even when the code is the same