detect-code-smells

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Code Smells Detector

代码坏味道检测器

Overview

概述

This skill analyzes PHP codebases for code smells (symptoms of deeper problems) and generates detailed reports with severity levels and refactoring recommendations.
本工具可分析PHP代码库中的代码坏味道(深层问题的外在表现),并生成包含严重等级和重构建议的详细报告。

Code Smells Catalog

代码坏味道目录

SmellDescriptionDetectionSeverity
God ClassClass doing too much>500 LOC, >15 methodsCRITICAL
Feature EnvyMethod uses another class moreForeign calls > own callsWARNING
Data ClumpsSame fields appear together3+ repeated params/fieldsWARNING
Long Parameter ListMethod with many params>4 parametersWARNING
Long MethodMethod doing too much>50 LOCWARNING
Primitive ObsessionPrimitives instead of objectsstring $email, int $moneyINFO
Message ChainsLong getter chains->get()->get()->get()WARNING
Inappropriate IntimacyClasses knowing too muchDirect field accessWARNING
坏味道类型描述检测方式严重等级
God Class类承担过多职责代码行数>500、方法数>15CRITICAL
Feature Envy方法过度依赖其他类外部调用次数超过自身调用次数WARNING
Data Clumps相同字段重复出现3个及以上重复参数/字段WARNING
Long Parameter List方法包含过多参数参数数量>4WARNING
Long Method方法逻辑过于冗长代码行数>50WARNING
Primitive Obsession过度使用基本类型而非对象如string $email、int $moneyINFO
Message Chains过长的 getter 调用链如->get()->get()->get()WARNING
Inappropriate Intimacy类之间过度了解内部细节直接访问其他类的字段WARNING

Detection Patterns

检测模式

God Class Detection

God Class 检测

bash
undefined
bash
undefined

Large classes (>500 lines)

大型类(>500行)

Grep: "^class " --glob "**/*.php"
Grep: "^class " --glob "**/*.php"

Then check file line counts

然后检查文件行数

Many public methods (>15)

大量公共方法(>15个)

Grep: "public function " --glob "**/*.php"
Grep: "public function " --glob "**/*.php"

Count per file

按文件统计数量

Many dependencies (>8)

大量依赖(>8个)

Grep: "__construct" --glob "**/*.php" -A 20
Grep: "__construct" --glob "**/*.php" -A 20

Count constructor parameters

统计构造函数参数数量

Problematic names

有问题的类名

Grep: "class.*Manager|class.*Handler|class.*Helper|class.*Util|class.Processor" --glob "**/.php"

**Indicators:**
- Class > 500 lines → CRITICAL
- Class > 15 public methods → CRITICAL
- Class > 8 constructor dependencies → WARNING
- Class name contains Manager, Handler, Helper, Util → INFO
Grep: "class.*Manager|class.*Handler|class.*Helper|class.*Util|class.Processor" --glob "**/.php"

**判定指标:**
- 类代码行数>500 → CRITICAL
- 类公共方法数>15 → CRITICAL
- 类构造函数依赖>8 → WARNING
- 类名包含Manager、Handler、Helper、Util → INFO

Feature Envy Detection

Feature Envy 检测

bash
undefined
bash
undefined

Methods using other class data excessively

过度使用其他类数据的方法

Grep: "$this->[a-z]+->get[A-Z]" --glob "**/*.php"
Grep: "$this->[a-z]+->get[A-Z]" --glob "**/*.php"

Multiple calls to same foreign object

多次调用同一外部对象

Grep: "$[a-z]+->.$[a-z]+->" --glob "**/.php"
Grep: "$[a-z]+->.$[a-z]+->" --glob "**/.php"

Getters called more than own methods

Getter调用次数超过自身方法调用

Grep: "function [a-z]+(" --glob "**/*.php" -A 30
Grep: "function [a-z]+(" --glob "**/*.php" -A 30

Analyze method bodies for foreign vs own calls

分析方法体中外部调用与自身调用的比例


**Indicators:**
- Method calls other object's methods > own methods → WARNING
- Multiple chained calls to foreign object → INFO
- Method only transforms data from another class → WARNING

**判定指标:**
- 方法调用外部对象的次数超过自身方法 → WARNING
- 多次链式调用外部对象 → INFO
- 方法仅转换来自其他类的数据 → WARNING

