Sullo stile di codifica - pagina 3

 

Preferisco separare le funzioni in azioni separate, in modo che il codice abbia una struttura chiara... è più facile da ottimizzare...

 
Mathemat >> :

Fondamentalmente, è un codice normale che esegue gli stessi calcoli della costruzione if annidata. Ma da qualche parte ho sentito che il ritorno nella funzione dovrebbe essere uno. Probabilmente lo si fa per non confondersi con loro. Non seguo strettamente questa regola.

Per altri aspetti il mio approccio è molto simile al tuo, C-4, tranne che per un paio di dettagli.


Sì, esiste una tale opinione. Ma l'operatore di ritorno non è la stessa cosa di GOTO. In pratica non ho mai incontrato alcun lancio di ritorno inaspettato. Al contrario, il programma diventa più leggibile e strutturato quando si usano tali operatori e condizioni (tutti i controlli vanno uno per uno dall'alto in basso formando una specie di colonna). Inoltre, a differenza di if() l'operatore return garantisce un'uscita dalla funzione, e questo è esattamente ciò che è necessario nella maggior parte dei casi, perché non ha senso valutare ulteriormente i dati se qualche condizione non è soddisfatta.

 

Mi è piaciuta molto l'ultima regola: "Non usare mai l'operazione 'copia e incolla'". Ma, ahimè, non lo seguo. Come è possibile usare l'editor dell'IDE e non usare il "Copy&Paste" che fa risparmiare molto tempo?

A quanto pare, no, non è così: ho notato che è per questo che trovo spesso errori logici, che sono difficili da cogliere.

P.S. Il motore del forum non mi permette di formattare questo frammento del mio primo post

// open
// .pairsToOpen
// .combineAndVerify( )
// Собирает из двух валют символ и выполняет все проверки, нужные для его открытия.
// Возвращает валидность пары для открытия.
// Последний аргумент - [...]
bool
combineAndVerify( string quoted, string base, double& fp1 )

Esattamente come è fatto con me: le prime tre righe sembrano diverse, più strutturate. Ok, con le buone o con le cattive:


Come faccio a commentare le funzioni

 

Ecco alcune altre regole che mi sono venute in mente di recente e che ho già implementato a casa mia:


1. Le variabili globali (GV) non sono dichiarate tutte all'inizio del codice, ma, se necessario, prima delle funzioni corrispondenti che le utilizzano.

2. Prima di ogni funzione, descriviamo anche quali GP utilizza (input) e quali modifica (output) quando viene chiamata. E dopo la funzione, potete anche spiegare quali GP non saranno più utilizzati.

3. Tutti questi commenti, insieme alle linee di separazione vuote tra le funzioni e la limitazione "lunghezza della funzione non più di 20 linee" aumentano la dimensione del file di codice di 1,5-2 volte. Non lo rende più difficile da compilare, e non abbiamo carta da perdere per questo.

4. A cosa servono i medici di base? Supponiamo di calcolare una qualche variabile di tipo complesso nella funzione foo( ..., <tipo>& variabile ), passandola per riferimento. Poi, se usiamo questa variabile ripetutamente in vari frammenti di codice, dovremo chiamare la funzione foo( ) ogni volta. Sembra che vada bene - oltre a spendere tempo ogni volta per la valutazione di questa variabile, aggiungiamo anche un paio di righe (per la dichiarazione della variabile e la chiamata della funzione) in ogni funzione che usa la variabile. Perché? Se questo è il cosiddetto riutilizzo del codice, è in qualche modo subottimale: oltre a rendere la funzione foo( ) troppo frequente nell'uso, rompiamo anche la struttura delle chiamate di funzione, rendendo la funzione utente foo( ) "fuori categoria" e le sue chiamate non gerarchiche. È più facile dichiarare la variabile come variabile "fuori categoria", cioè globale.

