OOP vs programmazione procedurale - pagina 11

 
Реter Konow:

Secondo me, c'è un difetto nel vostro sistema di risoluzione dei problemi. Il problema stesso dovrebbe essere chiaro e preciso, e quindi anche la sua soluzione. Se la soluzione è torbida e definita dalle parole "Il sistema si è dimostrato molto ragionevole" (come può essere ragionevole in 270 kb di codice?!), significa che l'autore capisce approssimativamente come funziona il suo sistema. E sono gli spaventosi artifizi di sintassi e le entità superflue nella soluzione che gli impediscono di capirla fino in fondo.

La ragionevolezza sta nel "potere predittivo" - un cambiamento significativo dei protocolli di lavoro non ha richiesto cambiamenti nel codice degli esperti responsabili della logica del loro lavoro. La modifica del codice era solo nel posto che gestiva direttamente il terminale a basso livello.


Il codice dato mostra molto bene come tutti gli OOP-hack possono essere ben sostituiti da "hack funzionali". Cioè, esattamente quello che dicevo sopra - può essere scritto in entrambi i modi.

Ma guardando il tuo codice vedo che devi tenere molto di più in memoria. Diciamo che nella maggior parte dei tuoi "se" sono "annegato" in un momento. Sono corretti, ma se dovessi mantenere questo codice - inserirei prima di ogni condizione qualche riga di commento, cosa fa questo controllo e perché questi campi sono usati nell'array. Simile al commento prima di dichiarare l'interfaccia CTradePositionI nel mio codice. Inoltre - condizioni complesse - mi stresserebbe anche personalmente molto.

Personalmente farei più errori nel tuo codice, e sarebbe più difficile prenderli. Cioè, nonostante la correttezza e la logica di un tale codice sarebbe più difficile per me mantenerlo, che se avessi scritto tutto in stile OOP.

In stile OOP dichiarerei interfacce di finestre, parti di canvas, elementi, canvas, poi scriverei classi reali di quegli oggetti, e poi darei puntatori a quelle interfacce nei blocchi giusti, e lavorerei specificamente con quelle entità, che sarebbero necessarie al momento - tutto il resto non sarebbe disponibile a quel punto. Questo per non dover ricordare cosa appartiene a cosa e cosa è responsabile di cosa. Quando si ottiene l'interfaccia più semplice composta da un paio di funzioni, si lavora solo con quella, e il resto è inutile e non disponibile per voi. Non c'è bisogno di ricordare assolutamente nulla.

 
George Merts:

Beh, hai fatto un casino...

È chiaro che qualsiasi compito può essere risolto sia in stile OOP, con l'assegnazione di interfacce, la costruzione della gerarchia di ereditarietà, la dichiarazione di funzioni virtuali, sia in puro stile procedurale - si può anche infilare tutto in una funzione enorme.

La questione è nella convenienza e nell'efficienza del supporto.

In MT - il posto più adatto all'OOP è il sistema degli ordini. Personalmente, ho interfacce virtuali per "posizione" e "componenti di posizione". "Posizione" è un insieme di ordini in MT4 o un insieme di posizioni in MT5. "Componente della posizione" è un ordine individuale o una posizione MT5 individuale (hedge o netting).

Ecco il file di interfaccia attuale(Retag Konow, si può apprezzare il numero di commenti rispetto alla quantità di codice, e li aggiungo periodicamente quando incontro che non ricordo alcune sottigliezze. Per esempio, dimentico regolarmente quali oggetti reali costituiscono un "componente di posizione". Non ho bisogno di ricordarlo - l'Expert Advisor lavora con i componenti secondo l'interfaccia, e quello che c'è dietro quell'interfaccia in realtà non ha importanza. Ma, devo ritornarci durante la modifica - ecco perché ho bisogno molto spesso del primo commento in questo file):

Il file per l'interfaccia del componente commerciale è il seguente (l'ho già dato sopra, ma lo ripeto:

