プロパティとメソッドを常にチェックせずに、JavaScriptでダックタイピングを使用するにはどうすればよいですか?


11

私はjavascriptがダックタイピングを使用することを知っていて、最初はC#のような強く型付けされた言語と比較して多型が簡単になると思った。しかし、現在、引数を取る私の関数には次のようなものが散らばっています。

if(myObj.hasSomeProperty())

または

if(myObj.hasSomeMethod())

または

if(isNumber(myParam))

これは本当にugいです。私はC#のバックグラウンドを持っていますが、定義済みのインターフェイスの方がはるかに優れていることがわかりました。

私は静的に型付けされた言語で効果的な戦略を誤って適用しようとしていて、javascriptでこれを行うためのいくつかのより良い方法がありますか?

私はただチェックできないことを知っていますが、javascriptランタイムエラーを追跡することは、コード内で実際にエラーが発生している場所で常に発生するとは限らないため、悪夢になります。


2
あなたは、動的に型付けされた言語の性質をただいじっているだけかもしれません。コンパイル時ではなく実行時に多くのエラーが発生するという考え方に慣れる必要があります。すべての引数が数字を入力するすべての関数の数字であるかどうかを確認する必要があると感じた場合、それはかなりの負担になる可能性があります(ただし、安全性を最重要目標としてlibを出荷する場合は価値があります)。規模の大小を問わず、間違った型が渡された場合に関数が失敗することを許可することが重要です。代わりに、より生産的な焦点はテストの構築にあるかもしれません。

これらのチェックを実行して、型が必要なインターフェイス要件に適合することを確認するのに役立つ場合(たとえば、必要なメソッドがあるかどうかを確認する)は、最も中心的で広く使用されている関数(不安定性= 0遠心性/求心性結合の指標がMartinから提供されています)。それはかなり小さな目標であるべきです。通常、スコープ内で分離された1回限りのローカル関数が多数あります。これらの関数は、おそらく包括的なランタイムチェックのセットを必要としません。それらはそれほど複雑になりません。

タイプスクリプトに切り替えます。それはまだカモ型ですが、コンパイル時に多くのエラーを検出するために静的型をサポートしています。
CodesInChaos

