Parlare dell'OLP nel salone - pagina 5

 
Alexey Volchanskiy:

Ho letto i diversi interessi di ognuno... Attualmente sto ridisegnando una classe per l'esposizione e il controllo della griglia virtuale, ne ho bisogno.

E ho lottato per 2 giorni con il costruttore di copia e l'operatore di assegnazione. È una classe complicata con membri di dati sotto forma di puntatori...

 
Dennis Kirichenko:

Ho lottato per 2 giorni con il costruttore di copie e l'operatore di assegnazione. C'è una classe complessa con membri di dati sotto forma di puntatori...

Sembra che io scriva cose molto primitive...

 
Dennis Kirichenko:

Potete usare un puntatore a una funzione.

Funzionerebbe così con una funzione virtuale?

E ho sempre detestato i puntatori a funzione internamente. Ora non ricordo perché, quando si lavorava in "C puro" - si usavano i puntatori a funzione. Ma quando sono passato al C++ ho dovuto rinunciarvi per qualche motivo. E da allora non li ho più usati. Un puntatore - deve essere ad un oggetto.

Ma non dirò che ho "assolutamente ragione". Sono d'accordo sul fatto che ho molta esperienza della vecchia scuola in me.

 
fxsaber:

Sembra che io scriva cose molto primitive...

Non essere modesto.

Non credo che nessuno possa eguagliare il tuo uso virtuoso delle definizioni.

 
George Merts:


...Con me questa funzione si presenta così:

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, non puoi vedere qui se _CompareByPrcVarWith() è un metodo di classe o una funzione ordinaria, per esempio. In C++, ci sono puntatori ai metodi di classe. Lì hanno le loro specificità. Ad essere onesti, non ho provato ad usare tali puntatori in MQL5.

Ma penso che tu abbia ancora una riserva per migliorare la struttura del codice.

Dopo tutto, cos'è una funzione?

FUNZIONE(lat.functio, "esecuzione, prestazione; dovere") è una relazione tra elementi in cui un cambiamento in uno comporta un cambiamento nell'altro.

È una funzione che fa qualcosa. Le stesse azioni dovrebbero essere combinate nel corpo di una funzione.

Nel tuo esempio è ovvio che le funzioni

_CompareByPartOfMaxDDWith(),

_CompareByPartOfMaxSLQueueWith(),

_CompareByLastPrcdataWith(),

_CompareByLastMnydataWith(), ecc.

fare un CONFRONTO e dare il risultato di questo confronto. Differiscono nei nomi. Imho, non è una buona pratica. Dovrebbero distinguersi per i parametri.

Quindi. Penso che dovreste unire tutte le funzioni in una sola, o renderle come metodi virtuali, o metodi template. Ovviamente, le classi devono seguire la gerarchia "genitore-figlio".

In generale, è molto facile scrivere codice complesso e molto difficile scrivere codice semplice.

 
Dennis Kirichenko:

George, qui non si vede se _CompareByPrcVarWith() è un metodo di classe o una funzione ordinaria. In C++ ci sono puntatori ai metodi di classe. Lì hanno le loro specificità. Onestamente, non ho provato a usare tali puntatori in MQL5.

Questa (e tutte quelle che iniziano con un trattino basso) è una funzione protetta della classe.

Sono impegnati nell'ARRANGEMENT e danno il risultato di questo confronto. Differiscono nei nomi. Imho, non è una buona pratica. È meglio che differiscano nei parametri.

Quindi. Penso che dovremmo unire tutte le funzioni in una sola, o renderle metodi virtuali, o metodi template. Ovviamente, le classi devono seguire la gerarchia "genitore-figlio".

Bene, sono tutti fusi in uno!

C'è solo una funzione - Compare() ma deve eseguire un confronto con una chiave passata. Corrispondentemente, scegliamo una delle funzioni di protezione specifiche. Ecco perché sono protetti (protected), in modo che l'utente non possa accedervi - sono chiamati solo da Compare() e questo è indicato dalla sottolineatura.

