Lie 2:コードは世界のモデルを中心に設計すべきですか?[閉まっている]


23

最近、Three Big Liesのブログ投稿を読みましたが、2番目の嘘を正当化するのに苦労しています。

(嘘#2)コードは世界のモデルの周りに設計されるべきである

コードが架空の世界の何らかのモデルまたはマップであることには価値がありません。一部のプログラマにとってこれがなぜこれほど魅力的であるかはわかりませんが、非常に人気があります。ゲームにロケットがある場合は、「ロケット」クラス(コードはC ++であると仮定)があり、これには1つのロケットのデータのみが含まれ、ロケットのような処理を行うことをご安心ください。どのデータ変換が実際に行われているか、またはデータのレイアウトはまったく考慮されません。または、1つのことはどこにあるのかという基本的な理解がなければ、おそらく複数あります。

この種の設計には多くのパフォーマンス上のペナルティがありますが、最も重要なことは、スケーリングしないことです。まったく。ロケット100個のコストは、ロケット1個の100倍です。そして、それ以上の費用がかかる可能性が非常に高いです!プログラマーでなくても、それは意味をなさないはずです。規模の経済。何かがもっとあるなら、それはもっと高くなくて、より安くなるはずです。そして、それを行う方法は、データを適切に設計し、同様の変換によって物事をグループ化することです。

特にこの嘘に関する私の問題はここにあります。

  1. 想像上の世界をモデル化することは、コードを視覚化して整理するのに役立つので、仮想的な世界のモデル/マップであるコードには価値があります。

  2. 「ロケット」クラスを持つことは、私にとって、クラスにとって完全に有効な選択です。「ロケット」は、AGM-114ヘルファイアなどのタイプのロケットに分類できます。これには、ペイロードの強度、最大速度、最大旋回半径、ターゲットタイプなどが含まれますが、発射されるすべてのロケットには位置が必要ですそして速度。

  3. もちろん、100個のロケットを所有するには1ロケット以上かかります。画面上に100個のロケットがある場合、それらの位置を更新するには100個の異なる計算が必要です。2番目の段落は、100個のロケットがある場合、状態を更新するのに100未満の計算コストが必要だと主張しているように聞こえますか?

ここでの私の問題は、著者が「欠陥のある」プログラミングモデルを提示しているが、それを「修正」する方法を提示していないことです。おそらく、ロケットクラスの類推につまずいているかもしれませんが、この嘘の背後にある理由を本当に理解したいと思います。代替手段は何ですか?


9
@gnat:この質問はソフトウェア設計の領域内にあるので、私はそれにいくらかのゆとりを与えたいと思っています。
ロバートハーベイ

12
そのブログ投稿はかなり不十分に書かれており、その主張を十分に擁護しサポートしていません。あまり考えません。
-whatsisname

21
その引用を書いた人は誰でも、オブジェクト指向の概念やソフトウェアでそれらがどのように実装されているかについてほとんど理解していないバカです。まず、私たちは架空の世界にマッピングするのではなく、現実の世界にマッピングします。また、100個のロケットがある場合、追加のロケットの状態のみが追加のリソースを使用し、モデルや動作は使用しません。彼はそれについて異なる考えを持っているようで、存在しない問題を修正することを提案します。最適化としての「類似したもののグループ化」は時々意味をなすかもしれませんが、クラスを使用するかどうかに完全に依存しません。学びたい場合は、このチャラタンを避けてください。
マーティンマート

3
著者が「3つの大きな嘘」について説明する合計5段落以上の文章を書くことを気にしなかったことを考えると、おそらく彼がしたよりも記事について考えるのにより多くの時間を費やしたでしょう。彼が努力をしなくてもいいなら、あなたもそうすべきではありません。
カレブ

9
彼が得ているのは、位置のリスト、速度のリストなどとは対照的に、100(おそらく仮想メソッドでも動的に割り当てられる)「ロケットオブジェクト」が必要かと思います(すべての位置と速度のリストは、オブジェクトのリストを単純なループで記述するのではなく、ベクトルの指示を使用して各ティック更新の位置に速度を追加できることを意味します)
ランダム832

回答:


63

まず、いくつかのコンテキストを見てみましょう。これは、Cell BE CPUのパフォーマンスの最後の低下をテーマにしたブログを書いているゲームデザイナーです。つまり、コンソールゲームプログラミング、具体的にはPlayStation 3用のコンソールゲームプログラミングについてです。

現在、ゲームプログラマは好奇心b盛で、コンソールゲームプログラマはさらに好奇心が強く、Cell BEはかなり奇妙なCPUです。(SonyがPlayStation 4の従来のデザインを採用した理由があります!)

したがって、このコンテキスト内でこれらのステートメントを調べる必要があります。

また、そのブログ投稿にはいくつかの簡略化があります。特に、この嘘#2はあまり提示されていません。

私は、現実世界から抽象化されたものはすべて、ある意味でモデルであると主張します。また、ソフトウェアは現実ではなく仮想であるため、常に抽象化であり、したがって常にモデルです。しかし!モデルは、実世界へのクリーンな1:1マッピングを持つ必要はありません。それは、結局のところ、そもそもそれをモデルにしているのです。

だから、ある意味で、著者は明らかに間違っています。ソフトウェアモデルです。期間。ある他の意味で、彼は正しい。そのモデルは実際には現実の世界にまったく似ている必要はない。

私は、長年にわたって他のいくつかの回答ですでに示した例を示します。OO101銀行口座の(有名な)紹介です。ほぼすべてのオブジェクト指向クラスで銀行口座は次のようになります。

class Account {
  var balance: Decimal
  def transfer(amount: Decimal, target: Account) = {
    balance -= amount
    target.balance += amount
  }
}

だから:balancedataでありtransfer操作です。

しかし!これは、ほとんどすべての銀行ソフトウェアで銀行口座がどのように見えるかを示しています。

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データbalanceあり、操作です(トランザクションログの左折)。(またTransactionSlip、不変でbalanceあり、純粋な関数でTransactionLogあり、追加のみの「ほぼ」不変のデータ構造であることに気付くでしょう...最初の実装で目立った同時実行バグを発見したことは間違いないでしょう。 )

これら両方ともモデルあることに注意してください。これらは両方とも同等に有効です。これらは両方とも正しいです。これらは両方とも同じことをモデル化します。しかし、それらは互いにまったく二重です。1つのモデルのデータであるすべてが他のモデルの操作であり、1つのモデルの操作であるすべてが他のモデルのデータです。

したがって、問題は、コードで「実世界」をモデル化するかどうかではなく、どのようにモデル化するです。

結局のところ、2番目のモデルは実際には、銀行が実際の世界でどのように機能するかでもあります。私は上記で示唆したように、この第2のモデルでは、時間ではないが長すぎる前に、どこがあったことを考慮すれば、実際には非常に重要である、並行処理のバグのほとんどは不変と純粋、そして免疫があるTransactionSlipのだった実際の周りに送られた紙の伝票馬と馬車で。

ただし、この2番目のモデルが実際のバンキングの仕組みと実際のバンキングソフトウェアの仕組みの両方に実際に一致するという事実は、それを自動的に何らかの「正しい」ものにするわけではありません。実際、最初の(「間違った」)モデルは、銀行の顧客が銀行をどのように見ているかにかなり近いためです。それらをtransferある操作(彼らはフォームに記入しなければならない)、とbalanceの一部であるデータ自分のアカウント文の一番下にあります。

そのため、高性能PS3シューティングゲームのコアゲームエンジンコードにはRocketタイプはありませんが、モデルが奇妙に見えても、進行中の世界の一部のモデリングが存在することは事実ですコンソールゲームの物理エンジンプログラミングの分野の専門家ではない人に。


1
これは、良いコードが現実の世界をモデル化することを意味するのではなく、実際、それは悪い世界のモデル、ひいては悪いコードを引き起こす現実の世界の誤解に過ぎないのでしょうか?
yitzih

14
私はむしろ、「現実世界はあなたが思っているものではない」または「「現実世界」とは文脈に依存する」と言いたいです。(繰り返しになりますが、銀行口座の所有者にとって、声明の一番下のデータは非常に現実的ですが、銀行の従業員にとっては短命です。)ブログ投稿の声明のほとんどは、「モデリング「実世界」とは、「写真を撮って、そこにあるすべてのものをクラスにする」という意味ではありません。
ヨルグWミットタグ

オンラインバンキングアプリケーションのフロントエンドは、おそらくbalanceデータとトランザクションをより多くのデータとして扱い、オペレーションとして転送します。これは、バックエンドが異なる扱いをする場合でも、ユーザーが見るものだからです。
user253751

@yitzih:すべてのモデルは抽象化と単純化であるため、すべてのモデルが間違っていると非難することができますが、それは建設的ではありません。すべてのモデルは目的を達成する必要があり、そのために十分なものでなければならず、不要なものにリソースを浪費しないようにします。政府のソフトウェアの場合、人間は選挙に参加したり、税金を支払ったり、別の人間と結婚したりする可能性があります。CRMソフトウェアの場合、人間は注文に関連付けられて配送先住所を持っている人です(s)彼が食べる方法をモデル化)…
ホルガー

