2017-07-28 17 views
1

當數據不正確地傳遞給子例程時,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是否返回true,那麼腳本將繼續運行,並且可能會發生奇怪的事情。

感謝

+3

@hanshenrik:我看不出有什麼幫助。 – Borodin

+1

這應該是調試的一部分,並且我認爲它給編碼這種特定檢查帶來了錯誤的安全感。確保一個給定的參數是真的,比如說,一個數組引用僅涵蓋了可能出現的一小部分錯誤,如果你試圖以數組的形式解引用其他的東西,Perl會引發它自己的異常。到目前爲止,最常見的錯誤大都無法檢測到,例如,您的參考可能會引用具有舊數據的數組。 – Borodin

+0

在沒有使整個運行無效的情況下發生代碼很少見,所以用有用的信息'死'會比讓程序繼續並提供不正確的結果更好。但是沒有任何類型檢查可以提供與最小的測試程序相同的保護。這就是爲什麼Java和C++的詳細和冗長的語法是基於一種誤解。 Perl對許多事情來說都是不應該臭名昭着的,但是即使只有非常基本的類型檢查,Perl也不是其中之一。 – Borodin

回答

3

這完全屬於下如何處理與一般子程序錯誤的問題。

已經有很好的討論,但我現在找不到那些帖子。

原則,這些都是在Perl

  • 的方式來處理錯誤子程序

    • 返回代碼,其中的一些錯誤指示

    • 回報 「特殊」 的價值觀,像undef拋出異常,在Perl中的設備是die

    呼叫者要麼檢查退貨,要麼檢測undef,要麼使用eval來捕獲並處理die。什麼是最適合的完全取決於上下文和代碼的作用。

    在現代語言中,我沒有看到很多原因被限制爲表示錯誤的「代碼」(如負值)。一方面,干涉會導致合法回報,或者限制他們通過指針/引用去執行,這是一個很大的設計決定。

    返回undef通常是一個很好的中間路徑方法,特別是在不太複雜的代碼中。它表明了一些「失敗」的子執行它的意思。然而,即使在最小的子集undef可能適合於指示結果,這是不可接受的。那麼如果它也被用於糟糕的輸入,我們有一個區分這些錯誤的問題。

    在簡單的die中引發基於Perl的異常增加了更多的可能性。在複雜的代碼中,您可能希望編寫(或使用)一個錯誤處理類,以模仿來自擁有它的語言的異常處理支持,然後拋出它。

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

    然後調用代碼可以分析對象。這將是最有條理的方式。

    一個不錯的簡單例子是Path::Tiny,在source中找到它自己的Path::Tiny::Error

    再一次,在任何一個特定情況下適合什麼取決於該應用的細節。


    對直接問題的一些評論。

    die(它告訴我們什麼都沒有成功),無信息的消息強調了返回什麼的困境。但是在這種情況下,我們如何使失敗信息化?

    請注意,如果子文件返回0或空字符串,則您的or結果爲die。如果我們將其替換爲//(已定義或),那麼對die替換爲undef,如果undef也可能表示結果不合適,我們仍無法打印特定消息。

    因此,在這種情況下,您可能需要在輸入錯誤時輸入die的函數,並輸入合適的消息。

    這會做調試。如果代碼需要能夠恢復那麼您最好返回更多結構化信息 - 拋出(或返回)您要編寫的錯誤處理類的對象。 (作爲特別的權宜措施,您可以從die解析信息。)

    至於舊的紀律檢查退貨問題,die是一個很好的工具。沒有「簡單子」,這是不值得的–你不想繼續出現錯誤,所以它可以die。而在複雜項目中錯誤處理比較複雜,所以我們需要更多的工具和結構,不能少。

    回想一下,異常「冒泡」,在未處理的情況下向上傳播調用堆棧,die也是如此。這可以很好地用於調試,而不必在每個呼叫上都有eval。最後,大部分是調試的一部分。

    對此沒有「最佳實踐」。但是默認的die -ing至少是合理的。

  • +0

    實際上是否可以抓住和處理「死亡」?你可以做一些像try {die'foo';} catch($ ex){}? – hanshenrik

    +0

    @hanshenrik哦,是的,這就是Perl中的(簡單) 異常處理機制。它被[eval](http://perldoc.perl.org/functions/eval.html)(它的塊形式)所捕獲。有一些模塊可以將它包裝起來,並提供'try'-style的語法,然後還有其他的方法可以超越。但它都是基於'die'-'eval'。 – zdim

    +0

    @JohnnyLoo我在你的問題上添加了一個更直接的評論部分 – zdim

    相關問題