静的型付けはトレードオフの価値がありますか?


108

主にタイプセーフがないPythonでコーディングを開始し、次にC#とJavaに移行しました。Pythonでの作業が少し速くなり、頭痛が少なくなることがわかりましたが、C#およびJavaアプリの複雑度ははるかに高いため、Pythonに本当のストレステストを与えたことはありません。

JavaとC#のキャンプは、タイプセーフティが適切に設定されていないように聞こえます。ほとんどの人は、あらゆる種類の恐ろしいバグに遭遇し、その価値以上の問題を抱えています。

これは言語の比較ではないため、コンパイル済みと解釈済みなどの問題に対処しないでください。型の安全性は、開発の速度と柔軟性に打撃を与える価値がありますか?どうして?

動的型付けのほうが速いという意見の例を望んでいた人たちに:

「開発中に動的に型指定された言語を使用します。これにより、フィードバック、ターンアラウンドタイム、および開発速度が速くなります。」- http://blog.jayway.com/2010/04/14/static-typing-is-the-root-of-all-evil/



8
@Prof Plum:開発のスピードと柔軟性に影響があることを証明する必要がありますか?我々は特定の側面について話しているので、型安全使用、JavaまたはC#決定的となり、それを提供する彼らの方法は...だけではない
マシューM.

32
厳密な言語での勤勉さにより、「頭痛」を最小限に抑えることができ、IDEの自動補完、コード生成、およびコードヒントによる速度の向上が見られる場合もあります。
ニコール

9
@Prof Plum:私は理解しています、あなた(または本当に誰か)がこれまでに作成されたすべての言語を完全にテストしたとは思いません^^問題は、私が見たほとんどの人々がプログラミング言語の特定の側面について不平を言うことです(静的一般的に、入力は特定の実装について文句を言いますが、それを実現できません。
マチューM.

5
@Prof Plum、スピードに関するブログ投稿で本当に言わなければならないことは、「RubyやSmalltalkのような現代の動的型付け言語に真剣に取り組んでいる人は、生産性が高いことを知っている」という大げさな主張です。実際には、開発を高速化する方法の実際の例はありません。
Carson63000

回答:


162

プログラマーが動的に型付けされた言語の型について心配する必要がないというのは一種の神話です。

動的に型付けされた言語の場合:

  • 配列、整数、文字列、ハッシュテーブル、関数参照、辞書、オブジェクトなどを操作しているかどうかをまだ知る必要があります。

  • オブジェクトの場合、そのクラスが属しているクラスを知る必要があります。

  • これらのタイプの1つを別のタイプであると予想される変数または関数パラメーターに割り当てることは、ほとんど常にエラーです。

  • 下位レベルでは、たとえば、TCPパケットにデータを入力する場合、ビット数や符号付きと符号なしの頻度などを頻繁に考慮する必要があります。

  • 本当に空の文字列が必要な場所でゼロを取得する問題に遭遇する可能性があります。言い換えれば、あなたはまだ型の不一致のバグをデバッグしています。唯一の本当の違いは、コンパイラがエラーをキャッチしていないことです。

  • あなたはコードをドキュメント化するのではなく、関数パラメータのタイプをコメントでドキュメント化する傾向があるので、あなたはタイピングをあまり節約していないと主張します。これが、doxygenスタイルのコメントブロックが、動的に型付けされたコード全体で実際にはるかに人気がある理由です。静的に型付けされた言語では、ほとんどの場合ライブラリに対してのみ表示されます。

それは、コンパイラが常にあなたの背中にいるわけではないので、動的に型付けされた言語でのプログラミングより快適に感じられないと言うことではありません。 、しかし、それは、効率的なバグの増加やバグ率の減少とはまったく別の問題であり、静的型付けでも動的型付けはせいぜいです。


10
私は、経験豊富なプログラマーがこの種のバグを作成/導入していないことについて少し争わなければなりません。謙虚であり、間違いを犯す可能性を認める優秀な開発者(および経験豊富な開発者は、必ずしもこのようなものではありません)は、これらのバグを作成する可能性が低くなります。
ジェイジェイジェイ14年

12
「あなたは多くのタイピングを保存していないと主張するだろう」にこれ以上同意できませんでした。最終的には、コメントでタイプを文書化し、テストでチェックします。これは、もしあれば、より多くのタイピングとメンテナンスを必要とます(結局、タイプが変更されるたびに、コメントを更新することを忘れないでください。 )。
セヴェリンコザック

Pythonショップでは、C#やJavaのような静的に型付けされた冗長な言語よりも、型のドキュメント化に多くの時間を費やしています。また、GoやRustなどの新しい世代の言語では型推論が使用されるため、「Object x = new Object()」ではなく「x:= new(Object)」と入力していることにも注意してください。
weberc2

動的言語がより快適だと言うときは同意しますが、その理由はわかりません。その説明はありますか?
ロドリゴルイス

ええ、変数の型を指定する代わりに、Pythonでデフォルト値または単体テスト(インラインdoctests)を使用できます。また、Pythonではスペルミスで奇妙なエラーが発生することがあります(動的言語では常に前夜ではありませんが、頻繁に使用できるオートコンプリートを使用すると発生しにくくなります)。パンまたはそれを再定義します。
aoeu256

123

タイプが強くなるにつれて、あなたはより多くの手助けをすることができます- あなたがそれらを戦う代わりに正しく使用すれば。問題空間を反映するように型を設計します。ロジックエラーは、ランタイムクラッシュやナンセンスな結果ではなく、コンパイル時の型の不一致になる可能性が高くなります。


37
+1!「論理エラーは、実行時のクラッシュやナンセンスな結果ではなく、コンパイル時の型の不一致になる可能性が高くなります」:本当に良い答えです!型を設計するのにより多くの時間をかけると、コードはより自然に続き、多くの場合、コンパイルするとすぐに修正されます。型の設計とは、ドメインとその操作を理解することを意味します。
ジョルジオ

78

免責事項:私はタイプ愛好家です;)

