web-dev-qa-db-ja.com

ハンガリー語の表記法は、静的型付けが不十分な言語の回避策ですか?

Eric Lippertの記事 ハンガリー記法の概要 で、彼はハンガリー記法(良い種類)の目的は

「タイプ」の概念を拡張して、ストレージ表現情報に加えて意味情報を包含します。

簡単な例としては、X座標を表す変数の前に「x」を付け、Y座標を表す変数に「y」を付けて、それらの変数が整数か浮動小数点かなどに関係なく、誤って書き込むと、 xFoo + yBar、コードは明らかに間違っています。

しかし、私はHaskellの型システムについても読んでいます。Haskellでは、actualコンパイラがチェックするタイプ。上記の例では、xFoo + yBar Haskellでは、プログラムを正しく設計した場合、互換性のない型として宣言されるため、実際にはコンパイルに失敗します。言い換えれば、Haskellの型システムはハンガリー語表記と同等のコンパイル時チェックを効果的にサポートしているようです

それで、ハンガリー記法は、型システムが意味論的情報をエンコードできないプログラミング言語のための単なるバンドエイドですか?それとも、ハンガリー記法は、Haskellのような静的型システムが提供できる以上のものを提供しますか?

(もちろん、私はHaskellを例として使用しています。私はこれまでに出会ったことはありませんが、同様に表現力豊かな(リッチ?ストロング?)型システムを持つ他の言語も確かにあります。)


明確にするために、私はnotで変数名にdataタイプではなく、プログラムのコンテキストでの変数の意味に関する情報たとえば、変数は整数、浮動小数点数、倍精度浮動小数点数型、長整数型などですが、変数の意味は、測定された相対的なx座標である可能性がありますインチで。これは、ハンガリー記法(およびHaskell型)を介してエンコードについて話している種類の情報です。

28

「はい」と言います。

あなたが言うように、ハンガリー記法の目的は、型ではエンコードできない名前で情報をエンコードすることです。ただし、基本的に2つのケースがあります。

  1. その情報は重要です。
  2. その情報は重要ではありません。

まず、ケース2から始めましょう。その情報が重要でない場合、ハンガリー語表記は単に不要なノイズです。

より興味深いケースは1番ですが、情報が重要な場合はチェックする必要があります。つまり、それはnameではなくtypeの一部である必要があります。 。

これにより、エリックリッペルトの引用に戻ります。

「タイプ」の概念を拡張して、ストレージ表現情報に加えて意味情報を包含します。

実際、それは「型の概念を拡張する」ことではなく、それはis型の概念です! (設計ツールとしての)タイプの全体の目的は、意味情報をエンコードすることです!ストレージ表現は、通常、タイプ全然に属さない実装の詳細です。 (そして特にOO language cannotは型に属します。表現の独立性はOOの主要な前提条件の1つであるためです。)

27
Jörg W Mittag

タイプの全体的な目的(設計ツールとして)は、意味論的情報をエンコードすることです!

私はこの回答が好きで、この回答をフォローアップしたいと思いました...

Haskellについては何も知りませんが、xFoo + yBarの例のようなものは、C、C++、Javaなどの何らかのタイプセーフティをサポートする任意の言語で実現できます。 C++では、独自のタイプのオブジェクトのみを受け取るオーバーロードされた「+」演算子を使用して、XDirクラスとYDirクラスを定義できます。 CまたはJavaでは、「+」演算子の代わりにadd()関数/メソッドを使用して追加する必要があります。

私は、セマンティクスではなくタイプ情報に使用されるハンガリー記法を常に見てきました(セマンティクスがタイプで表される場合を除いて)。変数の型を覚えておくための便利な方法です。「スマート」プログラミングエディターの前に、型を何らかの方法でエディターに表示します。

9
BHS

「ハンガリー記法」というフレーズが オリジナル とは異なる意味になっていることは理解していますが、質問には「いいえ」と答えます。セマンティック型または計算型のいずれかを使用して変数に名前を付けることは、SMLまたはHaskellスタイルの型指定と同じことを行いません。絆創膏すらありません。 Cを例にとると、変数にgpszTitleという名前を付けることができますが、その変数にはグローバルスコープがない可能性があり、nullで終了する文字列へのポイントを構成しない場合もあります。

