detect-code-smells
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode 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
代码坏味道目录
| Smell | Description | Detection | Severity |
|---|---|---|---|
| God Class | Class doing too much | >500 LOC, >15 methods | CRITICAL |
| Feature Envy | Method uses another class more | Foreign calls > own calls | WARNING |
| Data Clumps | Same fields appear together | 3+ repeated params/fields | WARNING |
| Long Parameter List | Method with many params | >4 parameters | WARNING |
| Long Method | Method doing too much | >50 LOC | WARNING |
| Primitive Obsession | Primitives instead of objects | string $email, int $money | INFO |
| Message Chains | Long getter chains | ->get()->get()->get() | WARNING |
| Inappropriate Intimacy | Classes knowing too much | Direct field access | WARNING |
| 坏味道类型 | 描述 | 检测方式 | 严重等级 |
|---|---|---|---|
| God Class | 类承担过多职责 | 代码行数>500、方法数>15 | CRITICAL |
| Feature Envy | 方法过度依赖其他类 | 外部调用次数超过自身调用次数 | WARNING |
| Data Clumps | 相同字段重复出现 | 3个及以上重复参数/字段 | WARNING |
| Long Parameter List | 方法包含过多参数 | 参数数量>4 | WARNING |
| Long Method | 方法逻辑过于冗长 | 代码行数>50 | WARNING |
| Primitive Obsession | 过度使用基本类型而非对象 | 如string $email、int $money | INFO |
| Message Chains | 过长的 getter 调用链 | 如->get()->get()->get() | WARNING |
| Inappropriate Intimacy | 类之间过度了解内部细节 | 直接访问其他类的字段 | WARNING |
Detection Patterns
检测模式
God Class Detection
God Class 检测
bash
undefinedbash
undefinedLarge 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 → INFOGrep: "class.*Manager|class.*Handler|class.*Helper|class.*Util|class.Processor" --glob "**/.php"
**判定指标:**
- 类代码行数>500 → CRITICAL
- 类公共方法数>15 → CRITICAL
- 类构造函数依赖>8 → WARNING
- 类名包含Manager、Handler、Helper、Util → INFOFeature Envy Detection
Feature Envy 检测
bash
undefinedbash
undefinedMethods 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
- 方法仅转换来自其他类的数据 → WARNINGData Clumps Detection
Data Clumps 检测
bash
undefinedbash
undefinedRepeated 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
undefinedbash
undefinedMethods 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个及以上参数 → CRITICALLong Method Detection
Long Method 检测
bash
undefinedbash
undefinedFind 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 → CRITICALGrep: "if\s*(.{.if\s(" --glob "**/.php" --multiline
**阈值:**
- 30行及以上 → INFO
- 50行及以上 → WARNING
- 100行及以上 → CRITICALPrimitive Obsession Detection
Primitive Obsession 检测
bash
undefinedbash
undefinedString 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 → EnumGrep: "=== 'pending'|=== 'active'|=== 'completed'|=== 'draft'" --glob "**/*.php"
**应替换为值对象的场景:**
- 邮箱地址 → Email
- 电话号码 → PhoneNumber
- URL → Url或Uri
- 金额 → Money(包含货币类型)
- 日期/时间段 → DateRange、Period
- 标识符 → UserId、OrderId等
- 状态/类型 → 枚举(Enum)Message Chains Detection
Message Chains 检测
bash
undefinedbash
undefinedLong 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 → CRITICALGrep: "$this->[a-z]+->get[A-Z].->get[A-Z]" --glob "**/.php"
**判定指标:**
- 2次链式getter调用 → INFO
- 3次及以上链式getter调用 → WARNING
- 循环中的调用链 → CRITICALInappropriate Intimacy Detection
Inappropriate Intimacy 检测
bash
undefinedbash
undefinedDirect 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"
undefinedGrep: "->getInternalState|->getRawData|->getFields" --glob "**/*.php"
undefinedReport Format
报告格式
markdown
undefinedmarkdown
undefinedCode Smells Analysis Report
代码坏味道分析报告
Summary
摘要
| Smell | Critical | Warning | Info |
|---|---|---|---|
| God Class | X | X | - |
| Feature Envy | - | X | X |
| Data Clumps | - | X | - |
| Long Parameter List | X | X | X |
| Long Method | - | X | X |
| Primitive Obsession | - | X | X |
| Message Chains | - | X | X |
| Inappropriate Intimacy | - | X | - |
Total Issues: X critical, X warnings, X info
| 坏味道类型 | 严重 | 警告 | 信息 |
|---|---|---|---|
| God Class | X | X | - |
| Feature Envy | - | X | X |
| Data Clumps | - | X | - |
| Long Parameter List | X | X | X |
| Long Method | - | X | X |
| Primitive Obsession | - | X | X |
| Message Chains | - | X | X |
| 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 (validation logic)
OrderValidator - Extract (notification logic)
OrderNotifier - Extract (pricing logic)
OrderPriceCalculator
- Extract
- Skills: ,
create-use-casecreate-domain-service
- 文件:
src/Service/OrderManager.php - 行数: 847
- 公共方法数: 23
- 依赖数: 12
- 问题: 类承担了过多职责
- 重构建议:
- 提取(验证逻辑)
OrderValidator - 提取(通知逻辑)
OrderNotifier - 提取(定价逻辑)
OrderPriceCalculator
- 提取
- 相关技能: ,
create-use-casecreate-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-dtocreate-builder
- 文件:
src/Domain/Order/Order.php:45 - 方法:
createOrder() - 参数数量: 9
- 问题: 参数过多,难以维护
- 重构建议: 引入参数对象
- 相关技能: ,
create-dtocreate-builder
Warning Issues
警告问题
SMELL-003: Data Clump
SMELL-003: Data Clump
- Files:
- — $street, $city, $zipCode
src/Domain/User/User.php:15 - — $street, $city, $zipCode
src/Domain/Company/Company.php:23 - — $street, $city, $zipCode
src/Application/DTO/CreateOrderDTO.php:8
- Issue: Address fields repeated across 3 classes
- Refactoring: Extract Address Value Object
- Skills:
create-value-object
- 涉及文件:
- — $street, $city, $zipCode
src/Domain/User/User.php:15 - — $street, $city, $zipCode
src/Domain/Company/Company.php:23 - — $street, $city, $zipCode
src/Application/DTO/CreateOrderDTO.php:8
- 问题: 地址字段在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
重构优先级
- Immediate: God Classes blocking testing
- High: Data Clumps causing duplication
- Medium: Long Parameter Lists
- Low: Message Chains, minor smells
undefined- 紧急: 阻碍测试的God Class
- 高: 导致代码重复的Data Clumps
- 中: 过长参数列表
- 低: 消息链、轻微坏味道
undefinedRemediation Skills
修复技能对应表
| Smell | Recommended Skill | Approach |
|---|---|---|
| God Class | | Extract focused classes |
| Feature Envy | | Move method to data owner |
| Data Clumps | | Extract Value Object |
| Long Parameter List | | Introduce Parameter Object |
| Long Method | | Extract methods |
| Primitive Obsession | | Replace with Value Object |
| Message Chains | (refactoring) | Hide delegate, extract method |
| Inappropriate Intimacy | (refactoring) | Move method, extract class |
| 坏味道类型 | 推荐技能 | 处理方式 |
|---|---|---|
| God Class | | 提取职责单一的类 |
| Feature Envy | | 将方法迁移至数据所属类 |
| Data Clumps | | 提取值对象 |
| Long Parameter List | | 引入参数对象 |
| Long Method | | 提取子方法 |
| Primitive Obsession | | 替换为值对象 |
| Message Chains | (refactoring) | 隐藏委托逻辑、提取方法 |
| Inappropriate Intimacy | (refactoring) | 迁移方法、提取类 |
Quick Analysis Commands
快速分析命令
bash
undefinedbash
undefinedFull 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/
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/
undefinedecho "=== 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/
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/
undefinedIntegration with Other Skills
与其他工具的集成
This skill works alongside:
- — SOLID violations overlap with some smells
analyze-solid-violations - — architectural context for smells
structural-auditor - — domain model quality assessment
ddd-auditor
本工具可与以下工具配合使用:
- — SOLID原则违规检测(与部分坏味道存在重叠)
analyze-solid-violations - — 架构审计(为坏味道提供架构层面的上下文)
structural-auditor - — 领域模型质量评估
ddd-auditor
References
参考资料
Based on Martin Fowler's "Refactoring" catalog:
- https://refactoring.guru/refactoring/smells
- "Refactoring: Improving the Design of Existing Code" (Fowler)
基于Martin Fowler的《重构》目录:
- https://refactoring.guru/refactoring/smells
- 《重构:改善既有代码的设计》(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,Responsein its nameConfig - Class implements a Builder pattern with fluent API
- "Long parameter list" is actually a constructor with proper dependency injection
- 类名包含、
DTO、Request、ResponseConfig - 类实现了带有流畅API的Builder模式
- "过长参数列表"实际是依赖注入的构造函数