プログラミング
ソフトウェアエンジニアリングとは複雑性の管理である
Software engineering is about managing complexity (hack8s.com)
要約
AIの普及により、ソフトウェアエンジニアリングとコーディングを混同する誤解が顕著になっています。コーディングはアイデアをコンピュータの命令に変換することですが、ソフトウェアエンジニアリングは、どの命令が存在すべきか、それらがどう相互作用するか、どのような制約が重要か、そしてシステムがどのように進化できるかを決定するプロセスです。AIはコーディングを加速しますが、エンジニアは文脈に基づいた複雑なトレードオフの決定と管理に責任を持ちます。
全文翻訳
ソフトウェアエンジニアリングとは複雑性の管理である
AIがますます可視化しているソフトウェアエンジニアリングに関する誤解があります。私たちはコーディングとソフトウェア構築を混同しがちです。特定の側面では重複がありますが、それらは同じものではありません。
コーディングとは、アイデアをコンピュータが実行できる命令に変換することです。ソフトウェア構築とは、そもそもどの命令が存在すべきか、それらがどのように相互作用すべきか、どの制約が重要か、決定のコストはいくらか、どのトレードオフが許容できると見なせるか、そして結果として生じるシステムが自身の制約と限界の下で崩壊することなくどのように進化できるかを決定することです。
基本的な前提から始めましょう。AIは、最初の問題(コーディング)に驚くほど優れているため、不可欠なツールです。第二の問題(ソフトウェア構築)こそが、ソフトウェアエンジニアリングが実際に始まる場所です。
難しい部分はコードを書くことではなかった
比較的普通のエンジニアリング要件を考えてみましょう。受信イベントを処理してデータを更新する必要があります。そして、技術的な議論中に生じる最初の質問のいくつかを次に示します。
同期的に処理すべきか?
キューに入れるべきか?
ちょうど1回の処理が必要か、それとも少なくとも1回の処理で十分か?
システムは結果整合性を許容できるか?
処理が途中で失敗した場合どうなるか?
再試行すべきか?
何回?
コンシューマーが3時間利用できない場合どうなるか?
イベントの順序を保持する必要があるか?
今日、どのくらいのトラフィックを予想するか?
2年後はどうなるか?
イベントが2回処理された場合の結果はどうなるか?
…などなど。
これらの質問は、構文とはほとんど関係がありません。プログラミング言語の選択は、チームの流暢さ、チームのパフォーマンス、システムのパフォーマンス、安全性、保守性、ツール、および運用特性に影響するため重要ですが、根本的な質問には答えません。
難しいのは、適切なトレードオフを表すアーキテクチャを選択することです。そして、普遍的に正しい答えはめったにありません。
1つの問題にはN個の完全に異なる正しい解決策がある
これは、ソフトウェアがビジネス内に存在する場合に特に明白です。2つの企業がエンジニアリングチームに、同じように聞こえる機能を構築するように依頼したと想像してください。彼らの要件は、紙の上では同じように見えるかもしれません。しかし:
企業Aは500人のユーザーを抱え、企業Bは2000万人のユーザーを抱えています。
企業Aはシステムを保守する3人のエンジニアを抱えているかもしれませんが、企業Bは200人のエンジニアを抱えているかもしれません。
間違いが深刻な財務的結果をもたらすため、一方には強い整合性が必要かもしれません。もう一方は、可用性とスループットと引き換えに結果整合性を喜んで受け入れるかもしれません。
一方の企業は3週間で出荷する必要があるかもしれません。もう一方は、システムが15年間稼働し続けることを期待するかもしれません。
一方の企業はすでにKafka、Kubernetes、PostgreSQL、オブザーバビリティインフラストラクチャ、および分散システムに経験のあるエンジニアを抱えているかもしれません。もう一方は、4人の開発者によって保守されている単一のアプリケーションサーバーとPostgreSQLデータベースを持っているかもしれません。
一方の企業にとって技術的に印象的なソリューションは、もう一方の企業にとっては無責任なソリューションになる可能性があります。
だからこそ、アーキテクチャは「Xを実装する最良の方法は何か?」と尋ねることに還元できません。正しい質問は通常、次のようなものに近くなります。「これらの制約、このチーム、このビジネス、このインフラストラクチャ、この予算、これらのリスク、および製品の予想される進化を考慮すると、今日、Xを実装する最も適切な方法は何か?」それは根本的に異なる質問です。
AIはソリューションを生成します。エンジニアはトレードオフを所有します。
この区別は、AIがソフトウェア組織にどのように採用されているかによって、ますます重要になっています。
AIはソフトウェア開発に驚くほど役立ちます。私たちはそれをアクセラレータとして使用します。ボイラープレートの生成、APIの探索、実装の提案、潜在的なバグの発見、見慣れないコードの説明、テストの生成、アプローチの比較、または単にアイデアを動作するコードに変えるために必要な機械的な作業量を削減することです。
しかし、この能力を、エンジニアリングの判断そのものを委任するという、はるかに広範なものに拡張する危険な傾向があります。
AIモデルに要件を与えてシステムを設計させ、「間違いなし」と言うことができます。それは設計します。
データベースを選択するように頼むことができます。それは選択します。
キュー、マイクロサービス、キャッシング、CQRS、イベントソーシング、Kubernetes、Redis、またはその他の抽象化を導入すべきかどうか尋ねることができます。それはあなたに答えを与えます。
答えが存在するからといって、根本的なエンジニアリングの問題が解決されたわけではありません。
本当の問題は、正しい決定は文脈に依存することです。多くの場合、分析、理解、評価に数時間、数日、あるいは数週間かかる膨大な量の文脈であり、しばしば同じ組織内の複数の部門が関与し、将来の変更が必要になったときに課題となる、形式化が難しいグレーゾーンを残すことがあります。
これが現実世界です。その文脈の一部はドキュメントに存在します。その多くは存在しません。それは顧客との会話に存在します。製品の歴史に存在します。エンジニアリングチームのスキルに存在します。3年前の運用インシデントに存在します。予算の制約に存在します。締め切りに存在します。契約上の義務に存在します。誰も触れたくないレガシーシステムの奇妙な動作に存在します。6ヶ月後に顧客が特定の機能をリクエストする可能性が高いことを知っていることに存在します。
そして時には、理論的にエレガントなアーキテクチャが、それを保守するチームにとって運用上の悪夢になることを認識するという、単なる経験に存在します。
あなたはこれらすべてを、AIプロンプトに別の段落を追加することで捉えられる小さな詳細として扱うことはできません。
トレードオフのないアーキテクチャはない
エンジニアリングは、基本的に、どのような問題を持つことをいとわないかを決定する規律です。
FAANG規模で働いていなくても、あなたのプロジェクトは十分なデータを処理する必要があるかもしれません。そのため、高価なハードウェアを体系的な非効率性に費やすことなく、適切なパフォーマンスを維持するために正しいエンジニアリング上の決定を下すことが不可欠になります。
「単純な」選択でさえ、考慮すべき要因が伴います。
データベースを積極的に正規化すると、整合性は向上するかもしれませんが、特定のクエリがより複雑になる可能性があります。正規化を解除すると、読み取りパフォーマンスは向上するかもしれませんが、同期の複雑さが増します。
キャッシングを追加すると、レイテンシは削減されますが、無効化の問題が発生します。
非同期処理を導入すると、コンポーネントは分離されますが、新しい障害モードが作成されます。
モノリスをマイクロサービスに分割すると、独立したデプロイメント境界が得られますが、分散システム特有の複雑さが導入されます。
積極的に最適化すると、パフォーマンスは向上するかもしれませんが、可読性が犠牲になる可能性があります。
積極的に抽象化すると、重複を減らすことができますが、システムを理解するのが難しくなります。
抽象化を回避すると、やがて反対の問題が発生します。
これらのいずれも独立して評価することはできません。すべての最適化は、どこかに複雑さを費やします。
したがって、エンジニアの仕事は、単にシステムを機能させることではありません。複雑さがどこに属するかを決定することです。
アルゴリズム的思考は、AIの時代にますます重要になる
だからこそ、AIの時代にアルゴリズム的思考がますます重要になると私は考えています。そして、アルゴリズム的思考とは、単に教科書のアルゴリズムを知っているとか、赤黒木を記憶から実装できることを意味するのではありません。
アルゴリズム的思考とは、従うべき一連の基本的なルールを定義し、日常的に適用することを意味します。
私は10項目の原則をまとめました。
問題を分解する。
不変条件を特定する。
データフローを理解する。
適切なデータ構造を選択する。
時間と空間の複雑性について推論する。
競合を特定する。
障害モードを理解する。
どの操作が高コストで、どの操作が実際に重要かを認識する。
本質的な複雑さと偶発的な複雑さを分離する。
前提が真でなくなったときに何が起こるべきかを理解する。
生産性が向上しているこの時代に、これは奇妙に聞こえるかもしれません。AIは、エンジニアが1つ書くのにかかっていた時間で10個の実装を生成できます。課題はt