あなたの質問に答えるのは難しいです:それらのトレードオフは何ですか?

極端な例を取り上げます。Haskellは静的に型付けされています。おそらく、実際に存在する最も強く型付けされた言語の1つです。

ただし、Haskellは、特定の概念(またはインターフェイス)に準拠する型で動作するメソッドを作成するという意味で、汎用プログラミングをサポートしています。

さらに、HaskellはType Inferenceを使用するため、変数の型を宣言する必要はありません。Pythonインタープリターがプログラムを実行して計算するのと同じように、コンパイル時に静的に計算されます。

私は、静的型付けを急ぐほとんどの人が実際に何か他のことについて不平を言っていることを発見しました(冗長性、ある型から別の型への切り替えの苦痛)が、Haskellは静的型付けされている間、これらの問題のどれも示さない...


簡潔さの例:

-- type
factorial :: Integer -> Integer

-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)

組み込みのサポートとは別に、簡単に説明することは困難です。

汎用プログラミングの例:

> reverse "hell­o" -- Strings are list of Char in Haskell
=> "olleh"
> reverse [1, 2, 3, 4, 5]
=> [5,4,3,2,1]

型推論の例:

> :t rever­se "hell­o"
:: [Char]

簡単に計算できます:

  • "hello"Char(として表される[Char])のリストです
  • reverse型に適用すると、型[A]が返されます[A]

ブラウザで試してみてください


4
悪魔の擁護者を演じるために、動的言語を支持する1つのトレードオフ(少なくともプロトタイピング中)は、型宣言がいくつかの単体テストと同じ目的を果たすことができる限り、単体テストと同じ方法でインターフェイスを固めることもできます(確かに少ないオーバーヘッドで)。また、強制なしの静的型付け言語は、安全ですが、明示的な型キャストを必要とします(特に型が十分にジェネリックでない場合)。これにより簡潔さが損なわれる可能性があります。
TR

7
Haskellを知りませんが、「実際に何か他のことについて不平を言っていました(冗長性、あるタイプから別のタイプへの切り替えの苦痛)」
ニコール

1
@Aidan:Haskellは進化する言語です。Haskell 98はHaskell 1.4よりも改善されました。Haskell 2010はそれよりも改善されました。一方、Haskellの存在意義のほとんどは、型システムの探索を支援することでした。マルチパラメータ型クラスは、便利な型システム拡張の解明に成功した例の1つです。(一方で、機能的な依存関係は行き止まりのように見えます。)
geekosaur

4
@Matthieu:WRT「おそらく、実際に存在する最も強く型付けされた言語の1つです。」Haskellを見て、AgdaCoqを紹介します。(おそらく最も強く型付けされた実用的に有用な言語であることを認めます。)
geekosaur

1
@Matthieu:証明アシスタントはCurry-Howard通信の直接的なアプリケーションであるため、中心的なプログラミング言語です(ただし、標準ライブラリはかなり限られています)。「型は命題である」対応をうまく利用するために依存型が必要なので、依存型研究の最前線にいます。
ギーコサウルス

37

私は静的に型付けされた言語と動的に型付けされた言語の両方が好きです。私にとって、タイプセーフの2つの最大の利点は次のとおりです。

1)多くの場合、関数がその型シグネチャから純粋に推測することができます(これはHaskellのような関数型言語で特に当てはまります)。

2)大幅なリファクタリングを行うと、コンパイラはすべてを機能させるために必要なすべてを自動的に通知します。C ++で何かをリファクタリングするとき、私の手順はしばしばa)変更したいことがわかっている部分を変更し、b)すべてのコンパイルエラーを修正するだけです。


私とまったく同じで、何かをリファクタリングしたいときはいつでも(私は主にgolang / typescript / javaを使用しています)、そう、これらの2つのステップは誰もが必要とするものです。1つの部分を変更してから、すべてのコンパイルエラーを修正してください:)完全な答え。
ニシュチャルゴータム

29

個人的には、タイプセーフティは、現在の仕事でより早く開発するのに役立ちます。コンパイラーは、ほとんど入力している間、多くの妥当性チェックを行い、実装しているビジネスロジックにもっと集中できるようにします。

結論としては、ある程度の柔軟性は失われますが、それ以外の場合はタイプの問題を追跡するのに費やす時間が得られるということです。


13

議論を取り巻く多くの強い意見がありますが、明らかにこれは実際には意見の問題ではなく、事実の問題です。それで、私たちは実証研究を見るべきです。そして、そこからの証拠は明らかです:

はい、静的型付けはトレードオフの価値があります-少しだけではなく、実際には実質的に。実際、静的な型付けにより、コード内のバグの数を少なくとも15%減らすことができるという確かな証拠があります(これは低い見積もりであり、実際の割合はほぼ確実に大きくなります)。それは驚くほど高い数字です。静的型付けのほとんどの支持者でさえ、このような劇的な違いを生んだとは思わなかったと思います。

これを考慮してください。プロジェクトのバグを一晩で15%削減する簡単な方法があると誰かが言ったら、それは簡単なはずです。1 それはほとんどことわざの銀の弾丸です。

この証拠は、論文「入力するか入力しないか:JavaScriptで検出可能なバグを定量化する」(Zheng Gao、Christian Bird、Earl T. Barr)に記載されています。私は誰もがそれを読むことを奨励します、それは模範的な研究を提示するよく書かれた論文です。

著者がどれだけ厳密に分析を行ったかを簡潔に要約することは困難ですが、ここに(非常に大まかな)アウトラインがあります:

TypeScriptFlowは、JavaScriptに基づく2つのプログラミング言語であり、互換性は維持されますが、型ヒントと静的型チェックを追加します。これにより、タイプごとに既存のコードを拡張し、タイプチェックを行うことができます。

研究者は、GitHubからJavaScriptで記述されたオープンソースプロジェクトを収集し、解決されたバグレポートを調べ、報告された各バグをTypeScriptまたはFlowの静的型チェッカーによってキャッチされるコードに還元しようとしました。これにより、静的型付けを使用して修正できるバグの割合の下限を見積もることができました。

研究者は、厳密な予防措置を講じて、分析でタイプに関連しないバグがタイプに関連していると見なされないようにしました。2

過去の研究と比較して、この新しい研究には特定の長所があります。

  • ある直接静的の比較 JavaScriptや活字体/フローとの間の唯一の違いは、タイピングであるので(もしあれば)いくつかの交絡因子と動的型は、。
  • TypeScriptとFlow(つまり、異なる型システム)の両方をチェックし、バグを修正するために(手動)型注釈を異なる人に再現させることにより、複数の次元でレプリケーションを実行します。そして、異なるプロジェクトの多数のコードベースでこれを実行します。
  • このペーパーでは、静的なタイピングが修正可能なバグに与える直接的な影響を測定します(曖昧な品質ではありません)。
  • 著者は、何をどのように事前に測定するかの厳密なモデルを定義します。さらに、それらの説明は信じられないほど明確であり、欠陥の分析を容易にします(研究論文が攻撃にさらされている場合、それは常に良いことです:攻撃がその議論をくつがえすことができなければ、それはさらに強力になります)。3
  • サンプルサイズが十分になるように適切なパワー分析を実行し、その後の統計分析は気密になります。
  • それらは交絡説明を除外するために過度に保守的であり、単一の可動部分のみを測定します。さらに、タイプを含めることですぐに修正可能なバグに分析を制限し、タイピングに対応するために高度なリファクタリングを必要とする可能性のあるものはすべて除外します。そのため、実際には、その効果はかなり大きくなりますが、彼らが報告したものよりも小さくありません。
  • そして最後に、彼らはわずかな効果ではなく、驚くべき違いを見つけます。過度に保守的な手順にもかかわらず、95%の信頼区間の下限でも、最小限の型チェックを追加するだけで消滅するバグが少なくとも10%あることがわかります。

誰もまだ発見していない根本的な欠陥がない限り、この論文はほぼ無料で静的型付けの大きな利点を最終的に示します。4


歴史的なノートでは、プログラミングのタイピングに関する研究は、長い間、証拠がまったく明確ではなかったため、大きなスタートを切っています。この理由は、静的の効果を調べるために系統的な実験を行っていることをされた動的型付けすることは容易ではありません:系統的な実験は、我々が調査している効果を分離する必要があります。残念ながら、プログラミング言語に関係しているため、タイピングの効果を分離することはできません。

実際に、異なる方言で静的型と動的型の両方を許可するプログラミング言語がありました(たとえば、VB Option Strict Onまたはor Off、または静的に型付けされたLisp)。しかし、これらは直接比較にはあまり適していませんでした。最も重要なことは、直接比較を可能にする既存の十分に大きなコードベースがなかったためです。せいぜい「実験室の設定」でそれらを比較することができます。そこでは、被験者は、言語の静的または動的に型付けされたバリアントでタスクをランダムに解決します。

残念ながら、これらの人工的なプログラミングの割り当ては、実際の使用法をうまくモデル化できません。特に、それらの多くは範囲が小さく、テキストの半分のページに要約できる明確に定義された問題を解決します。

幸いなことに、これは過去のものです。なぜなら、TypeScript、Flow、およびJavaScriptは、静的型付けを除いて実際には同じ言語であり、サンプルの広範なコードとバグの現実世界のデータセットがあるからです。


1元の論文からの引用に触発されました。

2私はこれに完全に満足していません。静的に型付けされた言語の主な長所の1つは、表面上型に関係のない問題を静的に型チェックできる方法で表現できることです。これにより、多くの論理エラーが型エラーに変換され、静的型付けで捕捉できるバグの割合が大幅に増加します。実際、この論文では型に関係のないバグを大まかに分類しており、それらの大部分は実際には静的型付けで捕捉できると主張しています。

