Hablando de la OLP en el salón - página 5

 
Alexey Volchanskiy:

He leído los diferentes intereses de cada uno... Actualmente estoy rediseñando una clase para la exposición y control de la red virtual, lo necesito.

Y he estado luchando durante 2 días con el constructor de copia y el operador de asignación. Es una clase complicada con miembros de datos en forma de punteros...

 
Dennis Kirichenko:

Llevo 2 días luchando con el constructor de copia y el operador de asignación. Hay una clase compleja con miembros de datos en forma de punteros...

Parece que escribo cosas muy primitivas...

 
Dennis Kirichenko:

Puede utilizar un puntero a una función.

¿Funcionará así con una función virtual?

Y siempre me han disgustado los punteros de función a nivel interno. No recuerdo ahora por qué, cuando se trabajaba en "C puro", se utilizaban los punteros de función. Pero cuando me pasé a C++ tuve que renunciar a ellos por alguna razón. Y no los he usado desde entonces. Un puntero - debe ser a un objeto.

Pero no voy a decir que tengo "toda la razón". Estoy de acuerdo en que tengo mucha experiencia de la vieja escuela.

 
fxsaber:

Parece que escribo cosas muy primitivas...

No seas modesto.

No creo que nadie pueda igualar su virtuoso uso de las definiciones.

 
George Merts:


...En mi caso, esta función tiene el siguiente aspecto:

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

      case FSM_BY_LAST_PRCDATA_A:      return(_CompareByLastPrcdataWith(pfdsAnother,true));
      case FSM_BY_LAST_PRCDATA_D:      return(_CompareByLastPrcdataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYDATA_A:      return(_CompareByLastMnydataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYDATA_D:      return(_CompareByLastMnydataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYLOTDATA_A:   return(_CompareByLastMnylotdataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYLOTDATA_D:   return(_CompareByLastMnylotdataWith(pfdsAnother,false));
      
      case FSM_BY_PRCYEARRECOVERY_A:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,true));
      case FSM_BY_PRCYEARRECOVERY_D:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYYEARRECOVERY_A:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYYEARRECOVERY_D:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYLOTYEARRECOVERY_A:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYLOTYEARRECOVERY_D:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,false));
      
      case FSM_BY_PRCVAR_A:            return(_CompareByPrcVarWith(pfdsAnother,true));
      case FSM_BY_PRCVAR_D:            return(_CompareByPrcVarWith(pfdsAnother,false));
      case FSM_BY_MNYVAR_A:            return(_CompareByMnyVarWith(pfdsAnother,true));
      case FSM_BY_MNYVAR_D:            return(_CompareByMnyVarWith(pfdsAnother,false));
      case FSM_BY_MNYLOTVAR_A:         return(_CompareByMnylotVarWith(pfdsAnother,true));
      case FSM_BY_MNYLOTVAR_D:         return(_CompareByMnylotVarWith(pfdsAnother,false));
      
      case FSM_BY_PRC_GRAILRATIO_A:    return(_CompareByPrcGrailratioWith(pfdsAnother,true));
      case FSM_BY_PRC_GRAILRATIO_D:    return(_CompareByPrcGrailratioWith(pfdsAnother,false));

      case FSM_BY_MAGIC_A:             return(_CompareByMagicWith(pfdsAnother,true));
      case FSM_BY_MAIGC_D:             return(_CompareByMagicWith(pfdsAnother,false));
      default:
         break;
      };
         
   return(NULL);
};

George, aquí no se puede ver si _CompareByPrcVarWith() es un método de clase o una función ordinaria, por ejemplo. En C++, existen punteros a los métodos de las clases. Allí tienen sus propias especificidades. Para ser honesto, no he tratado de usar tales punteros en MQL5.

Pero creo que todavía tiene una reserva para mejorar la estructura del código.

Después de todo, ¿qué es una función?

LaFUNCIÓN(lat.functio, "ejecución, desempeño; deber") es una relación entre elementos en la que un cambio en uno conlleva un cambio en el otro.

Es una función que hace algo. Las mismas acciones deben combinarse en el cuerpo de una función.

En su ejemplo es evidente que las funciones

CompararPorParteDeMaxDDCon(),

CompararPorParteDeMaxSLQueueWith(),

CompararPorLosÚltimosDatosCon(),

_CompareByLastMnydataWith(), etc.

hacer una COMPARACIÓN y dar el resultado de esta comparación. Se diferencian en los nombres. En mi opinión, no es una buena práctica. Deben distinguirse por los parámetros.

Así que. Creo que deberías fusionar todas las funciones en una, o hacerlas como métodos virtuales, o métodos de plantilla. Obviamente, las clases deben seguir la jerarquía "padre-hijo".

En general, es muy fácil escribir código complejo y muy difícil escribir código simple.

 
Dennis Kirichenko:

