OOPと手続き型プログラミングの比較 - ページ 23

 
Maxim Kuznetsov:

どうやらおしゃべりを見逃してしまったようですね :-) 司会者は炎上するような話題を取り締まっていますが・・・ここではOOP対OOPの話です。

ちなみに、@Peter Konowの 99%はOOPを使っていますが、本人は意識していません :-)。OOPは必ずしも「クラス&テンプレート」ではない。

また、その逆も然りで、プログラムにオブジェクトやクラスがあることは、OOPであることを示すものではありません。

それはとても興味深い考えですね。もしかしたらそうかもしれませんし、疑っているわけではありません。))


でも、どうしてわかるんですか?

 
Реter Konow:

それはとても興味深い考えですね。もしかしたらそうかもしれませんし、疑っているわけではありません。))


また、なぜそれを知っているのですか?

例えば、メッセージディスパッチによってOOを実装することができます(そして、クラス/テンプレートMQLにはない「プラスα」があります)。

あなたのコードに目を通していないので、おそらく読めないと思いますが、GUIライブラリがあるので、それ自身の(少なくとも1つの)キューを持ち、イベント/送信/状態の処理を通して、すべてを包み込んでいるのでしょう。そして、このまさに「ねじれ」は、結局は継承/ポリモーフィズムに過ぎないのです。

 
Dmitry Fedoseev:

ハリネズミについて。

"ハリネズミ "は空き地に立ち、上腕二頭筋を曲げながらポーズをとっています。- 私は強い、私は勇敢だ、私は機敏だ、私は強い、私は勇敢だ、私は機敏だ...。

熊が通りかかり、一蹴りすると、ハリネズミは木の陰に飛び、立ち上がって体を揺する。

- 私は強い、私は勇敢だ、私は機敏だ......。...でも、軽いし......。


幼馴染がよく言っていたように、ハリネズミは誇り高き鳥、蹴らなければ飛ばない ))
 
Alexey Volchanskiy:

ジョルジュ、今日、女の子とちょっと散歩して、おしゃべりして、シャイな男のことをちょっと思い出したんだ。正直なところ、小馬鹿にはしていません。みんな性格が違うし、育った環境も違う。

ああ...そしてレカは雛人形に...そして、当然ながら、その通りです。GOPよりずっと面白い。

まあ、私の問題は人見知りではないのですが。唯一自慢できるのは「よく伸びる舌」です。私の問題は、ペニオクを使った膣中心主義です。私はプライバシーとセックスに価値を置きすぎています。上に「...美人が目の前に迫ってくると、男はどれだけ頑張れるか見てきました」と書かれていますね。まあ、私もその一人なんですけどね。ただし、若くて強くて金持ちのうちは必要だけどね。女にヤル気があれば遅かれ早かれヤルだろうしな。若くて強くて金持ちでも 家がない病人なんだだから私の可能性はゼロだ...妻が出て行ったことも不思議じゃない。あなただけ、離婚したことを気にしていないようですね。一方、私は、妻が出て行けない条件を作れなかったことが、非常に悔しいです。

 

そして、OOPについてですが...。

もし私がRetag Konowと 同じ記憶力を持っていたら、「OOPは不要だ、インターフェース、クラス、オブジェクト、継承システム、仮想関数などをすべて構築する意味はない」と同意していたかもしれない。

アレクセイが言った通り、プロセッサーはどんなオブジェクトについても何も知らないんだ...。機能についても何も知らない。これは、どんなタスクも、OOPだけでなく、関数がなくても、リターンアドレスを記憶し、IPレジスタ(最近のCPUはこれを使う)を介して制御を渡すだけで解決できることを証明しています。

レツグ・コノウの 立場は、彼のコードを見せてもらうまで理解できませんでした。今はすべてがクリアになり、なんとか記憶にとどめ、長いifが気にならなければ、彼のような書き方のほうが合理的なのではないかとさえ思えるようになりました。しかも、この場合、OOPはまさに「カートの5輪目」になってしまうのです。

ただ、個人的に問題なのは、仕事の微妙なニュアンスがほとんど頭から抜けてしまうことです。例えば、多次元配列 G_COREの各インデックスが何を担っているのか、与えられたフラグメントの各条件が何を定義しているのか、毎回真剣に考えることになる。ロングコンディションの分析も、私にとっては緊張の連続です。

また、私自身がそのような理解しがたいコードを書いてしまうこともあります。同じように沈んでいるMY「不正解」コードの断片を紹介します(上に引用しています)。

virtual bool IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };

CTradePosComponentI トレーディングコンポーネントインターフェース関数で、このコンポーネントがブレイクイーブンにあるかどうかを判断する。

"間違い "とは、このコードでコンパクトさを犠牲にして可読性を高めていることです。機能がインターフェイスに含まれているので、できればインターフェイス全体が1つの画面で見えるようにしたかったのです。ただ、どんな機能があるのか覚えなくてもいいように、それらの機能が一度に見られるように。もし私がすべてを覚えていたら - 関数を文字列に「引き伸ばす」必要はないでしょう。それで、機能が十数行に引き延ばされたんですね......いいんですけど。しかし、すべての機能が隣り合わせのインターフェースに収まること、そして、すべての機能が見えることが重要でした。一目見ただけで、どんな機能があるのかがわかるようなインターフェイスにしたかったんです。そのため、-関数を1行に長く書き出す必要があったのです。しかし、それを理解するのは全く非現実的なことです。

当初、コードを書くとき - 最初、この関数はかなり違う書き方をしました。わかりやすく、コメント付きで。理解できるように。

こんな感じ。

virtual bool IsTPCInUnloss() const 
{ 
    // Отсеем вариант, когда СЛ отсутствует
    if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE)
         return(false);

    //  Проверим тип торговой компоненты
    if(GetTPCType() == POSITION_TYPE_BUY)
        { 
        // Торговая компонента - лонг
        if(GetTPCStopLoss() >= GetTPCOpenPrice())
            return(true);
        }
    else
        { 
        // Торговая компонента - шорт
        if(GetTPCStopLoss() <= GetTPCOpenPrice())
             return(true); 
        }; 

    return (false); 
};

そして、これらをすべてテストし、デバッグした後に初めて、コードをコメントから取り除き、「一列に並べる」のです。

しかし、これは例外的なことです。私は、「視認性」を重視する特別な場合に、ごく稀にこのようなことをします。それ以外の場合、私はコードを「広く」書き、インデントし、「ここに何があるのか」という質問に少しでも引っかかるような場所にはコメントを付けます。

そうしないと、どこで、何を、何のためにしたのか、すぐに忘れてしまうんです。

 
Maxim Kuznetsov:

例えば、メッセージディスパッチによってOOはかなり実現可能です(クラス/テンプレートMQLにはない「プラスα」もあります)。

私はあなたのコードに目を通していないので読めませんが、GUIライブラリを持っているので、それ自身の(少なくとも1つの)キューを持ち、イベント/文/状態の処理を通じて、多くのことが台無しになっているのでしょう。そして、このまさに「ねじれ」は、結局は継承/ポリモーフィズムに過ぎないのです。

さて、「A」と言ったからには「B」とも言いたいところだが......)。私の技術をより具体的に説明します。

ある種のタスクに対応する機能を大きなブロックにまとめることで、機能間のリンクを減らすことができるのです。これには長所と短所があります。

まず長所について。

OOPでは、多数の関数に分解された機構は、クラスと構造をつなぐために多くのオブジェクトを作成する必要があります。同時に、各関数プロトタイプは多数の形式パラメータに囲まれており、このパラメータを介して周囲のコードと通信を行う。この機構開発の過程で、機構部品間のリンクが増えたからこそ、コードの内部構造が複雑化したのです。

私の技術では、関数とブロックの間の通信は、全体に刻印されたグローバル変数によって、完全に簡素化されています。関数は、グローバルレベルで即座にパラメータを参照するため、パラメータを渡す必要はありません。

グローバル変数の 値は、カーソルを「追跡」する「オブジェクトフォーカス」ブロックによって設定されます。カーソルの現在座標からマウスがどのオブジェクト上にあるかを判断し、すべての要素、オブジェクト、ウィンドウのすべてのプロパティを格納するカーネル(G_CORE)にアクセスする。カーネルから、ブロックはカーソル下のオブジェクトのすべての主要プロパティの現在値を取得し、グローバル変数に配置します。カーソルがオブジェクトの上を移動すると、このブロックでグローバル変数が再定義され、常にフォーカスのあるオブジェクトに対応する。

次に、OnChartEvent()関数は、カーソル下の要素の状態を変化させるべきチャートイベントを捕捉します。これらのイベントにおいて、状態制御ブロック(OnChartEvent()自体に統合されている)は、どのウィンドウ、要素、オブジェクトがフォーカスされているか、そしてそれらのプロパティが何であるかを即座に確認することができます。このブロックには何も渡す必要はありません。必要なものはすべて、すでにグローバル変数にフォーカスが当たっているからです。G_COREカーネルでオブジェクトのプロパティの値を変更し、要素を再描画するのがその役割です。値を変更し、Drawブロックを呼び出します。

