Methode zur Fehlerbestimmung im Code durch Kommentieren

Eryomin Sergey | 28 März, 2016

Einführung

Dieser Artikel beschreibt einen einfachen Algorithmus zur Suche nach Fehlern in einem MQL4 Code. Die Probleme während der Kompilierung, durch Fehler in dem Code, treten häufig erst nach dem Schreiben eines Programms auf. Dies können alle Arten von Fehlern sein, aber trotzdem ist es notwendig den Code-Block, mitdem der Fehler zusammenhängt, schnell zu erkennen.

Höchstwahrscheinlich verbringen viele Menschen eine Mege Zeit und Nerven mit der Suche nach einer fehlenden Klammer. Es gibt jedoch eine Methode für das schnelle Auffinden der Fehler, die auf der Verwendung von Kommentaren baesiert. So ist es diese Mehtode, über die ic in diesem Artikel sprechen werde.



Konzeption

Einen großen Code ohne Fehler zu schreiben ist ziemlich angenehme. Aber leider ist das nicht immer der Fall. Es gibt sogar einen Witz, dass noch nie ein Programm ohne Fehler geschrieben wurde.Ich berücksichtige hier nicht die Feehler, die zu einer falschen Ausführung des Codes führen. Hier ist die Frage nach den Fehlern, die das Kompilieren unmöglich machen.

Die weitest verbreiteten Fehler sind: Einfügen ein unpassenden Klammer in einer komplexen Bedingung, Fehlen einer Klammer, nicht gesetzter Doppelpunkt, ein Komma (während der Deklaration von Variablen), usw. Häufig sehen wir welcher Eintrag den Fehler während der Kompilierung enthält sofort. Es gibt aber Fälle, in denen das Ermitteln von Fehlern dieser Art nicht so einfach ist. Weder der Compiler, noch einscharfes Auge kann uns helfen den Fehler sofort zu finden. In diesem Fall fängt, in der Regel, der lerndende (und nicht-) Programmierer an den gesamten Code durchzugehen, und versuchen den Fehler optisch zu erkennen. Wieder und wieder, bis die Nerven reißen und gesagt wird: "Es ist leichter es neu zu schreiben"!

Allerdings, MQL bietet, genau wie alle anderen Programmiersprachen, ein unglaubliches Werkzeug - Kommentieren. Sie können einige Teile des Codes mit seiner Verwendung "entfernen", "deaktivieren". In der Regel wird die Kommentierung im WOrtsinn verwendet, oder für die Deaktivierung von nicht genutzten Teilen des Codes. Die Kommentiereung kann außerdem erfolgreich für die Fehlersuche verwendet werden.



Algorithmus zur Fehlersuche

Die Suche nach fehlern führt in der Regel zu dem Teil des Codes, in dem der Fehler gemacht wurde, und wo dann optisch nach ihm gesucht wird. Ich denke, niemand wird daran zweifeln, dass es viel einfacher und schneller ist 5-10 Code-Einträge "mit dem Auge" zu untersuchen, als 100-150 Einträge.

Das Problem scheint sich einfach lösen zu lassen, wen Kommentieren verwendet wird. Zunächst ist es erforderlich einige unterschiedliche Teile des Codes (manchmal fast der ganze Code) zu kommentieren, um ihn zu "deaktivieren". Dann wird die Kommentierung von diesen Teilen des Codes wieder entfernt. Nach der normalen Beseitigung der Kommentierung, wird ein Versuch den Code zu Kompilieren durchgeführt. Ist die Kompilierung erfolgreich, ist der Fehler nicht in diesem Teil des Codes. Ist die Kompilierung erfolgreich, ist der Fehler nicht in diesem Teil des Codes. Danach wir der nächste Teil geöffnet, und so weiter. Ist der Problematische Teil mit dem Fehler gefunden, wird der Fehler optisch gesucht und behoben. Danach wid ein Versuch gemacht wieder eine Kompilierung durchzufühenren. Wenn alles erfolgreich durchläuft, ist der Fehler beseitigt.

für den Fall, dass neue Fehler auftreten, wird die Prozedur wieder holt bis diese beseitigt sind. Der Ansatz ist sehr nützlich, wenn große Porgamme geschrieben werden, und nicht selten funktioniert es beim Schreiben relativ kleiner Codes.

Es ist sehr wichtig den Block zum Komentieren richtig zu bestimmen. Wenn es eine Bedingung ist8 oder eine andere logische Konstruktion), dann sollte sie vollständig kommentiert werden. Wenn Sie einen Block kommentieren, in dem die Variablen deklariert sind, dann ist es wichtig keine Bläcke auszulassen in denen diese Variablen angezeigt werden. Dazu muss gersagt werden, dass die Kommentierung nach der Logik des Progrtammierens genutzt werden sollte. Das Handeln gegen diesen Grundsatz wird dazu führen, dass neue, desinformierende Fehler während der Kompilierung auftreten.



Beispiel

Ich werde die praktische Suche nach einem Fehler im Code veranschaulichen. Angenommen wir haben einen Code:

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {
//+--------------------------------------------------------------------------------------------------+
//|                                        search for opened orders by symbol
   int pos_sell=0;
 for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
 { 
  if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_sell=1;  break;   
  } 
 }
    
   int pos_buy=0;
 for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
 { 
  if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_buy=1;  break;   
  } 
 }
     
//|                                        search for opened orders by symbol                       |
//+-------------------------------------------------------------------------------------------------+  
 