Data Clumps Detection

Data Clumps 检测

bash
undefined
bash
undefined

Repeated parameter groups in constructors

构造函数中重复出现的参数组

Grep: "__construct(" --glob "**/*.php" -A 10
Grep: "__construct(" --glob "**/*.php" -A 10

Look for patterns: (string $x, string $y, string $z) appearing multiple times

查找重复模式:如(string $x, string $y, string $z)多次出现

Repeated parameter groups in methods

方法中重复出现的参数组

Grep: "function [a-z]+(" --glob "**/*.php"
Grep: "function [a-z]+(" --glob "**/*.php"

Look for same 3+ parameter combinations

查找3个及以上参数的重复组合

Multiple classes with same field groups

多个类中重复出现的字段组

Grep: "(private|readonly) (string|int|float)" --glob "**/*.php"
Grep: "(private|readonly) (string|int|float)" --glob "**/*.php"

Detect repeated field patterns

检测重复的字段模式


**Common Data Clumps:**
- `$street, $city, $zipCode, $country` → Address Value Object
- `$startDate, $endDate` → DateRange Value Object
- `$amount, $currency` → Money Value Object
- `$firstName, $lastName, $email` → Contact/Person Value Object

**常见数据泥团:**
- `$street, $city, $zipCode, $country` → 可提取为Address值对象
- `$startDate, $endDate` → 可提取为DateRange值对象
- `$amount, $currency` → 可提取为Money值对象
- `$firstName, $lastName, $email` → 可提取为Contact/Person值对象

Long Parameter List Detection

Long Parameter List 检测

bash
undefined
bash
undefined

Methods with many parameters

包含大量参数的方法

Grep: "function [a-z]+(" --glob "**/*.php"
Grep: "function [a-z]+(" --glob "**/*.php"

Count parameters (comma-separated)

统计参数数量(按逗号分隔)

Constructors with many parameters

包含大量参数的构造函数

Grep: "__construct(" --glob "**/*.php" -A 15
Grep: "__construct(" --glob "**/*.php" -A 15

Count parameters

统计参数数量


**Thresholds:**
- 4+ parameters → INFO
- 6+ parameters → WARNING
- 8+ parameters → CRITICAL

**阈值:**
- 4个及以上参数 → INFO
- 6个及以上参数 → WARNING
- 8个及以上参数 → CRITICAL

Long Method Detection

Long Method 检测

bash
undefined
bash
undefined

Find method definitions and count lines until closing brace

查找方法定义并统计到闭合大括号的行数

Grep: "function [a-z]+(" --glob "**/*.php" -A 60
Grep: "function [a-z]+(" --glob "**/*.php" -A 60

Analyze method length

分析方法长度

Nested control structures (indicator of complexity)

嵌套控制结构(复杂度指标)

Grep: "if\s*(.{.if\s(" --glob "**/.php" --multiline

**Thresholds:**
- 30+ lines → INFO
- 50+ lines → WARNING
- 100+ lines → CRITICAL
Grep: "if\s*(.{.if\s(" --glob "**/.php" --multiline

**阈值:**
- 30行及以上 → INFO
- 50行及以上 → WARNING
- 100行及以上 → CRITICAL

Primitive Obsession Detection

Primitive Obsession 检测

bash
undefined
bash
undefined

String parameters that should be Value Objects

应替换为值对象的字符串参数

Grep: "string $email|string $phone|string $url|string $currency|string $country" --glob "**/*.php"
Grep: "string $email|string $phone|string $url|string $currency|string $country" --glob "**/*.php"

Integer amounts

表示金额的整数

Grep: "int $amount|int $price|int $total|int $money|int $cents" --glob "**/*.php"
Grep: "int $amount|int $price|int $total|int $money|int $cents" --glob "**/*.php"

Float for money

表示金额的浮点数

Grep: "float $amount|float $price|float $money" --glob "**/*.php"
Grep: "float $amount|float $price|float $money" --glob "**/*.php"

String status/type

表示状态/类型的字符串

Grep: "string $status|string $type|string $state" --glob "**/*.php"
Grep: "string $status|string $type|string $state" --glob "**/*.php"

Magic strings

魔法字符串

Grep: "=== 'pending'|=== 'active'|=== 'completed'|=== 'draft'" --glob "**/*.php"