Personalmente, preferirei funzioni rigidamente gerarchizzate a questo discutibile riutilizzo del codice. Ho già detto della gerarchia: ogni funzione dell'ordine n-esimo è chiamata solo da una funzione dell'ordine (n-1)-esimo e solo dalla "propria" funzione. Vedi il mio esempio che spiega la gerarchia delle funzioni nell'immagine con sfondo verde qui sopra.

5. Ma naturalmente, il codice non è sempre ottimale nel senso della gerarchia, e a volte bisogna chiamare funzioni "aliene". In questo caso potete scrivere il suo posto nella gerarchia delle funzioni tra parentesi /* */ prima del nome della funzione "aliena".


Forse tutto questo è sciocco ed eccessivo, ma so molto bene che sto scrivendo del codice che probabilmente dovrò modificare più di una volta. Qui penso che sia meglio rassicurarsi nei commenti e nella struttura.

 
Vinin >> :
Sulla dimensione della funzione. Cerco di fare in modo che la funzione si adatti a uno schermo. In modo che possiate vedere il tutto.

Cerco di scrivere codice in modo che il codice sorgente possa essere corretto in blocchi, ed è conveniente aggiungere e cambiare

i commenti non dovrebbero essere meno del 30% della dimensione del codice

( imparato a fare questo negli 80x, guardando il codice sorgente dei sistemi operativi UNIX, RT11)

mezzo anno dopo il codice è dimenticato - se hai bisogno di correggerlo, i commenti ti danno una rapida comprensione dell'argomento!

(Ho avuto un'esperienza reale in un sito di produzione quando stavo leggendo il mio codice dopo 5 anni)

grazie ai commenti ho ricordato tutto in un giorno e ho fatto le modifiche entro la sera)

Cerco di allineare il codice per la leggibilità, non per lesinare sugli spazi e i rientri

confronta i due esempi: quale codice si legge meglio?


1)

extern string gslM001rus="Все что касается индикации" ;
// 
extern bool gpInfoParameter =false ; // выводить параметры
extern bool gpInfoLevel =true ; // выводить параметры
extern bool _gDeleteObjectGrafic =0 ; // 1-Удалять объекты на графике при завершении 0-не удалять
extern double FlatSBuy =0.0010 ; // =0.00050; // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern double FlatSSell =0.0010 ; // =0.00050; // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern int DayHistory =50 ; // Сколько дней в истории показывать
// флет азии 
extern int iTimeEndFlatAsiaHour = 5 ; // Конец утреннего флета
extern int iTimeEndFlatAsiaMin = 15 ; // Конец утреннего флета
// Время длины флета измеряется минутами от окончания и назад
// 360 минут эт о6 часов назад от 5:15 получаем 23:15 вчерашнего дня
extern int iTimeEndFlatAsiaSizeMin = 360 ; // + количество минут  флета// 
extern string sTimeBreakFlatAsia ="20:00:00" ; // Время до которого разумно ждать пробой и выставление ордеров
extern int pУровниHighLowDAY =1 ; // выводить уровни HIGH LOW
extern color ЦветПятницыHIGH =DeepSkyBlue ;
extern color ЦветПятницыLOW =DeepSkyBlue ;
extern color ЦветHIGHDAY =DarkViolet ;
extern color ЦветLOWDAY =DarkViolet ;
extern color lColorFAH =OrangeRed ;
extern color lColorFAL =SandyBrown ;
extern color lColorSignalSELL =Red ;
extern color lColorSignalBUY =Red ;

 


2)


extern string gslM001rus="Все что касается индикации"      ;
//                                                                  
extern bool   gpInfoParameter         =false               ; // выводить параметры
extern bool   gpInfoLevel             =true                ; // выводить параметры
extern bool   _gDeleteObjectGrafic    =0                   ; // 1-Удалять объекты на графике при завершении 0-не удалять
//                                                            
extern double FlatSBuy                =0.0010              ; // =0.00050;  // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern double FlatSSell               =0.0010              ; // =0.00050;  // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern int    DayHistory              =50                  ; // Сколько дней в истории показывать

