2009-04-26 22 views
7

大きなチームが大規模なアプリケーションを開発したとします。 ここでは、誰かがデータ構造を深くチェックするときに起こりうる潜在的な災害の単純化モデルを示します。 完全自動化または有効範囲を無効にすることはできない場合は、これを回避するにはどうすればよいですか? ありがとうございました:) !!!!Perlで自動ウイルス対策を無効にするにはどうすればよいですか?

use strict; use warnings;use Data::Dumper; 

my $some_ref = {akey=>{deeper=>1}}; 
print Dumper($some_ref); 
if($some_ref->{deep}{doot} == 1){ 
    print 'too deep '.$/; 
} 

if($some_ref->{deep}){ 
    print 'Already in a deep doot'.$/; 
} 

print Dumper($some_ref); 

これは、次のように出力します

$VAR1 = { 
      'akey' => { 
         'deeper' => 1 
        } 
     }; 
Use of uninitialized value in numeric eq (==) at autovivify_test.pl line 5. 
Already in a deep doot 
$VAR1 = { 
      'deep' => {}, 
      'akey' => { 
         'deeper' => 1 
        } 
     }; 

はい、私は警告があると知っているが、...それは遅すぎるかもしれません。

お元気ですか?私のハッシュリファレンスは、結ばれたハッシュを参照していると言ってもいいでしょう。

構造の深いところでチェックをチェックする良いFETCHメソッドを実装しても問題は解決しませんか?


私はTie::StrictHash、​​とperltieを見ました。私の解決策の ここでは単純化されたバージョン:

#!/usr/bin/env perl; 
#test_tie.pl 

package StrictHash; 
use strict; use warnings; 
use Tie::Hash; 
our @ISA = qw(Tie::StdHash); 
use Carp; 

sub TIEHASH { 
    my $class = shift; 
    my $hash = bless {@_}, $class; 
    return $hash; 
} 
##======================================================================== 
## FETCH fails if applied to a member that doesn't exist. 
##======================================================================== 
sub FETCH { 
    my ($hash, $key) = @_; 
    Carp::confess "key '$key' does not exist" unless exists $hash->{$key}; 
    return $hash->{$key}; 
} 
##======================================================================== 
package main; 
use strict;use warnings;use Data::Dumper; 
#Imagine StrictHash is in ./StrictHash.pm 
#use StrictHash; 
my %hash; 
tie %hash, 'StrictHash', akey => {deeper=>1} ; 

my $some_ref =\%hash; 
print Dumper($some_ref); 
if($some_ref->{deep}{doot} == 1){ 
    print 'too deep '.$/; 
} 

私が達成何がアプリに一つだけの場所に触れることです。 if($ some_ref - > {deep} {doot})のようなすべての場所はスタックトレースでdieを引き起こします。 だから簡単に見つけて修正します。 この種の新しい文章は不可能です。 Perlは大きなアプリにも適していますが、もっと知る必要があります;)

ありがとうございました! これは他人にも役立つことを願っています。

+0

あなたのご質問はありますか? –

+0

perlで自動ウイルス対策を無効にするにはどうすればよいですか? –

答えて

15

ハッシュ(Mooseを参照)の代わりにオブジェクトを使用するか、strict tied hashを使用します。

use warnings NONFATAL => 'all', FATAL => 'uninitialized'; 
+1

+1、勝利のために初期化されていません。 –

+0

ケントが言うように、 警告を使用することがありますNONFATAL => 'all'、FATAL => 'uninitialized'; は、最も受け入れやすい方法です。 これは開発中に設定されている可能性があります。 もう少し質問を残して、誰かがもっとスマートに何かを提案するかどうかを見てみましょう:)。 ありがとうございます。 –

+0

私はちょうど私のFETCHメソッドでちょうどいくつかのチェックを書く必要があることに気付きました。 本当にありがとう。 –

9

あなたはHash::Utilからの機能のいずれかを使用してハッシュ(コアモジュール)をロックすることができますか、あなたが本当にしたい場合は、警告をエラーに変えることができます。

use Hash::Util qw(lock_keys unlock_keys); 

my $some_ref = { akey => { deeper => 1 } }; 
lock_keys %$some_ref; 

print "too deep" if $some_ref->{deep}{shit} == 1; 

は今、最後の文は、例外がスローされます:

Attempt to access disallowed key 'deep' in a restricted hash 

欠点は、もちろん、あなたが例外を回避するために、ハッシュのキーをチェックするときに非常に注意する必要がありますことを、すなわち、 "if exists ..."のlofを使用して、アクセスする前に鍵をチェックしてください。

あなたが再びハッシュにキーを追加する必要がある場合は、後でそれをアンロックすることができます

unlock_keys %$some_ref; 
$some_ref->{foo} = 'bar'; # no exception 
+0

はい、これは大きなアプリです。ハッシュが結ばれたセッションであると想像してください。ありがとうございました。 –

3

私は@zoulをupvotedていますが、さらに一歩それを取る必要があります。

書き込みテスト

あなたはあなたのコードがテストで覆われているはず、とあなたは、テスト・ケース自体で宣言さ

use warnings FATAL => 'uninitialized'; 

でこれらのテストのいくつかを実行する必要があります。開発者が懸念事項に対処するための唯一の方法は、事前に事態を適切にチェックしないことです。コードがテストされていることを確認してください。

さらに進んで、Devel::Coverの下でテストを実行して、カバレッジレポートを入手しやすくしてください。

cover -delete 
PERL5OPT='-MDevel::Cover' prove -l 
cover -report Html_basic 

そして、テストで実行されているコードとステートメントの行をチェックし、そうでない場合は、これらの警告は致命的な作ることだけで、後の予期しない時にコードのダイを行います。

+1

このためにFATAL => '初期化されていません。'は必要ありません。 Test :: Warnモジュールでは、テストケースから正しい警告(または警告の欠落)を受け取ったことをテストできます。 –

+0

"Write Tests"はかなり簡単です:)。私はそれをやり始めましたが、仕事が待っていることを知っているので 私は何かするのがより簡単です。 投票ありがとうございます。 私は開発環境でFATAL => '初期化されていません'と考えています。 –

+0

警告の使用はレキシカルスコープであるため、テスト中にオンにしてもテスト対象のコードで有効にはなりません。 – ysth

1

もう1つの方法は、Data::Diverを使用してデータ構造にアクセスすることです。

no autovivification; 

非常に簡単:

if(1 == Dive($some_ref, qw/ deep structures are not autovivified now /) { 
    Do_Stuff(); 
} 
+0

ありがとう、私はちょうど私の問題を解決し、さらに誤動作を止めるための素早い方法を望んでいた。私は解決策の簡略化されたモデルを私の質問に追加します。 –

21

比較的新しいが、あなたがこれを行うことができますautovivificationモジュール、です。

+0

私はそれを試してみます。それは結び付いたハッシュ/配列でうまくいくのですか? –

+2

現在のバージョンに依存しないリンク: http://search.cpan.org/~vpit/autovivification/ –

+0

ありがとう...応答のリンクを更新しました。 – oeuftete

関連する問題