より現代的なハンガリーの表記法は、強力な型推論システムからの逸脱がさらに大きいと思います。なぜなら、「意味論的」情報(グローバルの「g」やフラグの「f」など)と計算型(「p」ポインター、「 i "整数など)。これは、変数名が(時間とともに変化する)計算タイプに漠然とした類似性しかなく、すべてに類似しているため、"次の一致 "を使用できないような不自然な混乱になってしまいます。特定の関数で変数を見つける-それらはすべて同じです。

5
Bruce Ediger

ハンガリー語の表記法は、型をまったく持たない言語であるBCPLのために考案されました。むしろ、それはちょうど1つのデータ型、Wordを持っていました。 Wordは、ポインタの場合もあれば、使用方法に応じて、文字、ブール値、または単純な整数の場合もあります。これは明らかに、キャラクターの逆参照のような恐ろしい間違いを非常に簡単にしました。したがって、ハンガリー語の表記法が発明されたので、プログラマーは少なくともコードを見て手動で型チェックを実行できました。

BCPLの子孫であるCは、整数、ポインター、文字などの異なる型を持っています。これにより、ハンガリー語の基本表記がある程度不必要になりました(intまたはポインターの場合、変数名をエンコードする必要はありませんでした)。しかし、このレベルを超えたセマンティクスは、まだタイプとして表現できませんでした。これにより、ハンガリー語で「システム」と「アプリ」と呼ばれるものが区別されます。変数がintであると表現する必要はありませんでしたが、コード文字を使用して、intがxまたはy座標かインデックスかを示すことができました。

より最近の言語では、カスタムタイプの定義が可能です。つまり、セマンティック制約を変数名ではなく、タイプにエンコードできます。たとえば、典型的なOO言語は、座標ペアとエリアに特定のタイプを持っているので、x座標をy座標に追加することを避けます。

たとえば、Joels 有名な記事 を称賛するAppsハンガリー語では、安全でない文字列にはプレフィックスusの例を、安全な文字列にはsの例を使用しています(htmlエンコード)。 HTMLインジェクションを防ぐための文字列。開発者は、コードを注意深く検査し、変数のプレフィックスが一致することを確認するだけで、HTMLインジェクションのミスを防ぐことができます。彼の例はVBScriptであり、当初はカスタムクラスを許可していなかった古い言語です。現代の言語では、問題はカスタムタイプで修正できます。実際、これはAsp.netがHtmlStringクラスで行うことです。このようにして、コンパイラは自動的にエラーを検出します。これは、人間の眼球に依存するよりもはるかに安全です。したがって、カスタム型の言語は、この場合「アプリハンガリー語」の必要性を排除します。

4
JacquesB

IDEには、変数のタイプが何であるかを示すポップアップヒントがなかった時期があったことを覚えておいてください。 IDEが編集中のコードを理解できなかったため、使用法から宣言法に簡単にジャンプできませんでした。また、手動でコードベース全体を調べずに変数名をリファクタリングできず、手作業で変更を加えて、見落とさないようにしたいときもありました。 Customerを検索するとCustomerNameも取得されるため、検索と置換を使用できませんでした...

あの暗い時代に戻って、変数が使用されていた場所で変数のタイプを知ることは役に立ちました。適切に維持されている場合(リファクタリングツールがないためにBIGである場合)、ハンガリー語の表記でそれが示されました。

それが生み出す恐ろしい名前の最近のコストは高すぎますが、それは比較的最近のものです。私が説明したIDE開発より前のコードがまだたくさんあります。

2
mcottle

はい、そうでなければ十分に強い型システムを持つ多くの言語にはまだ問題があります-既存の型に基づく/類似する新しい型の表現可能性。

つまり、型システムをより多く使用できる多くの言語では、名前といくつかの変換関数以外は既存の型と基本的に同じである新しい型を作成するオーバーヘッドが大きすぎるため、使用できません。

基本的に、これらの言語で完全にハンガリー語の表記を強制終了するには、ある種の強く型付けされたtypedefが必要です(F#スタイルのUoMでも実行できます)。

2
jk.

正しい!

アセンブラーなどの完全に型指定のない言語を除いて、ハンガリー語の表記法は不必要で煩わしいものです。間違いなく、ほとんどのIDEがタイプセーフティをチェックすることを考えるとき、ええと、タイプします。

余分な「i」「d」と「?」接頭辞はコードの可読性を低下させるだけで、誤解を招く可能性があります。たとえば、「牛職人」がiaSumsItemsのタイプをIntegerからLongに変更しても、フィールド名をリファクタリングする必要がないためです。

0
James Anderson