//+-------------------------------------------------------------------------------------------------+
//|                                                stop for break-even
  double stop_open; 
  for (int ia=OrdersTotal()-1; ia>=0; ia--) 
  { 
   if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; 
   if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(),
                                                                        OrderExpiration(),CLR_NONE);  
   } 
 if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(),
                                                                        OrderExpiration(),CLR_NONE);       
   } 
  }   
//|                                                stop for break-even                              |
//+-------------------------------------------------------------------------------------------------+ 
   int i;   
   bool trend_UP=true,trend_DOWN=true;   
//+-------------------------------------------------------------------------------   
if(!pos_buy)
 {  
  for(i=Level1; i>=0; i--)
   {
   
    if(Open[i]<iSAR(NULL,0,0.02,0.1,i))
    {
     trend_UP=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   {    
   
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_UP=false; break;
     }
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_UP=false; break;
     }
    }          
   
   } 
 }
 else
 {
  trend_UP=false; 
 }
//***************************************************************************
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }  
 
 
  if(Open[0]>iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("sell"); 
  }
  
  if(Open[0]<iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("buy"); 
  } 
   
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);  
   if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0)
   {   
     OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); 
      
     ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid);
     ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen);
   }
   
   if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) 
   {   
      OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red);   
      
      ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid);
      ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT);
      ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
      ObjectSet("sell", OBJPROP_COLOR, Red);  
   }
   
 
//+-------------------------------------------------------------------------------
//----
   return(0);
  }
//+------------------------------------------------------------------+

WIr sehen die folgende Fehlermeldung während der Kompilierung:


Es ist unmöglich den Block, in dem der Fehler gemacht wurde, schnell zu erkennen. Wir greifen zurück auf die Kommentierung. Kommentieren Sie alle logischen Konstruktionen:

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {
  /*
//+-----------------------------------------------------------------------------------------------+
//|                                        search for opened orders by symbol                     |
   int pos_sell=0;
 for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
 { 
  if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_sell=1;  break;   
  } 
 }
    
   int pos_buy=0;
 for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
 { 
  if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY)
                                                                        &&(OrderComment()=="sar_ao"))
  {
   pos_buy=1;  break;   
  } 
 }
     
//|                                        search for opened orders by symbol                    |
//+----------------------------------------------------------------------------------------------+  
*/
 
/*
//+----------------------------------------------------------------------------------------------+
//|                                                stop for break-even                           |
  double stop_open; 
  for (int ia=OrdersTotal()-1; ia>=0; ia--) 
  { 
   if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; 
   if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(),
                                                                OrderExpiration(),CLR_NONE);  
   } 
 if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(),
                                                                OrderExpiration(),CLR_NONE);       
   } 
  }   
//|                                                stop for break-even                          |
//+---------------------------------------------------------------------------------------------+ 
*/
 
 
/*
   int i;   
   bool trend_UP=true,trend_DOWN=true;   
//+-------------------------------------------------------------------------------   
if(!pos_buy)
 {  
  for(i=Level1; i>=0; i--)
   {
   
    if(Open[i]<iSAR(NULL,0,0.02,0.1,i))
    {
     trend_UP=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   {    
   
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_UP=false; break;
     }
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_UP=false; break;
     }
    }          
   
   } 
 }
 else
 {
  trend_UP=false; 
 }
 */
//***************************************************************************
 
/*
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }  
 
 */
 
 /*
  if(Open[0]>iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("sell"); 
  }
  
  if(Open[0]<iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("buy"); 
  } 
  */ 
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); 
 
/* 
   if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0)
   {   
     OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); 
      
     ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid);
     ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen);
   }
  */
  
  /* 
   if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) 
   {   
      OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red);   
      
      ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid);
      ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT);
      ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
      ObjectSet("sell", OBJPROP_COLOR, Red);  
   }
   
*/
//+-------------------------------------------------------------------------------
//----
   return(0);
  }
//+------------------------------------------------------------------+

Sie können einfac sicherstellen, dass dieser Code ohne Probleme kompiliert werden kann. Das bedeutet, dass der Teil des Codes, in dem der Fehler gemacht wurde "versteckt" ist. Öffnen Sie Teile des Codes /* ... */ schrittweise und versuchen Sie ihn zu kompilieren.

Die Kompilierung wird erfolgreich sein, bis wir den folgenden Block des Codes erreichen:

//***************************************************************************
 
 
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }

Deshalb ist der Fehler eine logische Konstruktion. Wir können sehen, dass sich dort eine unangebrachte runde Klammer in der Konstruktion ist, während der der eingehenden Untersuchung von diesem Teil des Codes:

   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }

Wenn wir sie entfernen, wird der Code erfolgreich kompiliert.

Wir werden sicherstellen, dass es keine weiteren Fehler in dem Code gibt, indem wir die verbleibenden Kommentare entfernen. Das bedeutet, dass wir unser Ziel erreicht haben - der Fehler im Code wurde schnell erfolgreich gefunden.



Fazit

Es wurde an einem praktischen Beispiel gezeigt, wie dieser Algorithmus für die Fehlersuche verwendet wird. Es wurde kein kleiner Code (194 Einträge) in diesem Beispiel verwendet, also könnte seine "Untersuchung" viel Zeit in Anspruch nehmen. Die Möglichkeit der Kommentierung selbst spart ausreichend Zeit, für Programmierer, die auf das Problem der Fehlersuche stoßen.