这个问题与技术无关,但我正在使用 C# 和 ASP.NET 并将其用于伪代码。哪种方法更好,为什么?
-
封装日志记录、事务和异常处理:
protected void Page_Load(object sender, EventArgs e) {
SomeBusinessClass.SomeBusinessMethod();
}
公共类 SomeBusinessClass {
公共无效SomeBusinessMethod(){
使用 (TransactionScope ts = new TransactionScope()) {
doStuff();
ts.Complete();
}
捕获(异常前){
LogError("保存订单时发生错误", ex);
}
}
}
}
-
将日志记录、事务和异常处理委托给调用者:
protected void Page_Load(object sender, EventArgs e) {
使用 (TransactionScope ts = new TransactionScope()) {
尝试 {
SomeBusinessClass.SomeBusinessMethod();
ts.Complete();
}
捕获(异常前){
LogError("保存订单时发生错误", ex);
}
}
}
公共类 SomeBusinessClass {
公共无效SomeBusinessMethod(){
doStuff();
}
}
我担心通过在业务逻辑代码中引入对日志记录、事务等的依赖关系,我会使其不那么通用。另一方面,UI 代码看起来干净多了。我无法打电话。让我知道我还应该考虑哪些其他因素。
This issue is technology agnostic, but I am working with C# and ASP.NET and will use this for the pseudo code. Which is the better approach, and why?
-
Encapsulate logging, transaction and exception handling:
protected void Page_Load(object sender, EventArgs e) {
SomeBusinessClass.SomeBusinessMethod();
}
public class SomeBusinessClass {
public void SomeBusinessMethod() {
using (TransactionScope ts = new TransactionScope()) {
doStuff();
ts.Complete();
}
catch (Exception ex) {
LogError("An error occured while saving the order", ex);
}
}
}
}
-
Delegate logging, transaction and exception handling to the caller:
protected void Page_Load(object sender, EventArgs e) {
using (TransactionScope ts = new TransactionScope()) {
try {
SomeBusinessClass.SomeBusinessMethod();
ts.Complete();
}
catch (Exception ex) {
LogError("An error occured while saving the order", ex);
}
}
}
public class SomeBusinessClass {
public void SomeBusinessMethod() {
doStuff();
}
}
I am concerned that by introducing dependencies on logging, transactions, etc in my business logic code, I make it less generic. On the other hand, the UI code looks so much cleaner. I can't make the call. Let me know what other factors I should consider.
发布评论
评论(3)
事务:业务层的核心关注点,因此它绝对应该处理这个问题(尽管您可以通过 工作单元实现)。
更新:我不再同意这部分内容。通常,控制器、演示者或其他顶级调用者是处理事务的最佳位置(例如 洋葱架构) - 在许多情况下,这就是定义工作逻辑单元的地方。
异常处理:在每一层根据需要使用 - 但仅在业务层使用当你实际上可以做一些事情(而不仅仅是记录它)。如果您的基础设施支持全局处理程序,请在 UI 层中使用全局处理程序。
日志记录:在任何需要的层中使用跟踪或信息日志记录,仅在顶层记录异常。
Transactions: a central concern of your business layer, so it should absolutely handle this (though you might centralize transaction handling via a unit of work implementation).
Update: I don't agree with this part any more. Often, the controller, presenter, or or another top-level caller is the best place to handle transactions (a la the the onion architecture) - in many cases, that's where the logical unit of work is defined.
Exception Handling: use as needed in every layer - but only use it in the business layer when you can actually do something about it (not just log it). Use a global handler in the UI layer if your infrastructure supports one.
Logging: use trace or informational logging in whatever layers need it, only log exceptions in the top layer.
使用控制反转:
更好的方法是
通过 IoC 容器将 _mybusiness 类以及填充的 _logger、_dbcontext 和 _exceptionhandler 传递到您的页面。如果您需要手动创建 _exceptionhandler,例如“new RedirectExceptionHandler(this)”,那么
现在它实际上归结为您的具体设计决策。不过,由于我使用 MVC,所以不知道如何在 ASP.NET 中执行 IoC。
另一种选择是使用面向方面的编程来捕获异常并进行日志记录。另一种选择(可在 www.sharparchitecture.net 中找到)是使用方法上的 [Transaction] 属性以声明方式处理事务。
Use Inversion of Control:
A better one would be
where _mybusiness class is passed to your page via IoC container, along with populated _logger, _dbcontext, and _exceptionhandler. If you need to create _exceptionhandler manually, for example "new RedirectExceptionHandler(this)", then
Now it really boils down to your specific design decisions. Don't know how to do IoC in ASP.NET, though, since I use MVC.
Another option is to use Aspect Oriented Programming to catch exceptions and do logging. Yet another option (available in www.sharparchitecture.net) is to handle transactions declaratively using [Transaction] attributes on method.
任何让 UI 更薄的东西都会让你的生活更轻松。
Anything that makes the UI thinner will make your life easier.