Perl - 处理传递给sub的无效数据的最佳实践

时间:2017-07-28 19:42:09

标签: perl

当数据错误地传递给子例程时,Perl的最佳做法是什么?子死亡还是刚回来?

这是我通常做的事情

my @text = ('line 1', 'line 2');

print_text(\@text) 
   or die "ERROR: something went wrong in the sub";

sub print_text{
   my ($aref_text) = @_;
   return unless ref($aref_text) eq "ARRAY";
   print "$_\n" for @{$aref_text};
   return 1;
}

这里,如果传递的输入无效,则只返回sub,并且它希望调用者像在此处一样检查错误。我想知道是否总是一个更好的做法只是" die"在子级别。在大脚本中,我害怕这样做,因为我不想因为一些简单的子程序失败而终止整个脚本。

另一方面,我害怕只是返回,因为如果调用者忘记检查sub是否返回true,那么脚本将继续运行并且可能发生奇怪的事情。

由于

1 个答案:

答案 0 :(得分:3)

这完全属于如何处理子程序中的错误的问题。

对此进行了很好的讨论,但我现在无法找到这些帖子。

原则上,这些是处理子程序中错误的方法

  • 返回代码,其中一些代表错误

  • 返回"特别"值,例如Perl中的undef

  • 抛出异常,Perl中的设备为die

调用者检查返回或测试undef,或使用eval来捕获和处理die。最合适的取决于上下文和代码的作用。

我认为现代语言中没有太多理由可以限制在"代码" (如负值)表示错误。首先,要么干涉合法的回报,要么限制它们通过指针/引用,这是一个重大的设计决定。

返回undef通常是一种很好的中途方法,特别是在代码中并不过分复杂。它表明一些"失败" sub来执行它的意思。但是,即使在最小的undef中,也可能适合表示不可接受的结果。然后,如果它也用于输入错误,我们就会有区分这些错误的问题。

在简单die上基于Perl抛出异常会增加更多可能性。在复杂的代码中,您可能希望编写(或使用)一个错误处理类,该类模仿具有它的语言的异常处理支持,然后抛出它。

my $error_obj = ErrorHandlingClass->new( params );

... or die $error_obj;

然后调用代码可以分析对象。这将是最有条理的方式。

一个很好的简单示例是Path::Tiny,其source中找到了自己的Path::Tiny::Error

同样,在任何一个特定情况下适用的内容取决于该应用程序的详细信息。

关于直接问题的一些评论。

die中的无信息消息强调了返回什么的困境(它没有告诉我们什么是失败的)。但在这种情况下,我们如何使失败提供信息?

请注意,如果子返回or或空字符串,则die会产生0。如果我们将其替换为//(已定义 - 或),那么die上的undef将替换为undef,如果die也可能指示一个糟糕的结果。

因此,在这种情况下,您可能希望函数在错误输入时使用die,并使用合适的消息。

这会在出现问题后进行调试。如果代码需要能够恢复,那么您最好返回更多结构化信息 - 抛出(或返回)您编写的错误处理类的对象。 (作为临时的止损措施,您可以解析来自die的消息。)

对于检查回报的古老的纪律问题,die是一个很好的工具。没有" 简单的"这是不值得的 - 你不想继续犯错误,所以die可以。在复杂的项目中,错误处理更复杂,因此我们需要更多工具和结构,而不是更少。

回想一下异常"冒泡",如果未处理,则向上传播调用堆栈,eval也是如此。这可以很好地用于调试,而不会在每次调用时都有die。最后,大部分内容都是调试的一部分。