George, aquí no se ve si _CompareByPrcVarWith() es un método de clase o una función ordinaria. En C++ existen punteros a los métodos de las clases. Allí tienen sus propias especificidades. Sinceramente, no he intentado utilizar dichos punteros en MQL5.

Esta (y todas las que empiezan por un guión bajo) es una función protegida de la clase.

Se dedican a la ARREGLO y dan el resultado de esta comparación. Se diferencian en los nombres. En mi opinión, no es una buena práctica. Será mejor que se diferencien en los parámetros.

Así que. Creo que deberías fusionar todas las funciones en una, o hacerlas como métodos virtuales, o métodos de plantilla. Obviamente, las clases deben seguir la jerarquía "padre-hijo".

Pues bien, ¡todos se han fusionado en uno!

Sólo hay una función - Compare() pero tiene que realizar una comparación con una clave pasada. En consecuencia, elegimos una de las funciones protectoras específicas. Por eso están protegidos (protected), para que el usuario no pueda acceder a ellos - se llaman sólo desde Compare() y esto se indica con el subrayado.

Esta es también una de las reglas de diseño del código: una función que comienza con un guión bajo no está pensada para ser llamada por los usuarios, sólo sirve para ciertas tareas de la clase. El acceso a ella está restringido.

 
Dennis Kirichenko:

Llevo 2 días luchando con el constructor de copia y el operador de asignación. Hay una clase compleja con miembros de datos en forma de punteros...


Denis, quería decir que todo el mundo tiene diferentes enfoques. En realidad, cuando abrí el hilo ayer, me interesaba ver si aparecían los llorones de ayer, a lo "a-a-a-a OOP es muy complicado, SB es una caja negra horrible". No se presentaron, lo cual era de esperar.

Pero han surgido personas y cada una tiene un enfoque diferente. También es interesante en términos de proyectos compartidos, de los que tanto habla Renat.

ZS: compartir en proyectos sigue sin funcionar, lo intenté hace poco.

 
George Merts:

Esta (y todas las que empiezan por un guión bajo) es una función de protección de la clase.

Pues bien, ¡se han fusionado en uno!

Sólo hay una función - Compare(), pero debe realizar una comparación contra una clave pasada. En consecuencia, se elige una de las funciones particulares protestadas. Por eso están protegidos (protected), para que el usuario no pueda acceder a ellos - se llaman sólo desde Compare(), lo que se indica con el subrayado.

Esta es también una de las reglas de diseño del código: una función que comienza con un guión bajo no está pensada para ser llamada por los usuarios, sólo sirve para ciertas tareas de la clase. El acceso a ella está restringido.


¿Cómo se fusionan si tienes muchos métodos _CompareXXX()? Y debería haber 1 según tengo entendido.

Pregunta, por ejemplo, ¿se llama al método_CompareByPartOfMaxDDWith() en algún otro lugar que no sea CFactoryBalanceResultSeries::Compare()?

 
Dennis Kirichenko:

¿Cómo se hace la fusión si se tienen muchos métodos _CompareXXX()? Y debería haber 1 según tengo entendido.

Pregunta, por ejemplo, ¿se llama al método_CompareByPartOfMaxDDWith() en algún otro lugar que no sea CFactoryBalanceResultSeries::Compare()?

Si el método _CompareXXX() está solo, no es diferente de la función virtual original Compare().

La cuestión es que los métodos _CompareBy...() se llaman sólo desde el Compare() principal. Y el subrayado del principio lo advierte.

El método general Compare() acepta punteros a dos objetos y la clave que especifica la comparación. En este método general se analiza la clave, y después se llama al método específico, que está diseñado para comparar sólo una clave. Además, cada uno de estos métodos calcula el valor de las claves de dos objetos pasados y dependiendo de si la clave es int, double, bool o string - se llama al método (también protegido) de comparación del tipo concreto.

Todos los métodos _CompareBy...() - podríamos escribirlos en una sola función. Pero entonces, en mi opinión, la legibilidad del código se deterioraría.

 
George Merts:

Si sólo hay un método _CompareXXX(), no es diferente de la función virtual original Compare().

La cuestión es que los métodos _CompareBy...() se llaman sólo desde el Compare() principal. Y el subrayado del principio lo advierte.

El método general Compare() acepta punteros a dos objetos y la clave que especifica la comparación. En este método general se analiza la clave, y después se llama al método específico, que está diseñado para comparar sólo una clave. Y cada uno de estos métodos calcula el valor de las claves de dos objetos pasados y dependiendo de si la clave es int, double, bool o string - se llama el método (también protegido) de comparación de tipo concreto.

Todos los métodos _CompareBy...() podrían escribirse en una sola función. Pero entonces la legibilidad del código se deterioraría en mi opinión.


Entiendo lo que quieres decir. Supongo que es cuestión de gustos. Pero yo lo haría todo con un solo método. Especialmente, si los métodos protegidos y privados no son llamados en ninguna otra parte excepto enCompare().