2
人間が銀行取引について何かを知っていれば、2番目の方法が簡単になります。また、銀行取引を機能させるために彼らが知っている銀行技術が発明されたため、機能する銀行ソフトウェアを作成できます。2番目のモデルが「現実の世界に似ている」からではなく、より良い銀行を説明しているからです。最初のモデルは、実世界の機能不全の銀行を正確に表現したものかもしれません!推測:優れたバンキングソフトウェアが必要な場合、プログラマは要件ドキュメントだけからでも、うまくバンキングを行う方法を学ぶ必要があります。
スティーブジェソップ

19

彼が提案するすべての「嘘」には同意しません。

TL; DRこの記事の著者は、彼らの記事をより面白くするために物議を醸そうとしていましたが、いわゆる「嘘」は正当な理由でソフトウェア開発者に受け入れられています。

うそ#1-ビッグOはスケーリングの目的で重要です。小さなアプリケーションが唯一の時定数の問題であるより長い時間がかかるかどうかは誰も気にしません。入力サイズを2倍にしても実行時間が10倍になることはありません。

嘘#2-現実の世界に合わせてプログラムをモデル化することで、プログラマは3年後にコードを見て、それが何をしているのかを簡単に理解できます。コードは保守可能である必要があります。そうでないと、プログラムが何をしようとしているかを理解しようとするだけで何時間も費やす必要があります。別の答えは、LaunchPadやなどのより一般的なクラスを持つことができることを示唆していますMassiveDeviceMover。これらは必ずしも悪いクラスではありませんが、Rocketクラスが必要です。誰かが何をするのMassiveDeviceMoverか、それが何を動かすのかをどうやって知るのでしょうか?それは動いている山、宇宙船、または惑星ですか?これは基本的に、クラスのようなものを追加MassiveDeviceMoverすると、プログラムの効率が低下することを意味します(ただし、読みやすく、理解しやすくなります)。

