10

現在の仕事では、オブジェクトに大きく依存する一連の Perl スクリプトを作成しています。(Perl のbless()ハッシュを使用して、可能な限り OO に近づけます)

さて、これをより適切に表現する方法がないため、私の会社のほとんどのプログラマーはあまり賢くありません。さらに悪いことに、彼らはドキュメントを読むのが好きではなく、他の人のコードを理解するのに問題があるようです。カウボーイコーディングはここでのゲームです. 彼らが問題に遭遇してそれを修正しようとするときはいつでも、実際には何も解決せず、通常は事態を悪化させる恐ろしい解決策を思いつきます。

これにより、率直に言って、ダックタイプの言語で書かれたコードを信頼していません。例として、オブジェクトの誤用に対して明示的なエラーが発生しないという問題が多すぎます。たとえば、 typeAに memberfooがあり、 のようなことをするとinstance->goo、すぐに問題に気付くことはありません。null/未定義の値が返され、おそらく原因を見つけるのに 1 時間を無駄にするでしょう。その後、元の問題を適切に特定できなかったため、別のものを変更することになります。

そこで私は、スクリプト言語を維持し (その急速な開発が利点です)、オブジェクトが適切に使用されていない場合に明示的なエラー メッセージを表示する方法についてブレインストーミングを行っています。コンパイル段階や静的型付けがないため、エラーは実行時に発生する必要があります。ユーザーが「このオブジェクトには X がありません」という非常に明確な通知を受け取る限り、私はこれで問題ありません。

私の解決策の一部として、メソッド/変数を使用する前に存在するかどうかを確認する必要はありません。

私の仕事は Perl ですが、これは言語にとらわれない可能性があると思います。

4

3 に答える 3

17

使用するモジュールを追加するショットがある場合は、Mooseを試してください。最新のプログラミング環境で必要なほとんどすべての機能を提供します。型チェック、優れた継承、イントロスペクション機能を備え、Perl クラスの最も優れたインターフェイスの 1 つであるMooseX::Declareを備えています。見てみましょう:

use MooseX::Declare;

class BankAccount {
    has 'balance' => ( isa => 'Num', is => 'rw', default => 0 );

    method deposit (Num $amount) {
        $self->balance( $self->balance + $amount );
    }

    method withdraw (Num $amount) {
        my $current_balance = $self->balance();
        ( $current_balance >= $amount )
            || confess "Account overdrawn";
        $self->balance( $current_balance - $amount );
    }
}

class CheckingAccount extends BankAccount {
    has 'overdraft_account' => ( isa => 'BankAccount', is => 'rw' );

    before withdraw (Num $amount) {
        my $overdraft_amount = $amount - $self->balance();
        if ( $self->overdraft_account && $overdraft_amount > 0 ) {
            $self->overdraft_account->withdraw($overdraft_amount);
            $self->deposit($overdraft_amount);
        }
    }
}

かっこいいと思いますよ、自分。:) これは Perl のオブジェクト システム上のレイヤーなので、(基本的には) 既に持っているもので動作します。

Moose を使用すると、サブタイプを非常に簡単に作成できるため、入力が有効であることを確認できます。怠惰なプログラマーは同意します: Moose でサブタイプを機能させるために行う必要があることはほとんどないため、そうしないよりは実行する方が簡単です! (クックブック 4より)

subtype 'USState'
    => as Str
    => where {
           (    exists $STATES->{code2state}{ uc($_) }
             || exists $STATES->{state2code}{ uc($_) } );
       };

多田さん、USState が使用できる型になりました。大騒ぎする必要もなく、わずかなコードで済みます。正しくない場合はエラーがスローされ、クラスのコンシューマーが行う必要があるのは、その文字列を含むスカラーを渡すことだけです。問題がなければ (どちらが正しいか? :)) 彼らは通常どおりにそれを使用し、あなたのクラスはガベージから保護されます。それはなんて素晴らしいことでしょう!

Mooseには、このような素晴らしいものがたくさんあります。

私を信じて。見てみな。:)

于 2010-05-29T03:09:35.630 に答える
5

Perlでは、

  • それを必要としuse strictuse warningsコードの100%でオンになっている

  • クロージャを作成することで、ほぼプライベートなメンバー変数を作成することができます非常に良い例は、 http: //www.usenix.org/publications/login/1998-10/perl.htmlの「PrivateMember Variables、Sortof」セクションです。彼らは100%プライベートではありませんが、あなたが何をしているのかを本当に知っていない限り、アクセスする方法はかなり明白ではありません(そしてあなたがあなたのコードを読んでその方法を見つけるために調査をすることを彼らに要求します)。

  • クロージャを使用したくない場合は、次のアプローチがある程度うまく機能します。

    すべてのオブジェクトメンバー変数(Perlではオブジェクトハッシュキー)をアクセサーでラップします。コーディング標準POVからこれを効率的に行う方法があります。最も安全性の低いものの1つは、Class :: Accessor::Fastです。Mooseにはもっと良い方法があると思いますが、私はMooseにあまり詳しくありません。

    プライベートコンベンション名の実際のメンバー変数を「非表示」にするようにしてください。たとえば$object->{'__private__var1'}、メンバー変数であり$object->var1()、ゲッター/セッターアクセサーになります。

    注:最後に、Class :: Accessor :: Fastは、そのメンバー変数がアクセサーと名前を共有するため、不適切です。ただし、Class :: Accessor :: Fastと同じように機能し、「foo」の$ obj-> {'__private__foo'}などのキー値を作成する非常に簡単なビルダーを使用できます。

    これは彼らが足で自分自身を撃つことを妨げることはありませんが、そうすることをはるかに難しくします。

    あなたの場合、$obj->gooまたはを使用する$obj->goo()と、少なくともPerlではランタイムエラーが発生します。

    もちろん、彼らは自分たちのやり方を邪魔することはできます$obj->{'__private__goo'}が、彼らがまったくの怠惰のためにハメ撮りカウボーイのがらくたをする場合、後者は正しいことをするよりもはるかに多くの仕事です$obj->foo()

    型文字列を検出するコードベースをスキャンすることもできますが$object->{"_、説明からはそれほど抑止力として機能しない可能性があります。

于 2010-05-29T01:58:26.370 に答える
4

Class::InsideOutまたはObject::InsideOutを使用すると、真のデータ プライバシーが得られます。Blessed ハッシュ参照にデータを格納するのではなく、Blessed スカラー参照がレキシカル データ ハッシュのキーとして使用されます。簡単に言えば、同僚が実行しようと$obj->{member}すると、実行時エラーが発生します。$objアクセサーを介する以外にデータを取得する簡単な方法はありません。

ここでは、裏返しの手法とさまざまな実装について説明します。

于 2010-05-29T21:57:26.217 に答える