3私は誰でも、特に動的型付けの支持者に、分析で対処されていない欠陥を見つけようとするよう勧めます。私は(もしあれば)多くはないと思うし、潜在的な欠陥が結果を実質的に変えることはないと確信している。

4実際の大規模プロジェクトでの静的型付けの実際のコストは、アーキテクチャの自然な部分になり、計画を簡素化することさえあるため、存在しないと思われます。静的型エラーの修正には時間がかかりますが、後で発見されるエラーよりもはるかに少ないです。これは、経験的に広く研究されており、数十年にわたって知られています(例えば、Code Completeを参照)。


3
私はこれがこの質問に対する遅い答えであることを知っていますが、新しい証拠(ここで説明します)が完全な静的対動的議論を変えると信じています。
コンラッドルドルフ

2
確かに面白いですが、javascriptの特定のタイプシステムにどれほど関連しているのだろうかと思います。Python(特にpython3)の型システムははるかに厳密で、暗黙的な変換ははるかに少ないです。
ピーターグリーン

@PeterGreenはい、それは間違いなく真実です。たぶん私たちは幸運であり、Pythonの型ヒントは今後も同様の分析につながります(PEP484およびPEP526で表明された目的は静的型付けを実装しないことなので、私は疑いますが)。
コンラッドルドルフ

1
要約を読むだけで、方法論に根本的な欠陥があることはすでにわかります。1つの分野を使用して記述されたコードベースを使用してから、型を追加してまったく異なる分野の引数を正当化することはできません。静的な規律として書かれたコードは、動的な規律とは根本的に非常に異なって見えるため、PythonをJavaで書くべきではないように、PythonでJavaを書くべきではありません。表面的な類似性にもかかわらず、typescriptとjavascriptでも根本的に異なる言語です。
ライライアン

2
@LieRyan私の説明や他の場所で述べられているように、分析を過度に保守的にするものがある場合。分析が無効になることは決してありません。あなたの1%の見積もりは、正直なところ、笑えます。それは完全にオフです、あなたの直観はあなたを失望させます。同様に、静的型付けの問題の特性化は、現代の静的型付け(Javaだけでなく)の実際の経験がほとんどない動的型付けの実践者の典型です。
コンラッドルドルフ

12

型の安全性は、開発の速度と柔軟性に打撃を与える価値がありますか?

本当にこれはあなたがやっていることに帰着します。たとえば、飛行機のバックアップシステムをプログラミングしているのであれば、タイプセーフティがおそらく道です。

動的言語と静的言語のプログラミングは、実際には2つの異なる動物です。どちらも、根本的に異なるアプローチが必要です。ほとんどの場合、静的と動的の間でアプローチの方法を移植できますが、他の方法の利点を失うことになります。

それは本当に考え方です。一方が他方より優れていますか?それは本当にあなたが誰であるかとあなたがどう考えるかに依存します。私が働くほとんどの人は、そうする必要がなければ動的な言語に触れることはありません。なぜなら、彼らはエラーの余地が多すぎると感じるからです。彼らはこれを考えるのは間違っていますか?いいえ、もちろんそうではありませんが、コーディングスタイルを適用するアプローチが動的な環境では機能しないことに気付いたということです。私がユーザーグループに行く他の人たちは正反対です。静的型付けは、特定の種類の問題を解決するアプローチを制限するため、面倒です。

正直に言うと、JavaScriptとC#の間を頻繁に行き来しています。さて、両方の言語を知って作業することは、ある程度他の言語に影響を与えますが、実際には、私が書いたコードはお互いにまったく異なって見えます。それらは根本的に異なるため、異なるアプローチが必要です。私が見つけたのは、「X言語でこれを行うのは非常に難しい」と思ったら、あなたのアプローチはおそらく少しずれているということです。以下に例を示します。人々は物事を行う「Python」の方法について話します。つまり、Python言語が問題をより簡単にする方法があるということです。他の方法でそれを行うことは一般に難しく、面倒です。言語がどのように機能するかを知っているという困難を乗り越えて、実際に機能する必要があります。それ'


プログラミング言語は、あなたが考える必要のないコードの機能のみを隠すべきだという印象を受けていました。これは、Javaのようなより高いレベルまでマシンコードを取得するために保持されます。なぜなら、その低いレベルの実装は、基本的に対処する必要のないものだからです。これは、オブジェクトタイプには当てはまりません。私の意見では、動的型付けはプログラミングを難しくします。なぜなら、それはあなたが自分自身を捕らえなければならないエラーのクラス全体を導入するからです。
MCllorf

7

最近尋ねられた同様の質問がありました:ウェブサイトの動的型と静的型言語

私の答えの核心を言い換えると:

システムが大きくなると、静的に型付けされた言語により、コンポーネントレベルでの堅牢性が確保され、システムレベルでの柔軟性が確保されます。

はい、Javaは厳密に型付けされており、Javaはひどいです(攻撃はありません。ひどいです。素晴らしいプラットフォームとエコシステムですが、これまでで最悪の言語の1つです(実際に使用されています))。
しかし、そのことから推測すると、厳密なタイピングが悪いというのは単なる誤fallです。これは、PHPを指して、動的な型指定の悪さを推測するようなものです(繰り返しますが、違反はありません。徐々に改善されています)。

