[翻訳]プログラミングはソフトウェアエンジニアリングとは違う

※この記事はSamer Buna氏の「[Software Engineering is different from Programming](https://edgecoders.com/software-engineering-is-different-from-programming-b108c135af26)」を翻訳したものです。Twitterより翻訳の許可を頂きました。ありがとうございます。

## プログラミングはソフトウェアエンジニアリングとは違う
**全てのソフトウェアエンジニアはプログラミングができますが、全てのプログラマはソフトウェアをエンジニアリングできません。**

エンジニアリングの比喩として、ソフトウェアエンジニアという用語を好まない人もいます。この記事はその用語については言及しません。気に入らなければ、Software Author、Software Craftsperson、またはSoftware Artistに置き換えてください。

ソフトウェアエンジニアは、職業として高品質のソフトウェアを書く人を意味します。彼らは科学と統計を用い、そして単なるお金を稼ぐ仕事だと見なさない人です、プログラミングの方法を知っていても、ソフトウェアエンジニアとはなりません。

誰でもプログラムを学ぶことができます。それは簡単です。誰でも自分自身のマシンで動くプログラムを作ることができますが、それらが他の人のマシンで動作することは保証しません。

これに似た私のお気に入りとしては、誰もがシャワーの中で歌って自分を楽しませることができますが、それがパーティータイムになると、あなたは自分自身の歌の録音を再生しません。あなたはプロの音楽を楽しみます。

もっと似たものを？もちろんです。

- 私たちは学校で数学と執筆を学びましたが、それによって数学者や著者になりませんでした。
- 私たちのほとんどは簡単に調理することを学ぶことができますが、それが多くの人々を養う時が来たとき、私たちはシェフを雇います。
- あなたは一から家を建てるために近所の便利屋を呼びません。

この記事で私が共有したい主なメッセージは、単純なプログラムは設計されたプログラムとは大きく異なるということです。

プログラミングという行為は、その最も単純な定義では、何らかの出力を生成するために何らかの入力でコンピューターに指示を与えることです。

ソフトウェアエンジニアリングは、多くのユーザーのために問題を解決することを目的としたコンピュータプログラムの設計、作成、テスト、および保守のことです。それは堅牢で安全な解決策を創り出すことであり、それらは長持ちし、根本的な問題の周りにあるいくつかの未知の問題も解決します。

ソフトウェアエンジニアは、彼らが解決する問題、彼らが提供するソリューション、それらのソリューションの限界、彼らのプライバシーへの影響、そしてセキュリティへの影響についてすべてを理解しています。

誰かが問題そのものを理解していないならば、彼らはそれに対する解決策をプログラムしようとはしません。

## 解決の考え方
ソフトウェアエンジニアは、自分のキャリアを単なるプログラムを書くこととは考えていません。彼らはニーズを満たし、問題を解決するという観点から考えています。これは重要なことで、なぜならば全ての問題がプログラムを必要とするわけではないからです。いくつかの問題は、既存のプログラムやまとめられた複数のプログラムによって解決することができます。いくつかの問題は早期に行動することによって完全に防ぐことができます。良いプログラムの設計というものは、将来の問題を防ぐための計画もよく含まれています。

> 「知識人は問題を解決し、天才は問題を起こらないようにする。」
アルバート・アインシュタイン

通常、複雑な問題は複数のプログラムを書く必要があります。いくつかの問題は並行して実行するプログラムを必要とし、他の問題はプログラムを順次実行することを必要とします。いくつかの問題はユーザーを教育することによって解決することができます。

プログラムを書く前に、ソフトウェアエンジニアは質問をします。

- どのような問題を解決しようとしているか？
- それらを解決するためにコードを書くこと以外に何ができるか？
- これらの問題をコードで解決しやすくするために何ができるか？

## コードの品質
優れたプログラムは明確で読みやすく、簡単に拡張することができ、他のプログラムとうまく機能します。それらをメンテナンスすることは悪夢ではありません。コードの品質は天秤にかけられるものではありません。締め切りや感情のためにずさんなショートカットを使用することは決して受け入れられません。

エンジニアリングソフトウェアの最も重要な側面の1つは、拡張性を考慮してゼロから設計することです。ソフトウェアを変更することは避けられない事実です。ユーザーはより多くの機能とソフトウェアを使用するためのより簡単な方法を要求するでしょう。

ソフトウェアは通常、それ自体ではあまり役に立ちません。有用なソフトウェア機能は、複数のソフトウェアが互いに通信し、データを交換し、そしてユーザーにデータとインターフェースを提示するタスクに関して共同作業をするときに始まります。

それを念頭に置いてプログラムを設計する必要があります。彼らはどんなメッセージを受け入れますか？どのようなイベントが監視されていますか？どのようなメッセージが出されますか？通信を認証および認可する方法はどうしますか？

優れたプログラムのもう1つの重要な側面は、コードの明確さです。テストの数やテストカバレッジレポートの数ではありません。このコードが他の人に読まれるかどうかという簡単な質問をします。あるいは、今日のコードの作成者である私は、これから数週間でこのコードを理解できるかどうかです。

> 「コンピュータサイエンスには、キャッシュの無効化と命名という 2つの難しいことしかありません。」
フィル・カールトン

コードの読みやすさは、あなたが思う以上に重要です。残念ながら、コードを明確にするための適切な指標はありません。良いソフトウェアパターンと慣習を記憶することは助けになるかもしれませんが、しばしば十分ではありません。優れたソフトウェアエンジニアは経験と直感をもってコードの明快さに目を向けます。次の執筆についての比喩は完璧です。大量の単語のリストを知っているだけでは、簡潔で明確な内容を書くのに役立ちません。

> 「短い手紙を書く時間がなかったので、代わりに長い手紙を書いた。」
マーク・トウェイン

プログラムはうまくいかないでしょう。それらを修正するときにそれらを簡単に修正できることは、良いソフトウェアの重要な性質です。プログラムで発生したエラーは明確なメッセージを持ち、監視のためにどこかに集中的に記録されるべきです。新しいエラーが報告されたら、それを修正する必要がある人はそのエラーをデバッグできるはずです。それらはシステムにフックし、実行コンテキストに関する情報をいつでも読むことができるはずです。彼らは、システムのあらゆる部分についての期待を容易に確認できるはずです。

## 環境とテスト
ソフトウェアエンジニアがプログラムを書くとき、彼らは彼らのプログラムが多くの異なる環境で、異なるリソースのマシンで、そして異なるタイムゾーンで動作することを確認します。ソフトウェアは、さまざまな画面サイズと向きで動作する必要があります。また、限られたメモリやCPUの使用を余儀なくされていることに対処する必要があります。

たとえば、Webブラウザ用のソフトウェアを作成するときは、さまざまな主要ブラウザすべてで動作する必要があります。デスクトップソフトウェアを作成するとき、それはほとんどの場合MacとWindowsユーザーのために働く必要があります。データに依存するアプリケーションを作成するときには、そのデータを取得するための接続が遅くなったり、しばらくの間完全にオフになったりする場合に備えて、ソフトウェアが機能する必要があります。

ソフトウェアの一部を書くために、ソフトウェアエンジニアは彼らが想像できるすべての可能なシナリオを考えようとします、そして、彼らはこれらのシナリオをテストすることを計画します。これは、予期しないことが起こらないハッピーパスと呼ぶものから始まりますが、さらに重要なことは、起こりそうなすべての問題を文書化し、そのためのテストを計画することです。ソフトウェアエンジニアの中には、これらのシナリオをシミュレートするコードをテストケースと呼ぶことから始めます。その後、これらのテストケースすべてに合格する目的のコードを作成します。

ソフトウェアエンジニアは、通常あいまいで不完全なソフトウェア要件を理解しています。優秀なソフトウェアエンジニアのユニークなスキルは、ソリューションの書き方ではなく、ソリューションに何を入れるべきかを特定することです。

## コストと効率
ほとんどの場合、ソフトウェアエンジニアは問題を迅速に解決できます。あなたが経験豊富なプログラマーを雇うことがより高いコストを意味すると思うならば、もう一度考えてください。あなたが雇うプログラマーの経験が豊富であればあるほど、彼らはより早く、堅牢で正確、信頼でき、そして保守可能な解決策を提供することができます。これは長期的に見て全体的にコストが低いことを意味します。

プログラムを実行するコストも考慮する必要があります。すべてのプログラムはコンピュータリソースを使用し、そのリソースは限られています。ソフトウェアエンジニアは、コンピュータリソースを不必要に使用しない効率的なプログラムを書くでしょう。たとえば、頻繁に使用されるデータのキャッシュはここで適用される戦略の1つですが、プログラムをより高速かつ効率的にすることができるのは、数千のツールやバリエーションの1つにすぎません。

初心者のプログラマーはあなたに安い解決策を与えるかもしれませんが、その解決策を実行することはあなたが経験豊富なプログラマーがそもそも効率的な解決策を作成した場合よりはるかにあなたとあなたのクライアントに多大な費用をかけます。

## 使いやすさ
優れたプログラムは、ユーザーエクスペリエンス（UX）を念頭に置いて設計されています。ヒューマンコンピュータインタラクションは、数え切れないほどの調査研究と発見を伴う大きなトピックです。これらの調査結果が広く受け入れられるほど、ソフトウェアは優れたものになります。

この大きな領域の味を知るために、ここでいくつか例を挙げましょう。

- ユーザーが自分の電子メールアドレスなどのデータを入力すると予想される入力フォームを設計するとき、優れたプログラムは電子メールアドレスに使用される大文字と小文字を無視します。それはまたそれのまわりの余分なスペースを削除します。CAPSLOCKキーがオンになっているため、ユーザーに苦労しないでください。電子メールは小文字で一意です。プログラムが新しいEメールアドレスを受け入れている場合は、そのことを早めに検証して、おそらく間違ったアドレスを使用したという明確なメッセージをユーザーに伝えます。これには、@記号を付けないなどの明白な検証の問題が含まれますが、スペルミスのある "gmail.**ocm**"を使用するような明白でない検証の問題も含める必要があります。」
- ユーザに何かをするようにリダイレクトするとき、良いプログラムは彼らの元の位置を覚えていて、彼らが終わったときにその位置にそれらをリダイレクトするでしょう。優れたプログラムはまた、ユーザーに要求される将来のステップに関連付ける必要がある、定義済みのデータと対話をすべて記憶しています。たとえば、Expedia（訳注：ホテル・航空券等の予約サイトのこと）でゲストとしてフライトを検索していたとします。その後、アカウントを作成することにしました。以前の検索はすべて新しいアカウントに保存され、まったく別のマシンからもそれらにアクセスすることができます。
- 良いプログラムは、ユーザーのシナリオを念頭に置いて設計されています。ユーザーの立場に身を置いてください。機能を追加しないでください。先日、私はfrequent flyer number（訳注：VIP会員番号のようなもの）を含めるのを忘れてユナイテッドのフライトを予約しました。確認を得た後、私は会員番号FF＃をフライトに追加するためにユナイテッドのウェブサイトに行きました、そしてそれを理解するのに10分もかかりました。サイトに明確な道はなかったので、その機能につながる可能性のあるすべてのリンクを調査する必要がありました。この機能が利用可能なページにアクセスしたところ、大きな形で埋められていたため、初めて見ることができませんでした。旅行者情報を編集し、そのフォーム上の約20の入力要素をスクロールし、使用したいFF＃の種類を選択し、さらにフォーム全体を送信するために必要な電話番号を入力する必要があることがわかりました。

## 信頼性、セキュリティ、そして安全性
これらはおそらく、アマチュアからソフトウェア専門家を引き離す最も重要な点です。彼らは安全でセキュアな解決策を書く責任があることを知っています。

ソフトウェアは、悪い入力、悪い状態、および悪いインタラクションに対して回復力がなければなりません。これは達成するのが非常に難しいです、そしてそれは我々がソフトウェアのミスで消えていく人々についての物語を聞く主な理由です。

ユーザーは悪いまたは間違った入力でソフトウェアを使用しようとしています。意図的にソフトウェアを壊し、そのソフトウェアに代表されるリソースに侵入しようとする人もいます。最近のEquifax（訳注：米国の信用情報会社）の大惨事の原因とされているとされる人物は、仕事をしていないと非難されています。その仕事とは、一般に公開されているすべてのソフトウェアで悪意のある入力に対する回復力を高めるためのものです。

セキュリティの話は、悪意のある悪意のある入力だけでなく、通常の入力についても同様です。ユーザーが自分のパスワードを忘れた場合、何回試行を許可できますか？あなたはそれらを後で締め出しますか？他の誰かがそれらをロックアウトしようとしている場合はどうなりますか？ユーザーが暗号化されていない接続で自分のパスワードを送信することを許可しますか？アカウントへのログイン試行が異常な場所から行われた場合はどうなりますか？ログインが自動化されていると思われる場合はどうしますか？

クロスサイトスクリプティングや偽造要求、中間者攻撃、単純なソーシャルフィッシングからユーザを保護するために何をしますか？サーバーにDDoS攻撃を受けた場合、バックアップ戦略はありますか？これらの質問は、計画されるべき多くの懸念のうちのいくつかを挙げるためだけのものです。

安全なプログラムは、機密情報を平文としてではなく、分割が非常に困難なアルゴリズムによる一方向暗号化データとして格納します。これは、プログラムとデータが危険にさらされた場合のバックアップ戦略です。ハッカーは暗号化されたデータを見つけるでしょうが、それはほとんど役に立ちません。

ソフトウェアは悪い状態になり、修正する必要があります。予期しない問題がプログラムのせいで発生します。あなたがそれに気付いておらず、あなたがそのことを計画していないのなら、あなたはソフトウェア専門家ではなく、単なる危険なプログラムの作者です。

ソフトウェアの欠陥は見えません。既知の欠陥を予測して防止するための私達の知的能力は限られています。ソフトウェアエンジニアが、正しい安全なソフトウェアを作成するのに役立つ優れたツールの価値を理解しているのはこのためです。

## ツールを受け入れる
より良いツールが必要なのは間違いありません。ツールは大きな違いを生み、しばしば過小評価されています。

FTPでファイルをデプロイする必要があることを想像してみてください。Chrome DevToolsを使わずにネットワークとパフォーマンスの問題をデバッグすることを想像してみてください。ESLintとPrettierなしでJavaScriptを書くのが今日どれほど非効率的であるか想像してみてください。

> あなたがJavaScript開発者であり、そして何らかの理由であなたがコードエディタのためにただ一つのプラグインを選ぶことを余儀なくされるならば、あなたはESLintを選ぶべきです。

あなたがコードを書く間に短いフィードバックを回し続けるツールは、追加することを歓迎するべきです。私たちが創り出すものに即座の視覚的表現を発明することについてのBret Victorの議論は私にとっては目を覚ますものでした。ツールを採用し改善することは、私たちをその明るい未来に導くための1つの方法です。今まで見たことがなければ、今すぐBretの話を見てください。

私が素晴らしい新しいツールを見つけたとき、私の唯一の後悔はそのツールを以前に使っていなかったことです。より良いツールは、あなたがより良いプログラマーになるのを助けます。それらを見つけ、使用し、評価し、そして可能であればそれらを改善してください。

言語の選択は重要です。型安全であることも重要です。JavaScriptに起こった最も良いことはTypeScript（そしてFlow）です。コードの静的解析はあなたが思うよりも大きなことです。あなたがそれをしていないのであれば、あなたは基本的に将来の未知のものに対して脆くしています。静的型付けシステムなしでコーディングしないでください。選択した言語に静的な型付けがない場合は、言語を変更するか、またはそのためのトランスパイラを見つけてください。今日のトランスパイラは、コード内のコメントを読むだけで動作するのに十分スマートです。ネイティブにサポートされていない言語の型チェックが将来行われると思います。

## ソフトウェアエンジニアリングの進化
2ヶ月、6ヶ月、1年でソフトウェアエンジニアリングを学ぶことは誰にもできません。ソフトウェアエンジニアになるためにブートキャンプで学ばないでください。私は過去20年以上にわたって学んできましたが、今日もまだ学んでいます。私は、約10年の学習と数千人のユーザーによって使用されるアプリケーションの設計、構築、および保守の後に初めて、自分自身を経験豊富なプログラマーと呼ぶに足る自信を持つようになりました。

ソフトウェアエンジニアリングはすべての人のためのものではありませんが、誰もが自分のコンピュータに関する問題を解決することを学ぶべきです。あなたが簡単なプログラムを書くことを学べるならそうするべきです。あなたが一般的なソフトウェアサービスを使うことを学ぶことができるならばそうするべきです。あなたがオープンソースソフトウェアの使い方を学ぶことができるなら、あなたは多くの力を身につけられるでしょう。

問題は進化し、ソフトウェアエンジニアリングも進化します。この職業の将来は、一般的なコンピュータユーザーが5年間勉強しなくても自分のコンピュータを使用できるようにすることです。使いやすいツールを使用して、ユーザーが自分自身で簡単な問題を解決できるようにします。その後、ソフトウェアエンジニアは、より良いツールを作成し、より大きな既知の問題を解決し、未知の問題を防ぐために最善を尽くします。

読んでくれてありがとう。