如何简化过度设计的 C# 代码?
How do I simplify over-engineered c# code?
这是我在练习中遇到的一个小问题。
任务是在保持 GameManager 功能的同时简化这种过度设计、外观花哨的代码。这个想法也是为了让它更具可读性。我不知道该做什么以及从哪里开始,因为我确实完全理解代码及其功能。我想到了将循环转换成它自己的函数,但仅此而已。
关于如何进行、删除什么、更改什么以及如何进行的任何建议?
提前致谢。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Game
{
public class GameManager : MonoBehaviour
{
List<IUpdateable> _gameEntities = new List<IUpdateable>();
int _npcCount = 1000;
public void Awake()
{
for (int i = 0; i < _npcCount; i++)
{
var npc = new NPC();
npc.ID = i;
_gameEntities.Add(npc);
}
var player = new Player();
player.ID = _npcCount + 1;
_gameEntities.Add(player);
}
public void ChangeNPCName(int id, string name)
{
foreach (var entity in _gameEntities)
{
if (entity is NPC)
{
var npc = entity as NPC;
if (npc.ID == id)
{
npc.ChangeName(name);
}
}
}
}
public void ChangePlayerName(string name)
{
foreach (var entity in _gameEntities)
{
if (entity is Player)
{
entity.ChangeName(name);
entity.Save();
}
}
}
}
public interface IUpdateable
{
void ChangeName(string name);
void Save();
}
public abstract class Entity<T> where T : IUpdateable
{
protected string _name;
private int _id;
public int ID { get => _id; set => _id = value; }
public void ChangeName(string name)
{
_name = name;
}
}
public class NPC : Entity<NPC>, IUpdateable
{
public void Save()
{
}
}
public class Player : Entity<Player>, IUpdateable
{
public void Save()
{
}
}
}
就如何进行而言,一般建议是针对现有代码编写一些单元测试,涵盖所有功能。然后您可以开始增量重构,并确信您的测试将验证代码的行为是否仍然正确。
乍一看,代码很紧凑,一眼就能看懂。唯一可以在简化方面解决的问题是摆脱 classes/interface 层次结构。
- 将
NPC
和 Player
替换为它们的基础 class 实体(只需通过 属性 或字段指定它们的种类,也许还有外部函数来自定义它们的 behavior/strategy)
- 这样,您就可以摆脱泛型和
IUpdateable
,这样实体就可以在所有地方用作简单的 class。
- 此外,您可以用数组替换列表,然后改进数据局部性(但是,这是 multi-aspect 情况,因此您必须通过一些测量来判断)
这是我在练习中遇到的一个小问题。
任务是在保持 GameManager 功能的同时简化这种过度设计、外观花哨的代码。这个想法也是为了让它更具可读性。我不知道该做什么以及从哪里开始,因为我确实完全理解代码及其功能。我想到了将循环转换成它自己的函数,但仅此而已。
关于如何进行、删除什么、更改什么以及如何进行的任何建议?
提前致谢。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Game
{
public class GameManager : MonoBehaviour
{
List<IUpdateable> _gameEntities = new List<IUpdateable>();
int _npcCount = 1000;
public void Awake()
{
for (int i = 0; i < _npcCount; i++)
{
var npc = new NPC();
npc.ID = i;
_gameEntities.Add(npc);
}
var player = new Player();
player.ID = _npcCount + 1;
_gameEntities.Add(player);
}
public void ChangeNPCName(int id, string name)
{
foreach (var entity in _gameEntities)
{
if (entity is NPC)
{
var npc = entity as NPC;
if (npc.ID == id)
{
npc.ChangeName(name);
}
}
}
}
public void ChangePlayerName(string name)
{
foreach (var entity in _gameEntities)
{
if (entity is Player)
{
entity.ChangeName(name);
entity.Save();
}
}
}
}
public interface IUpdateable
{
void ChangeName(string name);
void Save();
}
public abstract class Entity<T> where T : IUpdateable
{
protected string _name;
private int _id;
public int ID { get => _id; set => _id = value; }
public void ChangeName(string name)
{
_name = name;
}
}
public class NPC : Entity<NPC>, IUpdateable
{
public void Save()
{
}
}
public class Player : Entity<Player>, IUpdateable
{
public void Save()
{
}
}
}
就如何进行而言,一般建议是针对现有代码编写一些单元测试,涵盖所有功能。然后您可以开始增量重构,并确信您的测试将验证代码的行为是否仍然正确。
乍一看,代码很紧凑,一眼就能看懂。唯一可以在简化方面解决的问题是摆脱 classes/interface 层次结构。
- 将
NPC
和Player
替换为它们的基础 class 实体(只需通过 属性 或字段指定它们的种类,也许还有外部函数来自定义它们的 behavior/strategy) - 这样,您就可以摆脱泛型和
IUpdateable
,这样实体就可以在所有地方用作简单的 class。 - 此外,您可以用数组替换列表,然后改进数据局部性(但是,这是 multi-aspect 情况,因此您必须通过一些测量来判断)