描画ブロックに渡すパラメータは、window、canvas、elementの3つだけです。要素を再描画し、現在の状態に適した外観にします。ペインティングブロックのすべての補助関数は、フォーカスでグローバル変数を使用します。例えば、上記の関数 "Color part() "では、"WINDOW", "OBJECT", "CATEGORY_OBJECT" 等を使用します。これらはすべて、とても便利なものです。


次に短所です。

確かに大きなブロックやフォーカスオブジェクトはコードパーツ間の関係を簡素化しますが、ブロックが大きいために作業時に困難が生じるからです。私はOOPを使わないので、ロシア語と構文の完全な単純化は、ここで私を助けてくれます。

ブロックは時間が経つと、変更する必要がなくなり、成長が止まってしまいます。徐々にその構造を完全に記憶し、作業を最大限に簡素化することができます。

もちろん、ブロックの削り出し自体は、かなり長くて辛いものですが、どんな仕組みでもデバッグとはそういうものなのです。

 
George Merts:

そして、OOPについてですが...。

もし私がRetag Konowと 同じ記憶力を持っていたら、「OOPは不要だ、インターフェース、クラス、オブジェクト、継承システム、仮想関数などをすべて構築する意味はない」と同意していたかもしれない。

アレクセイが言った通り、プロセッサーはどんなオブジェクトについても何も知らないんだ...。機能についても何も知らない。これは、どんなタスクも、OOPだけでなく、関数がなくても、リターンアドレスを記憶し、IPレジスタ(最近のCPUはこれを使う)を介して制御を渡すだけで解決できることを証明しています。

レツグ・コノウの 立場は、彼のコードを見せてもらうまで理解できませんでした。今はすべてがクリアになり、なんとか記憶にとどめ、長いifが気にならなければ、彼のような書き方のほうが合理的なのではないかとさえ思えるようになりました。しかも、この場合、OOPはまさに「カートの5輪目」になってしまうのです。

ただ、個人的に問題なのは、仕事の微妙なニュアンスがほとんど頭から抜けてしまうことです。例えば、多次元配列 G_COREの各インデックスが何を担っているのか、与えられたフラグメントの各条件が何を定義しているのか、毎回真剣に考えることになる。ロングコンディションの分析も、私にとっては緊張の連続です。

また、私自身がそのような理解しがたいコードを書いてしまうこともあります。同じように沈んでいるMY「不正解」コードの断片を紹介します(上に引用しています)。

CTradePosComponentI トレーディングコンポーネントインターフェース関数で、このコンポーネントがブレイクイーブンにあるかどうかを判断する。

"間違ったこと "とは、このコードではコンパクトさを犠牲にして可読性が損なわれていることである。機能がインターフェイスに含まれているので、できればインターフェイス全体が1つの画面で見えるようにしたかったのです。ただ、どんな機能があるのか覚えなくてもいいように、それらの機能が一度に見られるように。もし私がすべてを覚えていたら - 関数を文字列に「引き伸ばす」必要はないでしょう。それで、機能が十数行に引き延ばされたんですね......いいんですけど。しかし、すべての機能が隣り合わせのインターフェースに収まること、そして、すべての機能が見えることが重要でした。一目見ただけで、どんな機能があるのかがわかるようなインターフェイスにしたかったんです。そのため、-関数を1行に長く書き出す必要があったのです。しかし、それを理解するのは全く非現実的なことです。

当初、コードを書くとき - 最初、この関数はかなり違う書き方をしました。わかりやすく、コメント付きで。理解できるように。

こんな感じ。

そして、すべてのテストとデバッグが終わってから、コードをコメントから取り除き、「ラインに引き込む」のである。

しかし、これは例外的なことです。この方法は、特に「視認性」が重要な場合に、ごく稀に行う方法です。それ以外の場合は、「ワイド」と「インデント」の両方でコードを書き、「ここには何があるのか」という疑問が少しでも生じそうな場所にはコメントを入れています。

そうしないと、どこに、何が、何のためにあるのか、すぐに忘れてしまうからです。

私たちのタスクは非常に異なっているので、あなたのソリューションについて何かを言うのは難しいです。私の記憶だけでなく、他にも何かあるはずです。自分のコードを理解することで、覚えやすくなることは間違いありません。あなたのコードの意味が薄いと言っているのではありません。ただ、あなたの問題にどうアプローチしたらいいのかわからない。あなたのやり方が正しいのかもしれません。批判しているわけではありません。個人的には、このスタイルのコードは非常に理解しにくいと思います。