個人的には、静的型システムを持つhaXeでほとんどの開発を行っています。Javaの表現よりもはるかに表現力が豊かであるだけでなく、型推論のために必要な労力がはるかに少ないだけでなく、オプションです。邪魔になった場合は、それをバイパスするだけです。

タイプセーフティは、足元で自分自身を撃つのを防ぐのに役立つ機能です(これは、多くの高レベル言語が正しくないものです)。
動的に型付けされた成功した言語については、コードの型を自由にチェックするオプションがあれば簡単に改善されます。
例えば、私は確かにRubyの実験を楽しんでいましたが、それはRubyが完全にオブジェクト指向であり、コンパイル時型システムの存在と完全に直交しているためです。

静的型システムは目立たないという主張は、単に優れた静的型システムの知識の欠如に基づいていると思います。それを正しく行う多くの言語があり、haXeはそれらの1つであり、その点で間違いなく最高の言語でもありません。

haXeコードの例:

class Car {
    public function new();
    public function wroom() trace('wroooooooom!')
}
class Duck {
    public function new();
    public function quack(at) trace('quackquack, ' + at + '!')
}

function letQuack(o) o.quack();
letQuack(new Car());
letQuack(new Duck());

これにより、コンパイル時エラーが生成されます。

Car should be { quack : Void -> Unknown<0> }
Car has no field quack
For function argument 'o'
Duck should be { quack : Void -> Unknown<0> }
Invalid type for field quack :
to : String -> Void should be Void -> Unknown<0>
For function argument 'o'

あなたが本当にタイプセーフに多くの努力をしなければならなかったと主張することはできません。

テストがあるので、タイプセーフは必要ないと言うのは、もっとばかげています。テストの作成は退屈で反復的です。そして、私は本当に、車のインスタンスが偽物ではなく、ダックが偽物の誰かを必要とすることを見つけるために、テストを書きたくありません。

結局、オーバーヘッドの型の安全性にどれだけの費用がかかったとしても、最終的には(Javaでも-それほどではないかもしれませんが)償却されます。


Pythonでは、ドキュメントのソースおよび後で確認するために、doctestがrepl / shellからコピーアンドペーストされます。 docs.python.org/3/library/doctest.html
aoeu256

5

何らかの理由で、私はもう頻繁にオブジェクトのタイプに関連するエラーを作成しません。C#のような言語では、コンパイラが検出可能な型安全性エラーを生成するよりも、ランタイムキャストに関連するエラーを生成する可能性が高くなります。これは、通常、静的な型付き言語。私がルビーを書くとき、コードはオブジェクトのタイプをかなり強く示唆する傾向があり、REPLの可用性は、目的のメソッド/属性が存在することを既に実験的に検証したことを意味するか、そうするユニットテストがあるでしょう基本的に同じことなので、Rubyで型安全性の問題に遭遇することはめったにありません。

しかし、それは静的に型付けされたシステムが彼らより優れているわけではないということではありません。

静的に型付けされた言語内では、型システムも実際に重要です。例として、関数型言語のSomeモナド(type <Some>:= yes x | no)のようなものを使用すると、ほとんどの型システムで一般的な恐ろしいNullReferenceExceptionを本質的に防ぐコンパイル時のチェックが得られます。パターンマッチングコードを実行すると、null条件の処理に失敗したことを示すコンパイル時エラーが発生します(そのメカニズムを使用して型を宣言した場合)。また、F#でパイプライン演算子|>のようなものを使用すると、同様のタイプのエラーを減らすことができます。

静的型付けのHindley-Milnerの伝統では、型がインターフェイスXをサポートすると主張するという保証よりもはるかに多くのものを構築できます。そして、それらのものを手に入れたら、静的型付けシステムは多くなると思いますより貴重。

それがオプションではない場合、C#のDesign By Contract拡張機能は、静的型システムの価値を高めるメカニズムの別のセットを追加できますが、それらの機能パラダイムのいくつかよりもさらに規律が必要です。


5

場合によります。

人的故障モードは多くの場合統計的です。強力な型チェックは、いくつかの特定のタイプの人的障害(バグのあるコードを引き起こす)の可能性を減らします。しかし、失敗する可能性があるからといって、必ずしもそうなるとは限りません(マーフィーの非耐性)。

潜在的な障害オッズのこの削減がコストに見合うかどうかは異なります。

原子力発電所またはATCシステム用のコードを作成している場合、人的障害モードの低減は非常に重要です。仕様がなく、障害の結果がほぼゼロであるWebサイトのアイデアをラピッドプロトタイピングしている場合、障害モードまたは確率の減少により、何も買わない場合と買わない場合がありますが、開発時間(キーストロークの増加など)に費用がかかる場合があります。脳細胞では、必要な現在のタイプを記憶することによって気が散ります。