In base a queste interfacce - ho implementato sia il sistema di ordini MT4 che MT5 per ordini reali e storici.

L'Expert Advisor che richiede una posizione riceve questa interfaccia e non deve tenere conto della differenza tra gli ordini MT4 e MT5. E se viene aggiunto un nuovo tipo di ordine o viene cambiato l'ordine di lavorare con essi - non cambierà nulla per l'Expert Advisor, solo la nuova classe del tipo di ordine verrà aggiunta, e supporterà anche questa interfaccia.

Il sistema si è dimostrato molto intelligente quando sono stati introdotti i conti di copertura. Gli esperti - assolutamente nessun cambiamento rispetto a questo.

Reg Konow, come ti occupi della differenza dei tipi di ordine in MT4 e MT5?

Se viene introdotto un nuovo tipo di conto (oltre alla copertura e al netting) - quali cambiamenti dovranno essere fatti, e nello stesso posto?

A mio parere, in realtà, se ricordate tutto il vostro codice alla lettera, e potete facilmente dire perché questa o quella linea è stata scritta nel vostro codice un anno fa - allora, davvero, tutti questi miglioratori OOP sono solo gesti inutili.

L'OOP è necessaria proprio quando non si ricorda tutto quando si modifica il codice - l'OOP permette di isolare i blocchi l'uno dall'altro per limitare l'insieme delle entità disponibili in qualsiasi momento in un particolare punto del programma.


George, a volte scrivi una tale clinica sulle donne, ma rispetta il codice ))))

 
George Merts:

La ragionevolezza sta nel "potere predittivo" - un cambiamento significativo nei protocolli operativi - non ha richiesto modifiche al codice EA responsabile della logica del loro funzionamento. La modifica del codice è stata fatta solo nel posto che gestiva direttamente il terminale a basso livello.


Il codice dato mostra molto bene come tutti gli OOP-hack possono essere ben sostituiti da "hack funzionali". Cioè, esattamente quello che dicevo sopra - può essere scritto in entrambi i modi.

Ma guardando il tuo codice vedo che devi tenere molto di più in memoria. Diciamo che nella maggior parte dei tuoi "se" sono "annegato" in un momento. Sono corretti, ma se dovessi mantenere questo codice - inserirei prima di ogni condizione qualche riga di commento, cosa fa questo controllo e perché questi campi sono usati nell'array. Simile al commento prima di dichiarare l'interfaccia CTradePositionI nel mio codice. Inoltre - condizioni complesse - mi stresserebbe anche personalmente molto.

Personalmente farei più errori nel tuo codice, e sarebbe più difficile prenderli. Cioè, per tutta la correttezza e la logica di un tale codice, il suo supporto sarebbe più difficile per ME che se avessi scritto tutto in stile OOP.

In stile OOP dichiarerei interfacce di finestre, parti di canvas, elementi, canvas, poi scriverei classi reali di quegli oggetti, e poi darei puntatori a quelle interfacce nei blocchi giusti, e lavorerei specificamente con quelle entità, che sarebbero necessarie al momento - tutto il resto non sarebbe disponibile a quel punto. Questo per non dover ricordare cosa appartiene a cosa e cosa è responsabile di cosa. Quando si ottiene l'interfaccia più semplice costituita da un paio di funzioni, si lavora solo con quella, e il resto è inutile e non disponibile per voi. Non devi ricordare assolutamente nulla.

Nel mio codice, il gran numero di caratteri e il loro annidamento è dovuto al comportamento complesso di diverse definizioni di controllo a diversi eventi e in diversi stati. Tuttavia, questa funzione copre tutte queste opzioni e "serve" completamente l'intera GUI. Quando si ridisegna qualsiasi elemento, il colore della parte è determinato dal valore originale del colore nel kernel e da questa funzione.

P.S. Per quanto riguarda lo stile OOP o procedurale, allora - "A ciascuno il suo" (c).

 
Alexey Volchanskiy:

Georges, a volte scrivi una tale clinica sulle donne, ma rispetta il codice )))

Riguardo al codice - sono lusingato. (Davvero, non scherzo).

E riguardo alle ragazze... Non sono un Casanova come te... Sono io che mi trattengo e non dico quello che penso... Ho sempre avuto e ho ancora molti problemi in questo senso, anche se una vita personale confortevole è sempre stata molto importante per me... È un bene che qualche volta la fortuna mi abbia sorriso, e che ci sia qualcosa da ricordare, dopo tutto.

 
George Merts:

Riguardo al codice - sono lusingato. (Davvero, non scherzo).

E riguardo alle donne... Non sono un Casanova come te... Sono io che mi trattengo e non dico quello che penso... Ho sempre avuto e ho ancora molti problemi in questo senso, anche se una vita personale confortevole è sempre stata molto importante per me... È un bene che qualche volta la fortuna mi abbia sorriso, e che ci sia qualcosa da ricordare, dopo tutto.


È solo che abbiamo atteggiamenti diversi nei confronti delle donne. Penso che dovrebbero essere aiutati. Sì, sono capricciosi, con i loro cavilli, volubili nelle loro predilezioni, ecc. Bisogna solo non prenderli sul serio, altrimenti ci saranno tragedie morali.

 
George Merts:

Beh, hai fatto un casino...

È chiaro che qualsiasi compito può essere risolto sia in stile OOP, con l'assegnazione di interfacce, la costruzione della gerarchia di ereditarietà, la dichiarazione di funzioni virtuali, sia in puro stile procedurale - si può anche infilare tutto in una funzione enorme.

La questione è nella convenienza e nell'efficienza del supporto.


Possiamo farlo, ma l'efficienza del funzionamento varia. Non stiamo parlando di supporto qui, è troppo relativo.

Ci sono compiti che proceduralmente non possono essere risolti in modo ottimale.

 
Alexey Volchanskiy:

Abbiamo solo atteggiamenti diversi nei confronti delle donne. Penso che dovrebbero essere aiutati. Sì, sono irritabili, con le loro stranezze, volubili nelle loro predilezioni, ecc. Bisogna solo non prenderli sul serio, altrimenti ci saranno tragedie morali.


Alexei, hai fatto un esperimento su quanto sia infinito il desiderio di aiuto di una donna? Ha incontrato la soddisfazione dell'aiuto e quanto è durato?

 
Реter Konow:


Immagino che tu non usi nemmeno le strutture per memorizzare i dati? I vostri array multidimensionali riportano alla memoria l'antico MQL4, dove si dovevano usare tali soluzioni per mancanza di strutture. Ma ora qual è il punto? Per esempio

 int Элемент                     =  G_CORE[Окно][Деталь_полотна][_MAIN_ELEMENT];
 int Состояние_детали            =  G_CORE[Окно][Элемент][_CURRENT_STATE]; 

potreste sostituirlo con

 int Элемент                     =  G_CORE[Окно][Деталь_полотна].MAIN_ELEMENT;
 int Состояние_детали            =  G_CORE[Окно][Элемент].CURRENT_STATE; 

Questo è più breve, più sicuro e più veloce. Nel primo caso non c'è controllo in fase di compilazione su quei valori di indici di array che gli passate. E poi devi pulire ogni sorta di "array out of range" in runtime - e questo nel migliore dei casi. Peggio è quando l'indice è accettabile ma non corretto. Ecco perché è buona pratica di programmazione coinvolgere il compilatore il più possibile, rilevando gli errori in fase di compilazione e non catturandoli a runtime come nel tuo caso.

Sì, in questo momento sei bravo a ricordare quali valori dare in pasto a dove. Ma questo è probabilmente perché sei costantemente occupato con questo progetto. Provate a fare una pausa per, diciamo, mezzo anno, e sentite la differenza. Alcune persone lo hanno già menzionato. O pensi che siamo tutti sclerotici o qualcosa del genere? :) È una cosa comune per un programmatore...

