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

 
Andrei:

でも、MQL4ではOOPでプログラミングできないので、やはりそちらの方が人気がありますね。

すでに私のコードを示しましたが、もう一度示します。

class CTradeProcessorI : public CMyObject
{
public:
   void CTradeProcessorI() {    SetMyObjectType(MOT_TRADE_PROCESSOR_I); };
   virtual void ~CTradeProcessorI() {};
   
   // Настроечный интерфейс
   virtual void SetSlippage(uint uiSlippage) = 0;
   
   // Торговый интерфейс
   // Все функции возвращают код возврата торгового сервера
   virtual int Buy(long & lTicket,ECurrencySymbol csSymbol,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0;               // Всегда по цене Ask, если успешно - возвращается lTicket
   virtual int Sell(long & lTicket,ECurrencySymbol csSymbol,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0;              // Всегда по цене Bid, если успешно - возвращается lTicket  

   virtual int ModifyTPSL(CTradePosComponentI* ptpcComponent,double dTP=0,double dSL=0) = 0;       
   virtual int ModifyTPSL(long lTPCTicket,double dTP=0,double dSL=0) = 0;       

   virtual int CloseTradeComponent(CTradePosComponentI* ptpcComponent,double dCloseVolume=EMPTY_VALUE) = 0;              // dCloseVolume - закрываемый объем. Если равен EMPTY_VALUE или равен или больше, чем объем торговой компоненты с указанным тикетом - закрывается вся торговая компонента.   
   virtual int CloseTradeComponent(long lTPCTicket,double dCloseVolume=EMPTY_VALUE) = 0;              // dCloseVolume - закрываемый объем. Если равен EMPTY_VALUE или равен или больше, чем объем торговой компоненты с указанным тикетом - закрывается вся торговая компонента.   
   
   virtual int PendingSet(long & lTicket,ECurrencySymbol csSymbol,ENUM_ORDER_TYPE otOrderType,double dSetPrice,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0; // если успешно - возвращается lTicket
   virtual int PendingDelete(long lTicket) = 0; 
   virtual int PendingDelete(COrderInfoCore* poiOrder) = 0; 
   
   virtual int PendingModify(long lTicket,double dSetPrice,double dTP=0,double dSL=0) = 0;       
   virtual int PendingModify(COrderInfoCore* poiOrder,double dSetPrice,double dTP=0,double dSL=0) = 0;       
   
   // Проверка кода возврата
   virtual bool TradeOperationWasSuccessful(int iTradeResCode) = 0;
   
   // Если функция возвращает true, то при возникновении пользовательских ошибок (iTradeResCode > ERR_USER_ERROR_FIRST) советник прекратит работу
   // В случае false - работа будет продолжена
   virtual bool IsUserErrorsFalal() = 0;
};


これは、トレードプロセッサーのインターフェースで、MT4とMT5の両方でまったく同じです。

ユーザーはこのインターフェイスを手に入れるだけで、取引行動のあらゆる可能性を手にすることができるのです。MT4なのかMT5なのかさえも分からなくていい。購入する必要があります。関数Buyを呼び出すと、オープンな取引コンポーネント(MT4では注文、MT5ではポジション)のチケットが満たされ、取引サーバーのリターンコードが 返されます。

MT4とMT5のプロトコルの違いについて考える必要すらありません - インターフェースが必要なものをすべて提供します。

これらはすべてOOPの機能です。

 
George Merts:

すでに私のコードを示しましたが、もう一度示します。

これは、取引プロセッサーのインターフェースで、MT4とMT5の両方でまったく同じです。

ユーザーはこのインターフェイスを受け取るだけで、取引行動のあらゆる可能性を手にすることができるのです。彼はMT4かMT5かを知る必要すらありません。

そして、それはすべてOOPのおかげです。

典型的なケースでの使用例はありますか?

 
Andrei:
MQL4=MQL5という理論であれば、MQL4はMT5で動かすことができますし、その逆もしかりです。
私のコードは、MT4とMT5で全く変わらずに動作します。
 
Andrei:

典型的なケースでの使用例はありますか?

さて、ここで私の関数がTP-SLをトレードプロセッサーに変更するリクエストを送信したとします。

EEAWorkRetcode CChngTPSLRequest::_ProceedRequestInto(CTradeProcessorI* ptpProcessor)
{
   ASSERT_MYPOINTER(ptpProcessor);
   
   m_uiServerRetCode = ptpProcessor.ModifyTPSL(m_lComponentTicket,m_dTP,m_dSL);

   if(ptpProcessor.TradeOperationWasSuccessful(m_uiServerRetCode) != true)
      {
      Print("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode);
      TRACE_INTEGER("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode);
      return(WR_SERVER_PROCEED_ERROR);
      };
   
   return(WR_SUCCEEDED);   
};

まず、EAパートオブジェクト - フォームのトレードアクション要求(ここでは、そのような要求の1つは、TP-SLを変更することです)。その後、取引処理装置に取引行為に関する情報を送信するすべての要求に対して ProceedRequestInto()関数が呼び出さ れます。

取引処理装置自体は以下のクラスのオブジェクトである。

// СTradeProcessor - переносимый класс торгового процессора
// Именно этот класс необходимо использовать для торговли. 
// Класс реализует интерфейс CTradeProcessorI

#ifdef __MQL5__
#include <MyLib\Trade\MT5TradeProcessor.mq5>
#else // __MQL5__
#include <MyLib\Trade\MT4TradeProcessor.mq5>
#endif //__MQL5__

#ifdef __MQL5__
class CTradeProcessor : public CMT5TradeProcessor
#else // __MQL5__
class CTradeProcessor : public CMT4TradeProcessor
#endif //__MQL5__

{
public:
   void CTradeProcessor(uint uiSlippage = DEFAULT_TRADE_POINT_SLIPPAGE);
   void ~CTradeProcessor() {};
 
   // Функции отложенных ордеров, которые используют платформоспецифические  
   virtual int PendingDelete(COrderInfoCore* poiOrder);
   virtual int PendingModify(COrderInfoCore* poiOrder,double dSetPrice,double dTP=0,double dSL=0);          
};

つまり、プラットフォームによって、CTradeProcessorクラスはCMT5TradeProcessorクラスまたはCMT4TradeProceccorクラスから継承されます。

もちろん、OOPでなくても、スイッチやifdefの助けを借りれば、これらはすべて可能だ。しかし、私の考えでは、OOPアプローチの方が便利で明快です。主な理由は、エンティティを互いに分離することができ、大量のグローバル変数を取り除くことができるからです。

ちなみに、もうひとつの「OOPの響き」は、ちょうど保留中のオーダーを扱う追加機能にあります。MT4とMT5でチケットへの参照が異なるため、取引プロセッサが取引のチケットで動作し、不便です。そのため、オーダーインタフェースの子孫である共通クラスCOrderInfoCoreが存在するのです。このオブジェクトへのポインタだけをプロセッサに渡す方が、はるかに便利です。このように、プラットフォームに依存したフラグメントを回避することができるのです。

 
George Merts:

さて、ここで私の関数がTP-SLをトレードプロセッサーに変更するリクエストを送信したとします。

まず、EAパートオブジェクト - フォームのトレードアクション要求(ここでは、そのような要求の1つは、TP-SLを変更することです)。次に、取引処理装置に取引行為に関する情報を送信するすべての要求に対して ProceedRequestInto()関数が呼び出さ れます。

私には複雑すぎて、そこで実際に何が起こっているのか理解できないようです。そして、その中身を理解していなければ、使いこなすことは難しいでしょう...。MT5用に別バージョンを書いて、必要な時に引っ掛ける方が簡単ではないか?
 
George Merts:
私のコードは、MT4とMT5で全く変わらずに動作します。

なぜ、異なる端末で動作させるのか?

 
Andrei:
複雑すぎて、本当の内情はわからないと思うのですが......。そして、その仕組みを理解しなければ、誰も使ってくれないと思うのですが......。MT5用に別バージョンを書いて、必要な時に差し込む方が楽なのでは?
なぜ、「本当の中身を理解する」必要があるのか?プラットフォームに関係なく、あるアクションを実行する固定されたインターフェイスがあり、それを私たちは使っているのです。そして、そこにあるのは、低レベルのもので、どんな違いがあるのでしょうか?
 

George Merts:

しかし、私見では、OOPのアプローチの方がはるかに便利で明快です。 そして最も重要なことは、エンティティを互いに分離し、大量のグローバル変数を取り除くことができることです。

そこがポイントです。あらゆるものをあらゆるものから分離してしまうと、そのようなコードを扱うのがずっと難しくなります。もちろん、必要なすべての変数の現在値を知る必要がある場合、コードの適切なデバッグが不可能になることは言うまでもありません。

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

なぜ、異なる端末で動作させるのか?

なぜなら、私のメイン口座はMT4で開いており、ストラテジーテスターは MT5の方がはるかに優れているからです。

Freelanceでよくあるクライアントの要望、「MT4とMT5の両方で動くこと」ですが、それには理由があるということです。私自身はフリーランスで仕事をする理由がわからないのですが、そこで働いている人に、なぜ顧客がクロスプラットフォームを要求するのか聞いてみてはいかがでしょうか。

 
George Merts:
なぜ「内部で実際に行われていることを理解する」必要があるのでしょうか。プラットフォームに関係なく、アクションを実行する固定されたインターフェイスがあり、それを私たちは使っているのです。そして、そこにあるのは、低レベルのもので、どんな違いがあるのでしょうか?
低レベルの話ではなく、内部変数をすべて把握することも含めて、ありとあらゆる時点で、そこに何が流れていて、何に流れているかというロジックを......。この冗長なロジックをすべて理解しないと、このコードを非著作者に使う意味がまったくなくなってしまう......。