Sobre el estilo de codificación - página 3

 

Prefiero separar las funciones en acciones independientes, para que el código tenga una estructura clara... es más fácil de optimizar...

 
Mathemat >> :

Básicamente, es un código normal que realiza los mismos cálculos que la construcción del if anidado. Pero en algún lugar he oído que el retorno en la función debe ser uno. Probablemente, se hace para no mezclarse con ellos. No sigo estrictamente esta regla.

En otros aspectos, mi enfoque es muy parecido al tuyo, C-4, salvo por un par de detalles.


Sí, existe esa opinión. Pero el operador return no es lo mismo que GOTO. En la práctica nunca me he encontrado con ningún lanzamiento de retorno inesperado. Por el contrario, el programa se vuelve más legible y texturizado cuando se utilizan dichos operadores y condiciones (todas las comprobaciones van una a una de arriba a abajo formando una especie de columna). Además, a diferencia de if() el operador return garantiza la salida de la función, y esto es exactamente lo que se necesita en la mayoría de los casos, porque no tiene sentido seguir evaluando los datos, si no se cumple alguna condición.

 

Me ha gustado mucho la última regla: "No utilizar nunca la operación 'copiar y pegar'". Pero, por desgracia, no lo sigo. ¿Cómo es posible utilizar el editor del IDE y no utilizar el "Copy&Paste" que ahorra mucho tiempo?

Resulta que no: me doy cuenta de que es por esto que a menudo encuentro errores lógicos, que son difíciles de detectar.

P.D. El motor del foro no me permite formatear este fragmento de mi primer mensaje

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

Exactamente como se hace conmigo: las tres primeras líneas parecen diferentes, más estructuradas. Bien, por las buenas o por las malas:


Cómo comento las funciones

 

He aquí algunas reglas más que me han venido a la mente recientemente y que ya he puesto en práctica en mi propia casa:


1. Las Variables Globales (VG) no se declaran todas al principio del código, sino según sea necesario, antes de las correspondientes funciones que las utilizan.

2. Antes de cada función, describimos también qué GPs utiliza (de entrada) y cuáles modifica (de salida) cuando es llamada. Y después de la función, también puede explicar qué GPs dejarán de utilizarse.

3. Todos estos comentarios, junto con las líneas de separación vacías entre las funciones y la limitación "longitud de la función no más de 20 líneas" aumentan el tamaño del archivo de código entre 1,5 y 2 veces. No dificulta la compilación, y no nos sobra el papel en ello.

4. ¿Para qué sirven los médicos de cabecera? Supongamos que calculamos alguna variable de tipo complejo en la función foo( ..., <tipo>& variable ), pasándola por referencia. Entonces, si usamos esta variable repetidamente en varios fragmentos de código, tendremos que llamar a la función foo( ) cada vez. Parece que está bien - aparte de gastar tiempo cada vez para la evaluación de esta variable, también añadimos un par de líneas (para la declaración de la variable y la llamada a la función) en cada función que utiliza la variable. ¿Por qué? Si esto es lo que se llama reutilización de código, es de alguna manera subóptima: además de hacer que la función foo( ) sea demasiado frecuente en su uso, también rompemos la estructura de las llamadas a la función, haciendo que la función foo( ) del usuario esté "fuera de categoría" y sus llamadas no sean jerárquicas. Es más fácil declarar la variable como una variable "fuera de categoría", es decir, global.

Personalmente, prefiero las funciones jerárquicas estrictas a una reutilización de código tan cuestionable. Ya he dicho sobre la jerarquía: cada función del orden n-ésimo es llamada sólo por una función del orden (n-1)-ésimo y sólo por "su propia" función. Vea mi ejemplo explicando la jerarquía de funciones en la imagen con fondo verde de arriba.

5. Pero, por supuesto, el código no siempre es óptimo en el sentido de la jerarquía, y a veces hay que llamar a funciones "ajenas". En este caso puedes escribir su lugar en la jerarquía de funciones entre paréntesis /* */ antes del nombre de la función "ajena".


Tal vez todo esto sea una tontería y un exceso, pero sé muy bien que estoy escribiendo código que probablemente tendré que editar más de una vez. Aquí creo que es mejor tranquilizarse comentando y estructurando.

 
Vinin >> :
Sobre el tamaño de la función. Intento que la función se ajuste a una pantalla. Para que puedas ver el conjunto.

Intento escribir el código de manera que el código fuente pueda ser corregido en bloques, y que sea conveniente añadir y cambiar

los comentarios no deben ser inferiores al 30% del tamaño del código

( aprendió a hacer esto en los 80x, mirando el código fuente de los sistemas operativos UNIX, RT11)

medio año más tarde, el código se olvida - si necesitas corregirlo, ¡los comentarios te permiten comprender rápidamente el tema!

(Tuve una experiencia real en un sitio de producción cuando estaba leyendo mi propio código después de 5 años)

gracias a los comentarios me acordé de todo en un día e hice los cambios por la noche)

Intento alinear el código para que sea legible y no escatimar en espacios y sangrías

Compara los dos ejemplos, ¿qué código se lee mejor?


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("Наконец-то дошли!");

Básicamente, es un código normal que realiza los mismos cálculos que la construcción del if anidado. Pero en algún lugar he oído que el retorno en la función debe ser uno. Probablemente, se hace para no mezclarse con ellos. No sigo estrictamente esta regla.

Por lo demás, mi enfoque es muy parecido al tuyo, salvo un par de detalles.

¡Prefiero la misma forma de salir solo!

más fácil de controlar


Si quieres devolver un valor, entonces


en lugar de

si ( a > c )

retorno ( 3 );

si ( l < b )

volver (5);

...

...

si ( h != b )

volver (100);

---

prefiere


si ( a > c )

codret = 3;

si ( l < b )

codret = 5;

...

...

si ( h != b )

codret = 100;


// especialmente si se realizan algunas operaciones adicionales comunes para todas las salidas antes de la devolución

... por ejemplo aquí hacemos otra cosa

retrun( codret);

}


 

un pequeño comentario...

Para dividir los textos en bloques utilizo una línea de caracteres con el código U0151. Para los que no lo sepan, se escribe así:

  1. mantener pulsada la tecla Alt
  2. en el teclado numérico pulse en secuencia los dígitos del código de símbolos 0, luego 1, luego 5 y luego 1
  3. liberar Alt

para los tipos de letra "correctos" se obtiene un signo menos pero sin "espacios" en los extremos. luego se copia tantas veces como sea necesario una línea sólida que sirve como un buen borde visual...

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

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

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

 

también una línea inteligente para el bloque de texto de los comentarios: parece perfectamente simétrico, pero hay una línea de apertura y otra de cierre:


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

bloque de comentarios de varias líneas
...................

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

 

Yura, tu ejemplo con una vuelta, por supuesto, es lógico. Pero atención que en este caso todos los ifs se ejecutan siempre, a diferencia del caso con muchos retornos, cuando la salida de la función se obtiene inmediatamente después de alcanzar la cadena con la condición.

ForexTools, gracias, he tomado en cuenta sus ideas de diseño.