3
ラピッドプロトタイピングのシナリオは、アメリカ海軍の研究に関するPaul Hudakの論文で間違っていることが示唆されています。アメリカ海軍の研究では、異なる言語でAEGISのようなシミュレーションを開発する必要がありました。ほぼすべての基準を満たしています。ラピッドプロトタイピング、要件が明確でない要件、および障害のコストがほぼゼロでした(これは非常に非公式な実験です)。Haskellがeveyカテゴリで勝者になりました:開発時間、要件を超え、LOCが少なくてすみ、すべての競技者の間で唯一の実例を作成しまし
アンドレスF。15年


勝者のRelational Lispではなかったのですか?男、シェンのような奇妙で強力な拡張機能をすべて備えたLispで物事をコーディングしている人々を示すビデオがあればいいのにと思います)、述語ディスパッチなどを備えたスーパーCLOSフレームワークなど...
aoeu256

4

Lispで書かれた非常に複雑なシステムがたくさんありましたが、静的型付けが必要だという不満をLisperが聞いたことはありません。私がそれを使ったとき、静的型システム(およびCommon Lispで静的に型を指定できる)がキャッチするほど遅くなる問題を覚えていません。

さらに、主流の静的に型付けされた言語は、エラーをキャッチするのに適していないようです。レイアウトを設計する際に、重要なのは、特定の数は、それはだかどうか、ページ上の縦測定であるということですintunsignedfloat、またはdouble。一方、コンパイラは、それが安全ではないと判断する型変換にフラグを立てる場合が多く、垂直方向の測定値と文字列の文字数を喜んで追加します。静的型システムのこの弱点は、シモニーのハンガリー記法の背後にある最初のアイデアでしたが、それがい役に立たないようになりました。


4

型はインターフェイスの制約であるため、ユニットテストでテストしたいもののサブセットであるため、多くのトレードオフが類似しています。

  • 静的な型は、コードが型システムで表現できる要件を満たしているかどうかについて、より機能的でないもの(顧客フィードバックや高レベルのテストなど)の構築からのフィードバックの遅延と引き換えに、早期のフィードバックを提供します。
  • コードが特定の要件を満たしていることを知ると、リファクタリングとデバッグが容易になりますが、インターフェースの変更と要件の変更にオーバーヘッドが追加されます。
  • 特に、静的に型付けされた言語に強制力がない場合、バグを引き起こすデータで使用されるコードに対するセキュリティが強化されます(条件とアサーションの必要性が減ります)許容可能な形式(明示的な型キャストなど)。
  • 明示的な型注釈は、コードを読む際の理解を助けたり、冗長な情報や不要な情報でコードを混乱させることがあります。
  • 実装によっては、簡潔さを損なう可能性があります。これは、型注釈が必要か推論されるか、型システムが一般的な型/インターフェースをどれだけうまく表現できるか、構文、型システムで表現できる制約をテストするかどうかなどに依存します(つまり、同じテストはおそらく単体テストよりも言語機能として簡潔ですが、テストするつもりはないかもしれません)。
  • さらに(ただし、TDDとは無関係)、静的型はコンパイル時に最適化するのに役立ちますが、型のチェック(およびそれらのチェックと最適化の実行に時間がかかる)が必要になります。ハードウェアにうまくマッピングされます。これにより、パフォーマンス要件のあるコードの開発が容易になりますが、これらの制約にうまく適合しないコードでは問題が発生する可能性があります(ポイント3)。

要約すると、動的言語はプロトタイピングに特に有用であると主張しますが、コードが正しいことを確認する必要がある場合は、強力な型システムを選択する必要があります。


3

はい、間違いなく。強く型付けされた言語とPython(Pythonは強く型付けされた)の両方を使用すると、動的言語のよく書かれたコードのほとんどは、いずれにせよ強く型付けされたコードと同じ規則に従う傾向があります。動的型付けは、シリアル化と逆シリアル化に非常に役立ちますが、他のほとんどの場合、実際にはあまり利点がありません。そして、あなたのコードの大部分がシリアライゼーション関連でない限り、なぜ無料のエラーチェックを捨てるのですか?


4
JavaやC#などの厳密に型指定された言語は、Reflectionを使用して逆シリアル化を自動的に処理します。
マチューM.

3

モーガン、私はあなたが試すための興味深いアイデアを得ました:静的+動的型付け。Python、C#、およびJavaについて言及しました。.NETとJavaの両方にPythonの非常に優れた移植があることをご存知でしたか?どちらの場合でも、ポートを使用すると、これらのプラットフォームのライブラリを使用したり、既存のコードと相互運用したりできます。これにより、いくつかの可能性が得られます。

  1. レガシーコードを静的で柔軟性のない言語で保持します。新しいものにはPythonを使用します。
  2. Pythonを使用して、成熟したプラットフォーム上で新しいもののプロトタイプを作成します。保持したいコンポーネントをより成熟した言語で再コーディングします。
  3. 頻繁に変更する部分には動的言語を使用します。
  4. 動的な言語を使用して、実行中のコードを変更するなどのアイデアを試すことができます。
  5. 強く型付けされた言語を使用する重要な部分を除いて、すべてを動的言語で実行します。

私はこれらのアプローチを90年代後半まで使用して、C / C ++での開発の苦痛を回避しました。ネイティブライブラリと、場合によってはパフォーマンスが必要でした。しかし、より良い構文、柔軟性、安全性などが必要でした。したがって、適切なトレードオフを得るためにそれらを慎重に組み合わせることが重要でした。多くの場合、実際には、言語全体とレガシーコードを別の言語/プラットフォーム用に破棄するよりも優れていました。