さらに、開発者の時間のコストはずっと前にハードウェアのコストを超え始めました。最適化を念頭に置いて設計しようとすることから始めるのは恐ろしい考えです。簡単で理解しやすい方法でプログラムを作成し、プログラムのどの部分が実行に多くの時間を費やしているかを見つけた後、プログラムを微調整します。忘れないでください:実行時間の80%がプログラムの20%によって使用されています。

嘘#3-コードは非常に重要です。よく書かれた(そしてモジュール化された)コードにより、再利用が可能になります(無数の工数を節約できます)。また、不正なデータを選別して認識できるため、処理できます。データは素晴らしいですが、コードがなければ、分析して有用な情報を取得することはできません。


5
私は#3にもっと同情的だと思います。プログラミングの30年で、バグ、パフォーマンスの問題、その他の問題の大部分は、データ表現を修正することで解決されました。データが正しい場合、コードは実際にそれ自体を書き込みます。
リーダニエルクロッカー

6
#3の本当の問題は、リンゴとオレンジを比較することであり、コードがデータよりも重要であったり、その逆であったりすることではありません。
ドックブラウン

3
入力データはあなたの手にありませんが、ソフトウェアでデータを表現する方法は完全にその中にあります。「コーディング」のその部分を呼び出しているかもしれませんが、そうではないと思います。たとえば、多くの場合、言語に依存せず、コーディングが始まる前に行われます。ただし、Iい入力データをクリーンアップするコードは、多くの場合良いことです。しかし、「クリーン」の定義ができるまでそれはできません。
リーダニエルクロッカー

3
実際、Lie#3は嘘だとは思いません。Fred Brooksはすでに何十年も前に書いています。「あなたのフローチャートを見せて、テーブルを隠してください。私はこれからも神秘になります。あなたのテーブルを見せてください。(今日では、代わりに「アルゴリズム」と「データ型」または「スキーマ」について話すことになるでしょう。)そのため、データの重要性は長い間よく知られています。
ヨルグWミットタグ

1
@djechlin私のポイントは、データが重要ではない、またはコードがより重要であるということではありませんでした。単にそのデータはコードよりも重要ではありません。これらは両方とも非常に重要であり、互いに大きく依存しています。
-yitzih

6

電子商取引システムでは、クラスレベルで「ロケット」を扱うのではなく、「製品」を扱います。ですから、それはあなたが何を達成しようとしているか、そしてあなたが望む抽象化のレベルに依存します。