没有&#34;最佳实践&#34;为了这。但是 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.4.RELEASE) 2017-07-28 22:16:44.293 INFO 8624 --- [ main] com.algotest.DemoApplication : Starting DemoApplication on DESKTOP -JHL7NBI with PID 8624 (C:\Dropbox\Projects\AlgoTest\Jar\Server\AlgoTest.jar started by Server in C:\Dropbox\Projects\AlgoTest\Jar\Serv er) 2017-07-28 22:16:44.295 INFO 8624 --- [ main] com.algotest.DemoApplication : No active profile set, falling back to default profiles: default 2017-07-28 22:16:44.326 INFO 8624 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.cont ext.annotation.AnnotationConfigApplicationContext@8df31b: startup date [Fri Jul 28 22:16:44 CEST 2017]; root of context hierarchy 2017-07-28 22:16:48.992 ERROR 8624 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connection s of pool. java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:526) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:505) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:479) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:489) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:1677) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:1601) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:633) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:347) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:219) ~[mysql-connector-java-6.0.6.jar:6.0.6] at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:310) ~[tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:735) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:667) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:482) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.15.jar:na] at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.15.jar:na] at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) [spring-jdbc-4.3.9.RELEASE.jar :4.3.9.RELEASE] at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) [spring-jdbc-4.3.9.RELEASE.jar:4. 3.9.RELEASE] at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:326) [spring-jdbc-4.3.9.RELEASE.jar:4.3.9. RELEASE] at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:366) [spring-jdbc-4.3.9.RELEASE.jar:4.3.9. RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.DatabaseLookup.getDatabase(DatabaseLookup.java:72) [spring-boot-autoconfigure -1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.determineDatabase(JpaProperties.java:139) [spring-boot-autoconf igure-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.jpaVendorAdapter(JpaBaseConfiguration.java:105) [spring- boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bb95dfe1.CGLIB$jpaVendo rAdapter$5(<generated>) [spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bb95dfe1$$FastClassBySp ringCGLIB$$6b52e508.invoke(<generated>) [spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) [spring-core-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer .java:358) [spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$bb95dfe1.jpaVendorAdapt er(<generated>) [spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_144] at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_144] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) [spr ing-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) [s pring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireC apableBeanFactory.java:1173) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanF actory.java:1067) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory .java:513) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.j ava:483) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.9. RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [ spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.9.RE LEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.9.RELE ASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) [spring-beans- 4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:113 8) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring -beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-bean s-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) [s pring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireC apableBeanFactory.java:1173) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanF actory.java:1067) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory .java:513) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.j ava:483) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.9. RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [ spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.9.RE LEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.9.RELE ASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) [spring-beans- 4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:113 8) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring -beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-bean s-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) [s pring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireC apableBeanFactory.java:1173) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanF actory.java:1067) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory .java:513) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.j ava:483) [spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.9. RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [ spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.9.RE LEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.9.RELE ASE.jar:4.3.9.RELEASE] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078) [spring-context -4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.ja va:857) [spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) [spring-context- 4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.4.RELEASE.jar:1.5.4.R ELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at com.algotest.DemoApplication.main(DemoApplication.java:27) [AlgoTest.jar:na] Caused by: com.mysql.cj.core.exceptions.CJException: Access denied for user 'springuser'@'localhost' to database 'db_example' at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_144] at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_144] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_144] at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:1.8.0_144] at com.mysql.cj.core.exceptions.ExceptionFactory.createException(ExceptionFactory.java:54) ~[mysql-connector-java-6.0.6.jar:6.0 .6] at com.mysql.cj.core.exceptions.ExceptionFactory.createException(ExceptionFactory.java:93) ~[mysql-connector-java-6.0.6.jar:6.0 .6] at com.mysql.cj.core.exceptions.ExceptionFactory.createException(ExceptionFactory.java:133) ~[mysql-connector-java-6.0.6.jar:6. 0.6] at com.mysql.cj.core.exceptions.ExceptionFactory.createException(ExceptionFactory.java:117) ~[mysql-connector-java-6.0.6.jar:6. 0.6] at com.mysql.cj.mysqla.io.MysqlaProtocol.checkErrorPacket(MysqlaProtocol.java:807) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.io.MysqlaProtocol.checkErrorPacket(MysqlaProtocol.java:732) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.io.MysqlaProtocol.checkErrorPacket(MysqlaProtocol.java:701) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.authentication.MysqlaAuthenticationProvider.proceedHandshakeWithPluggableAuthentication(MysqlaAuthentica tionProvider.java:536) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.authentication.MysqlaAuthenticationProvider.connect(MysqlaAuthenticationProvider.java:204) ~[mysql-conne ctor-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.io.MysqlaProtocol.connect(MysqlaProtocol.java:1414) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.mysqla.MysqlaSession.connect(MysqlaSession.java:132) ~[mysql-connector-java-6.0.6.jar:6.0.6] at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:1619) ~[mysql-connector-java-6.0.6.jar:6.0.6] ... 76 common frames omitted 2017-07-28 22:16:49.001 WARN 8624 --- [ main] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from d atasource org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.sp ringframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLNonTransientConnect ionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up. at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData 的默认值是相当合理的。