异常处理(EH)似乎是当前的标准,并且通过搜索网络,我找不到任何试图改进或替换它的新颖想法或方法(好吧,存在一些变化,但没有新颖的).
虽然大多数人似乎忽略它或只是接受它,但EH 有一些巨大的缺点:代码看不到异常,它会创建许多可能的退出点.乔尔在软件上写了一篇关于它的文章.比较goto完美,它让我再次思考EH.
我尽量避免使用EH,只使用返回值,回调或任何适合目的的东西.但是当你必须编写可靠的代码时,你现在就无法忽略EH:它从new可能抛出异常开始,而不是仅仅返回0(就像过去一样).这使得任何C++代码行都容易受到异常的影响.然后C++基础代码中的更多地方抛出异常...... std lib执行它,依此类推.
这感觉就像走在摇摇欲坠的地面上.所以,现在我们被迫关注异常!
但它很难,真的很难.你必须学会编写异常安全代码,即使你有一些经验,它仍然需要仔细检查任何一行代码是安全的!或者你开始在任何地方放置try/catch块,这会使代码混乱,直到它达到不可读状态.
EH取代了旧的干净确定性方法(返回值..),它只有一些但可以理解且易于解决的缺点,在您的代码中创建许多可能的退出点的方法,以及如果您开始编写捕获异常的代码(您是什么的)在某些时候被迫做某事),然后它甚至通过你的代码创建了许多路径(catch块中的代码,考虑一个服务器程序,你需要除了std :: cerr之外的日志工具..).EH有优势,但这不是重点.
我的实际问题:
如何检查SqlDataReader对象中是否存在列?在我的数据访问层中,我创建了一个方法,为多个存储过程调用构建相同的对象.其中一个存储过程具有另一个列,其他存储过程不使用该列.我想修改方法以适应每个场景.
我的应用程序是用C#编写的.
如果方法名称以"Try"开头,我们正在与我们的同事讨论它意味着什么.
有以下意见:
什么是官方定义?"尝试"在方法名称中说什么?有关于此的官方指南吗?
C#中的例外有多贵?只要堆叠不深,它们似乎并不是非常昂贵; 但我读过相互矛盾的报道.
有没有被反驳的确定性报告?
我知道这是一个非常广泛的问题,但是短暂的"取决于"的答案将不被接受.战略诞生于处理广泛的问题.
在设计错误和异常处理策略时,应用程序设计人员应该考虑哪些问题?
策略将如何根据软件类型(COTS,内部业务应用程序,咨询软件,游戏,托管Web应用程序,嵌入式等)而有所不同?软件类型重要吗?
道德,政治和法律问题?
关于错误处理(用户,开发人员,业务支持,管理)的各种观点.
我会探讨的一些想法:
各种错误报告路由(即UI,日志记录,自动管理通知).
纵深防御和健壮性(故障转移应急和故障安全机制,针对尚未知晓的问题进行恢复).
公平对待用户和客户(即最小化对软件用户和软件服务的其他人的影响).
我正在寻找类似的想法和概念列表.
如果我需要进一步澄清问题并感谢所有人的贡献,请使用评论指出我!
常问问题
开发平台(Java,.NET,移动) - 从开发人员的角度来看肯定会对策略的最终实现细节产生一些影响,但从用户的角度来看则更少.
愚人节肯定不是.我被要求处理的大多数遗留系统没有明确的错误处理策略.
这可以成为社区维基吗? 不,这似乎是一个很好的问题,很难想出好的问题.
这个策略是什么意思?长期计划,提供方向,重点,为错误和异常处理带来一致性和协调性.如果有一个更大的团队从事软件工作,那么该策略可以通过书面形式进行制定和分发.
这似乎是重复的问题(见在Java或C异常管理的最佳实践和哪个,为什么你喜欢的异常或返回代码),这些问题处理上的错误处理(主要是开发者)某个角度来说,我想了解更多关于其他观点以及它们如何为整体战略做出贡献.
我创建了一个从文件中解析一些文档的类.
class Parser
{
public Parse(string fileName)
{
///
}
}
Run Code Online (Sandbox Code Playgroud)
有时可能会出现解析错误,解析器必须返回某些数据.我为此创建了特殊课程.
class ParsingError
{
// some data
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能正确处理这些错误.我至少有两个选择:
创建我自己的异常或返回值.
方案一
myParser.Parse(fileName, out error);
Run Code Online (Sandbox Code Playgroud)
方案二
try
{
myParser.Parse(fileName)
}
catch(MyParsingException ex)
{
// use ex.Error field
}
Run Code Online (Sandbox Code Playgroud)
UPDATE
如果我没有弄错,那么例外背后的意识形态就是它应该处理一些特殊的东西,这是该方法无意处理的一些情况.
这让我想知道是否例如:
解析器在文件中找到未知字段,或者编码错误
这会被视为特殊情况吗?
我最近被告知我滥用异常来控制应用程序中的流量,所以我这是我试图以某种方式澄清情况.
在我看来,一个方法应该在遇到情况时抛出异常,这种情况无法在内部处理或者可能由调用方更好地处理.
那么 - 是否存在任何特定的规则集,可用于在开发应用程序时回答以下问题:
什么时候应该抛出一个异常,什么时候应该编写具有强大的nothrow保证的代码,这可能只是返回 bool表示成功或失败?
我应该尝试最小化情况的数量,当方法抛出异常时,或者相反,它应该最大化以在处理这些情况时提供灵活性吗?
我应该坚持在开发我的应用程序时使用的框架/运行时设置的异常抛出约定,还是应该包装所有这些调用,以便它们匹配我自己的异常抛出策略?
我还建议使用错误代码进行错误处理,这似乎非常有效,但从语法的角度来看很丑陋(同样,当使用它们时,开发人员失去了为方法指定输出的能力).你怎么看待这件事?
实施例为第三个问题(I用的I/O架构和遇到以下情况):
所描述的框架不使用异常来处理错误,但其他代码确实使用它们.我是否应该将所有可能的失败包裹起来
'???'并在这种情况下抛出异常?或者我应该将方法的签名更改为bool PrepareTheResultingOutputPath仅指示操作是否成功?
public void PrepareTheResultingOutputFile(
String templateFilePath, String outputFilePath)
{
if (!File.Exists(templateFilePath))
// ???
if (!Directory.MakePath(outputFilePath))
// ???
if (File.Exists(outputFilePath))
if (!File.Remove(outputFilePath))
// ???
if (!File.Copy(templateFilePath, outputFilePath)
// ???
}
Run Code Online (Sandbox Code Playgroud)
另一个例子 - 即使.NET Framework不遵循一些严格的异常抛出策略.一些方法被记录为抛出10多种不同的异常类型,包括普通的异常类型NullArgumentException,但其中一些只是返回bool以指示操作的成功或失败.
谢谢!
我们可以返回一个元组
std::pair<bool, std::string> fooFunction();
Run Code Online (Sandbox Code Playgroud)
但这使得创建返回值时代码变得多余,并强制调用者处理元组(在 c++17 中使用结构绑定很容易)
if ( okayCondition)
return {true, {}};
else
return { false, "blabla error"};
Run Code Online (Sandbox Code Playgroud)
或者我们可以使用
std::optional<std::string> fooFunction();
Run Code Online (Sandbox Code Playgroud)
这对于返回 bool 的现有函数很有趣,因为由于 std::optional 运算符 bool,大多数调用者不需要更新
//Legacy code ok
if (fooFunction())
Run Code Online (Sandbox Code Playgroud)
我知道一种更重的方法,一个模板化的 ReturnStatus 类,它会在调用者不测试返回状态值的情况下抛出。
还有其他方法吗?
我正在设计一个WCF服务,它将返回一个响应代码(例如0表示成功,或另一个表示错误).此外,Web服务的所有方法都将执行几种常见的验证(例如验证apiKey).
我想知道是否有最佳实践方法或组织和检索这些响应代码和消息.
谢谢你的任何建议.
可能重复:
C++ - 返回代码异常的参数
在进行C++编程时,您有两种报告错误的选择.我想很多老师会建议你抛出一个异常,它是从std :: exception派生的.另一种可能更"C"形式的方法是返回非零值,因为零是"ERROR_SUCCESS".
确切地说,返回异常可以提供更多的错误和恢复信息; 虽然代码会膨胀一点,但在你的脑海中保持异常安全对我来说有点困难,至少.其他方式,如返回其他内容,将使报告错误更容易; 缺点是管理恢复将是一个可能很大的问题.
作为优秀的程序员,人们会不会考虑老板的意见?对我来说,我想返回一些非零值.