2
あなたは、ダックタイピングの唯一の最大の問題にぶつかりました。オブジェクト指向のJavaScriptを実行したい場合は、実行時エラーに耐える必要があります。作成後すぐにユニットテストでエラーが見つかることを期待してください:-(
Ross Patterson

@RossPatterson OPの問題は、動的な型付けにあり、アヒルの型付けにはありません。TypeScriptとGoはどちらもダックタイプですが、OPの問題を回避します。アヒルのタイピングの問題は別の問題です。つまり、アヒルのテストに合格するが、期待する契約を満たさないメンバーがいる可能性があるということです。
CodesInChaos

回答:


11

プロパティとメソッドを常にチェックせずに、JavaScriptでダックタイピングを使用するにはどうすればよいですか?

シンプル:プロパティとメソッドを常にチェックする必要はありません。

Rubyでは、あなたが呼んでいるものは「チキンタイピング」と呼ばれます。動的にアヒル型の言語では、呼び出し元が適切なオブジェクトを渡すと単純に信頼します。契約の彼の側を尊重するのは、呼び出し側の仕事です。

私はjavascriptがダックタイピングを使用することを知っていて、最初はC#のような強く型付けされた言語と比較して多型が簡単になると思った。

ここで、入力の複数の直交軸を混同しています。タイピングには4つの直交軸があります。

  • いつ:動的型付け(型は実行時まで認識されず、チェックされます)対静的型付け(型は実行前に認識され、チェックされます)
  • 内容:アヒルのタイピング(タイプは動作に基づく)、構造タイピング(タイプは構造に基づく)、名義型(タイプは名前に基づく)
  • 見えますか?明示的な型付け(型には明示的に注釈を付ける必要がある)対暗黙的な型付け(型は推測される)
  • 強い型付けと弱い型付け–覚えやすいタイトルやかっこ内の説明を付けていないことに気づいたかもしれません。これは、上記の7つの用語とは異なり、それぞれに広く受け入れられている正確な定義が1つあり、互いに矛盾する半ダースほど使用されている漠然とした定義が約12個ある。理想的にはこれらの用語を完全に避け、使用する必要がある場合は、最初に正確に定義する必要あります

C#について述べたので、ほとんど静的に型付けされていますが、typeを介した動的型付けをサポートしていますdynamicが、ほとんどは型付けされていますが、匿名型は構造型付けを使用しており、構文パターン(LINQクエリ理解構文など)は-typedまたは構造的に型付けされ、ほとんど明示的に型付けされますが、ジェネリック型引数およびローカル変数の暗黙的な型付けをサポートします(ただし、ローカル変数の場合は、他のほとんどの言語と比較すると、型をそのままにすることはできず、代わりに明示的な擬似型を与えるvarつまり、暗黙的な型が必要な場合は、明示的にそうする必要があります)。C#が強く型付けされているか弱い型付けされているかは、使用する2つの用語の定義の問題ですが、特に安全でない配列共分散のために、C#には多くの実行時型エラーが存在する可能性があることに注意してください。

私はただチェックできないことを知っていますが、javascriptランタイムエラーを追跡することは、コード内で実際にエラーが発生している場所で常に発生するとは限らないため、悪夢になります。

デバッグは習得が容易なスキルではありません。ただし、デバッグを容易にする手法があります。たとえば、Saff Squeezeは、デバッグにテストとリファクタリングを使用するKent Beckによって記述された手法です。

高ヒット、低ヒット

回帰テストとSaffスクイーズ

ケントベック、スリーリバーズインスティテュート

要約:欠陥を効果的に特定するには、システムレベルのテストから始めて、欠陥を実証する可能な限り最小のテストになるまで、徐々にインラインとプルーニングを行います。


そのヒットemハイヒットemローリンクはhttp 500を取得し、人間向けのメッセージとして「ページはもう利用できません」と表示されます。
joshp

threeriversinstitute.orgドメインは放棄されたようです。
バートヴァンインゲンシェナウ

ああ、いまいましい。また、WayBack Machineにもアーカイブされいません。
ヨルグWミットタグ

発信者はどのように契約の側を尊重することになっていますか?パラメーターがどうあるべきかを(コードで)伝える方法はないようです。すべての関数の形式は、関数fname(objParam、objParam、...)です。これは、JavaScriptのような言語が、使用法を伝えるために外部ドキュメントに完全に依存しているということですか?
軍団

@Legion:ドキュメント、適切な命名、常識、動作仕様としてのテスト、ソースコードの読み取り、命名。これは、実際にはC#やJavaなどの弱い型システムとそれほど変わらないことに注意してください。例えば、戻り値の意味はIComparer<T>.Compare(T, T)型からではなくドキュメントからのみ明らかです。そして、そのタイプでjava.util.Collections.binarySearch(java.util.List<T>)はどこで…と言うのですか
-JörgW Mittag

1

私はただチェックできないことを知っていますが、javascriptランタイムエラーを追跡することは、コード内で実際にエラーが発生している場所で常に発生するとは限らないため、悪夢になります。

実際、典型的な慣行は確認することではありません。そして、はい、これは実際の問題から別の場所で報告されるjavascriptエラーを受け取ることを意味します。しかし実際には、これが大きな問題になるとは思いません。

JavaScriptで作業するとき、私は常に自分が書いているものをテストしています。ほとんどのコードには、エディターを保存するたびに自動的に実行される単体テストがあります。何かが予想外にうまくいかないとき、私はほとんどすぐに知っています。私がミスを犯したのはほとんど常に最後に触れたものなので、ミスを犯したかもしれないコードの非常に小さな領域があります。

実行時エラーが発生した場合、少なくともスタックトレースを取得し、ブラウザー内エラーの場合は、任意のレベルのスタックトレースに移動して変数を検査することができます。通常、不正な値がどこから来たのかを簡単に遡ることができるため、元の問題まで遡ることができます。

主に静的に型付けされた言語で書いたとき、あなたが私のような人なら、テストする前に大きなコードブロックを書いたので、値がどこから来たのかをトレースする練習がありませんでした。JavaScriptのような言語でのプログラミングは異なります。異なるスキルを使用する必要があります。そのようなプログラミングはあなたがC#のような他の言語で働いて開発したスキルではないので、かなり難しいように思われます。

そうは言っても、明示的な型については多くのことが言われていると思います。それらは文書化やエラーの早期発見に最適です。今後、静的型チェックをjavascriptに追加するFlowやTypescriptのようなものの採用が増えると思います。


0

私はあなたが正しいことをしていると思います、あなたはあなたの目にもっと楽しいスタイルを見つける必要があります。ここにいくつかのアイデアがあります:

  • 代わりにif(myObj.hasSomeProperty())を使用できますif( myobj.prop !== undefined )。これ、BTWは非厳密モードでのみ動作しますif( typeof myobj.prop !== 'undefined' )。厳密モードではを使用する必要があります。

  • いくつかの型チェックをオフロードして、別々のバリデーターにすることができます。これには、インターフェイスが成熟したら、たとえばif( is_valid( myobject ))is_valid始まる検証をスキップできるという利点がありますif( !DEBUG ) return true;

  • 入力を正規の形式に複製することが理にかなっている場合があります。その場合、さまざまな検証ターゲットを複製関数/オブジェクトに収集できます。たとえばmy_data = Data( myobj, otherstuff )Dataコンストラクターでは、さまざまな検証をすべて1か所で便利に実行できます。

  • 型の検証をより洗練されたものに合理化する(パフォーマンスに影響する)ライブラリを使用できます。長期的にこのルートを採用しなくても、自分のスタイルにスムーズに移行できると感じるかもしれません。いくつかの例には、xtype.jstype-checkvalidator.jsなどが含まれます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.