私は最近 Three Big Lies ブログの投稿を読みましたが、ここに引用されている2番目の嘘を正当化するのに苦労しています。
(LIE#2)コードは、世界のモデルの周囲で設計する必要があります
架空の世界のある種のモデルまたはマップであるコードに価値はありません。これが一部のプログラマにとってなぜ説得力があるのかはわかりませんが、非常に人気があります。ゲームにロケットがある場合、「ロケット」クラス(コードはC++であると想定)があり、1つのロケットのデータを含み、ロケットのようなものを実行します。実際に行われているデータ変換、またはデータのレイアウトはまったく考慮されません。または、そのことについては、1つのものがある場合、おそらく1つ以上あるという基本的な理解がなければ、.
この種のデザインには多くのパフォーマンス上のペナルティがありますが、最も重要なのは、スケーリングしないことです。全然。 100ロケットは1ロケットの100倍の費用がかかります。そしてそれはそれ以上の費用がかかる可能性が非常に高いです!プログラマーではない人にとっても、それは意味をなさないはずです。規模の経済。何かが増えれば、安くなるはずです。そして、それを行う方法は、データを適切に設計し、同様の変換によって物事をグループ化することです。
これは特にこの嘘に関する私の問題です。
架空の世界のモデル化が(少なくとも私自身は)コードの視覚化と整理に役立つので、架空の世界のモデル/マップであるコードには価値があります。
「ロケット」クラスを持つことは、私にとって、クラスにとって完全に有効な選択です。おそらく、「ロケット」は、AGM-114ヘルファイアなどのタイプのロケットに分解できます。このタイプには、ペイロード強度、最大速度、最大回転半径、ターゲットタイプなどが含まれますが、発射されるすべてのロケットには位置が必要です。と速度。
もちろん、100個のロケットがあると、1個以上のロケットが必要になります。画面に100ロケットがある場合、それらの位置を更新するには100の異なる計算が必要です。 2番目の段落は、ロケットが100個ある場合、状態を更新するための計算にかかるコストは100未満であると主張しているように聞こえますか?
ここでの私の問題は、作成者が「欠陥のある」プログラミングモデルを提示しているが、それを「修正」する方法を提示していないことです。おそらく、私はロケットクラスの類推でつまずいているかもしれませんが、この嘘の背後にある理由を本当に理解したいと思います。代替は何ですか?
まず、いくつかのコンテキストを見てみましょう。これはゲームデザイナーがブログに書いているもので、そのテーマはCell BE CPUからのパフォーマンスの最後の低下を引き出していることです。つまり、コンソールゲームのプログラミング、具体的にはPlayStation 3のコンソールゲームのプログラミングです。
現在、ゲームプログラマーは好奇心旺盛な一群であり、コンソールゲームプログラマーはなおさらそうです。CellBEはかなり奇妙なCPUです。 (ソニーがPlayStation 4の従来のデザインを採用したのには理由があります!)
したがって、このコンテキスト内でこれらのステートメントを確認する必要があります。
そのブログ投稿にもいくつかの簡略化があります。特に、この嘘#2は不十分です。
現実世界から抽象化するすべてはある意味でモデルであると私は主張します。そして、ソフトウェアは現実のものではなく仮想のものであるため、それは常に抽象概念であり、したがって常にモデルです。だが!モデルは、現実の世界に1対1でマッピングする必要はありません。つまり、そもそもそれがモデルになるのです。
したがって、ある意味で、著者は明らかに間違っています。ソフトウェアはモデルです。限目。他の意味では、彼は正しいです。そのモデルは実際には実際の世界にまったく似ている必要はありません。
私が長年にわたって他のいくつかの回答で既に示した例、有名なOO 101銀行口座の例の紹介。ここに、ほとんどすべての銀行口座がどのように見えるかを示します= OOこれまでのクラス:
class Account {
var balance: Decimal
def transfer(amount: Decimal, target: Account) = {
balance -= amount
target.balance += amount
}
}
つまり、balance
はdataであり、transfer
はoperationです。
だが!銀行口座は、これまでほとんどすべての銀行ソフトウェアで次のようになっています。
class TransactionSlip {
val transfer(amount: Decimal, from: Account, to: Account)
}
class Account {
def balance =
TransactionLog.filter(t => t.to == this).map(_.amount).sum -
TransactionLog.filter(t => t.from == this).map(_.amount).sum
}
したがって、ここでtransfer
はdataであり、balance
はoperationです(左折り返しトランザクションログ)。 (また、TransactionSlip
は不変であり、balance
は純粋な関数であり、TransactionLog
は追加専用の「ほぼ」不変のデータ構造である可能性があることにも気づくでしょう...あなた方の多くは、最初の実装で目立った同時実行のバグを発見しましたが、今やそれは魔法のように消え去ります。
これらの両方はモデルであることに注意してください。これらはどちらも有効です。これらは両方とも正しいです。これらはどちらも同じモデルです。それでも、それらは互いに正確にdualです。1つのモデルのデータであるすべてのものは、他のモデルの操作であり、1つのモデルの操作であるすべてのものは、他のモデル。
したがって、問題は、コードで「現実世界」をモデル化するかどうかではなく、どのようにモデル化するかではありません。
結局のところ、2番目のモデルは、実際にはバンキングが実際に機能する方法でもあります。上記でほのめかしたように、この2番目のモデルはほとんど不変で純粋であり、同時実行のバグの影響を受けません。これは、TransactionSlip
sがあったactual馬と馬車で運ばれた紙片。
ただし、この2番目のモデルが実際の銀行業務の仕組みと実際の銀行業務ソフトウェアの仕組みの両方に実際に一致するという事実は、それを自動的に何らかの「正しい」ものにするわけではありません。 first( "wrong")モデルは実際には、銀行業customersが銀行を見る方法をかなり正確に近似しているためです。 それらに対して、transfer
は操作です(フォームに入力する必要があります)、balance
は、アカウントステートメントの下部にあるdataの一部です。
したがって、高性能PS3シューティングゲームのコアゲームエンジンコードでは、Rocket
タイプはありませんが、それでもコンソールゲームの物理エンジンプログラミングの専門家ではない人にとってモデルが奇妙に見えても、進行中の世界のモデリング。
私は彼が提案するすべての「嘘」に同意しません。
TL; DRこの記事の著者は、彼らの記事をより面白くするために物議を醸そうとしていましたが、いわゆる「嘘」はソフトウェア開発者に受け入れられています正当な理由で。
嘘#1-Big Oはスケーリングの目的で重要です。小さなアプリケーションがより長い時間を必要とする場合、誰も気にしません。唯一の時定数が問題であり、入力サイズを2倍にしても、実行時間が10倍にならないことを気にします。
嘘#2-現実の世界の後でプログラムをモデリングすることにより、プログラマーは3年後にコードを見て、何が行われているかを簡単に理解できます。コードは保守可能である必要があります。そうしないと、プログラムが何をしようとしているのかを理解するためだけに何時間も費やす必要があります。別の答えは、LaunchPad
やMassiveDeviceMover
のようなより一般的なクラスを使用できることを示唆しています。これらは必ずしも悪いクラスではありませんが、Rocket
クラスが必要です。 MassiveDeviceMover
が何をするのか、または何が動くのか、誰がどのように知っているはずですか?山、宇宙船、または惑星を動かしていますか?これは基本的に、MassiveDeviceMover
のようなクラスを追加すると、プログラムの効率が低下することを意味します(ただし、より読みやすく理解しやすくなります)。
さらに、開発者の時間のコストは、ずっと前にハードウェアのコストを超え始めました。あなたの思考の最前線で最適化を用いて設計しようとすることから始めることは恐ろしい考えです。簡単で理解しやすい方法でプログラムを作成し、プログラムの実行に多くの時間を費やしている部分を見つけたら、プログラムを微調整します。忘れないでください: 実行時間の80%がプログラムの20%によって使用されています。
嘘#3-コードは非常に重要です。よく書かれた(そしてモジュール化された)コードは再利用を可能にします(無数の人の時間を節約します)。また、不良データをふるいにかけて認識し、処理できるようにすることもできます。データはすばらしいですが、コードがなければ、分析して有用な情報を取得することは不可能です。
Eコマースシステムでは、クラスレベルで「ロケット」を扱うのではなく、「製品」を扱います。したがって、それは達成しようとしていることと、希望する抽象化のレベルに依存します。
ゲームでは、ロケットは多くのタイプの「動くオブジェクト」の1つにすぎないと主張できます。他のすべての動くオブジェクトと同じ物理がそれらに適用されます。したがって、少なくとも「ロケット」は、より一般的な「移動オブジェクト」基本クラスから継承します。
いずれにせよ、あなたが引用した一節の著者は彼の主張を少し誇張しているようです。ロケットには、「燃料残量」や「推力」などの固有の特性があり、100ロケットに対してこれを表すのに100クラスは必要ありません。1つだけ必要です。ほとんどのまともなプログラミング言語ではオブジェクトの作成はかなり低コストであるため、ロケットのようなものを追跡する必要がある場合、高すぎる可能性があるためロケットオブジェクトを作成してはならないという考えはあまり意味がありません。
現実の世界の問題は、物理学のせいです。現実の世界では、個々の原子や、ロケットの可能性のあるものの巨大な溶融スラグよりも移動しやすいため、物を物理的なオブジェクトに分離します。
同様に、現実の世界は、私たちが依存している多くの便利な機能を提供しています。ペンギンを例外にするのは本当に簡単です-「...以外のすべての鳥は飛ぶ」そして、ロケットとラベルを付けるのは本当に簡単です。つまり、ペンギンをロケットと呼んで、それを点火すると、それは機能しません。
したがって、現実の世界で物事を概念的に分離する方法機能するこれらの制約の下で。コードで物事を行っている場合、明確に異なるthose制約の下でうまく機能するように物事を分離する必要があります。
代替は何ですか?
ネットワークについて考えてください。ポート、ワイヤー、ルーターはコードでモデル化していません。代わりに、ネットワーク通信を接続とプロトコルに抽象化します。これは、現実世界での実装に関係なく、有用な抽象化であるためです。そして、それだけで問題となる便利な制約を課します(例:接続が開かれるまで通信できません)コード内。
だから、はい、現実の世界が機能した後にコードをモデリングすることもありますが、それは偶然です。人々がOOPについて話すとき、オブジェクトは現実のオブジェクトではありません。学校とチュートリアルがそうでないと言うことは、何十年もの長い悲劇です。
別の方法は、プログラムが気にするものをモデル化することです。プログラムがロケットを扱っている場合でも、Rocket
というエンティティは必要ありません。たとえば、LaunchPad
エンティティとLaunchSchedule
エンティティとMassiveDeviceMover
エンティティがあるとします。これらすべてがロケットの発射を支援するものであるという事実は、ロケットを自分で処理しているという意味ではありません。
ここでの私の問題は、作成者が「欠陥のある」プログラミングモデルを提示しているが、それを「修正」する方法を提示していないことです。おそらく、私はロケットクラスの類推でつまずいているかもしれませんが、この嘘の背後にある理由を本当に理解したいと思います。代替は何ですか?
これが本当の問題ですが、私は開発者として私の見解を示します。おそらくそれが役立つでしょう。
第一に、私はそれを嘘とは呼びません。よくある誤解です。それを嘘と呼ぶのは単なる誇大宣伝です。
Oneある意味で彼は正しい。これに多くの時間を費やすつもりはないので、問題の一部ではありません。しかし、本質的には彼は正しいです。これを「ラボで機能するものは実際には機能しない可能性がある」と言い換えることができます。多くの場合、開発者は「ラボ」では機能するが、実際のアプリケーションでは機能しない設計を採用しています。
Three少し石鹸のように聞こえますが、基本的に彼は正しいです。しかし、これは「ニーズに合わせてコードを記述し、ニーズをコードに適合させようとしないでください」と書き直すことができます。
2繰り返しますが、ここで彼は正しいです。私は、開発者が単純な「乗り物」クラスが機能する「ロケット」クラス、またはさらに単純な「可動」クラスを開発するのに数週間以上費やすのを見てきました。ロケットが画面の左側から右側に移動して音を出すだけの場合は、車、電車、ボート、ハエと同じクラスを使用できます。 100のコストは1 * 100未満である必要があり、引数は開発に費やされた時間のようであり、計算コストにはそれほど多くありません。再利用できる一般的なクラスが「安価」であることにこだわっていますが、再利用できない特定のクラスは数多くあります。これはおそらく「一般的なクラスは特定のクラスよりも優れています。より具体的なクラスの唯一の理由は、物事がどのように機能するかの実世界モデルを満たすことである場合」です。
本質的には、流行語を減らして記事全体を書き直すことができ、せいぜい1段落だけになるでしょう。とはいえ、それはプログラミングの狭い領域に焦点を当てたブログ投稿です。私はいくつかの組み込みプログラミングを行いましたが、これらのステートメントの背後にある一般的な考えに同意することができますが、GDCでのプレゼンテーションに適したものにするために、それらの周りにはかなりの「ふわふわ」があります。
最後に、この記事は2008年に書かれたものです(私が知る限り最高です)。物事は急速に変化します。この発言は今日も当てはまりますが、組み込みシステムは今日よりはるかに一般的で、開発パターンは変化しています。多分この記事/話への応答でさえ。