アヒル型の言語での静的タイピングの側面をシミュレートします
-
05-10-2019 - |
質問
私の現在の仕事では、オブジェクトに大きく依存するPerlスクリプトのスイートを構築しています。 (Perlを使用します bless()
可能な限りOOに近づくためのハッシュで)
さて、これをより良い方法を持たないために、私の会社のほとんどのプログラマーはあまり賢くありません。さらに悪いことに、彼らはドキュメントを読むのが好きではなく、他の人のコードを理解するのに問題があるようです。カウボーイコーディングはここのゲームです。彼らが問題に遭遇してそれを修正しようとするたびに、彼らは実際に何も解決し、通常それを悪化させる恐ろしい解決策を思いつきます。
これにより、率直に言って、ダックタイプの言語で書かれたコードでそれらを信頼していません。例として、オブジェクトを誤用するための明示的なエラーが得られないという問題が多すぎます。たとえば、タイプの場合 A
メンバーがいます foo
, 、そして彼らはようなことをします、 instance->goo
, 、彼らはすぐに問題を見るつもりはありません。それはヌル/未定義の値を返し、おそらく彼らは原因を見つける1時間を無駄にするでしょう。その後、元の問題を適切に識別しなかったため、何か他のものを変更することになります。
したがって、私はスクリプト言語を維持する方法をブレーンストーミングしています(その急速な発展は利点です)が、オブジェクトが適切に使用されない場合は明示的なエラーメッセージを提供します。コンパイルステージや静的タイピングがないため、エラーは実行時に行わなければならないことを理解しています。ユーザーが「このオブジェクトがxを持っていない」という非常に明示的な通知を受け取っている限り、私はこれで大丈夫です。
私の解決策の一部として、使用する前にメソッド/変数が存在するかどうかを確認する必要はありません。
私の仕事はPerlにありますが、これは言語不可知論者になると思います。
解決
使用するモジュールを追加するショットがある場合は、試してみてください ムース. 。最新のプログラミング環境などで必要なすべての機能を提供します。タイプチェック、優れた継承、内省機能があり、 Moosex ::宣言, 、Perlクラスの最も素晴らしいインターフェイスの1つです。見てください:
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のオブジェクトシステムの上のレイヤーなので、すでに持っているもので動作します(基本的に)。
ムースを使用すると、サブタイプを非常に簡単に作成できるため、入力が有効であることを確認できます。怠zyなプログラマーは同意します:サブタイプをムースで機能させるためにはほとんど行わなければならないので、そうするよりも簡単です! (から 料理本4)
subtype 'USState'
=> as Str
=> where {
( exists $STATES->{code2state}{ uc($_) }
|| exists $STATES->{state2code}{ uc($_) } );
};
そしてTADA、USSTATEはあなたが使用できるタイプになりました!大騒ぎも、ムサイも、ほんの少量のコードもありません。正しくない場合、エラーが発生し、クラスの消費者はすべて、その文字列が入ったスカラーを渡すことです。それが問題ない場合(それは...正しいですか?:))彼らはそれを通常のように使用し、あなたのクラスはゴミから保護されています。それはどれほどいいですか!
ムースにはこのような素晴らしいものがたくさんあります。
私を信じて。見てみな。 :)
他のヒント
Perlで、
それを必要とします
use strict
とuse warnings
コードの100%でオンになっています作成して、ほぼプライベートなメンバー変数を作成してみることができます 閉鎖. 。非常に良い例は、「プライベートメンバー変数、一種の」セクションです http://www.usenix.org/publications/login/1998-10/perl.html 。彼らは100%プライベートではありませんが、あなたが何をしているのかを本当に知っていない限り、アクセスする方法はかなり明白ではありません(そして、彼らがあなたのコードを読んで、その方法を見つけるために調査をする必要があります)。
閉鎖を使用したくない場合は、次のアプローチが多少うまく機能します。
すべてのオブジェクトメンバー変数(別名オブジェクトハッシュキーのPerl)をアクセサに包みます。コーディング標準POVからこれを効率的に行う方法があります。最も安全でないのは、クラス::アクセサ::高速です。ムースにはより良い方法があると確信していますが、私はムースにそれほど精通していません。
プライベートコンベンション名で実際のメンバー変数を「非表示」するようにしてください。
$object->{'__private__var1'}
メンバー変数になります$object->var1()
ゲッター/セッターアクセサになります。注:最後に、クラス::アクセサ:: fastは、メンバー変数がアクセサと名前を共有するため、fastは悪いです。ただし、クラス::アクセサ::高速のように機能する非常に簡単なビルダーを使用でき、$ obj-> {'__ private__foo'}などの重要な値を作成します。
これにより、彼らが足で自分自身を撃つことを妨げることはありませんが、そうするのがずっと難しくなります。
あなたの場合、彼らが使用する場合
$obj->goo
また$obj->goo()
, 、少なくともPerlでは、ランタイムエラーが発生します。彼らはもちろん彼らの邪魔にならないようにすることができます
$obj->{'__private__goo'}
, 、しかし、彼らが純粋な怠inessのためにゴンゾ・カウボーイのがらくたをするなら、後者は正しいことをするよりもはるかに多くの仕事です$obj->foo()
.また、検出するコードベースのスキャンを受けることもできます
$object->{"_
文字列をタイプしますが、説明からは、それほど抑止力として機能しない可能性があります。
使用できます クラス:: Insideout また オブジェクト:: Insideout これにより、真のデータプライバシーが得られます。祝福されたハッシュ参照にデータを保存するのではなく、祝福されたスカラー参照は、語彙データハッシュの鍵として使用されます。簡単に言えば、同僚が試してみると $obj->{member}
実行時間エラーが発生します。何もありません $obj
彼らがアクセサを除く以外のデータを取得する簡単な方法で彼らがつかむことはできません。