//                                                         
// флет азии                                               
//                                                         
extern int    iTimeEndFlatAsiaHour    = 5                  ; // Конец утреннего флета
extern int    iTimeEndFlatAsiaMin     = 15                 ; // Конец утреннего флета
// 
// Время длины флета измеряется минутами от окончания  и назад
//   360 минут эт о6 часов назад от 5:15 получаем 23:15 вчерашнего дня
//
extern int    iTimeEndFlatAsiaSizeMin = 360                ; // + количество минут  флета
//                                                            
//                                                              
//                                                            
extern string sTimeBreakFlatAsia      ="20:00:00"          ; // Время до которого разумно ждать пробой и выставление ордеров
//                                                         
extern int    pУровниHighLowDAY       =1                   ; // выводить уровни HIGH LOW
//
extern color  ЦветПятницыHIGH         =DeepSkyBlue         ;
extern color  ЦветПятницыLOW          =DeepSkyBlue         ;
extern color  ЦветHIGHDAY             =DarkViolet          ;
extern color  ЦветLOWDAY              =DarkViolet          ;
extern color  lColorFAH               =OrangeRed           ;
extern color  lColorFAL               =SandyBrown          ;
extern color  lColorSignalSELL        =Red                 ;
extern color  lColorSignalBUY         =Red                 ;
//
//
 
                                                    
 
Mathemat >> :

if(param1!=1)return;

if(param2!=2)return;

...

if(param5!=5)return;

Print("Наконец-то дошли!");

Fondamentalmente, è un codice normale che esegue gli stessi calcoli della costruzione if annidata. Ma da qualche parte ho sentito che il ritorno nella funzione dovrebbe essere uno. Probabilmente, è fatto per evitare di confondersi con loro. Non seguo strettamente questa regola.

Per il resto, il mio approccio è molto simile al tuo, tranne che per un paio di dettagli.

Preferisco lo stesso modo di uscire da solo!

più facile da controllare


Se volete restituire un valore, allora


invece di

se ( a > c )

ritorno ( 3 );

se ( l < b )

ritorno (5);

...

...

se ( h != b )

ritorno (100);

---

preferire


se ( a > c )

codret = 3;

se ( l < b )

codret = 5;

...

...

se ( h != b )

codret = 100;


// specialmente se alcune operazioni aggiuntive comuni a tutte le uscite sono eseguite prima del ritorno

... per esempio qui facciamo qualcos'altro

retrun( codret);

}


 

un po' di commenti...

Per dividere i testi in blocchi uso una linea di caratteri con il codice U0151. Per quelli che non lo sanno, si scrive così:

  1. tenere premuto Alt
  2. sulla tastiera numerica premere in sequenza le cifre del codice simbolo 0 poi 1 poi 5 poi 1
  3. rilascio Alt

per i font "corretti" si ottiene un segno meno ma senza "spazi" alle estremità. poi copiarlo tante volte quanto necessario una linea solida che serve come un buon bordo visivo...

// обычная линия
// -----------------------------------------------------------------------------------

// сплошная линия
// —————————————————————————————————

// —————————————————————————————————
// Вот такие часто делаю ЗАГОЛОВКИ
// —————————————————————————————————

 

anche una linea di chunking intelligente per il blocco di testo di commento - sembra perfettamente simmetrico, ma c'è una prima linea di apertura e una seconda di chiusura:


/*///—————————————————————————————————————————
это

blocco di commento multilinea
...................

/*///-----------------------------------------

 

Yura, il tuo esempio con un solo ritorno, ovviamente, è logico. Ma fate attenzione che in questo caso tutti gli if vengono sempre eseguiti, a differenza del caso con molti return, quando l'uscita dalla funzione si ottiene immediatamente dopo aver raggiunto la stringa con la condizione.

ForexTools, grazie, ho preso in considerazione le tue idee di design.