【问题标题】:How do I separate error handling from business logic in Perl?如何在 Perl 中将错误处理与业务逻辑分开?
【发布时间】:2010-12-03 20:25:01
【问题描述】:

如何将异常处理/错误处理与业务逻辑分开? 我正在用 Perl 编写代码,错误/异常处理和业务逻辑使得在审查时很难理解代码。

如何重构我的代码以使其更具可读性,同时具有错误处理功能。 另请注意,我不使用 try catch 或类似的东西。

我们的一位高级程序员建议我们重新打开操作系统标准错误并将所有内容写入那里,我们可以被调用者捕获。

编辑:这是我如何处理错误。我有很多 Perl 模块.. 所以check2.pm

package check2;
sub printData {
      print STDERR "Error Message from sub routine \n";
    }
    1;

我在我的 Perl 脚本中使用它,check.pl

在我的 Perl 脚本中

#!/usr/bin/perl
use LoadModules;
use strict;
use warnings;

load check2;

my $stderrholder;
local *SAVEERR;

# First, save existing STDERR
open SAVEERR, ">&STDERR" or print "not able to open";
close STDERR;

# Open the STDERR to a variable
open STDERR, ">", \$stderrholder or die "Failed to reopen STDERR $!\n";

#Start of processing

# Now print something to STDERR, redirected to $ stderrholder
print STDERR " Error Message from Main script \n";

check2::printData();

#End of processing

# Now close and restore STDERR to original condition.
close STDERR;
#open STDERR, ">&SAVEERR";

# Now check if there were any processing errors.
if(length($stderrholder)) {
  print "\nProcessing errors\n" ;
if(length($stderrholder)) {
  print "\nProcessing errors\n" ;
  print $stderrholder;
} else {
  print "\nNo Processing errors\n" ;
}

如果有人能帮我指出其中的错误,我将不胜感激。

【问题讨论】:

  • 所以这和编程无关?伙计,所以一天比一天更糟..
  • 投票可能更多地证明了问题的基调而不是其内容。

标签: perl error-handling


【解决方案1】:

导致错误的代码

 sub whatever { 
    die "OH NOES" if an_error($occurred);
 }

你的主程序:

 use Try::Tiny; # essential
 my $logger = anything_you_want;
 try {
     whatever;
 }
 catch {
     $logger->error("Error: $_");
 };

出现问题时抛出异常。在有意义的地方处理异常;通常在顶层。

有时您可以“修复”异常;示例:如果主服务器不可用,则连接到故障转移服务器。在这种情况下,请在比顶级应用程序更高级别但比“连接”功能更接近的地方处理故障转移:

sub connect {
    die "Error connecting: ..." if ...;
}

sub make_connection {
   my $connection = try { connect($main_server) };
   $connection ||= try { connect($backup_server) };
   die "Couldn't connect to either server" unless $connection;
   return $connection;
}

然后,您将在顶级代码中处理“无法连接到任一服务器”,而不是处理每个单独的连接错误。

最后,您还可以使用Error monad。这允许您返回失败代码,但它确保在失败后不执行任何代码。 (这种方法更适用于基于事件的异步代码...但是大多数 Perl 程序员不喜欢 monad,而是尝试对所有内容使用异常。这很好,不过...异常是处理错误的好方法。)

【讨论】:

    【解决方案2】:

    好问题,但我认为即使它使代码更复杂,您也不应该从业务逻辑中删除错误处理,因为通常情况下业务逻辑需要了解错误。

    我认为您可能需要重构业务逻辑,以便错误处理围绕业务逻辑进行。这可能行得通,但我认为始终分开错误处理是不可能的,甚至不是一个好主意。

    我认为您问题的答案很大程度上取决于应用程序的类型和业务逻辑的复杂性。

    【讨论】:

      【解决方案3】:

      怎么弄的很困难?你能举个例子说明什么是困难的吗?

      在处理错误时,您可以在 perl 中编写相当易读的代码。例如,open(my $filehandle, '>', $filename) or die "Failed to open $filename" 是一个可以理解的英文句子。此外,您可以使用autodie 来启用自动捕获常见错误。

      我们的一位高级程序员建议我们重新打开操作系统标准错误并将所有内容写入那里,我们可以被调用者捕获。

      我想这总比没有好,但不要止步于此。将整个代码封装在一个 while(1) 循环中,并且一个巨大的 try/catch 不会让你做任何复杂的事情,而且它是一个巨大的代码气味。

      最后:

      请注意,我不使用 try catch 或类似的东西。

      为什么不呢?

      【讨论】:

      • 为什么不呢?我们的一位高级程序员建议我们重新打开操作系统标准错误并在那里编写所有内容,我们可以通过调用者捕获它。事实上它已经在代码中了..我确实建议使用 try catch..但他们没有听..因为我不是高级..
      • “打开操作系统标准错误并在那里写入所有内容,我们可以通过调用者捕获它”没有意义。
      • 我把它读作“..我们重新打开 stderr 并在那里写入所有内容” - 虽然我不明白为什么它会被关闭 - 打印到 stderr(或任何错误日志)是如此基本如果他们甚至不这样做,我会感到害怕。
      猜你喜欢
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 2011-02-07
      • 2015-04-20
      • 1970-01-01
      相关资源
      最近更新 更多