(注:答えはすでにそれを言っていましたが、私はその動的型付けを再強調したいと思います!= no / weaktyping。変数のタイプは実行時に決定され、タイプの注釈は不要であり、実行時に変更される可能性があります。


2

それに対する真に客観的な答えを得ることはできませんが、私の経験では、TDDをマスターするまで型安全性は非常に重要です。テストがコードの前に記述されている場合、ユニットテストの範囲が広くなると、コンパイラのチェックが面倒になり、実際に邪魔になり始めます。


これは主観的なQAなので、それで問題ありません。
モーガンハーロッカー

1
誰がダウン投票を説明したいですか?
pdr

説明に役立つことはできませんが、+ 1を付けました。これは有用な貢献だと思います。動的型付けの主な懸念の1つは、静的に型付けされた言語でコンパイラーによって強制される仮定のために、どこかで変更を加え、他のどこかで何かを壊すことです。強力な単体テストのカバレッジは、ここであなたを保護します。
Carson63000

5
あなたが有効なポイントを作ったので、私はダウンボートしませんでしたが、違反は意図していませんでしたが、あなたの投稿は少しTDDのファンボーイ的であると思われます。
カールビーレフェルト

@Karl、犯罪なし、それは本物の質問でした。私はプロTDD unapologeticallyすることができ、私は認める
PDR

2

この質問はたくさん出てくると思いますが、ソフトウェアの品質(およびバグがないこと)は、開発プロセス、システムの設計方法、およびコード品質に対するあなたと同僚のコミットメントに関係していると思います。

私の最後の仕事は主にpython開発でした。私は大規模な国際的なWebホスティング会社に勤務し、米国、カナダ、および韓国に開発チームがありました。ユーザーがドメイン名とWebホスティングアカウントを管理できるようにする、フロントエンドの顧客アプリ用のカスタムpython Webフレームワーク。バックエンド:すべてのpythonも。個々のサーバーと通信して、新しいWebホスティングサイトのプロビジョニング、新しいブログの作成、ネームサービスシステムでのDNSエントリの作成などを行うPython Webサービス。などなど。現在の仕事では、クライアントアプリケーションはすべてJavaで実行されます。私たちの主な製品は、javaとflashの混合です。古いアプリ用のカスタムJava Webフレームワーク、新しい内部ツール用のウィケット。

両方で働いていたので、私はそれを見るたびにこの質問に悩まされると言わなければなりません。動的に型指定された言語を使用しており、実際にコードをテストしている場合は問題ありません。システムが適切に設計されていて、標準に準拠していれば問題ありません。型をチェックするコンパイラの欠如のために出てきたバグの多くは決してありませんでした。今日の私のJavaの仕事のように、ほとんどのバグは論理エラーでした。


2

型の安全性は、開発の速度と柔軟性に打撃を与える価値がありますか?どうして?

静的型付けは、ネットでの増加ソフトウェアのライフサイクル全体で開発のスピードと柔軟性インチ 総労力と不便さは減りますが、多くの労力と不便さは前もって動き、より目立つようになります。動作するコードを持つことへの入り口の障壁は高くなりますが、いったんその障壁を乗り越えると(型チェッカーを満たすことで)、そのコードの拡張と保守にかかる作業ははるかに少なくなります。

次の理由により、ソフトウェア開発には常に頭痛の種があります。

  • あなたが達成しようとしていることの固有の複雑さ

  • 特に複雑なことをしようとするとより多くの間違いを犯すことを考えると、人間に固有の誤りやすさ

遅かれ早かれ、これらの課題に対処するために時間がかかる必要があります。それを回避する方法はありません。静的型付けは、これらの課題に後でよりも早く対処するだけです。遅ければ早いほど、間違いを発見した(ifの問題ではなくいつの問題である)ので、その間違いを修正するのに費用がかかるためです。

型チェッカーによって報告された間違いを修正する方が、実行時に発生した型関連の例外をデバッグするよりもはるかに安価です。型チェックを実行時まで延期することは、問題を覆い隠すだけです。


1

これは私自身の意見ですが、いや、型の安全性に価値があるとは思いません。一瞬でもない。

私は長い間開発者でした。C ++、C#から始めて、javascript(node.jsを介したフロントエンドとバックエンド)に移動しました。JavaScriptで開発して以来、私の生産性は飛躍的に向上し、タイプベースの言語を使用すると実際に悪化します。私もコンパイルに反対です、私はすべてを今実行中にしたいです。通訳言語は、プログラミングに対する私の愛を本当に見つけた場所です。

タイプに関しては、何の利点もありません。メモリ管理と同じ方法で型が表示されるようになりました。完全に不要です。明日の言語は、型について何も知らないように開発者を完全に保護するはずです。コンピューターは型を理解し、開発者をそこから除外する必要があります。

以下に例を示します。私はSwift(Appleの新しい言語)を使用して、1日前に実際にその名前まで生きて、それを試してみました:var n = 1/2は機能しませんでした。私は、ここで何が起こっているのかのようでした。そして悲しいことに、var n:Float = 1/2を実行する必要があることに気付きました。これは、型システムをどれほど嫌いで、どれだけ不必要に悪化させているかを思い出させてくれました。

さらに、ユーザー定義型(クラスなど)が不要であることを言いたいと思います。型はまったく必要ありません。私が欲しいのは、varとオブジェクトだけです。任意のオブジェクトを任意のオブジェクトとして使用できる場所。そして、オブジェクトは動的であり、絶えず変化しています。何が機能し、何が機能しないかに関して、実行時の問題になる場所。

開発者は、大まかなプロジェクトでは型付けが緩い言語はどれほど良くないかを言いたいです。しかし、私は反対だと思います。強く型付けされた言語は、大規模なプロジェクトにとって恐ろしいものです。そして、javascriptが大きなプロジェクトでは機能しないと言ったら、node.js / javascriptでバックエンドをすべて実行している400億以上の企業、またはPHPで始まったFacebookにUberに尋ねてください。

静的に型付けされた言語に関しては、今日の短い反復には向いていません。簡単な例を示します。10人の開発者が継続的統合サーバーを使用して.netプロジェクトで作業しており、1人の開発者がミスを送信し、ビルド全体が壊れています。問題のある開発者が自分の間違いを修正するために。効率的なハァッについて話しますか?型システム/静的言語はそのように相互依存しており、コードを相互依存にします。ただし、スクリプトファイルが相互依存することはありません。いずれかのスクリプトに問題があり、生産が停止しない場合、表示される問題はすべてランタイムに委ねられます。そして、ランタイムは決して停止しません。決して壊れません。間違った出力を生成する可能性がありますが、


1
多くの「私」は、多くの議論の実体ではありません。ちなみに、エラーがビルドを「中断」するかどうかは、静的と動的のどちらでもありません。あなたはユニットテストを持っていると1が失敗した場合は、「ビルドが壊れている」とそれが修正されるまでうまくいけば、生産にデプロイしない
nafg

そのようなことを暗示していると思われたのはなぜですか?
nafg

javascriptには型がないため、javascriptの生産性は急上昇しませんでした。C ++とC#は重い言語であるため、生産性が飛躍的に向上します。Javascript +型を使用すると、実際に生産性がさらに向上します。大規模なプロジェクトではJavaScriptが不可能であると言う人はいません。大規模プロジェクトのJavascriptは確かに実行可能です。しかし、それは理想的ではありません。単体テストは型チェックの代わりに使用します。また、型テストは100%のカバレッジですが、単体テストでは型カバレッジが制限されます。
ブライアンイェ

1
@BrianYeh c ++とc#は型に集中しているため、重い言語です。私は自分の仕事でreactjsを使い始めたばかりで、型とコンポーネントの絶え間ない使用により、生産性は再び低下しました。型と単体テストが好きなら、それは良いことです。私たち全員がこのプログラミングスタイルを共有しているわけではありません。

1
@foreyez reactjsには型がありません。おそらくフローを指しているのでしょう。単体テストは型チェックの代わりになるので、型チェックがない場合はさらに単体テストが必要です。単体テストとタイプは対立する力です。生産性の低下は幻想です。タイプセーフな言語でキャッチしたタイプエラーは、動的に型付けされた言語ではキャッチされないエラーです。速く見えるだけです。タイプセーフな言語では、これらのエラーに事前に対処する必要があります。
ブライアンイェ

0

はい。

私は、JavaやC#のように型が「強力」ではないPHPアプリケーションで働いてきました。通常、「型のシミュレーション」を終了しました。これは、不適切な自動変換を回避するため、またはデータを検証するためです。

動的型言語は、複雑なアプリではなく、OSスクリプトや高速の小さなアプリに適しています。

概要:「弱い型」または「動的な型」プログラミング言語、または複雑なビジネスアプリケーション用の「強い型」プログラミング言語を選択する必要がある場合は、「強い型」プログラミング言語を選択します。


0

一歩後退して、動的型付けがいつ問題を引き起こすのかを考えることは有益だと思います。

1つのケースは、コードブランチがまったくテストされていないが、率直に言って、テストされていないコードは、動的型付けが使用されているかどうかに関係なくバグがある可能性があります。

ただし、もう1つのより微妙な問題は、不完全な代替可能性です。

型がまったく完全に間違っている場合、特定のコードパスが使用されない限り、それはすぐに検出される可能性があります。

一方、型が不完全な代替物である場合、コードはほとんど動作する可能性がありますが、後ほど検出されない微妙な方法で壊れる可能性があります。

プログラミングで最も一般的な2つのタイプは、数字と文字列です。多くの動的言語では、それらは互いに不完全な代替物です。たとえば、javascriptまたはphpで、文字列が予想される場所に数字を指定した場合、またはその逆の場合、プログラムはエラーを発生させることなく実行されますが、微妙な方法で誤動作する可能性があります。

Pythonは、特定の問題を回避しました。数字と文字列は互いに代用することはできず、一方が使用されると予想される場所で使用しようとすると、通常は急速に失敗します。

しかし、不完全な持続可能性の問題を完全に回避することはできませんでした。異なるタイプの数は互いに不完全な代替物になる可能性があるため、異なるタイプのシーケンスも可能です。


ここで得ていることは、静的型と動的型の利点とコストを一般的な方法で比較することは不可能だと思うことです。使用します。

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