OOP에 대한 흥미로운 해석 - 페이지 8

 
fxsaber :

좋아해서 이렇게 씁니다. 동시에 디버깅할 때 모든 것이 매우 나빠집니다.


이 표현에도

누가 무엇을 반환했는지 이해하기 어렵습니다. 더 복잡한 것들은 (나는 끊임없이 연습한다) - 그것은 매우 어렵다.

반환 값으로 2-3 사용 ... 글쎄, 논리 연산 (또는 조건부 삼항 연산자 )으로 결합 된 함수 실행의 5 결과를 보자 - github 또는 다른 곳에서 이것을 보았습니다. 그러한 코드로 알아낼 수 있습니다

그러나 이 "좋은 것"이 약 12개 정도라면 ... IMHO, 이것은 실용적이지 않습니다.

 
Maxim Kuznetsov :

나는 확실히 mql 개발자가 아닙니다.

그러나 C에서 switch는 상당히 효율적인 바이너리 검색 을 생성하고 불필요한 페이지 스왑이나 캐시 충돌을 일으키지 않습니다. 즉, 배열 및 구조를 통한 간접 주소 지정보다 더 나은 경우가 많습니다.

어딘가에 그들이 썼고 여기에 개발자가 비슷한 정보를 가지고 있습니다.

이것만 찾았습니다:

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

MQL5에서 함께 배우고 쓰기

슬라바 , 2011.04.14 09:59

아니요, 불행히도 그렇지 않습니다. 문자열 유형의 경우에만 ... else if ... else

스위치에서 정수 유형 을 사용하기 때문에 다음과 비교할 때 몇 배의 속도 향상이 달성됩니다.


 
Igor Makanu :

그러나 이 "좋은 것"이 약 12개 정도라면 ... IMHO, 이것은 실용적이지 않습니다.