**Should be Value Objects:**
- Email addresses → Email
- Phone numbers → PhoneNumber
- URLs → Url or Uri
- Money amounts → Money (with currency)
- Dates/periods → DateRange, Period
- Identifiers → UserId, OrderId, etc.
- Status/Type → Enum
Grep: "=== 'pending'|=== 'active'|=== 'completed'|=== 'draft'" --glob "**/*.php"

**应替换为值对象的场景:**
- 邮箱地址 → Email
- 电话号码 → PhoneNumber
- URL → Url或Uri
- 金额 → Money(包含货币类型)
- 日期/时间段 → DateRange、Period
- 标识符 → UserId、OrderId等
- 状态/类型 → 枚举(Enum)

Message Chains Detection

Message Chains 检测

bash
undefined
bash
undefined

Long getter chains

过长的getter调用链

Grep: "->get[A-Z][a-z]+()->get[A-Z][a-z]+()" --glob "**/*.php"
Grep: "->get[A-Z][a-z]+()->get[A-Z][a-z]+()" --glob "**/*.php"

Triple or more chains

三次及以上的调用链

Grep: "->.->.->" --glob "**/*.php"
Grep: "->.->.->" --glob "**/*.php"

Law of Demeter violations

违反迪米特法则的情况

Grep: "$this->[a-z]+->get[A-Z].->get[A-Z]" --glob "**/.php"

**Indicators:**
- 2 chained getters → INFO
- 3+ chained getters → WARNING
- Chains in loops → CRITICAL
Grep: "$this->[a-z]+->get[A-Z].->get[A-Z]" --glob "**/.php"

**判定指标:**
- 2次链式getter调用 → INFO
- 3次及以上链式getter调用 → WARNING
- 循环中的调用链 → CRITICAL

Inappropriate Intimacy Detection

Inappropriate Intimacy 检测

bash
undefined
bash
undefined

Direct public property access

直接访问公共属性

Grep: "$[a-z]+->(?!get|set|is|has|can)[a-z]+" --glob "**/*.php"
Grep: "$[a-z]+->(?!get|set|is|has|can)[a-z]+" --glob "**/*.php"

Friend classes accessing private state (via reflection)

友元类通过反射访问私有状态

Grep: "ReflectionClass|ReflectionProperty|setAccessible" --glob "**/*.php"
Grep: "ReflectionClass|ReflectionProperty|setAccessible" --glob "**/*.php"

Classes knowing internal structure

类了解其他类的内部结构

Grep: "->getInternalState|->getRawData|->getFields" --glob "**/*.php"
undefined
Grep: "->getInternalState|->getRawData|->getFields" --glob "**/*.php"
undefined

Report Format

报告格式

markdown
undefined
markdown
undefined

Code Smells Analysis Report

代码坏味道分析报告

Summary

摘要

SmellCriticalWarningInfo
God ClassXX-
Feature Envy-XX
Data Clumps-X-
Long Parameter ListXXX
Long Method-XX
Primitive Obsession-XX
Message Chains-XX
Inappropriate Intimacy-X-
Total Issues: X critical, X warnings, X info
坏味道类型严重警告信息
God ClassXX-
Feature Envy-XX
Data Clumps-X-
Long Parameter ListXXX
Long Method-XX
Primitive Obsession-XX
Message Chains-XX
Inappropriate Intimacy-X-
问题总数: X个严重问题,X个警告问题,X个信息提示

Critical Issues

严重问题

SMELL-001: God Class

SMELL-001: God Class

  • File:
    src/Service/OrderManager.php
  • Lines: 847
  • Public Methods: 23
  • Dependencies: 12
  • Issue: Class has too many responsibilities
  • Refactoring:
    • Extract
      OrderValidator
      (validation logic)
    • Extract
      OrderNotifier
      (notification logic)
    • Extract
      OrderPriceCalculator
      (pricing logic)
  • Skills:
    create-use-case
    ,
    create-domain-service
  • 文件:
    src/Service/OrderManager.php
  • 行数: 847
  • 公共方法数: 23
  • 依赖数: 12
  • 问题: 类承担了过多职责
  • 重构建议:
    • 提取
      OrderValidator
      (验证逻辑)
    • 提取
      OrderNotifier
      (通知逻辑)
    • 提取
      OrderPriceCalculator
      (定价逻辑)
  • 相关技能:
    create-use-case
    ,
    create-domain-service