習慣の問題なんでしょうね(笑)

 
Реter Konow:

私たちのタスクは非常に異なっているので、あなたのソリューションについて何かを言うのは難しいです。私の記憶だけでなく、他にも何かあるはずです。自分のコードを理解することで、覚えやすくなることは間違いありません。あなたのコードの意味が薄いと言っているのではありません。ただ、あなたの問題にどうアプローチしたらいいのかわからない。あなたのやり方が正しいのかもしれません。批判しているわけではありません。個人的には、このスタイルのコードは非常に理解しにくいと思います。

習慣の問題でしょう(笑)。


まったく無意味な話です。コードを「良い」「悪い」と分類する基準はない のです。そのため、OOPについては明確ではありません。

それは、作者や第三者が長い時間をかけてコードを読み、修正したり、バグを見つけたりすることができることである。


ここでは、上記のフェドセーエフがOOPスイッチを交換しました。この例は、不幸中の幸いかもしれませんが、私にとってはOOPの悪質さを証明するものです。100ポジションのスイッチを持つ明確なコードが、1行で置き換えられています。このラインを理解するためには、どこかに行かなければならない。私にとっては許されないことです。

ジョージ・マーツ 氏による上記2番目の例

デバッグ後、クリアコードをNOTクリアコードに置き換えた場合。私の基準では、質の高い(読みやすい)コードは、私にとって受け入れがたいコードに置き換わってしまいました。


そこで、OOP支持者の皆さんに質問です。OOPを 適用するとプログラムが見やすく なり、Fedoseevがスイッチで示した例は失敗なのか、逆にFedoseevの例は非常に正確にOOPを特徴づけていて、OOPではほとんどの場合、見やすさが損なわれてしまうのか?

 
СанСаныч Фоменко:

1.全く無意味な会話:コードを「良い」「悪い」と分類 する基準はありません。そのため、OOPについては明確ではありません。

私にとっては、作者や第三者がコードを読み、それを使って修正し、かなり長い時間をかけてバグを見つけることができる......という事実が示す、コードの実行可能性(feasibility)がその基準になっています。


2.ここでは、上記のフェドセーエフがOOPスイッチを交換しました。この例は、不幸中の幸いかもしれませんが、私にとってはOOPの悪質さを証明するものです。100ポジションのスイッチを持つ明確なコードが、1行で置き換えられているのです。このラインを理解するためには、どこかに行かなければならない。私にとっては許されないことです。

ジョージ・マーツ 氏による上記2番目の例

デバッグ後、クリアコードをNOTクリアコードに置き換えた場合。私の基準では、高品質のコード(読みやすい)は、私にとって受け入れがたいものに変わりました。


3.そこで、OOP支持者の皆さんに質問です。OOPを適用 するとプログラムが見やすく なり、Fedoseyevがスイッチで示した例は失敗なのか、逆にFedoseyevの例はOOPを非常に正確に表現しており、OOPではほとんどの場合、見やすさが損なわれてしまうのか?


1.基準があるんです。主な判断基準はスピードです。

コードのわかりやすさは、間違った判断基準です。コードは見るためでなく、動くために書かれている。

2.なるほど、関数でコードを構成するほど成熟していない人がいることがわかりました。ですから、あなたは間違ったトピックにいます。「1ページコード vs. 関数構造化コード」というトピックを取り上げるべきでしょう。

それに、このサンプルは構造化や明確性・非自明性ではなく、バラストコード片を排除するためのものでした。

3... Why don't you...エンジニアリング・グラフィックスを学ぶ?あるいは記述幾何学。そこでは、すべてが視覚的なのです。

 
Dmitry Fedoseev:

コードの視認性は間違った判断基準です。コードは見るために書くのではなく、動くために書くのです。

そうですね、私は反対です。

コードの可視化は非常に重要なことです。なぜなら、明確なコードは保守と修正が非常に容易だからです。

その通りです。私は裸の関数を書き、それを実際に「難読化」して、見えないように、理解できないようにしました。これは強引な決断だった。今回は、クラス全体を透明化することの方が重要でした。私は、ある極めて些細な機能のわかりやすさを犠牲にしています。もちろん、この関数の本体を.mq5ファイルに記述してもよかったのですが、インターフェースは2つのファイルに分けるのではなく、.mqhヘッダーファイルで完全に記述するべきだと考えています。

スピードも留意すべき点ですが、「何が何でもスピードアップ」という努力はしない方がいいと思います。合理的な充足感が必要です。