작은 괴물.

   static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES )
  {
     return (VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders. OrderSelect (Index, Select, Pool) :
           #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
             VIRTUAL::SnapshotPtr ?
             #ifdef __MQL5__ // Выбор по тикету в MT5 - разнообразный набор вариантов.
               (Select == SELECT_BY_TICKET) ? :: OrderSelect (Index, Select, Pool) && VIRTUAL::SnapshotPtr.CopyOrder()
                                            :
             #endif // #ifdef __MQL5__
                                              ((((Index == INT_MIN ) || (Index == INT_MAX )) && (Pool == MODE_TRADES) &&
                                               :: OrderSelect (Index, Select, Pool) &&
                                             #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder( true ))
                                             #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder())
                                             #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
                                               || VIRTUAL::SnapshotPtr. OrderSelect (Index, Select, Pool))
                                  :
           #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
           #ifdef __MQL5__
             #ifdef __MT4ORDERS__
               :: OrderSelect (Index, Select, Pool)
             #else // __MT4ORDERS__
               false
             #endif // __MT4ORDERS__
           #else // __MQL5__
             :: OrderSelect (Index, Select, Pool)
           #endif // __MQL5__
           );
  }

매크로를 통해 다양한 설정을 사용할 때 논리 연산 을 통해 간결하게 작성할 수 있습니다. 그러나 그것은 물론 끔찍합니다.

 
fxsaber :

매크로를 통해 다양한 설정을 사용할 때 논리 연산 을 통해 간결하게 작성할 수 있습니다. 그러나 그것은 물론 끔찍합니다.

"목적이 수단을 정당화합니다"의 예

내 질문 은 나와 완전히 다르고 이해할 수 없는 스타일에 관한 것이었습니다.

 
fxsaber :

작은 괴물.

그들은 주어진 말의 이빨을 보지 않습니다. 하지만 여기에 수십 분의 잊지 못할 디버깅 시간을 제공한 다른 사람의 코드에 대한 몇 가지 예가 더 있습니다. 아마도 누군가가 당신의 코드를 알아볼 것입니다.

      Res = (!FillingMode || (Type >= ORDER_FILLING_RETURN ) || ((FillingMode & (Type + 1 )) != Type + 1 )) ?
            (((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE ) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT )) ?
             ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC ) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK )) :
            ( ENUM_ORDER_TYPE_FILLING )Type;
     return ((arrow_color == INT_MAX ) ? (MT4ORDERS::NewOrderCheck() ? 0 : - 1 ) :
           (((( int )arrow_color != INT_MIN ) || MT4ORDERS::NewOrderCheck()) &&
            MT4ORDERS:: OrderSend (MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ?
            (MT4ORDERS::IsHedging ? ( long )MT4ORDERS::LastTradeResult.order : // PositionID == Result.order - особенность MT5-Hedge
             ((MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_DEAL ) ?
              (MT4ORDERS::IsTester ? (_B2(:: PositionSelect (MT4ORDERS::LastTradeRequest.symbol)) ? PositionGetInteger ( POSITION_TICKET ) : 0 ) :
                                       // HistoryDealSelect в MT4ORDERS::OrderSend
                                      :: HistoryDealGetInteger (MT4ORDERS::LastTradeResult.deal, DEAL_POSITION_ID )) :
              ( long )MT4ORDERS::LastTradeResult.order)) : - 1 ));

그렇게 쓰기 쉬웠는지 모르겠지만 디버깅, 더군다나 읽기만 하는 것은 비현실적입니다. 그리고 그렇게 쓸 이유가 없다고 봅니다.

 
traveller00 :

그리고 그렇게 쓸 이유가 없다고 봅니다.

물론 주관적입니다. 나는 추가 변수와 다중 반환을 좋아하지 않습니다. 어떤 이유에서인지 EX5가 없으면 더 짧고 빠르게 실행될 것이라고 생각합니다.

 
fxsaber :

물론 주관적입니다. 나는 추가 변수와 다중 반환을 좋아하지 않습니다. 어떤 이유에서인지 EX5가 없으면 더 짧고 빠르게 실행될 것이라고 생각합니다.

그건 그렇고, 코드가 더 짧고 빨라질 것이라는 이러한 확신은 그것이 정당하다는 사실이 아닙니다.

이것

 bool a=A();
bool b=B();
//....много промежуточных результатов
bool x=X();
bool Res=a||b||x ;
return Res;

그리고 여기있다

 return A()||B()||X();

나는 속도가 동일할 것이라고 확신합니다(사용된 코드와 메모리의 양).

두 번째 옵션은 쓰기가 더 빠르고 모든 사람이 작성하고 무언가를 추가/복잡해야 할 때 두 번째 옵션을 남겨두고 이미 읽기 어려울 정도로 부풀려졌을 뿐입니다.

이와 관련하여 주기적으로 리팩토링을 수행하면 문제가 없습니다.

 
Aleksey Mavrin :

이와 관련하여 주기적으로 리팩토링 을 수행하면 문제가 없습니다.

자유시간이 많거나 객관적으로 너무 압박을 받아 빠져나갈 수 없는 사람들에게만.

ZY 리턴이 많으면 100% 다른 코드가 됩니다.
 
fxsaber :

자유시간이 많거나 객관적으로 너무 압박 을 받아 빠져나갈 수 없는 사람들에게만.

ZY 리턴이 많으면 100% 다른 코드가 됩니다.

이해하지만 부분적으로는 동의합니다. 코드가 디버깅을 위해 "완벽하게 준비된" 경우 더 빨리 발견될 수 있는 비교적 긴 오류 포착이 모든 사람에게 발생했다고 생각합니다.

무엇이 더 많은 시간을 소모하는지 수 없습니다. "편리한" 코드를 더 길게 작성하거나 버그를 디버깅하고 검색하는 등 저는 항상 다르게 생각합니다.

 
fxsaber :

ZY 리턴이 많으면 100% 다른 코드가 됩니다.

디버거에서 C++ VS2019

원천:

 bool a( int v) { return (v > 0 ); }
bool b( int v) { return (v < 0 ); }
bool c( int v) { return (v == 0 );}

bool tst1( int v1, int v2, int v3)
{
         if (a(v1)) return ( true );
         if (b(v2)) return ( true );
         if (c(v3)) return ( true );
         return ( false );
}

bool tst2( int v1, int v2, int v3)
{
         return (a(v1) && b(v2) && c(v3));
}

int main()
{
         int x = 1 , y= 2 , z= 3 ;
         bool result1 = tst1(x, y, z);
         bool result2 = tst2(x, y, z);
}

asm의 디버거

 bool tst1( int v1, int v2, int v3)
{
         if (a(v1)) return ( true );
000 E1918  mov         eax,dword ptr [v1]  
000 E191B  push        eax  
000 E191C  call        a ( 0 E137Ah)  
000 E1921  add         esp, 4   
000 E1924  movzx       ecx,al  
000 E1927  test        ecx,ecx  
000 E1929  je          tst1+ 3 Fh ( 0 E192Fh)  
000 E192B  mov         al, 1   
000 E192D  jmp         tst1+ 6 Fh ( 0 E195Fh)  
         if (b(v2)) return ( true );
000 E192F  mov         eax,dword ptr [v2]  
000 E1932  push        eax  
000 E1933  call        b ( 0 E13ACh)  
000 E1938  add         esp, 4   
000 E193B  movzx       ecx,al  
000 E193E  test        ecx,ecx  
000 E1940  je          tst1+ 56 h ( 0 E1946h)  
000 E1942  mov         al, 1   
000 E1944  jmp         tst1+ 6 Fh ( 0 E195Fh)  
         if (c(v3)) return ( true );
000 E1946  mov         eax,dword ptr [v3]  
000 E1949  push        eax  
000 E194A  call        c ( 0 E11B8h)  
000 E194F  add         esp, 4   
000 E1952  movzx       ecx,al  
000 E1955  test        ecx,ecx  
000 E1957  je          tst1+ 6 Dh ( 0 E195Dh)  
000 E1959  mov         al, 1   
000 E195B  jmp         tst1+ 6 Fh ( 0 E195Fh)  
         return ( false );
000 E195D  xor         al,al  
}


 bool tst2( int v1, int v2, int v3)
{
         return (a(v1) && b(v2) && c(v3));
000 E19C8  mov         eax,dword ptr [v1]  
000 E19CB  push        eax  
000 E19CC  call        a ( 0 E137Ah)  
000 E19D1  add         esp, 4   
000 E19D4  movzx       ecx,al  
000 E19D7  test        ecx,ecx  
000 E19D9  je          tst2+ 6 Dh ( 0 E1A0Dh)  
000 E19DB  mov         edx,dword ptr [v2]  
000 E19DE  push        edx  
000 E19DF  call        b ( 0 E13ACh)  
000 E19E4  add         esp, 4   
000 E19E7  movzx       eax,al  
000 E19EA  test        eax,eax  
000 E19EC  je          tst2+ 6 Dh ( 0 E1A0Dh)  
000 E19EE  mov         ecx,dword ptr [v3]  
000 E19F1  push        ecx  
000 E19F2  call        c ( 0 E11B8h)  
000 E19F7  add         esp, 4   
000 E19FA  movzx       edx,al  
000 E19FD  test        edx,edx  
000 E19FF  je          tst2+ 6 Dh ( 0 E1A0Dh)  
000 E1A01  mov         dword ptr [ebp- 0 C4h], 1   
000 E1A0B  jmp         tst2+ 77 h ( 0 E1A17h)  
000 E1A0D  mov         dword ptr [ebp- 0 C4h], 0   
000 E1A17  mov         al, byte ptr [ebp- 0 C4h]  
}



나는 계산하지 않기 위해 2개의 열에서 명령에 대한 하나의 호출을 줄였습니다.

ts1:                                                    tst2:
000 E1918  mov         eax,dword ptr [v1]                 000 E19C8  mov         eax,dword ptr [v1]
000 E191B  push        eax                               000 E19CB  push        eax  
000 E191C  call        a ( 0 E137Ah)                       000 E19CC  call        a ( 0 E137Ah)  
000 E1921  add         esp, 4                              000 E19D1  add         esp, 4   
000 E1924  movzx       ecx,al                             000 E19D4  movzx       ecx,al  
000 E1927  test        ecx,ecx                           000 E19D7  test        ecx,ecx  
000 E1929  je          tst1+ 3 Fh ( 0 E192Fh)                 000 E19D9  je          tst2+ 6 Dh ( 0 E1A0Dh)  
000 E192B  mov         al, 1                                000 E19DB  mov         edx,dword ptr [v2]  
000 E192D  jmp         tst1+ 6 Fh ( 0 E195Fh)                 000 E19DE  push        edx 


보시다시피 여기에서 명령이 거의 서로 반복됩니다. 첫 번째 테스트에서 몇 가지 반환값을 더 추가해야 한다는 것이 분명합니다.

99% 확실하게 프로세서 수준에서 이러한 코드는 사이클까지 동일한 속도로 실행될 것이라고 생각합니다. 프로세서에는 여전히 최적화, 병렬화 및 xs가 있습니다.