ゲームでは、ロケットは多くの種類の「動く物体」の1つにすぎないと主張できます。他のすべての移動オブジェクトと同じ物理学がそれらに適用されます。したがって、少なくとも「ロケット」は、より一般的な「移動オブジェクト」の基本クラスから継承します。

いずれにせよ、あなたが引用した文章の著者は、彼の主張を少し誇張しているようです。ロケットには、「燃料の残量」や「推力」などの独自の特性がありますが、100個のロケットでこれを表すために100個のクラスは必要ありません。必要なのは1個だけです。オブジェクトの作成は、ほとんどの適切なプログラミング言語ではかなり低コストです。したがって、ロケットのようなものを追跡する必要がある場合、Rocketオブジェクトは高価すぎる可能性があるため、Rocketオブジェクトを作成すべきではないという考えはあまり意味がありません。


5

現実の世界での問題は、そのようなひどい物理です。現実の世界では物事を物理的なオブジェクトに分離します。なぜなら、それらは個々の原子やロケットである可能性のある何かの巨大な溶融スラグよりも動きやすいからです。

同様に、現実の世界は、私たちが依存している多くの便利な機能を提供します。「...を除くすべての鳥が飛ぶ」というペンギンの例外を作るのは本当に簡単です。そして、物事をロケットと分類することは本当に簡単です。つまり、そのペンギンをロケットと呼び、それを照らすと...それはうまくいきません。

したがって、現実の世界で物事を分離する方法は、これらの制約の下で概念的に機能します。コードで物事を行うときは、明らかに異なるこれらの制約の下でうまく機能するように物事を分離する必要があります。

代替手段は何ですか?

ネットワークについて考えてください。ポート、ワイヤ、およびルーターをコードでモデル化しません。代わりに、ネットワーク通信を接続とプロトコルに抽象化します。これは、実世界での実装に関係なく有用な抽象化であるためです。そして、コードでのみ重要な有用な制約(たとえば、接続が開かれるまで通信できません)を配置します

そう、実世界が機能した後にコードをモデリングすることもありますが、それは偶然です。人々がOOPについて話すとき、オブジェクトは現実世界のオブジェクトではありません。そうでなければ学校やチュートリアルは数十年の悲劇だと言う。


1
+1:プロトコルは非常に「現実世界」の抽象化です。今日の世界においてさえ、プロトコル担当官は、例えば、州の訪問にとって最も重要なスタッフの一部です。オバマとプーチンのG8会議でレッドカーペットに最初に行くのは誰ですか?抱きしめたり握手しますか?アラブ人とインド人を迎えるにはどうすればよいですか?等々。「現実の世界」には「物理的な世界」の「もの」ではない「もの」がたくさんあります。現実の世界のモデリングは、物理的な世界のモデリングを意味するものではありません。ない場合でも、Rocketこの男のコードを入力し、私はそれにもかかわらず、いくつかのモデル...があることを賭けに喜ん
イェルクWミッターク

…実世界。「物理的」なもの(「タッチ可能な」という意味)に対応していない場合でも。私は、もちろん、あまりにもであるなど四元、テンソル、フィールド、として、けれども、そこに実際の「物理的な」オブジェクト(「物理学者が認識かもしれないもの」の意味で)を見つけるために驚かない」現実世界のもの」と「現実世界のモデル」。
ヨルグWミットタグ

アラン・ケイは、ダイナブックを、出生時に子供に与えられ、それが彼らの脳の延長となるコンピューターとして構想しました。MVCパターンの目的は、ビューとコントローラーが脳とモデルの間のギャップを埋めて、直接操作メタファー、つまりコンピューターが脳の単なる拡張であるという錯覚をサポートすることです。自分の考えでモデルオブジェクトを直接操作します。そしてそれがドメインモデルが「現実の世界」をモデル化すると言うときの意味です。脳に抽象化を実装する必要があります。
ヨルグWミットタグ

そして、コンソールゲームの物理エンジンについて考えるとき、おそらくロケットについてはまったく考えないでしょう。したがって、コードにロケットのモデルが存在するべきではありません。しかし、おそらく他の「現実世界の考え」を考えているので、コードにはそれらのモデルがあるはずです。
ヨルグWミットタグ

2

別の方法は、プログラムが気にすることをモデル化することです。プログラムがロケットを扱う場合でも、というエンティティを必要としない場合がありますRocket。たとえば、LaunchPadエンティティとLaunchScheduleエンティティとエンティティがありMassiveDeviceMoverます。これらすべてがロケットの打ち上げに役立つという事実は、ロケット自体を扱っているという意味ではありません。


0