Quindi il compito è quello di ridurre al minimo la probabilità di darsi la zappa sui piedi. Vi consiglio vivamente di creare i vostri tipi usando enum invece dell'onnipresente int. E non devono necessariamente avere valori enumerati, l'importante è che sia un tipo separato e indipendente, che sarà controllato dal compilatore, e non vi permetterà di scambiare gli argomenti delle funzioni, ecc.

 

Scrivo solo ed esclusivamente OOP.

Nel 1900, non potevo entrarci - Pascal 6.0, poi Borland C++ 4.5. Ma quando l'ho imparato, non riesco a immaginare nient'altro - è così semplice e conveniente ora.

 
Alexey Navoykov:

Immagino che tu non usi nemmeno le strutture per memorizzare i dati? I vostri array multidimensionali riportano alla memoria l'antico MQL4, dove si dovevano usare tali soluzioni per mancanza di strutture. Ma ora qual è il punto? Per esempio

potreste sostituirlo con

Questo è più breve, più sicuro e più veloce. Nel primo caso non c'è controllo in fase di compilazione su quei valori di indici di array che gli passate. E poi devi pulire ogni sorta di "array out of range" in runtime - e questo nel migliore dei casi. Peggio ancora è quando l'indice è accettabile ma non corretto. Ecco perché è buona pratica di programmazione coinvolgere il compilatore il più possibile, rilevando gli errori in fase di compilazione e non catturandoli a runtime come nel tuo caso.

Sì, in questo momento sei bravo a ricordare quali valori dare in pasto a dove. Ma questo è probabilmente perché sei costantemente occupato con questo progetto. Provate a fare una pausa per, diciamo, mezzo anno, e sentite la differenza. Alcune persone lo hanno già menzionato. O pensi che siamo tutti sclerotici o qualcosa del genere? :) È una cosa comune per un programmatore...

Quindi il compito è quello di ridurre al minimo la probabilità di darsi la zappa sui piedi. Vi consiglio vivamente di creare i vostri tipi usando enum invece dell'onnipresente int. E non devono avere valori enumerati, l'importante è che sia un tipo separato e indipendente, che sarà controllato dal compilatore, e non vi permetterà di scambiare gli argomenti delle funzioni, ecc.

Ho letto i tuoi post su altri thread e ho capito che sei un grande esperto di programmazione. Naturalmente, io non sono e non pretendo di essere tale. Tuttavia, mi considero uno specialista nel risolvere i compiti in quanto tali. Beh, non sei d'accordo che l'efficacia della soluzione è la cosa più importante?

Il sovraccarico della sintassi e la complessità delle regole non hanno mai contribuito a mantenere la soluzione efficiente. Sono state la semplicità e la brevità espresse in concisione, universalità e leggibilità dei blocchi di codice a farlo.

Le mie regole nella programmazione sono meno codice, meno regole, meno sintassi e meno commenti a spese dell'uso del linguaggio nativo e di nomi significativi di variabili e funzioni.

La mia tesi principale è "se puoi fare a meno di qualcosa in una soluzione, dovresti assolutamente farne a meno".

Non credo affatto che ci siano persone sclerotiche qui)). Semplicemente guardando i codici dati diventa chiaro perché sono facilmente dimenticati. Anche il fatto stesso di programmare in una lingua straniera gioca un ruolo. Quando si programma nella propria lingua, ci si sente assolutamente diversi. Senti potere e libertà invece di tensione e costrizione. Una lingua straniera richiede più sforzo, richiede più tempo per entrare nel codice e scivola fuori dalla testa più velocemente. È solo un "fattore biologico".

Pertanto, considero (abbastanza ragionevolmente) inefficiente usare OOP in generale per risolvere i miei compiti. Un sacco di regole, sintassi e tutto in una lingua straniera. In questo modo il talento non può svilupparsi veramente, il che significa che il risultato sarà più povero.

Motivazione: