プログラマに制限が必要な理由

制限により、アート、デザイン、生活が向上します。

私たちはノーリミットまたはプッシュザリミットの文化から来ていますが、実際にはリミットが必要です。私たちは彼らと一緒に過ごしたほうがいいのですが、彼らは正しい限界である必要があります。

より良い音楽の検閲

歌や本、映画で言うことができるものに外部から課せられた制限がある場合、作家は特定のポイントを示すために比pointに頼らなければなりませんでした。

1928年のコールポーターの名作、Let’s Do It(Let’s Fall in Love)をお楽しみください。私たちは皆、「それ」が意味することを知っています。「恋に落ちる」ではありません。彼らは検閲を避けるためにタイトルに括弧を追加しなければならなかったと思う。

2011年に早送りして、ノブにある3つの6 Mafia's Slobを見てください。実際に比phor的な最初のスタンザを除いて、歌詞の残りは鼻の上にあります。

芸術性(またはその欠如)のメリットを少しの間置いておきますが、コールポーターの歌は、スリー6マフィアの歌が想像を絶するほど詳細な形で私たちの上に掲げていることを暗示しています。

問題は、Three 6 Mafiaの歌詞で説明されているようにメイキングを購読しないと、最悪な下品で、せいぜいマークを逃してしまうことです。しかし、コールポーターのおかげで、リスナーはファンタジーを作る自分の個人的な愛を思い起こすことができます。

そのため、制限は物事により大きな魅力を与えることができます。

サメが機能していません

ジョーンズの物語を伝えるスティーブンスピルバーグの当初の計画は、サメを見せることでした。しかし、常に壊れていました。ほとんどの場合、彼らは映画のスターであるサメを見せることができませんでした。

ブロックバスターの先駆けとなったこの映画は、スピルバーグができることに機械的な困難が制限を課さなければ、現在の化身には存在しません。

なぜこの映画はサメが登場する映画よりもはるかに優れているのですか?繰り返しになりますが、不足している部分は各視聴者によって埋められます。彼らは自分の個人的な恐怖症を取り、スクリーンに投影します。したがって、恐怖は視聴者ごとにパーソナライズされています。

アニメーターはこれを長年知っています。画面のクラッシュを再生し、余波に切り取ります。これには2つの利点があります。クラッシュをアニメーション化する必要はありません。クラッシュは視聴者の心の中で起こります。

ほとんどの人は、バンビの母親が撃たれるのを見たと思います。彼女が撃たれるのを見ないだけでなく、彼女が撃たれた後に彼女を見ることはありません。しかし、人々は両方を見たことを誓います。しかし、それは決して示されていません。

そのため、制限は物事を改善することができます。はるかに良い。

選択肢、どこでも選択

あなたが画家だと想像して、私に絵を描いてほしいと頼みます。私が言うのは「美しいものを塗ってください。私が本当に好きになるもの。」

今、あなたはスタジオに入り、そこに座って空白のキャンバスを見つめます。そして、じっと見つめることはできません。どうして?

可能性が多すぎるからです。文字通り何でもペイントできます。制限はありません。そして、これはあなたを麻痺させる問題です。これは、パラドックスオブチョイスとして知られています。

代わりに、自分が好きな風景を描くように言ったら、少なくとも無限の可能性の半分がなくなるでしょう。無限の可能性が残っていますが、ポートレートについての考えはすぐに却下されます。

さらに進んで、黄金の夕日の間にビーチに波が打ち寄せる海の景色が大好きだと言ったら、無限の数の絵画が残っていますが、それらの制限は実際に何を描くべきかを考えるのに役立ちます。

そして、あなたがそれを知る前に、あなたは海景のスケッチを始めることができます。

そのため、制限により作成が容易になります。

ハードウェアはソフトウェアよりも簡単です

ハードウェアを使用すると、コンピューター内の複数のコンポーネントで共有されるトランジスターやコンデンサーが表示されることはありません。キーボード回路の抵抗器は、グラフィックカードからアクセス、共有、または影響を受けることはできません。

グラフィックカードには、専用の抵抗があります。ハードウェアエンジニアは、より多くの抵抗器を販売するため、これを行いません。彼らは選択肢がないのでそれをします。

宇宙の法則は、これを破壊せずに行うことはできないと規定しています。ユニバースはハードウェアエンジニアにルールを課しています。つまり、可能なことを制限しています。

これらの制限により、ソフトウェアよりもハードウェアについて考えて作業することが容易になります。

ソフトウェアでは不可能なことは何もない

ほぼすべてが可能なソフトウェアにカットします。ソフトウェアエンジニアがプログラムのすべての部分で変数を共有することを制限するものはありません。これはグローバル変数として知られています。

アセンブリ言語プログラミングでは、コード内の任意のポイントにジャンプして実行を開始できます。これはいつでもできます。プログラムに意図しないコードを実行させるデータに書き込むこともできます。これは、バッファオーバーフローの脆弱性を悪用するハッカーが採用する方法です。

通常、オペレーティングシステムは、プログラムができることをプログラム外のものに制限します。しかし、プログラムが所有するコードとデータに対してプログラムができることには制限がありません。

ソフトウェアの作成と保守を非常に困難にしているのは、制限がないことです。

ソフトウェア開発を適切に制限する方法

私たちはソフトウェア開発に制限が必要であることを知っており、経験から、他の創造的な努力の制限が私たちに利益をもたらすことを知っています。

また、コードをランダムに検閲するために社会に頼ったり、パラダイムを制限するための機械的な欠陥に頼ったりすることはできません。そして、ユーザーが設計に適切な制限を必要とするほど要件を指定することは期待できません。

私たちは自分自身を制限しなければなりません。しかし、これらの制限が有益であることを確認したいと思います。それでは、どのような制限を選択する必要があり、どのように決定する必要がありますか?

その質問に答えるには、経験と長年の実践に頼って、適切な限界を追求するために私たちを導く必要があります。しかし、私たちが持っている最も便利なツールは過去の失敗です。

私たちの過去の行動の痛み、例えばストーブに触れると、同様の苦痛を避けたい場合に自分自身にどのような制限を加える必要があるかがわかります。

私の人々を行かせて

初期の頃、人々はコードをあちこち飛び回ってプログラムを書いていました。これはスパゲッティコードと呼ばれていました。この種のコードに従うことは、スパゲッティのボウルで一本鎖をたどるようなものだったからです。

業界は、この慣行が逆効果であることを認識し、最初はそれを許可する言語で記述されたコードからのGOTOステートメントの使用を禁止しました。

最終的に、新しいプログラミング言語は、GOTOをサポートしないというメリットで販売されました。これらは、構造プログラミング言語として知られていました。そして今日、主流の高レベル言語はすべてGOTOなしです。

これが発生したとき、新しい言語があまりにも制限的であり、GOTOがあれば、より簡単にコードを書くことができると不満を言う人もいました。

しかし、より進歩的な精神が勝ち、​​私たちはそのような破壊的なツールの絶滅に感謝しなければなりません。

プログレッシブマインドが認識したのは、コードが記述または変更されたものよりも多く読み取られることです。そのため、足の短剣の小さなグループには少し不便かもしれませんが、長期的にはこの制限ではるかに良いでしょう。

コンピューターは引き続きGOTOを実行できます。実際、彼らはする必要があります。私たちは、業界として、プログラマーがプログラマーを直接使用することを制限することにしたのです。すべてのコンピューター言語は、GOTOを使用するコードにコンパイルされます。しかし、言語設計者は、より統制のとれた分岐を採用する構成を作成しました。 break文を使用してforループを終了します。

ソフトウェア業界は、言語設計者が指示する制限から大きな恩恵を受けています。

シャックルをもたらす

では、今日のGOTOとは何ですか?また、言語デザイナーは、疑いを持たないプログラマーのために何を用意していますか?

これに答えるために、私たちは日常的に遭遇する現在の問題に目を向けるべきです。

  1. 複雑
  2. 再利用性
  3. グローバルな可変状態
  4. 動的な入力
  5. テスト中
  6. ムーアの法則の終

上記の問題を解決するためにプログラマが許可されていることをどのように制限しますか?

複雑

時間の経過とともに複雑さが増します。単純なシステムとして開始されるものは、時間が経つにつれて複雑なシステムに進化します。複雑なシステムとして開始されるものは、時間の経過とともに混乱に発展します。

では、複雑さを軽減するためにプログラマをどのように制限するのでしょうか?

1つは、プログラマーに完全に分解されたコードの作成を強制することができます。まったく不可能ではないにしても、これを行うことは困難ですが、この行動を奨励し、それに報いる言語を作成できます。

多くの関数型プログラミング言語、特に純粋な言語は、これらの両方を行います。

計算である関数を書くと、非常に分解された方法で物事を書かなければなりません。また、問題のメンタルモデルを検討する必要があります。

また、プログラマーが関数で実行できることを制限することもできます。つまり、すべての関数を純粋にします。純粋な関数は副作用のない関数です。つまり、関数は自分の外部にあるデータにアクセスできません。

純粋関数は、渡されたデータのみを処理し、結果を計算して返します。同じ入力で純粋関数を呼び出すたびに、常に同じ出力が生成されます。

これにより、純粋関数に関する推論は、純粋関数よりもはるかに簡単になります。これは、純粋関数ができることはすべて関数に完全に含まれているためです。また、自己完結型のユニットであるため、ユニットテストをより簡単に行うこともできます。また、計算に負荷がかかる場合は、結果をキャッシュできます。同じ入力がある場合、出力は常に同じであることがわかります。キャッシュの完璧なシナリオ。

プログラマーを純粋な関数のみに制限すると、関数はローカルな効果しか持たず、開発者がソリューションを自然に分解できるため、複雑さが大幅に制限されます。

再利用性

プログラミングが行われている限り、業界はこの問題に取り組んでいます。最初にライブラリがあり、次に構造化プログラミング、そしてオブジェクト指向継承がありました。

これらのアプローチはすべて、限られた魅力と成功しかありません。しかし、ほとんどすべてのプログラマーによって常に機能し、採用されている1つの方法は、コピー/貼り付け(コピーパスタ)です。

コードをコピーして貼り付ける場合、間違っています。

まだプログラムをテキストとして書いている限り、コピー/貼り付けからプログラマーを制限することはできませんが、できることは彼らにもっと良いものを与えることです。

関数型プログラミングには、copypastaよりもはるかに優れた標準機能があります。高階関数、カリー化および合成。

高階関数を使用すると、プログラマーはデータおよび関数であるパラメーターを渡すことができます。これをサポートしない言語では、関数をコピーして貼り付けてからロジックを編集するだけです。高階関数を使用すると、ロジックを関数の形式でパラメーターとして渡すことができます。

カリー化により、パラメーターを1つずつ関数に適用できます。これにより、プログラマーは関数の汎用バージョンを作成し、パラメーターの一部を「ベイクイン」して、より特殊なバージョンを作成できます。

コンポジションを使用すると、プログラマはLegos™などの機能を組み立てて、ある機能から次の機能にデータが流れるパイプラインに組み込まれた機能を再利用できます。 Unixパイプは、これを単純化した形式です。

そのため、コピーパスタを排除することはできませんが、言語サポートおよびコードベースで許可されていないコードレビューによって不要にすることができます。

グローバルな可変状態

これはおそらくプログラミングの最大の問題であり、ほとんどの人は問題に気付いていません。

コンピューターの再起動や問題のあるアプリケーションの再起動によって、プログラムの不具合のほとんどの解決策が修正される理由を疑問に思ったことはありませんか?それは国家のせいです。プログラムの状態が破損しています。

プログラムのどこかで、状態が無効な方法で変更されました。これらは、修正が最も難しいバグの一部です。どうして?再現が非常に難しいからです。

確実に再現できない場合、実際に修正したかどうかを知る方法はありません。修正をテストしても問題ありません。しかし、それはあなたがそれを修正したからか、それはまだ起こっていないからですか?

適切な状態管理は、信頼性を確保するためにプログラムで実行できる最も重要なことです。

関数型プログラミングは、言語レベルでプログラマーに制限を設けることでこの問題を解決します。プログラマは可変変数を作成できません。

最初は、彼らが行き過ぎているように見えるかもしれませんし、あなたがこれを読んでいるときにあなたの熊手を研ぐかもしれません。しかし、そのようなシステムを実際に使用すると、すべてのデータ構造を不変にしながら状態を管理できることがわかります。つまり、変数の値がいったん変更されると、変更できなくなります。

これは、状態を変更できないという意味ではありません。そのためには、現在の状態を新しい状態を生成する関数に渡す必要があるということです。ピッチフォークを再度実行する前に、Structural Sharingを使用して、これらの操作を内部で最適化するメカニズムがあるので安心できます。

カバーの下に突然変異が起こることに注意してください。 GOTOが削除された昔のように、コンパイラーまたはランタイムは引き続きGOTOを実行します。プログラマーには利用できません。

また、副作用が発生する必要がある場合、関数型言語にはプログラムの潜在的に危険な部分を含める方法があります。良い実装では、コードのこれらの部分は明らかに危険であるとマークされ、純粋なコードから分離されています。

また、コードの98%に副作用がない場合、状態を破損するバグは2%にしかなりません。これにより、プログラマーは、危険な部分が集められているため、この種のバグを見つけるための格闘の機会を得ることができます。

そのため、プログラマを純粋な機能(またはほとんど)のみに制限することにより、より安全で信頼性の高いプログラムを作成します。

動的な入力

静的な入力と動的な入力をめぐる長い古い戦いがあります。静的型付けは、変数の型がコンパイル時に検証される場所です。型を定義すると、コンパイラは、型を正しく使用していることを確認するのに役立ちます。

Static Typingに対する議論は、プログラマに不必要な負担をかけ、冗長なタイピング情報でコードを散らかすことです。また、このタイプ情報は、関数の仕様とインラインであるため、構文的にノイズが多くなります。

動的な型付けは、変数の型がコンパイル時に指定も検証もされない場所です。実際、ダイナミックタイピングを使用するほとんどの言語はコンパイルされた言語ではありません。

Dynamic Typingに対する議論は、コードを大幅にクリーンアップしますが、変数の誤用はすべてプログラマーにキャッチされないということです。プログラムが実行されるまでキャッチされません。これは、すべての最善の努力にもかかわらず、タイプバグが本番環境に入ることを意味します。

どちらがベストですか?ここではプログラマーを制限することを検討しているため、マイナス面にもかかわらず静的型付けの議論を期待するかもしれません。ええ、はい、しかし、両方の世界で最高のものを手に入れることができたらいいと思いませんか?

結局のところ、すべての静的タイピングシステムが均等に作成されるわけではありません。多くの関数型プログラミング言語は、型推論をサポートしており、コンパイラは、使用している方法で記述している関数の型を推論できます。

これは、指定のすべてのオーバーヘッドなしで静的な型付けができることを意味します。ベストプラクティスでは、推測ではなくタイピングを指定することを規定していますが、HaskellやElmなどの言語では、タイピングの構文は実際には目立たず、非常に役立ちます。

静的に型指定される非機能言語、つまり命令型言語は、その投資に対するリターンがほとんどない型を指定することでプログラマに負担をかける傾向があります。

対照的に、HaskellとElmの型システムは、実際にはプログラマーのコードを改善し、プログラムが適切に機能しないコンパイル時にそれらを通知します。

したがって、プログラマーを適切な静的型付けに制限することにより、コンパイラーは、冗長で侵入的な型情報を開発者に負担をかける代わりに、実際にバグの検出、型の推測、コーディングの支援を行うことができます。

テスト中

テストコードの記述は、現代のプログラマの存在の悩みの種です。多くの場合、開発者はテスト対象の元のコードよりもテストコードの作成に多くの時間を費やします。

データベースまたはWebサーバーとインターフェイスする機能のテストコードを記述することは、完全に自動化することが不可能ではないにしても困難です。通常、2つのオプションがあります。

  1. テストを書かない
  2. データベースまたはサーバーのモックアップ

オプション#1は明らかに優れたオプションではありませんが、複雑なシステムのモックアップは、テストしようとしているモジュールの作成に費やす時間よりも時間がかかるため、多くの人がこの方法を採用しています。

ただし、コードを純粋な関数に制限すると、副作用や突然変異を引き起こすため、データベースに直接接続できません。それでもデータベースにアクセスする必要がありますが、モジュールの大部分を純粋なままにする非常に薄いインターフェイスレイヤーとして危険なコードレイヤーがあります。

純粋な関数のテストははるかに簡単です。しかし、私たちの存在の悩みの種であるテストコードを記述する必要があります。それとも私たち?

機能プログラムを自動的にテストするプログラムがあることがわかりました。プログラマが提供しなければならない唯一のことは、関数が従わなければならないプロパティです。逆関数とはHaskell自動テスターはQuickCheckと呼ばれます。

そのため、大部分の関数を純粋に制限することで、テストをはるかに簡単にし、場合によっては純粋に簡単にします。

ムーアの法則の終

ムーアの法則は実際には法則ではありませんが、2年ごとに計算能力が2倍になるという観察結果です。

これは50年以上にわたって真実です。しかし、悲しいことに、現在の技術では限界に達しました。そして、コンピューターを構築する非シリコンベースの技術を開発するには数十年かかるかもしれません。

それまでは、コンピューターの速度を2倍にする最善の方法は、コア、つまりCPUのコンピューティングエンジンの数を2倍にすることです。問題は、ハードウェアメーカーがコアを追加できないということではありません。問題はバッテリーとソフトウェアです。

計算能力を2倍にするということは、CPUが消費する電力を2倍にすることを意味します。これにより、今日よりもさらに早く電池が消耗します。バッテリー技術は、ユーザーの飽くなき欲求に大きく遅れをとっています。

そのため、バッテリーを消耗させるためにコアを追加する前に、すでに持っているコアの使用を最適化する必要があります。これがソフトウェアの出番です。現在、命令型言語はプログラムを並行して実行することを非常に難しくしています。

今日それを行うには、開発者に負担がかかっています。プログラムをスライスし、並列部分に分割する必要があります。これは簡単な作業ではありません。そして実際、JavaScriptのような言語では、プログラマーはコードを並列に実行できないため、つまりシングルスレッドであるため、これを制御できません。

しかし、Pure Functionsでは、実行順序は関係ありません。重要なのは、入力が利用可能であることです。これは、コンパイラーまたはランタイムシステムが、実行する機能とタイミングを決定できることを意味します。

関数を純粋な関数に制限することにより、プログラマーが並列処理を心配する必要がなくなります。

機能的なプログラムは、開発者に複雑さを追加することなく、マルチコアマシンを活用できるはずです。

少ない労力でより多くのことを

これまで見てきたように、適切な制限を課すことで、アート、デザイン、生活を劇的に改善することができます。

ハードウェアエンジニアは、ツールの自然な制限から仕事を容易にし、過去数十年で大きな進歩を遂げることができました。

私たちソフトウェアエンジニアが自分自身に制限を課し、少ない労力でより多くのことができるようにすべき時ではないでしょうか。

これが気に入ったら、下のをクリックして、他の人がこれを中に表示するようにします。

ElmのFunctional Programmingを使用してWebアプリの開発を学び、支援するWeb開発者のコ​​ミュニティに参加したい場合は、FacebookグループのLearn Elm Programming https://www.facebook.com/groups/learnelm/をご覧ください。

私のTwitter:@cscalfani