SMELL-002: Long Parameter List

SMELL-002: Long Parameter List

  • File:
    src/Domain/Order/Order.php:45
  • Method:
    createOrder()
  • Parameters: 9
  • Issue: Too many parameters, hard to maintain
  • Refactoring: Introduce Parameter Object
  • Skills:
    create-dto
    ,
    create-builder
  • 文件:
    src/Domain/Order/Order.php:45
  • 方法:
    createOrder()
  • 参数数量: 9
  • 问题: 参数过多,难以维护
  • 重构建议: 引入参数对象
  • 相关技能:
    create-dto
    ,
    create-builder

Warning Issues

警告问题

SMELL-003: Data Clump

SMELL-003: Data Clump

  • Files:
    • src/Domain/User/User.php:15
      — $street, $city, $zipCode
    • src/Domain/Company/Company.php:23
      — $street, $city, $zipCode
    • src/Application/DTO/CreateOrderDTO.php:8
      — $street, $city, $zipCode
  • Issue: Address fields repeated across 3 classes
  • Refactoring: Extract Address Value Object
  • Skills:
    create-value-object
  • 涉及文件:
    • src/Domain/User/User.php:15
      — $street, $city, $zipCode
    • src/Domain/Company/Company.php:23
      — $street, $city, $zipCode
    • src/Application/DTO/CreateOrderDTO.php:8
      — $street, $city, $zipCode
  • 问题: 地址字段在3个类中重复出现
  • 重构建议: 提取Address值对象
  • 相关技能:
    create-value-object

SMELL-004: Feature Envy

SMELL-004: Feature Envy

  • File:
    src/Service/ReportGenerator.php:89
  • Method:
    generateUserReport()
  • Issue: Method makes 15 calls to User object, only 2 to own class
  • Refactoring: Move method to User or create UserReportBuilder
  • Skills:
    create-domain-service
  • 文件:
    src/Service/ReportGenerator.php:89
  • 方法:
    generateUserReport()
  • 问题: 方法调用User对象15次,仅调用自身类2次
  • 重构建议: 将方法迁移至User类或创建UserReportBuilder
  • 相关技能:
    create-domain-service

SMELL-005: Primitive Obsession

SMELL-005: Primitive Obsession

  • File:
    src/Domain/User/User.php:12
  • Field:
    private string $email
  • Issue: Email should be Value Object for validation
  • Refactoring: Create Email Value Object
  • Skills:
    create-value-object
  • 文件:
    src/Domain/User/User.php:12
  • 字段:
    private string $email
  • 问题: 邮箱应作为值对象以实现验证逻辑
  • 重构建议: 创建Email值对象
  • 相关技能:
    create-value-object

SMELL-006: Message Chain

SMELL-006: Message Chain

  • File:
    src/Application/Handler/CreateOrderHandler.php:34
  • Code:
    $user->getCompany()->getAddress()->getCountry()
  • Issue: Law of Demeter violation, tight coupling
  • Refactoring: Add shortcut method or delegate
  • 文件:
    src/Application/Handler/CreateOrderHandler.php:34
  • 代码:
    $user->getCompany()->getAddress()->getCountry()
  • 问题: 违反迪米特法则,耦合度过高
  • 重构建议: 添加快捷方法或委托逻辑

Info Issues

信息提示

SMELL-007: Long Method

SMELL-007: Long Method

  • File:
    src/Infrastructure/Repository/OrderRepository.php:78
  • Method:
    findByComplexCriteria()
  • Lines: 45
  • Issue: Method approaching complexity threshold
  • Refactoring: Extract query builder or specification
  • 文件:
    src/Infrastructure/Repository/OrderRepository.php:78
  • 方法:
    findByComplexCriteria()
  • 行数: 45
  • 问题: 方法复杂度接近阈值
  • 重构建议: 提取查询构建器或规格类

Refactoring Priority

重构优先级

  1. Immediate: God Classes blocking testing
  2. High: Data Clumps causing duplication
  3. Medium: Long Parameter Lists
  4. Low: Message Chains, minor smells
undefined
  1. 紧急: 阻碍测试的God Class
  2. 高: 导致代码重复的Data Clumps
  3. 中: 过长参数列表
  4. 低: 消息链、轻微坏味道
