【问题标题】:How can i refactor these functions?我如何重构这些功能?
【发布时间】:2021-09-20 03:49:30
【问题描述】:

所以基本上,在游戏中,我有一个“墙验证器”,它检查墙是否满足所有要求。然后,根据哪个需求失败,程序调用相应的消息函数。

这里是代码,我称之为墙验证器:

    internal void PlaceWall(Vector2 wallStartPosition, Vector2 wallEndPosition)
    {
        _wallStartPosition = wallStartPosition;
        _wallEndPosition = wallEndPosition;

        _wallValidator.InitializeVectors(wallStartPosition, wallEndPosition);
        if (_wallValidator.WallDoesNotMeetTheRequirements())
        {
            _wallValidator.SendAppropriateMessage();
            return;
        }

        PlaceNewWall();
    }

现在我在两个不同的功能中检查了所有要求两次,它们在墙验证器中:

    internal bool WallDoesNotMeetTheRequirements()
    {
        if (WallPositionIsBeyondBoard()||
            PlayerUsedAllAvailableWalls()||
            WallIsNotOnTheSameLine() ||
            WallIsTooLong() ||
            WallTilesHavePairCoordinates() ||
            WallDoesNotCoverTwoSolidTiles() ||
            WallInterceptsWithOtherWall())
            return true;

        return false;
    }

    internal void SendAppropriateMessage()
    {
        if (WallPositionIsBeyondBoard())
            _player.output?.DisplayWallHasPositionBeyondBoardMessage();
        if (PlayerUsedAllAvailableWalls())
            _player.output?.DisplayNotEnoughWallsMessage();
        if (WallIsNotOnTheSameLine())
            _player.output?.DisplayWallIsNotOnTheSameLineMessage();
        if (WallIsTooLong())
            _player.output?.DisplayWallIsTooLongMessage();
        if (WallTilesHavePairCoordinates())
            _player.output?.DisplayWallTilesHavePairCoordinatesMessage();
        if (WallDoesNotCoverTwoSolidTiles())
            _player.output?.DisplayWallDoesNotCoverTwoSolidTilesMessage();
        if (WallInterceptsWithOtherWall())
            _player.output?.DisplayWallInterceptsWithOtherWallMessage();
    }

您将如何重构这些函数?
我尝试制作一个“需求”类,它在其构造函数中接受“检查功能”和“要发送的消息”,但失败了。此选项在测试环境中不起作用。原因是我正在使用 NUnit 测试框架,当我尝试在不分配“ConsoleOutput”(实现所有消息功能的类)的情况下测试墙放置时,我总是会在“需求”类初始化。
所以,基本上,我想在代码中说的是“发送适当的消息到输出如果它不为空,但如果是,那么返回真的”。但是对于当前状态下的每一个新要求,我需要在两个不同的地方添加检查功能。
我不太喜欢这种“双重检查要求并发送消息”选项,我觉得我错过了这个问题的简单答案。
附言抱歉我的英语不好;D,希望我能以您能理解的方式解释一切。

【问题讨论】:

  • 为所有失败案例和成功创建一个枚举。让WallDoesNotMeetTheRequirements 返回枚举值。将枚举值传递给您的消息函数。您还可以将消息放入以枚举值作为键的字典中并轻松查找。
  • WallDoesNotMeetTheRequirements() 不需要 - 从SendAppropriateMessage() 返回布尔值。

标签: c# design-patterns refactoring


【解决方案1】:

如 cmets 中所述,制作一个返回操作结果的枚举,包括不同的错误情况。

public enum WallPlacementResult{
    Success,
    NotOnTheSameLine,
    TooLong
    ...
}

WallPlacementResult CheckWallRequirements(){
      if (WallIsNotOnTheSameLine()) return WallPlacementResult.NotOnTheSameLine;
      if (WallIsTooLong()) return WallPlacementResult.TooLong;
      ...
    return WallPlacementResult.Success;
}

void SendAppropriateMessage(WallPlacementResult result)
{
    switch(result){
        case WallPlacementResult.NotOnTheSameLine:
             _player.output?.DisplayWallHasPositionBeyondBoardMessage();
        break;
        case WallPlacementResult.TooLong:
        ...
    }
}

另一种选择可能是使用generic result object 之类的东西。总的来说,我建议将任何 UI 任务(例如显示消息)委托给 UI 层。检查逻辑可能会受益于放置在较低层中,以便更容易进行单元测试等。

【讨论】:

  • 完美。那会做的。谢谢^_^
猜你喜欢
  • 1970-01-01
  • 2021-06-03
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
  • 2016-08-28
相关资源
最近更新 更多