使用布尔方法与属性验证表格的实现合理性及优化问询
问题与代码分析
初始实现代码
public class TableProcessor : TableFormat, ITableProcessor { public List<Parts> PartsList { get; set; } public List<Parts2> Parts2List { get; set; } public List<Parts3> Parts3List { get; set; } public bool IsTableValid { get; set; } public TableProcessor(List<List<object>> Table) : base(Table) { PartsList = GetPartsList(); Parts2List = GetParts2List(); Parts3List = GetParts3List(); IsTableValid = IsTableValid(); } private List<Parts> GetPartsList() private List<Parts2> GetParts2List() private List<Parts3> GetParts3List() public bool ListsCountSame() public bool ListsContainCertainObject() private bool IsTableValid() { bool ListsCountSame = ListsCountSame(); bool listsContainCertainObject = ListsContainCertainObject(); if(!ListsCountSame || !listsContainCertainObject) { Environment.Exit(0); } return true; } }
问题描述
我负责实现上述TableProcessor类,它的作用是处理已解析的表格数据,生成对应的对象列表。所有列表创建完成后,需要验证原始表格数据是否合法。我实现了两个布尔类型的检查方法,整合到IsTableValid()方法中,然后通过构造函数里的IsTableValid属性触发验证逻辑——如果表格数据异常,就调用Environment.Exit(0)退出程序。
我的疑问是:这个布尔属性仅仅用来触发检查,后续完全没有其他场景会用到它,这种实现是不是不良编程实践?补充说明:这些检查必须在所有列表创建完成后执行,不然我会把验证逻辑整合到其他属性的方法里。
更新后的实现代码
public TableProcessor(List<List<object>> Table) : base(Table) { PartsList = GetPartsList(); Parts2List = GetParts2List(); Parts3List = GetParts3List(); TableValidation(); } private List<Parts> GetPartsList() private List<Parts2> GetParts2List() private List<Parts3> GetParts3List() private void ListsCountCheck() //检查失败则调用Environment.Exit(0) private void ListsContainCertainObjectCheck()//检查失败则调用Environment.Exit(0) private void TableValidation() { ListsCountCheck(); ListsContainCertainObjectCheck(); } }
回答
你的初始实现确实属于不良编程实践,原因如下:
- 语义不符:
IsTableValid作为布尔属性,从命名上看应该是用来告知调用者表格是否合法的状态,但实际它的作用是触发验证并直接退出程序,完全违背了属性的语义预期,会让后续维护代码的人产生误解。 - 副作用隐藏:通过属性赋值触发带有退出程序的副作用,这种操作非常隐蔽。属性通常被认为是读取或设置状态的轻量操作,没人会想到赋值一个属性会导致程序直接终止。
而你更新后的实现是更合理的选择:
- 语义清晰:
TableValidation()方法从命名就能明确它的作用是执行表格验证,调用意图一目了然。 - 副作用明确:将验证逻辑封装在专门的方法中,方法内部的退出操作虽然强硬,但至少逻辑集中且意图清晰。
不过额外提一点:直接调用Environment.Exit(0)退出程序的方式过于粗暴,尤其是在类库代码中,这会剥夺调用者处理错误的机会。更合理的做法是抛出明确的自定义异常(比如InvalidTableDataException),让调用者决定是终止程序还是进行错误恢复。
内容的提问来源于stack exchange,提问作者Humble Newbie
相关产品推荐
相关产品推荐