undefined

Remediation Skills

修复技能对应表

SmellRecommended SkillApproach
God Class
create-use-case
,
create-domain-service
Extract focused classes
Feature Envy
create-domain-service
Move method to data owner
Data Clumps
create-value-object
Extract Value Object
Long Parameter List
create-dto
,
create-builder
Introduce Parameter Object
Long Method
create-use-case
Extract methods
Primitive Obsession
create-value-object
Replace with Value Object
Message Chains(refactoring)Hide delegate, extract method
Inappropriate Intimacy(refactoring)Move method, extract class
坏味道类型推荐技能处理方式
God Class
create-use-case
,
create-domain-service
提取职责单一的类
Feature Envy
create-domain-service
将方法迁移至数据所属类
Data Clumps
create-value-object
提取值对象
Long Parameter List
create-dto
,
create-builder
引入参数对象
Long Method
create-use-case
提取子方法
Primitive Obsession
create-value-object
替换为值对象
Message Chains(refactoring)隐藏委托逻辑、提取方法
Inappropriate Intimacy(refactoring)迁移方法、提取类

Quick Analysis Commands

快速分析命令

bash
undefined
bash
undefined

Full smell detection

完整坏味道检测

echo "=== God Classes ===" &&
find . -name ".php" -path "/src/" -exec wc -l {} ; | awk '$1 > 400' &&
echo "=== Long Parameter Lists ===" &&
grep -rn "function [a-z]
(" --include=".php" src/ | grep -E "($[a-z]+,\s){5,}" &&
echo "=== Primitive Obsession ===" &&
grep -rn "string $email|string $phone|int $amount|float $price" --include=".php" src/ &&
echo "=== Message Chains ===" &&
grep -rn "->get[A-Z].
->get[A-Z].->get[A-Z]" --include=".php" src/ &&
echo "=== Magic Strings ===" &&
grep -rn "=== '[a-z]'|== '[a-z]'" --include="*.php" src/
undefined
echo "=== God Classes ===" &&
find . -name ".php" -path "/src/" -exec wc -l {} ; | awk '$1 > 400' &&
echo "=== Long Parameter Lists ===" &&
grep -rn "function [a-z]
(" --include=".php" src/ | grep -E "($[a-z]+,\s){5,}" &&
echo "=== Primitive Obsession ===" &&
grep -rn "string $email|string $phone|int $amount|float $price" --include=".php" src/ &&
echo "=== Message Chains ===" &&
grep -rn "->get[A-Z].
->get[A-Z].->get[A-Z]" --include=".php" src/ &&
echo "=== Magic Strings ===" &&
grep -rn "=== '[a-z]'|== '[a-z]'" --include="*.php" src/
undefined

Integration with Other Skills

与其他工具的集成

This skill works alongside:
  • analyze-solid-violations
    — SOLID violations overlap with some smells
  • structural-auditor
    — architectural context for smells
  • ddd-auditor
    — domain model quality assessment
本工具可与以下工具配合使用:
  • analyze-solid-violations
    — SOLID原则违规检测(与部分坏味道存在重叠)
  • structural-auditor
    — 架构审计(为坏味道提供架构层面的上下文)
  • ddd-auditor
    — 领域模型质量评估

References

参考资料

Based on Martin Fowler's "Refactoring" catalog:
基于Martin Fowler的《重构》目录:

When This Is Acceptable

可接受的例外情况

  • DTOs — Data classes are NOT a code smell; they serve a clear data transfer purpose
  • Configuration classes — Classes with many constants/properties for configuration
  • Builder pattern — Method chaining in builders creates apparent "Feature Envy" but is by design
  • DTO类 — 数据类不属于代码坏味道,它们明确承担数据传输的职责
  • 配置类 — 包含大量常量/属性的配置类
  • 构建器模式 — 构建器中的方法链式调用看似存在Feature Envy,但属于设计意图

False Positive Indicators

误报识别指标

  • Class has
    DTO
    ,
    Request
    ,
    Response
    ,
    Config
    in its name
  • Class implements a Builder pattern with fluent API
  • "Long parameter list" is actually a constructor with proper dependency injection
  • 类名包含
    DTO
    Request
    Response
    Config
  • 类实现了带有流畅API的Builder模式
  • "过长参数列表"实际是依赖注入的构造函数