PHP 项目复杂度控制
代码层面的复杂度控制
1 函数复杂度控制
// ❌ 高复杂度示例 - 圈复杂度=8
function processOrder(array $order): array {
if ($order['status'] === 'pending') {
if ($order['type'] === 'digital') {
if ($order['paid']) {
if ($order['stock'] > 0) {
// 处理逻辑
} else {
// 无库存
}
} else {
// 未支付
}
} else {
// 实体商品
}
} else {
// 其他状态
}
}
// ✅ 低复杂度示例 - 用策略模式 + 提前返回
function processOrder(Order $order): array
{
$handler = new OrderHandlerFactory()->create($order->getType());
return $handler->process($order);
}
2 方法拆分原则
// ❌ 单一方法做太多事情
function handleUserRegistration(array $data): void
{
// 验证数据
// 处理头像上传
// 创建用户
// 发送通知
// 记录日志
}
// ✅ 拆分为独立职责
class UserRegistrationService
{
public function register(RegistrationData $data): User
{
$this->validator->validate($data);
$user = $this->createUser($data);
$this->uploadAvatar($data->getAvatar());
$this->sendWelcomeNotification($user);
$this->logger->info('User registered', ['user_id' => $user->id]);
return $user;
}
private function createUser(RegistrationData $data): User
{
// 仅负责创建用户
}
}
架构层面的复杂度控制
1 依赖注入
// ❌ 直接在类内部创建依赖
class OrderService
{
private $repository;
public function __construct()
{
$this->repository = new OrderRepository();
}
}
// ✅ 依赖注入
class OrderService
{
private OrderRepositoryInterface $repository;
private NotificationServiceInterface $notifier;
public function __construct(
OrderRepositoryInterface $repository,
NotificationServiceInterface $notifier
) {
$this->repository = $repository;
$this->notifier = $notifier;
}
}
2 分层架构
// 目录结构示例 app/ ├── Controllers/ # 控制器层 - 处理HTTP请求 ├── Services/ # 服务层 - 业务逻辑 ├── Repositories/ # 仓储层 - 数据访问 ├── Models/ # 模型层 - 数据实体 ├── DTOs/ # 数据传输对象 ├── Exceptions/ # 异常处理 └── Contracts/ # 接口定义
测试复杂度控制
1 单元测试示例
// ❌ 测试覆盖过多功能
class OrderServiceTest extends TestCase
{
public function testOrderProcessing()
{
// 测试支付、库存、通知等多个功能
}
}
// ✅ 单一职责测试
class OrderServiceTest extends TestCase
{
/** @test */
public function it_calculates_order_total_correctly()
{
$order = $this->createOrder([
'items' => [['price' => 100, 'qty' => 2]]
]);
$this->assertEquals(200, $order->getTotal());
}
/** @test */
public function it_applies_discount_when_total_exceeds_threshold()
{
// 只测试折扣逻辑
}
}
重构复杂度控制
1 识别需要重构的信号
// 信号1: 类过于庞大
class GrandService {
private $methods = [];
// 包含超过500行代码
}
// 信号2: 过长的参数列表
function createUser(
string $name,
string $email,
string $phone,
string $address,
bool $isAdmin,
bool $isVerified,
array $permissions,
// ... 越来越多的参数
): User {}
// 重构为参数对象
class UserCreationData
{
public string $name;
public string $email;
public ?string $phone;
public ?string $address;
public bool $isAdmin = false;
}
function createUser(UserCreationData $data): User {}
2 使用设计模式控制复杂度
// 策略模式控制业务逻辑复杂度
interface PaymentStrategy
{
public function pay(Order $order): bool;
}
class AlipayStrategy implements PaymentStrategy
{
public function pay(Order $order): bool
{
// 支付宝支付逻辑
}
}
class WechatPayStrategy implements PaymentStrategy
{
public function pay(Order $order): bool
{
// 微信支付逻辑
}
}
class PaymentContext
{
public function __construct(
private PaymentStrategy $strategy
) {}
public function executePayment(Order $order): bool
{
return $this->strategy->pay($order);
}
}
代码质量工具
1 PHP CodeSniffer 配置
<!-- phpcs.xml -->
<?xml version="1.0"?>
<ruleset name="Project Rules">
<description>Project coding standards</description>
<!-- 不同规则集 -->
<rule ref="PSR12"/>
<rule ref="Generic.NamingConventions"/>
<!-- 复杂度限制 -->
<rule ref="Generic.Metrics.CyclomaticComplexity">
<properties>
<property name="absoluteComplexity" value="10"/>
<property name="complexity" value="8"/>
</properties>
</rule>
</ruleset>
2 PHPStan 配置
# phpstan.neon
parameters:
level: 8
analyzers:
- src
reportUnmatchedIgnoredErrors: true
checkMissingIterableValueType: true
checkGenericClassInNonGenericObjectType: false
持续集成与复杂度监控
# GitHub Actions 示例
name: Code Quality Check
on: [pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install Dependencies
run: composer install
- name: Run PHPCS
run: vendor/bin/phpcs src/
- name: Run Static Analysis
run: vendor/bin/phpstan analyse src/ --level=max
- name: Run Unit Tests
run: vendor/bin/phpunit --coverage-clover coverage.xml
- name: Upload Coverage
uses: codecov/codecov-action@v1
性能复杂度控制
// ❌ N+1查询问题
foreach ($users as $user) {
$orders = Order::where('user_id', $user->id)->get(); // 每个循环都查询
}
// ✅ 使用预加载
$users = User::with('orders')->get();
foreach ($users as $user) {
$orders = $user->orders; // 只查询一次
}
总结清单
✅ 代码质量检查清单
- [ ] 函数不超过30行代码
- [ ] 圈复杂度不超过10
- [ ] 类不超过500行代码
- [ ] 方法参数不超过5个
- [ ] 每个类只做一件事
- [ ] 使用依赖注入
- [ ] 符合PSR-12规范
✅ 架构检查清单
- [ ] 遵循SOLID原则
- [ ] 使用单一职责原则
- [ ] 依赖倒置原则
- [ ] 使用接口定义契约
- [ ] 服务层不包含HTTP逻辑
✅ 测试检查清单
- [ ] 核心业务逻辑有单元测试
- [ ] 测试覆盖率达到80%以上
- [ ] 每个测试只测试一个功能
- [ ] 测试可独立运行
通过持续关注这些维度,并使用合适的工具和规范,可以有效控制PHP项目的复杂度,保持项目的可维护性和可扩展性。
