多くのプログラミング言語があり、新しい言語は常にポップアップし続けています。 以前に存在していたものよりも優れていますか? 明らかに、プログラミング言語に関して「より良い」ものの明確な定義が与えられるまで、この質問に答えることはできません。
過去の傾向を見ると、より良いプログラミング言語を作成する方法の1つは、既存の言語の冗長な機能を特定し、それなしで新しい言語を設計することです。
「完璧は、追加するものがないときではなく、削除するものがないときに達成されます」
アントワーヌドサンテグジュペリ
この記事では、冗長性としてすでに広く認識されているさまざまなプログラミング言語の機能のいくつかの例と、同じ機能を持ち、いつか同じグループに割り当てることができる他のいくつかを参照します。
足で自分を撃つ無制限の方法
最初のコンピューターが作成されたとき、それらのプログラムはマシンコードまたはアセンブリ言語で作成する必要がありました。 マシンコードは、一般的にプロセッサが実行できるすべてを完全に表現できます。これは、マシンコードがプロセッサ命令のセットに厳密に対応しているためです。 正しいプログラムはマシンコードで記述できますが、ハングする、クラッシュする、または動作するハードウェアを誤って使用するプログラムを含む、無数の誤ったプログラムを記述することもできます。
今日、あなたは高レベルのプログラミング言語でコードを書いている可能性が最も高いですが、それでも、エラーなく動作させるのはそれほど簡単ではないことに同意するでしょう。 すべての正しいプログラムには、多くの誤ったオプションがあります。
マシンコードを使用すると、独自の不正なプログラムを作成する方法が無制限にあります。 任意のプロセッサコマンドをいつでも実行できます。 正しい命令シーケンスのセットは、可能なすべての命令シーケンスのセットのほんの一部です。
最初のプログラマーは、マシンコードでプログラムを記述するとエラーが発生しやすく、さらにコードが長く読みにくいことをすぐに発見しました。 この問題を解決する1つの方法は、アセンブリ言語を作成することでした。 しかし、実際にはあまり役に立ちませんでした。アセンブラープログラムは人間が読みやすいものでしたが、マシン命令を1つずつ繰り返しただけでした。したがって、記述される可能性のある誤ったプログラムのセットは同じままでした。
高レベル言語
マシンコードとアセンブラーで苦しみ続けた後、プログラマーは高レベルのプログラミング言語を思いつきました。 最初のそのような言語は現在あまり使用されていませんが、これらの「低レベル」高レベル言語の例の1つはまだ使用されていますが、Cです。
Cでは、ほとんどすべての有効なプログラムを作成できます。 落下する可能性がある不正なプログラムを作成するためのキャリッジと小さなカートがまだあります。 しかし、この言語はマシンコードに対する抽象化であるため、このような言語では表現できないマシン命令のセットがいくつかあります。 それらのほとんどは無効なプログラムです。つまり、それらを切断する抽象化は有益です。
何が起こったかに注意してください。マシンコードから高レベル言語への切り替えにより、いくつかの可能性が取り除かれました。 マシンコードで何でも書くことができますが、すべてが高級言語で書けるわけではありません。 このアプローチの長所は短所を上回っているため、これを我慢しました。
後藤
1968年、Edsgar Dijkstraはgotoオペレーターの危険性に関する有名な作品を発表しました。 その中で、彼はgoto演算子を使用するという概念自体が悪質であり、プログラムはgotoなしではるかに優れていると示唆しました。 これは何十年も続いた議論を引き起こしましたが、今日、ダイクストラが正しいことを理解するようになりました。 現在、多くの一般的なプログラミング言語にはgoto演算子がありません(JavaやJavascriptなど)。
gotoは絶対に不要な演算子であることが判明したため、gotoを言語から削除しても、この言語で記述できる有効なプログラムの数は減りません。 しかし、それは無効の数を減らします
パターンをキャッチしましたか? 不要なものを取り除く-あなたは改善を得る。 これは何も新しいことではありません-ロバートC.マーティンは何年も前にこれについて話しました 。
遭遇した最初の関数だけを言語から削除することはできません。この場合、有効なプログラムを作成できなくなる可能性があります。
ただし、言語を損なわずに一部の機能を削除できます。
例外
今日、誰もがエラーを何らかの例外処理メカニズムで処理することに同意しています。 少なくとも、エラーコードだけでは不十分であることに同意します。 もっと深刻なものが必要ですが、同時にユーティリティとパフォーマンスのバランスを維持する必要があります。
私たちのプログラミング言語の例外の問題は、それらが基本的にGOTOに変装しているということです。 そして、GOTOを使用することは悪いことであることがすでにわかっています。
最善の方法は、特定のコードブロックの成功またはそのエラーに関する情報を収集する複合型を使用することです。
ポインタ
Robert C. Martinが指摘したように、CやC ++などの古いプログラミング言語ではポインターを操作できますが、ポリモーフィズムの概念を導入するとすぐに、きれいなポインターは不要になります。 Javaにはポインターがなく、Javascriptにはポインターがありません。 C#にはポインターがありますが、WinApi関数への直接呼び出しのようなまれな場合にのみ必要です。
これらの言語はすべて、参照によって何かを渡すためにポインタが必要ないことを証明しています。 ポインターを削除できます。
数値型
最も強く型付けされたプログラミング言語では、16ビット整数、32ビット整数、32ビット符号なし整数、小数浮動小数点など、いくつかの数値タイプから選択する機会が与えられます。 これは1950年代には意味がありましたが、今日ではほとんど重要ではありません。 適切な数値タイプの選択、全体像の喪失など、マイクロ最適化に多くの時間を費やしています。 ダグラス・クロックフォードが言ったように、 「Javascriptには数値型が1つしかありません。これは素晴らしいアイデアです。 これが間違った番号タイプであるのは残念です。」
最新のコンピューターのリソースを使用して、1つの数値タイプのみを提供するプログラミング言語を購入できます。 このような言語は、さまざまな数値型に関連するこの混乱をすべて頭から抜け出すのに最適な方法です。
ヌルポインター
ヌルポインターは、プログラミング言語で最も誤解されている概念の1つです。 一部の値が設定されている場合と設定されていない場合があるという事実には何の問題もありません。 このような概念は多くのプログラミング言語に存在します。 HaskellではMaybe、F#ではオプション、T-SQLではnullです。 これらすべての言語に共通するのは、この機能がオプションであることです。 値を「nullable」として宣言できますが、デフォルトではそうではありません。
ただし、Tony Hoar 自身が10億ドルと認識し推定した間違いにより、多くの言語にはヌルポインターがあります:C、C ++、Java、C#。 問題は「nullポインター」の概念ではありませんが、デフォルトポインターはnullになる可能性があるため、nullがポインターの期待される有効な値であるケースと、それが欠陥である状況を区別できなくなります。
nullポインターのない言語を作成すれば、nullポインターによるアクセスエラーの生成や処理について考える必要はありません。
Tony Hoarがこのバグの損害を10億ドルに評価するのに正しければ、Nullポインターを今すぐ取り除けば、将来多くのお金を節約できます。 ヌルポインターのないチューリング完全なプログラミング言語(前述のT-SQL、Haskell、F#など)が存在するため、この概念がなくても有効なプログラムを表現できることがわかっています。
変数値を変更する
手続き型、命令型、オブジェクト指向スタイルの中心概念の1つは、プログラムの実行中に変数の値を変更できることです。 これが「変数」と呼ばれる理由です。 プロセッサにはレジスタが含まれており、プログラム中に行うことは、そこにデータを書き込み、コマンドを実行し、結果を読み取るだけなので、これは論理的で直感的に正しいようです。 一方、これは論理的です。ほとんどのプログラムは、外界の状態を何らかの形で変更するように設計されています-データベースへのデータの書き込み、電子メールの送信、画面への画像の表示、ドキュメントの印刷など。
ただし、変数の値を変更すると、ソフトウェアエラーの大きな原因になることが判明しました。 たとえば、C#の次のコード行を想像してください。
var r = this.mapper.Map(rendition);
Map — rendition ? — . — Map. , ? - ? . . # ( Java, Javascript) .
- , -, \ — . « isDirty ? ? - customerStatus?».
, :
, ( ) , .
, , goto. goto, . , , .
- C# Java - . — . ( ) — . .
, ?
.
, , - - , , . , - — - . .
. 20 . , . : , ( ), . — .
. , . , .
(, Java #) , . , . , SOLID , , - , , . — . — , . — #, Java.
. .
, , , . , « », — .
- - .NET Java, , , , . API , .
- — , . , — -. , , . , - .
: -. - , .
, , — . — . C# Java .
, , : AtomEventStore IXmlWritable:
public interface IXmlWritable { void WriteTo(XmlWriter xmlWriter, IContentSerializer serializer); }
WriteTo IContentSerializer, :
public interface IContentSerializer { void Serialize(XmlWriter xmlWriter, object value); XmlAtomContent Deserialize(XmlReader xmlReader); }
, Deserialize() XmlAtomContent. XmlAtomContent? :
public class XmlAtomContent : IXmlWritable
, IXmlWritable — , , IXmlWritable !
, . F# (, -, OCaml) ! F# and rec, . — .
! — .
« »: Scott Wlaschin C# F# , F# , C#. Evelina Gabasova.
, , . — , , (, ), .
, , :
- GOTO
? , , - !