You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP版Gilded Rose重构:Switch替换If后测试失败排查

Gilded Rose PHP重构问题排查

问题描述

正在进行PHP版Gilded Rose重构练习,已针对原版GildedRose.php编写单元测试且全部通过。尝试将原代码中40行if语句替换为switch-case结构以提升可读性,但出现错误导致测试不通过,需排查问题。

单元测试示例

public function testAgedBrieAtBeginning(): void          //  +1 quality till sell_in = 0 than +2 quality
{
    $items = [new Item('Aged Brie', 2, 0)];
    $gildedRose = new GildedRose($items);
    $gildedRose->updateQuality();
    $this->assertEquals($items[0]->sell_in, 1);
    $this->assertEquals($items[0]->quality, 1);
}

public function testAgedBrieWhenSellInZero(): void
{
    $items = [new Item('Aged Brie', 0, 2)];
    $gildedRose = new GildedRose($items);
    $gildedRose->updateQuality();
    $this->assertEquals($items[0]->sell_in, -1);
    $this->assertEquals($items[0]->quality, 4);
}

public function testAgedBrieDontIncreaseMaximum(): void       // stand at 50 quality
{
    $items = [new Item('Aged Brie', -28, 50)];
    $gildedRose = new GildedRose($items);
    $gildedRose->updateQuality();
    $this->assertEquals($items[0]->sell_in, -29);
    $this->assertEquals($items[0]->quality, 50);
}

修改后的GildedRose.php代码

<?php

declare(strict_types=1);

namespace GildedRose;

final class GildedRose
{
/**
 * @var Item[]
 */
private $items;

public function __construct(array $items)
{
    $this->items = $items;

}

public function updateQuality(): void
{
    switch ($this->items) {
        case 'Normal':
            $this->tickNormal();
            return;
        case 'Aged Brie':
            $this->tickAgedBrie();
            return;
        case 'Sulfaras, Hand of Ragnaros':
            $this->tickSulfuras();
            return;
        case 'Backstage passes to a TAFKAL80ETC concert':
            $this->tickBackstage();
            return;
    }

}

private function tickNormal(): void  // for Dexterity, Elixir & Conjured
{
    $this->sell_in--;

    if($this->quality == 0) {
        return;
    }

    $this->quality--;
    if ($this->sell_in <= 0) {
        $this->quality--;
    }
}
private function tickAgedBrie()
{
    $this->sell_in -= 1;

    if($this->quality >= 50) {
        return;
    }

    $this->quality += 1;
    if ($this->sell_in <= 0) {
        $this->quality += 1;
    }
}

private function tickSulfuras() : void
{

}

private function tickBackstage() : void
{
    $this->sell_in -= 1;

    if ($this->quality >= 50) {
        return;
    }
    if ($this->sell_in < 0) {
        $this->quality = 0;
        return;
    }

    $this->quality += 1;
    if ($this->sell_in < 10) {
        $this->quality += 1;
    }
    if ($this->sell_in < 5) {
        $this->quality += 1;
    }
}

}

问题分析与修复方案

你的代码存在几个核心错误,导致测试失败:

1. 未遍历物品数组

原代码逻辑是遍历每个Item实例进行属性更新,但你现在的updateQuality方法直接对整个$this->items数组做switch判断,数组无法匹配任何字符串case,导致所有物品都未被处理。

2. 错误访问属性

GildedRose类本身没有sell_in和quality属性,这两个属性属于Item类的实例。你在tick方法中直接使用$this->sell_in,会触发"未定义属性"的致命错误。

3. switch判断对象错误

应该针对单个Item的name字段做switch判断,而非整个物品数组。

4. 方法缺失返回类型

tickAgedBrie方法未声明返回类型,在strict_types=1模式下会引发类型错误。

5. Normal物品逻辑错误

原代码中"Normal"是默认情况(非特殊物品),而非物品名为"Normal",你的case 'Normal'永远无法匹配到实际物品。


修复后的核心代码示例

public function updateQuality(): void
{
    foreach ($this->items as $item) {
        switch ($item->name) {
            case 'Aged Brie':
                $this->tickAgedBrie($item);
                break;
            case 'Sulfaras, Hand of Ragnaros':
                $this->tickSulfuras($item);
                break;
            case 'Backstage passes to a TAFKAL80ETC concert':
                $this->tickBackstage($item);
                break;
            default:
                // 处理普通物品和Conjured物品
                $this->tickNormal($item);
                break;
        }
    }
}

private function tickNormal(Item $item): void
{
    $item->sell_in--;
    $decrement = str_contains($item->name, 'Conjured') ? 2 : 1;

    if ($item->quality <= 0) {
        return;
    }

    $item->quality -= $decrement;
    if ($item->sell_in <= 0) {
        $item->quality -= $decrement;
    }
    // 确保quality不低于0
    $item->quality = max(0, $item->quality);
}

private function tickAgedBrie(Item $item): void
{
    $item->sell_in--;

    if ($item->quality >= 50) {
        return;
    }

    $item->quality++;
    if ($item->sell_in <= 0) {
        $item->quality++;
    }
    // 确保quality不超过50
    $item->quality = min(50, $item->quality);
}

private function tickBackstage(Item $item): void
{
    $item->sell_in--;

    if ($item->quality >= 50) {
        return;
    }

    if ($item->sell_in < 0) {
        $item->quality = 0;
        return;
    }

    $item->quality++;
    if ($item->sell_in < 10) {
        $item->quality++;
    }
    if ($item->sell_in < 5) {
        $item->quality++;
    }
    $item->quality = min(50, $item->quality);
}

private function tickSulfuras(Item $item): void
{
    // Sulfuras无需更新sell_in和quality
}

内容的提问来源于stack exchange,提问作者massariH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:54:30