ここでの私の問題は、著者が「欠陥のある」プログラミングモデルを提示しているが、それを「修正」する方法を提示していないことです。おそらく、ロケットクラスの類推につまずいているかもしれませんが、この嘘の背後にある理由を本当に理解したいと思います。代替手段は何ですか?

これは本当の問題ですが、開発者としての私の考えをお伝えします。

まず、一般的な誤解として、私はそれが嘘だとは言いません。それを嘘と呼ぶのは誇大宣伝です。

ある意味で彼は正しい。これに多くの時間を費やすつもりはありません。それは問題の一部ではないからです。しかし、本質的に彼は正しい。これを「ラボで機能するものは実際の生活では機能しない可能性がある」と言い換えることができます。開発者は、「ラボ」で動作する設計に固執しますが、実際のアプリケーションでは失敗します。

Three Soundsは私には少し石鹸のように聞こえますが、基本的に彼は再び正しいです。ただし、これは「ニーズに合わせてコードを記述し、コードにニーズを合わせようとしないでください」に書き換えることができます。

二つの繰り返しには、ここで彼は正しいです。単純な「乗り物」クラス、またはさらに単純な「可動」クラスが機能する場合、開発者が「ロケット」クラスの開発に数週間以上費やしているのを見てきました。ロケットが画面の左側から右側に移動して音を出すだけであれば、車、電車、ボート、ハエと同じクラスを使用できます。100は、1 * 100未満の引数のコストが開発に費やされた時間であり、計算コストではあまりないようです。再利用できる一般クラスの数を減らすことは「安価」ですが、再利用できない多くの特定のクラスです。これはおそらく「一般クラスは特定のクラスよりも優れているため、

本質的に、記事全体をより少ない流行語で書き直すことができ、それはせいぜい長い段落に過ぎません。とはいえ、それはプログラミングの狭い領域に焦点を当てたブログ投稿です。私はいくつかの組み込みプログラミングを行ってきましたが、これらのステートメントの背後にある一般的な考え方に同意することができますが、GDCでのプレゼンテーションに適したものにするためにそれらの周りにかなりの「ふわふわ」があります。

最後に、この記事は2008年に執筆されました(私が知る限り)。物事は急速に変化します。今日の声明は真実ですが、組み込みシステムは当時よりはるかに一般的であり、開発パターンが変わります。おそらく、この記事/トークに応えてでも。


-1

プラットフォーム、メモリ使用の効率、およびデータという学術的な懸念がこれらの中心にあるのは興味深いことです。しかし、人間の要素は完全に無視されます。

ソフトウェアは、人々のニーズを満たすことです。通常、これはビジネス用語で定量化されます-何かを望む顧客と、それを実現するために喜んで支払う支援者がいます。方程式の両側のニーズを満たすようにソフトウェアが作成されている場合、それは良いソフトウェアであり、そうでない場合は悪いソフトウェアです。

プラットフォームが顧客にとって重要でない場合、プラットフォームは重要ではありません。顧客にとってメモリ効率が重要でない場合、それは重要ではありません。データが顧客にとって重要でない場合、データは重要ではありません。コードは機能するが、読み取りや保守ができず、顧客が適切な価格で迅速かつ信頼性の高い変更を望んでいる場合、不適切に記述されたコードは悪いことです。コードは機能しますが、読み取りや保守ができず、顧客が高額なリファクタリングを気にかけない、または支払おうとする場合、コードの記述が不十分であることは良いことです。

大きな嘘は、人間の要素以外は重要だということです。データが重要な理由 それが必要な顧客や利害関係者がいるからです。それが「大きな真実」です。


4
残念ながら、顧客は、読みやすく保守しやすく、テストの労力やバグのない安価で迅速で汚いコードを望んでいます。
後年

@ user889742ハ!本当です。アーキテクトがこれまでずっと解決しようとしてきたエンジニアリングの問題と、業界をこのように興味深いスペースにする理由を正確に述べています。
Price Jones

彼はゲーム開発者であり、ゲームのメンテナンス時代は比較的短命ですが、今日は2008年よりも長いため、人間の要素を無視しています。1日目のパッチは、今日ではゲームの標準であるようです。2008年には、ゲーム用のパッチはまだ比較的まれでした。
ラバーダック

-1

私見コードが「世界のモデルを中心に設計されている」なら、デザイナーと開発者、そしてメンテナーの両方にとって理解しやすいです。しかし、それは私だけでなく、ソフトウェアだけではないと思います。ウィキペディアから:科学モデリングは科学活動であり、その目的は、世界の特定の部分または機能を、既存の通常一般に受け入れられている知識を参照することにより、理解、定義、定量、視覚化、またはシミュレートしやすくすることです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.