相关疑难解决方法(0)

使用异常进行流量控制

我最近被告知我滥用异常来控制应用程序中的流量,所以我这是我试图以某种方式澄清情况.

在我看来,一个方法应该在遇到情况时抛出异常,这种情况无法在内部处理或者可能由调用方更好地处理.


那么 - 是否存在任何特定的规则集,可用于在开发应用程序时回答以下问题:

  • 什么时候应该抛出一个异常,什么时候应该编写具有强大的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以指示操作的成功或失败.

谢谢!

language-agnostic exception-handling exception

7
推荐指数
1
解决办法
1943
查看次数

Scala-way处理for-comprehensions的条件?

我正在尝试创建一个整洁的结构,以便理解基于未来的业务逻辑.这是一个示例,其中包含基于异常处理的工作示例:

(for {
  // find the user by id, findUser(id) returns Future[Option[User]]
  userOpt <- userDao.findUser(userId)        
  _ = if (!userOpt.isDefined) throw new EntityNotFoundException(classOf[User], userId)

  user = userOpt.get       

  // authenticate it, authenticate(user) returns Future[AuthResult]
  authResult <- userDao.authenticate(user)   
  _ = if (!authResult.ok) throw new AuthFailedException(userId)

  // find the good owned by the user, findGood(id) returns Future[Option[Good]]
  goodOpt <- goodDao.findGood(goodId)        
  _ = if (!good.isDefined) throw new EntityNotFoundException(classOf[Good], goodId)

  good = goodOpt.get        

  // check ownership for the user, checkOwnership(user, good) returns Future[Boolean]
  ownership <- goodDao.checkOwnership(user, …
Run Code Online (Sandbox Code Playgroud)

scala exception-handling future

7
推荐指数
3
解决办法
3050
查看次数

在.NET中使用try-catch进行流量控制是"糟糕的"吗?

我刚刚在一个项目中找到:

try
{
    myLabel.Text = school.SchoolName;
}
catch
{
    myPanel.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)

我想和开发人员谈谈,而不是写这个,说发生null异常(因为school理论上可能是null,不是myLabel)会使计算机发出三次蜂鸣声并睡两秒钟.但是,我想知道我是否错过了关于这一点的规则.显然,这不是try/catch的预期用途,但这是不好的,因为它因性能考虑而无视意图或不好?我觉得这很糟糕,但我想说的不仅仅是"那真的很糟糕".

c# try-catch

6
推荐指数
3
解决办法
4325
查看次数

避免使用try-catch语句的充分理由

示例#1:

try { fileChooser.setSelectedFile(new File(filename)); }
catch (NullPointerException e) { /* do nothing */ }

示例#2:

if (filename != null)
    fileChooser.setSelectedFile(new File(filename));

出于性能或稳定性(或任何其他原因),#1本质上是不好的,还是只是有点不同?这不是一个很好的例子,因为#1优于#2没有优势,但在不同情况下可能存在(例如,可读性提高,代码行数减少等).


编辑:共识似乎是#1是禁忌.最受欢迎的原因:开销

此外,@ Raph Levien有一个很好的见解:

避免#1的一个原因是它会中毒你使用异常断点的能力.正常运行的代码永远不会故意触发空指针异常.因此,将调试器设置为每次发生时都停止是有意义的.在#1的情况下,您可能会例行地获得此类异常.除其他正当理由外,还有潜在的性能影响.

另外,请参阅链接以获取更多深度.

java exception-handling try-catch

6
推荐指数
3
解决办法
2804
查看次数

使用Throwable以外的事情除了例外

我总是在错误的背景下看到Throwable/Exception.但是我可以想到扩展一个Throwablejust来打破一堆递归方法调用会非常好的情况.比如说,您试图通过递归搜索的方式在树中查找并返回一些对象.一旦你发现它粘在一些Carrier extends Throwable并抛出它,并在调用递归方法的方法中捕获它.

正面:您不必担心递归调用的返回逻辑; 既然你找到了你需要的东西,为什么还要担心如何将这个引用备份到方法堆栈中.

否定:您有一个不需要的堆栈跟踪.该try/catch块也变得违反直觉.

这是一个愚蠢的简单用法:

public class ThrowableDriver {
    public static void main(String[] args) {
        ThrowableTester tt = new ThrowableTester();
        try {
            tt.rec();
        } catch (TestThrowable e) {
            System.out.print("All good\n");
        }
    }
}

public class TestThrowable extends Throwable {

}

public class ThrowableTester {
    int i=0;

    void rec() throws TestThrowable {
        if(i == 10) throw new TestThrowable();
        i++;
        rec();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,是否有更好的方法来达到同样的目的?另外,以这种方式做事有什么不妥之处吗?

java stack throw throwable

6
推荐指数
1
解决办法
1111
查看次数

在Java中捕获StackOverflowError是否安全?

我有两个不同的函数实现(例如,树的大小),一个是递归的,另一个是使用显式堆栈.

递归非常快(可能是因为它不需要在堆上分配任何东西)但可能会导致某些"罕见"输入上的堆栈溢出(在树的例子中,它将出现在任何不平衡的树上).显式版本较慢但不太可能导致堆栈溢出.

默认情况下使用递归实现是否安全,并通过执行显式实现从StackOverflowError异常中恢复?

这被认为是不好的做法吗?

这是一个代码的小例子:

interface Node {
  List<? extends Node> getSons();
}

static int sizeRec (Node root) {
  int result = 1;
  for (Node son : root.getSons()) {
    result += sizeRec(son);
  }
  return result;
}

static int sizeStack (Node root) {
  Stack<Node> stack = new Stack<Node>();
  stack.add(root);
  int size = 0;
  while (! stack.isEmpty()) {
    Node x = stack.pop();
    size ++;
    for (Node son : x.getSons()) {
       stack.push(son);
    }
  }
  return size;
}

static int size (Node root) { …
Run Code Online (Sandbox Code Playgroud)

java stack-overflow

6
推荐指数
2
解决办法
513
查看次数

SQL唯一键插入

我有一个Users表,它对用户名有唯一约束(出于显而易见的原因).

我正在使用EF 4.0 DAL来填充数据库,并在编写CreateUser()方法的过程中.

是吗...

  1. 如果我尝试插入已存在的用户名,最好捕获抛出的SqlException.
  2. 在我尝试将其插入数据库之前,请明确检查用户名?

如果你也可以说明原因,那就太好了!

.net c# entity-framework exception-handling sql-server-2008-r2

5
推荐指数
1
解决办法
735
查看次数

累积验证违规的设计模式

让我们想象一下,我们有一个进程,它接受以下类型的数据:

{"date":"2014-05-05", "url":"http://some.website.com","counter":3}
Run Code Online (Sandbox Code Playgroud)
  • 这些数据应该被正式验证:值date应该是一个可解析的日期,url也应该符合正常的 url 语法。
  • 此外,这些数据应该在逻辑上得到验证:date应该在未来,url应该是一个可访问的地址,返回200 OK.

为了使它干净,必须将这两个验证例程分成不同的单元(类、实用程序等)。然而,所需的最终行为必须让用户清楚地了解数据中存在的所有违规行为。就像是:

{"Errors":[ "Specified date is not in the future",//Formal validation failed "Specified URL has invalid syntax"//Logical validation failed ]}

  • 我已经看到了所需行为的一些实现,但它们使用了那些利用Error对象的实现,并且充满了像Error.hasErrors()or之类的检查 error==null,这看起来并不优雅。
  • 我还看到了 的实现javax.validation,它同时为您提供所有领域的所有违规行为。可以为内容验证实施相同的方法,但我不确定这是执行此操作的最佳方法。

问题:处理各种性质的多个异常/违规的最佳做法是什么?

UPD:答案的简短摘要: collect Violations, build an Exception,包含它们的上下文、原因和描述,使用拦截器进行渲染。请参阅答案中的参考链接:

http://beanvalidation.org/1.0/spec/ JSR 303 规范

http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html Spring Bean 验证

http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html Java EE 验证

使用哪种设计模式进行验证

为什么不使用异常作为常规控制流?

java validation design-patterns exception-handling

5
推荐指数
1
解决办法
3340
查看次数

C# 字典等效于 Python 的 get() 方法

在 Python 中,如果我有一个 dict,并且我想从一个可能不存在密钥的 dict 中获取一个值,我会执行以下操作:

lookupValue = somedict.get(someKey, someDefaultValue)
Run Code Online (Sandbox Code Playgroud)

其中,如果someKey不存在,则someDefaultValue返回。

在 C# 中,有些TryGetValue()类似:

var lookupValue;
if(!somedict.TryGetValue(someKey, lookupValue))
    lookupValue = someDefaultValue;
Run Code Online (Sandbox Code Playgroud)

一个问题是,如果someKeynull然后抛出异常,所以你进行了空检查:

var lookupValue = someDefaultValue;
if (someKey != null && !somedict.TryGetValue(someKey, lookupValue))
    lookupValue = someDefaultValue;
Run Code Online (Sandbox Code Playgroud)

哪个,TBH,是 icky(3 行用于 dict 查找?)有没有更简洁(即 1 行)的方式,很像 Python 的get()

c# python dictionary

5
推荐指数
1
解决办法
1237
查看次数

为什么例外对性能有害?

看到这个问题,每个人都谈论"性能"会如何受到影响,或者当性能成为问题时应该避免例外,等等.

但是我没有看到一个很好的解释,为什么抛出异常对性能不利,这个问题中的每个人似乎都认为这是理所当然的.

我问这个的原因是,我正在尝试优化一个应用程序,并注意到在某些操作上抛出并吞下了几百个异常,例如单击按钮来加载新页面.

java performance exception

5
推荐指数
1
解决办法
508
查看次数