Questa è anche una delle regole di progettazione del codice - una funzione che inizia con un trattino basso non è destinata ad essere chiamata dagli utenti, serve solo a certi compiti in classe. L'accesso è limitato.

 
Dennis Kirichenko:

Ho lottato per 2 giorni con il costruttore di copie e l'operatore di assegnazione. C'è una classe complessa con membri di dati sotto forma di puntatori...


Denis, volevo dire che ognuno ha approcci diversi. In realtà, quando ho aperto il thread ieri, ero interessato a vedere se sarebbero apparsi i piagnoni di ieri, del tipo "a-a-a-a OOP è molto complicato, SB è un'orribile scatola nera". Non si sono presentati, il che è prevedibile.

Ma le persone sono emerse e ognuno ha un approccio diverso. È anche interessante in termini di progetti condivisi, di cui Renat parla tanto.

ZS: la condivisione nei progetti non funziona ancora, l'ho provato di recente.

 
George Merts:

Questa (e tutte quelle che iniziano con un trattino basso) sono funzioni di protezione della classe.

Bene, sono fusi in uno solo!

C'è solo una funzione - Compare(), ma deve eseguire un confronto con una chiave passata. Corrispondentemente, viene scelta una delle particolari funzioni protestate. Ecco perché sono protetti (protected), in modo che l'utente non possa accedervi - sono chiamati solo da Compare(), che è indicato dalla sottolineatura.

Questa è anche una delle regole di progettazione del codice - una funzione che inizia con un trattino basso non è destinata ad essere chiamata dagli utenti, serve solo a certi compiti in classe. L'accesso è limitato.


Come vengono uniti se si hanno molti metodi _CompareXXX()? E dovrebbe essercene 1, a quanto ho capito.

Domanda: per esempio, il metodo_CompareByPartOfMaxDDWith() è chiamato da qualche altra parte se non in CFactoryBalanceResultSeries::Compare() ?

 
Dennis Kirichenko:

Come si fa a unire se si hanno molti metodi _CompareXXX()? E dovrebbe essercene 1, a quanto ho capito.

Domanda: per esempio, il metodo_CompareByPartOfMaxDDWith() è chiamato da qualche altra parte se non in CFactoryBalanceResultSeries::Compare() ?

Se il metodo _CompareXXX() è uno, non è diverso dalla funzione virtuale Compare() originale.

Il punto è che i metodi _CompareBy...() sono chiamati solo dal principale Compare(). E la sottolineatura all'inizio lo avverte.

Il metodo generale Compare() accetta puntatori a due oggetti e la chiave che specifica il confronto. In questo metodo generale si analizza la chiave, e dopo si chiama il metodo specifico, che è progettato per confrontare solo una chiave. Inoltre, ognuno di questi metodi calcola il valore delle chiavi di due oggetti passati e a seconda che la chiave sia int, double, bool o string - viene chiamato il metodo (anche protetto) di confronto del tipo concreto.

Tutti i metodi _CompareBy...() - potremmo scrivere in una sola funzione. Ma allora, secondo me, la leggibilità del codice si deteriorerebbe.

 
George Merts:

Se c'è solo un metodo _CompareXXX(), non è diverso dalla funzione virtuale Compare() originale.

Il punto è che i metodi _CompareBy...() sono chiamati solo dal principale Compare(). E la sottolineatura all'inizio lo avverte.

Il metodo generale Compare() accetta puntatori a due oggetti e la chiave che specifica il confronto. In questo metodo generale si analizza la chiave, e dopo si chiama il metodo specifico, che è progettato per confrontare solo una chiave. E ognuno di questi metodi calcola il valore delle chiavi di due oggetti passati e a seconda che la chiave sia int, double, bool o string - si chiama il metodo (anche protetto) di confronto del tipo concreto.

Tutti i metodi _CompareBy...() potrebbero essere scritti in una sola funzione. Ma allora la leggibilità del codice si deteriorerebbe secondo me.


Capisco quello che vuoi dire. Credo che sia una questione di gusti. Ma io farei tutto con un solo metodo. Soprattutto, se i metodi protetti e privati non sono chiamati da nessun'altra parte tranneCompare().