我如何重构这些功能?
How can i refactor these functions?
基本上,在游戏中,我有一个“墙验证器”,它检查墙是否满足所有要求。然后,根据失败的要求,程序调用适当的消息函数。
Here is the code, where I call wall validator:
internal void PlaceWall(Vector2 wallStartPosition, Vector2 wallEndPosition)
{
_wallStartPosition = wallStartPosition;
_wallEndPosition = wallEndPosition;
_wallValidator.InitializeVectors(wallStartPosition, wallEndPosition);
if (_wallValidator.WallDoesNotMeetTheRequirements())
{
_wallValidator.SendAppropriateMessage();
return;
}
PlaceNewWall();
}
Right now I check all requirements two times in two different functions here they are in wall validator:
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();
}
你会如何重构这些函数?
我已经尝试制作一个“要求”class,它在其构造函数中接受“检查功能”和“要发送的消息”,但失败了。此选项在测试环境中不起作用。原因是我正在使用 NUnit 测试框架,当我尝试在不分配“ConsoleOutput”(Class,它实现所有消息功能)的情况下测试墙放置时,我总是会在以下位置收到“NullPointer”异常“需求”点class初始化。
所以,基本上,我想在代码中说的是“发送适当的消息到输出如果它不为空,但如果是,那么 就 return 正确 ”。但是对于当前状态下的每一个新需求,我都需要在两个不同的地方添加检查功能。
我不太喜欢这个“双重检查要求并发送消息”的选项,我觉得我错过了这个问题的简单答案。
P.S。抱歉我的英语不好 ;D,希望我能以您能理解的方式解释一切。
如评论中所述,制作一个 returns 操作结果的枚举,包括不同的错误情况。
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 层。检查逻辑可能有利于放置在较低层,以便更容易进行单元测试等。
基本上,在游戏中,我有一个“墙验证器”,它检查墙是否满足所有要求。然后,根据失败的要求,程序调用适当的消息函数。
Here is the code, where I call wall validator:
internal void PlaceWall(Vector2 wallStartPosition, Vector2 wallEndPosition)
{
_wallStartPosition = wallStartPosition;
_wallEndPosition = wallEndPosition;
_wallValidator.InitializeVectors(wallStartPosition, wallEndPosition);
if (_wallValidator.WallDoesNotMeetTheRequirements())
{
_wallValidator.SendAppropriateMessage();
return;
}
PlaceNewWall();
}
Right now I check all requirements two times in two different functions here they are in wall validator:
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();
}
你会如何重构这些函数?
我已经尝试制作一个“要求”class,它在其构造函数中接受“检查功能”和“要发送的消息”,但失败了。此选项在测试环境中不起作用。原因是我正在使用 NUnit 测试框架,当我尝试在不分配“ConsoleOutput”(Class,它实现所有消息功能)的情况下测试墙放置时,我总是会在以下位置收到“NullPointer”异常“需求”点class初始化。
所以,基本上,我想在代码中说的是“发送适当的消息到输出如果它不为空,但如果是,那么 就 return 正确 ”。但是对于当前状态下的每一个新需求,我都需要在两个不同的地方添加检查功能。
我不太喜欢这个“双重检查要求并发送消息”的选项,我觉得我错过了这个问题的简单答案。
P.S。抱歉我的英语不好 ;D,希望我能以您能理解的方式解释一切。
如评论中所述,制作一个 returns 操作结果的枚举,包括不同的错误情况。
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 层。检查逻辑可能有利于放置在较低层,以便更容易进行单元测试等。