Valores

Si no está roto, no lo arregles

Demasiado del “diseño” de Darktable ha comenzado con “sería genial si pudiéramos …”. Te diré qué es genial: colgar buenas fotos tuyas en tus paredes lo antes posible. Las artes visuales no son artes escénicas (como la música o el teatro), por lo que solo el resultado importa. Todo lo que viene antes es sobrecarga, y normalmente quieres mantenerlo al mínimo. Eso no quiere decir que el proceso no pueda disfrutarse por sí mismo. Sin embargo, para disfrutar del proceso, necesitas dominar tus herramientas y doblegarlas a tu voluntad, de lo contrario solo las peleas y todo el proceso se convierte en frustración. El problema es que el “diseño” de Darktable pone demasiado esfuerzo en ser diferente solo por serlo.

En este proceso de agregar “nuevas cosas geniales”, Darktable ha roto los atajos de teclado y muchos comportamientos básicos de la GUI, reemplazando código limpio por espagueti y añadiendo más desorden a la GUI sin nunca podar cosas.

Ansel tiene un proceso de diseño explícito que comienza obligatoriamente con problemas definidos que enfrentan usuarios definidos. Resulta que la cantidad de código a escribir es inversamente proporcional a la cantidad de pensamiento que has hecho sobre tu solución, por lo general para identificar el problema raíz de lo que te dicen los usuarios y encontrar el camino más sencillo hacia la solución (que a menudo ni siquiera es una solución de software…).

Pero los errores no te esperan en el pensamiento, solo te esperan en el código que escribiste. Así que, cuanto más pienses, menos codificas, menos carga de mantenimiento creas para ti mismo en el futuro. Pero, por supuesto… necesitas tener suficiente tiempo para pensar las cosas. Esencialmente, eso significa adiós a la programación de aficionados los sábados por la tarde.

No lo extiendas si no puedes simplificarlo primero

Mucho de la programación de Darktable se ha hecho copiando y pegando código, de otras partes del software, o incluso de otros proyectos, principalmente porque los colaboradores no tienen tiempo ni habilidades para emprender grandes reescrituras. Esto desencadena duplicación de código y aumenta la longitud de las funciones, añadiendo bifurcaciones internas e introduciendo if y switch case anidados a veces en más de 4 niveles, haciendo que la estructura y la lógica sean más difíciles de comprender y que los errores sean más difíciles (y frustrantes) de rastrear, mientras que es más probable que ocurran.

En cualquier caso, cuando el código responsable de las características existentes solo está creciendo (a veces por un factor de 10 en 4 años), plantea serias preguntas sobre la mantenibilidad futura, en un contexto donde los contribuyentes se quedan no más de un par de años, y los desarrolladores tienen un tiempo limitado para invertir. Es simplemente irresponsable, ya que se sacrifica la mantenibilidad a largo plazo por cosas nuevas brillantes.

Simplificar y generalizar el código, a través de API limpias, antes de agregar nuevas características es una necesidad, y Ansel solo acepta código que yo personalmente entiendo y tengo las habilidades para mantener. KISS.

Lógica básica de programación

No se aceptarán solicitudes de extracción que no coincidan con los requisitos mínimos de calidad de código. Estos requisitos apuntan a garantizar la mantenibilidad y estabilidad a largo plazo mediante la imposición de código claro y legible estructurado con una lógica simple.

  1. Los procedimientos deben descomponerse en funciones de unidad reutilizables siempre que sea posible. La excepción a esto son los procedimientos lineales especializados (sin bifurcaciones) que realizan tareas demasiado específicas para ser reutilizadas en otro lugar, pero en este caso utiliza comentarios para descomponer los procedimientos en “capítulos” o pasos que se puedan detectar y entender fácilmente.
  2. Las funciones deben realizar solo una tarea a la vez. Por ejemplo, el código de la GUI no debe mezclarse con el código de procesamiento de SQL o píxeles. Los getters y setters deben ser funciones diferentes.
  3. Las funciones deben tener solo un punto de entrada y un punto de salida (return). Las únicas excepciones aceptadas son un retorno temprano si el búfer de memoria en el que se supone que la función debe operar no está inicializado o si un bloqueo de mutex de hilo ya está capturado.
  4. Las funciones deben tener nombres y argumentos legibles y explícitos que anuncien su propósito. Los programas están destinados a ser leídos por humanos, si programas para la máquina, hazlo en binario.
  5. Las funciones solo pueden anidar hasta 2 estructuras condicionales if. Si se necesitan más de 2 if anidados, la estructura de tu código debe ser reevaluada y probablemente descompuesta en funciones más granulares.
  6. If solo debería probar casos uniformes como el estado o el valor de idealmente una (pero tal vez más) variable(s) del mismo tipo. Si se necesitan probar casos no uniformes (como IF user param IS value AND picture buffer IS initialized AND picture IS raw AND picture HAS embedded color profile AND color profile coeff[0] IS NOT NaN), se deben posponer a una función de verificación que devuelva un gboolean TRUE o FALSE y ser nombrada adecuadamente para que los demás desarrolladores entiendan el propósito de la verificación sin ambigüedades en una lectura rápida del código, como color_matrix_should_apply(). El código de bifurcación será entonces if(color_matrix_should_apply()) pix_out = dot_product(pix_in, matrix);
  7. Los comentarios deben mencionar por qué hiciste lo que hiciste, como tus suposiciones base, tus razones y cualquier referencia académica o documentación que usaste como base (DOI y URLs deben estar ahí). Tu código debería decir explícitamente lo que hiciste. Si te encuentras teniendo que explicar lo que tu código está haciendo en los comentarios, generalmente es una señal de que tu código está mal estructurado, las variables y funciones están mal nombradas, etc.
  8. No se aceptarán soluciones rápidas que oculten problemas en lugar de abordarlos en su raíz. Si estás interesado en esos, podrías considerar contribuir al darktable corriente. Las únicas excepciones serán si los problemas son bloqueantes (hacen que el software se bloquee) y no se ha encontrado una mejor solución después de un tiempo decente de investigación.
  9. Siempre recuerda que el mejor código es el más simple. KISS. Para lograr este objetivo, generalmente es mejor escribir el código desde cero en lugar de intentar mezclar y combinar fragmentos de código existente a través de extensas copias y pegas.

En un mundo ideal, cualquier PR seguiría las mejores prácticas de patrones de diseño .

Algunos fragmentos de sabiduría aleatoria de internet:

Todo el mundo sabe que depurar es dos veces más difícil que escribir un programa en primer lugar. Entonces, si eres tan ingenioso como puedas cuando lo escribes, ¿cómo vas a depurarlo alguna vez? — Brian W. Kernighan
Cualquier tonto puede escribir código que una computadora pueda entender. Los buenos programadores escriben código que los humanos puedan entender. — Martin Fowler, Refactoring: Improving the Design of Existing Code
Siempre programa como si el tipo que terminará manteniendo tu código fuera un psicópata violento que sabe dónde vives. — John Woods
Siempre que tengo que pensar para entender lo que el código está haciendo, me pregunto si puedo refactorizar el código para hacer que esa comprensión sea más inmediatamente aparente. — Martin Fowler, Refactoring: Improving the Design of Existing Code
El código es malo. Se descompone. Requiere mantenimiento periódico. Tiene errores que necesitan ser encontrados. Las nuevas características significan que el código viejo tiene que ser adaptado. Cuanto más código tengas, más lugares hay para que los errores se escondan. Cuanto más tarda la extracción o compilación. Cuanto más tarda un nuevo empleado en entender tu sistema. Si tienes que refactorizar, hay más cosas que mover.
El código lo producen los ingenieros. Para hacer más código se necesitan más ingenieros. Los ingenieros tienen costos de comunicación n^2, y todo ese código que añaden al sistema, mientras expanden su capacidad, también aumenta una canasta completa de costos. Deberías hacer lo que sea posible para aumentar la productividad de los programadores individuales en términos del poder expresivo del código que escriben. Menos código para hacer lo mismo (y posiblemente mejor). Menos programadores para contratar. Menos costos de comunicación organizativa.
Rich Skrenta 
Los buenos programadores escriben buen código. Los grandes programadores no escriben código. Los programadores Zen borran código. John Byrd 

Lógica específica de programación en C

Ansel y darktable están escritos en C. Este lenguaje está destinado a programadores avanzados para escribir errores rápidos en aplicaciones a nivel de sistema y SO. Da demasiada libertad para hacer cosas dañinas y no se puede depurar antes de ejecutar el programa o escribir tus propias pruebas (que pueden tener errores de sí mismas o pueden sesgar el tipo de errores que permiten pasar, y de todos modos, nadie escribe pruebas). Sin embargo, la mayoría de los colaboradores no están capacitados en C, muchos de ellos ni siquiera son programadores profesionales (aunque los programadores profesionales de C probablemente no deberían estar cerca de aplicaciones de usuario final), por lo que C es un lenguaje peligroso para cualquier aplicación de código abierto.

C te permitirá escribir en búferes que no han sido asignados (resultando en un error segfault) y te permitirá liberarlos más de una vez, pero no liberará búferes cuando ya no se necesiten más (resultando en fugas de memoria si te olvidas de hacerlo manualmente). El problema es que, dado que la asignación/liberación del búfer puede estar lejos (en la vida útil del programa como en el código fuente) de donde lo usas, es fácil estropearlo. C también te permitirá convertir cualquier puntero en cualquier tipo de dato, lo que habilita muchos errores de programador y corrupción de datos. Los métodos nativos de manejo de cadenas no son seguros (por razones que nunca me molesté en entender), por lo que tenemos que usar los de GLib para prevenir explotes de seguridad.

Básicamente, C te convierte en tu propio y peor enemigo, y depende de ti observar las reglas de seguridad cuya sabiduría se hará clara solo una vez que las rompas. Mucho como los errores en un programa C. Considera que escribes tu código para que sea leído por tontos que nunca han programado en C antes.

También necesitas tener en cuenta que el compilador hará la mayoría de las optimizaciones por ti, pero será muy conservador al respecto. La regla general es que, si tu código es fácilmente comprensible por un humano (lógica simple), será entendido correctamente por el compilador, que tomará las medidas de optimización apropiadas. Por otro lado, las optimizaciones manuales en el código, que generan código críptico que se supone más rápido en sistemas de un solo hilo, generalmente se retrovuelven y generan programas más lentos después de la compilación.

Patrones y estructuras

  1. Los bucles for se reservan para iterar sobre matrices de tamaño conocido de antemano, por lo que se conoce el número de pasos de iteración. Extendiendo esa lógica, también se pueden utilizar para iterar sobre elementos de GList * (que no tienen propiedad de tamaño ya que son asignados dinámicamente), aunque esto comprueba si cada elemento (GList *)->next no es NULL. Los bucles for generalmente no deben usar sentencias break o return dentro de su flujo de control, a menos que el bucle esté buscando un elemento específico dentro de la matriz y lo devuelva tan pronto como se encuentre. Si tu bucle tiene una condición de parada, usa while.
  2. C no es un lenguaje orientado a objetos, pero puedes y debes utilizar la lógica OO cuando sea pertinente en C usando estructuras para almacenar datos y punteros a métodos, luego getters y setters  uniformes para definir y acceder a los datos.
  3. Estructuras como while, for, if o switch no deben anidarse en más de 3 (y preferiblemente 2) niveles. Usa funciones si eso sucede:
     1// Mal
     2void procesar(float *array, char *output)
     3{
     4  if(condition)
     5  {
     6    for(int i = 0; i < 5; i++)
     7    {
     8      if(array[i] > 1.f)
     9        array[i] = ...
    10    }
    11    output = "true";
    12  }
    13  else
    14  {
    15    ...
    16  }
    17}
    18
    19// Bien
    20char *_process(float *array)
    21{
    22  for(int i = 0; i < 5; i++)
    23  {
    24    if(array[i] > 1.f)
    25      array[i] = ...
    26  }
    27  return "true";
    28}
    29void procesar(float *array, char *output)
    30{
    31  if(condition)
    32  {
    33    output = _process(array);
    34  }
    35  else
    36  {
    37    output = _something_else(array);
    38  }
    39}
  4. Las largas secuencias de comprobaciones deberían colocarse en funciones que devuelvan gboolean que indiquen claramente qué estamos verificando, para que en los procedimientos obtengamos:
     1gboolean _is_raw(dt_image_t *image)
     2{
     3  return (image->flag & DT_RAW == DT_RAW) &&
     4         (image->buffer != NULL) &&
     5         strcmp(image->ext, "dng");
     6}
     7
     8void procesar(dt_image_t *image)
     9{
    10  if(_is_raw(image))
    11    ...
    12  else if(_is_raster(image))
    13    ...
    14}
    en lugar de
    1if((image->flag & DT_RAW == DT_RAW) && (image->buffer != NULL) && strcmp(image->ext, "dng"))
    2  ...
    3else if(...)
    4  ...

[9115]: “3. Siempre accede a los datos de los búferes usando la sintaxis de array, desde su puntero base, en lugar de usar punteros no constantes sobre los cuales realizas cálculo aritmético. Por ejemplo, haz: " [9116]: " C " [9117]: " float *const buffer = malloc(64 * sizeof(float)); " [9118]: " for(int i = 0; i < 64; i++) " [9119]: " { " [9120]: " buffer[i] = ... " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos.3. Siempre accede a los datos de los búferes usando la sintaxis de array, desde su puntero base, en lugar de usar punteros no constantes sobre los cuales realizas cálculo aritmético. Por ejemplo, haz: " [9116]: " C " [9117]: " float *const buffer = malloc(64 * sizeof(float)); " [9118]: " for(int i = 0; i < 64; i++) " [9119]: " { " [9120]: " buffer[i] = ... " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. C " [9117]: " float *const buffer = malloc(64 * sizeof(float)); " [9118]: " for(int i = 0; i < 64; i++) " [9119]: " { " [9120]: " buffer[i] = ... " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. float *const buffer = malloc(64 * sizeof(float)); " [9118]: " for(int i = 0; i < 64; i++) " [9119]: " { " [9120]: " buffer[i] = … " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = … " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. for(int i = 0; i < 64; i++) " [9119]: " { " [9120]: " buffer[i] = ... " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. { " [9120]: " buffer[i] = … " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = … " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. buffer[i] = ... " [9121]: " } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. } " [9122]: " " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = … " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. " [9123]: " No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. No hagas: " [9124]: " C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. C " [9125]: " float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. float *buffer = malloc(64 * sizeof(float)); " [9126]: " for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = … " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. for(int i = 0; i < 64; i++) " [9127]: " { " [9128]: " *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. { " [9128]: " *buffer++ = … " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. *buffer++ = ... " [9129]: " } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. } " [9130]: " " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: "4. El uso de incrementos de variables en línea (ver un [ejemplo de pesadilla aquí](https://www.youtube.com/watch?v=_7Wok3JoOcE)) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. " [9131]: " La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. La última versión no solo es menos clara de leer, sino que impedirá la paralelización y las optimizaciones del compilador porque el valor del puntero depende de la iteración del bucle y necesitaría ser compartido entre hilos si los hubiera. La versión anterior lleva a una lógica de acceso a la memoria independiente de la iteración del bucle y puede ser paralelizada de forma segura. " [9132]: “4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. 4. El uso de incrementos de variables en línea (ver un ejemplo de pesadilla aquí ) está estrictamente prohibido, a menos que sea la única operación de la línea. Estos son un desastre que provoca muchos errores de programación. Esto está permitido: " [9133]: " C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. C " [9134]: " uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. uint32_t counter; " [9135]: " for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. for(int i = 0; i < 64; i++) " [9136]: " { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. { " [9137]: " if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. if(array[i] > threshold) " [9138]: " counter++; " [9139]: " } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. counter++; " [9139]: " } " [9140]: " " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. } " [9140]: " " [9141]: “5. Las sentencias case en la estructura switch no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. " [9141]: "5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. 5. Las sentencias `case` en la estructura `switch` no deben ser aditivas. No hagas: " [9142]: " C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos.C " [9143]: " int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. int tmp = 0; " [9144]: " switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. switch(var) " [9145]: " { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. { " [9146]: " case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE1: " [9147]: " case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE2: " [9148]: " tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. tmp += 1; " [9149]: " case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE3: " [9150]: " do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. do_something(tmp); " [9151]: " break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. break; " [9152]: " case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE4: " [9153]: " do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. do_something_else(); " [9154]: " break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. break; " [9155]: " } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. } " [9156]: " " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso VALUE3 hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. " [9157]: " En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. En una lectura superficial, no será inmediatamente claro que el caso `VALUE3` hereda las cláusulas definidas por los casos anteriores, especialmente en situaciones donde hay más casos. Haz: " [9158]: " C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos.C " [9159]: " int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. int tmp = 0; " [9160]: " switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. switch(var) " [9161]: " { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. { " [9162]: " case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE1: " [9163]: " case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE2: " [9164]: " do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. do_something(tmp + 1); " [9165]: " break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. break; " [9166]: " case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE3: " [9167]: " do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. do_something(tmp); " [9168]: " break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. break; " [9169]: " case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. case VALUE4: " [9170]: " do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. do_something_else(); " [9171]: " break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. break; " [9172]: " } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. } " [9173]: " " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. " [9174]: " Cada caso es independiente y el resultado no depende del orden de declaración de los casos. Cada caso es independiente y el resultado no depende del orden de declaración de los casos.

[9181]: “7. Ordena y almacena tus variables en estructuras que pasas como argumentos de función en lugar de usar funciones con más de 8 argumentos. No hagas: " [9182]: " C " [9183]: " void function(float value, gboolean is_green, gboolean is_big, gboolean has_hair, int width, int height, ...) " [9184]: " { " [9185]: " ... " [9186]: " }7. Ordena y almacena tus variables en estructuras que pasas como argumentos de función en lugar de usar funciones con más de 8 argumentos. No hagas: " [9182]: " C " [9183]: " void function(float value, gboolean is_green, gboolean is_big, gboolean has_hair, int width, int height, …) " [9184]: " { " [9185]: " … " [9186]: " } ```C " [9183]: " void function(float value, gboolean is_green, gboolean is_big, gboolean has_hair, int width, int height, …) " [9184]: " { " [9185]: " … " [9186]: " } void function(float value, gboolean is_green, gboolean is_big, gboolean has_hair, int width, int height, …) " [9184]: " { " [9185]: " … " [9186]: " } { " [9185]: " … " [9186]: " } … " [9186]: " } }

[9193]: " void main() " [9194]: " { " [9195]: " if(condition1) " [9196]: " function(3.f, TRUE, FALSE, TRUE, 80, 90, …); " [9197]: " else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; void main() " [9194]: " { " [9195]: " if(condition1) " [9196]: " function(3.f, TRUE, FALSE, TRUE, 80, 90, …); " [9197]: " else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; { " [9195]: " if(condition1) " [9196]: " function(3.f, TRUE, FALSE, TRUE, 80, 90, …); " [9197]: " else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; if(condition1) " [9196]: " function(3.f, TRUE, FALSE, TRUE, 80, 90, …); " [9197]: " else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; function(3.f, TRUE, FALSE, TRUE, 80, 90, …); " [9197]: " else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; else if(condition2) " [9198]: " function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; function(3.f, FALSE, TRUE, TRUE, 80, 90, …); " [9199]: " else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; else " [9200]: " function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; function(3.f, FALSE, FALSE, FALSE, 110, 90, …); " [9201]: " } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; } " [9202]: " " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; " [9203]: " Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; Haz: " [9204]: " C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; C " [9205]: " typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; typedef struct params_t " [9206]: " { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; { " [9207]: " gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; gboolean is_green; " [9208]: " gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; gboolean is_big; " [9209]: " gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; gboolean has_hair; " [9210]: " int width; " [9211]: " int height; " [9212]: " } params_t; int width; " [9211]: " int height; " [9212]: " } params_t; int height; " [9212]: " } params_t; } params_t;

[9219]: " void function(float value, params_t p) " [9220]: " { " [9221]: " … " [9222]: " } void function(float value, params_t p) " [9220]: " { " [9221]: " … " [9222]: " } { " [9221]: " … " [9222]: " } … " [9222]: " } }

[9229]: " void main() " [9230]: " { " [9231]: " params_t p = { .is_green = (condition1), " [9232]: " .is_big = (condition2), " [9233]: " .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de [darktable](https://github.com/darktable-org/darktable/blob/master/src/bauhaus/bauhaus.c#L2210-L2251). El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. void main() " [9230]: " { " [9231]: " params_t p = { .is_green = (condition1), " [9232]: " .is_big = (condition2), " [9233]: " .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. { " [9231]: " params_t p = { .is_green = (condition1), " [9232]: " .is_big = (condition2), " [9233]: " .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de [darktable](https://github.com/darktable-org/darktable/blob/master/src/bauhaus/bauhaus.c#L2210-L2251). El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. params_t p = { .is_green = (condition1), " [9232]: " .is_big = (condition2), " [9233]: " .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. .is_big = (condition2), " [9233]: " .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de [darktable](https://github.com/darktable-org/darktable/blob/master/src/bauhaus/bauhaus.c#L2210-L2251). El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. .has_hair = (condition1 || condition2), " [9234]: " .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. .width = (condition1 || condition2) ? 80 : 110,} " [9235]: " .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de [darktable](https://github.com/darktable-org/darktable/blob/master/src/bauhaus/bauhaus.c#L2210-L2251). El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. .height = 90 }; " [9236]: " function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. function(3.0f, p); " [9237]: " } " [9238]: " " [9239]: " El primer ejemplo está tomado de [darktable](https://github.com/darktable-org/darktable/blob/master/src/bauhaus/bauhaus.c#L2210-L2251). El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. } " [9238]: " " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. ``` " [9239]: " El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables. El primer ejemplo está tomado de darktable . El copiado y pegado de llamadas a funciones es innecesario y la multiplicación de argumentos posicionales hace que sea imposible recordar cuál es cuál. Tampoco muestra qué argumentos son constantes a lo largo de las diferentes ramas, lo que hará que la refactorización sea difícil. El segundo ejemplo no es más conciso, sin embargo, la estructura no solo hace que la función sea más fácil de llamar, sino que la declaración de la estructura permite establecer explícitamente cada argumento, con comprobaciones en línea si es necesario. La dependencia de los argumentos de entrada en las condiciones externas también se hace inmediatamente clara, y los argumentos booleanos se establecen directamente a partir de las condiciones, lo que hará que el programa sea más fácil de extender en el futuro y menos propenso a errores de programación debido a malentendidos en la dependencia de las variables.

Optimización de OpenMP

Los píxeles son esencialmente vectores RGBA de 4D. Desde 2004, los procesadores tienen habilidades especiales para procesar vectores y aplicar Instrucciones Simples en Múltiples Datos (SIMD). Esto nos permite acelerar los cálculos procesando un píxel completo (SSE2) hasta 4 píxeles (AVX-512) al mismo tiempo, ahorrando muchos ciclos de CPU.

Los compiladores modernos tienen opciones de auto-vectorización que pueden optimizar C puro, y la biblioteca OpenMP permite proporcionar sugerencias para mejorar eso, dado que el código se escribe de manera vectorizable y se usan algunas pragmas.

Escribe código vectorizable: https://info.ornl.gov/sites/publications/files/Pub69214.pdf 

Mejores prácticas para la auto-vectorización:

[9276]: “* evita ramas en bucles que cambian el flujo de control. Usa declaraciones en línea como absoluto = (x > 0) ? x : -x; para que puedan convertirse en máscaras de bytes en SIMD, " [9277]: “* los píxeles solo deben ser referenciados desde el puntero base de su matriz y los índices de los bucles, de modo que puedas predecir qué dirección de memoria se accede solo desde el índice del bucle, " [9278]: “* evita llevar argumentos struct en funciones llamadas en bucles OpenMP, y desempaqueta los miembros del struct antes del bucle. La vectorización no se puede realizar en estructuras, sino solo en escalares y matrices float e int. Por ejemplo: " [9279]: " lang-C " [9280]: " typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t;* evita ramas en bucles que cambian el flujo de control. Usa declaraciones en línea como `absoluto = (x > 0) ? x : -x;` para que puedan convertirse en máscaras de bytes en SIMD, " [9277]: "* los píxeles solo deben ser referenciados desde el puntero base de su matriz y los índices de los bucles, de modo que puedas predecir qué dirección de memoria se accede solo desde el índice del bucle, " [9278]: "* evita llevar argumentos `struct` en funciones llamadas en bucles OpenMP, y desempaqueta los miembros del `struct` antes del bucle. La vectorización no se puede realizar en estructuras, sino solo en escalares y matrices `float` e `int`. Por ejemplo: " [9279]: " lang-C " [9280]: " typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t;

  • los píxeles solo deben ser referenciados desde el puntero base de su matriz y los índices de los bucles, de modo que puedas predecir qué dirección de memoria se accede solo desde el índice del bucle, " [9278]: “* evita llevar argumentos struct en funciones llamadas en bucles OpenMP, y desempaqueta los miembros del struct antes del bucle. La vectorización no se puede realizar en estructuras, sino solo en escalares y matrices float e int. Por ejemplo: " [9279]: " ```lang-C " [9280]: " typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t;
  • evita llevar argumentos struct en funciones llamadas en bucles OpenMP, y desempaqueta los miembros del struct antes del bucle. La vectorización no se puede realizar en estructuras, sino solo en escalares y matrices float e int. Por ejemplo: " [9279]: " ```lang-C " [9280]: " typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t;

" [9280]: " typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t; typedef struct iop_data_t " [9281]: " { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t; { " [9282]: " float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t; float[4] pixel; " [9283]: " float factor; " [9284]: " } iop_data_t; float factor; " [9284]: " } iop_data_t; } iop_data_t;

[9291]: " float foo(float x, struct iop_data_t *bar) " [9292]: " { " [9293]: " return bar->factor * (x + bar->pixel[0] + bar->pixel[1] + bar->pixel[2] + bar->pixel[3]); " [9294]: " } float foo(float x, struct iop_data_t *bar) " [9292]: " { " [9293]: " return bar->factor * (x + bar->pixel[0] + bar->pixel[1] + bar->pixel[2] + bar->pixel[3]); " [9294]: " } { " [9293]: " return bar->factor * (x + bar->pixel[0] + bar->pixel[1] + bar->pixel[2] + bar->pixel[3]); " [9294]: " } return bar->factor * (x + bar->pixel[0] + bar->pixel[1] + bar->pixel[2] + bar->pixel[3]); " [9294]: " } }

[9301]: " void loop(const float *in, float *out, const size_t width, const size_t height, const struct iop_data_t bar) " [9302]: " { " [9303]: " for(size_t k = 0; k < height * width; ++k) " [9304]: " { " [9305]: " out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; void loop(const float *in, float *out, const size_t width, const size_t height, const struct iop_data_t bar) " [9302]: " { " [9303]: " for(size_t k = 0; k < height * width; ++k) " [9304]: " { " [9305]: " out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; { " [9303]: " for(size_t k = 0; k < height * width; ++k) " [9304]: " { " [9305]: " out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; for(size_t k = 0; k < height * width; ++k) " [9304]: " { " [9305]: " out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; { " [9305]: " out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; out[k] = foo(in[k], bar); " [9306]: " // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; // la función no vectorizada se llamará en cada iteración (costosa) " [9307]: " } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; } " [9308]: " } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; } " [9309]: " " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; " [9310]: " debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; debería escribirse: " [9311]: " lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; lang-C " [9312]: " typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; typedef struct iop_data_t " [9313]: " { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; { " [9314]: " float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; float[4] pixel DT_ALIGNED_PIXEL; // alinear en direcciones de 16 bits " [9315]: " float factor; " [9316]: " } iop_data_t; float factor; " [9316]: " } iop_data_t; } iop_data_t;

[9323]: " #ifdef _OPENMP " [9324]: " #pragma declare simd " [9325]: " #endif " [9326]: " /* declara la función vectorizable e implementa en línea para evitar llamadas desde dentro del bucle / " [9327]: " inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; #ifdef _OPENMP " [9324]: " #pragma declare simd " [9325]: " #endif " [9326]: " / declara la función vectorizable e implementa en línea para evitar llamadas desde dentro del bucle / " [9327]: " inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; #pragma declare simd " [9325]: " #endif " [9326]: " / declara la función vectorizable e implementa en línea para evitar llamadas desde dentro del bucle / " [9327]: " inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; #endif " [9326]: " / declara la función vectorizable e implementa en línea para evitar llamadas desde dentro del bucle / " [9327]: " inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; / declara la función vectorizable e implementa en línea para evitar llamadas desde dentro del bucle */ " [9327]: " inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; inline float foo(const float x, const float pixel[4], const float factor) " [9328]: " { " [9329]: " float sum = x; { " [9329]: " float sum = x; float sum = x;

[9336]: " /* usa una reducción SIMD para vectorizar la suma / " [9337]: " #ifdef _OPENMP " [9338]: " #pragma omp simd aligned(pixel:16) reduction(+:sum) " [9339]: " #endif " [9340]: " for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; / usa una reducción SIMD para vectorizar la suma */ " [9337]: " #ifdef _OPENMP " [9338]: " #pragma omp simd aligned(pixel:16) reduction(+:sum) " [9339]: " #endif " [9340]: " for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; #ifdef _OPENMP " [9338]: " #pragma omp simd aligned(pixel:16) reduction(+:sum) " [9339]: " #endif " [9340]: " for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; #pragma omp simd aligned(pixel:16) reduction(+:sum) " [9339]: " #endif " [9340]: " for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; #endif " [9340]: " for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; for(size_t k = 0; k < 4; ++k) " [9341]: " sum += pixel[k]; sum += pixel[k];

[9348]: " return factor * sum; " [9349]: " } return factor * sum; " [9349]: " } }

[9356]: " void loop(const float *const restrict in, " [9357]: " float const restrict out, " [9358]: " const size_t width, const size_t height, " [9359]: " const struct iop_data_t bar) " [9360]: " { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float *const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; void loop(const float *const restrict in, " [9357]: " float const restrict out, " [9358]: " const size_t width, const size_t height, " [9359]: " const struct iop_data_t bar) " [9360]: " { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float *const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; float const restrict out, " [9358]: " const size_t width, const size_t height, " [9359]: " const struct iop_data_t bar) " [9360]: " { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; const size_t width, const size_t height, " [9359]: " const struct iop_data_t bar) " [9360]: " { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; const struct iop_data_t bar) " [9360]: " { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; { " [9361]: " / desempaqueta los miembros del struct */ " [9362]: " const float const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; / desempaqueta los miembros del struct */ " [9362]: " const float *const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; const float *const restrict pixel = bar->pixel; " [9363]: " const float factor = bar-> factor; const float factor = bar-> factor;

[9370]: " #ifdef _OPENMP " [9371]: " #pragma omp parallel for simd default(none)
" [9372]: " dt_omp_firstprivate(in, out, pixel, factor, width, height)
" [9373]: " schedule(simd:static) aligned(in, out:64) " [9374]: " #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). #ifdef _OPENMP " [9371]: " #pragma omp parallel for simd default(none) \ " [9372]: " dt_omp_firstprivate(in, out, pixel, factor, width, height) \ " [9373]: " schedule(simd:static) aligned(in, out:64) " [9374]: " #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP). #pragma omp parallel for simd default(none)
" [9372]: " dt_omp_firstprivate(in, out, pixel, factor, width, height)
" [9373]: " schedule(simd:static) aligned(in, out:64) " [9374]: " #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). dt_omp_firstprivate(in, out, pixel, factor, width, height) \ " [9373]: " schedule(simd:static) aligned(in, out:64) " [9374]: " #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP). schedule(simd:static) aligned(in, out:64) " [9374]: " #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). #endif " [9375]: " for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP). for(size_t k = 0; k < height * width; ++k) " [9376]: " { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). { " [9377]: " out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP). out[k] = foo(in[k], pixel, factor); " [9378]: " } " [9379]: " } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). } " [9379]: " } " [9380]: " " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP). } " [9380]: " " [9381]: "* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa `collapse(2)` en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: "* usa un indexado plano de arrays siempre que sea posible (`for(size_t k = 0 ; k < ch * width * height ; k += ch)`) en lugar de bucles anidados ancho/alto/canales, " [9383]: "* usa la palabra clave `restrict` en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (`*out` siempre debe ser diferente de `*in`) para que no se desencadenen dependencias de variables entre hilos " [9384]: "* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: "* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: "* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: "* evita conversiones de tipos en bucles, " [9388]: "* declara los punteros de entrada/salida como `*const` y las variables como `const` para evitar el false-sharing en bucles paralelos (usando `shared(variable)` pragma de OpenMP). " [9381]: “* si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).

  • si usas bucles anidados (por ejemplo, bucle sobre el ancho y la altura del array), declara los punteros de píxeles en el bucle más interno y usa collapse(2) en la pragma de OpenMP para que el compilador pueda optimizar el uso de la caché/memoria y dividir el bucle más equitativamente entre los diferentes hilos, " [9382]: “* usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • usa un indexado plano de arrays siempre que sea posible (for(size_t k = 0 ; k < ch * width * height ; k += ch)) en lugar de bucles anidados ancho/alto/canales, " [9383]: “* usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • usa la palabra clave restrict en punteros de imágenes/pixels para evitar aliasing y evita operaciones in situ en píxeles (*out siempre debe ser diferente de *in) para que no se desencadenen dependencias de variables entre hilos " [9384]: “* alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • alinea arrays en 64 bytes y píxeles en bloques de 16 bytes para que la memoria sea contigua y la CPU pueda cargar líneas de caché completas (y evitar errores de segmentación), " [9385]: “* escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • escribe funciones pequeñas y optimiza localmente (un bucle/función), usando OpenMP y/o pragmas de compilador, " [9386]: “* mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • mantén tu código estúpidamente simple, sistemático y evita la aritmética de punteros ingeniosa porque solo llevará al compilador a detectar dependencias de variables y aliasing de puntero donde no los hay, " [9387]: “* evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • evita conversiones de tipos en bucles, " [9388]: “* declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).
  • declara los punteros de entrada/salida como *const y las variables como const para evitar el false-sharing en bucles paralelos (usando shared(variable) pragma de OpenMP).

Formato del código

[9401]: “- Usa espacios en lugar de tabulaciones, " [9402]: “- La indentación usa 2 espacios, " [9403]: “- Elimina espacios al final, " [9404]: “- { y } van en su propia línea,- Usa espacios en lugar de tabulaciones, " [9402]: “- La indentación usa 2 espacios, " [9403]: “- Elimina espacios al final, " [9404]: “- { y } van en su propia línea,

  • La indentación usa 2 espacios, " [9403]: “- Elimina espacios al final, " [9404]: “- { y } van en su propia línea,
  • Elimina espacios al final, " [9404]: “- { y } van en su propia línea,
  • { y } van en su propia línea,

Directrices

[9417]: “1. Haz cosas que dominas: sí, es bueno aprender cosas nuevas, pero Ansel no es un sandbox, es un software de producción, y no es el lugar adecuado para recibir tu formación. " [9418]: “2. KISS y sé perezoso: Ansel no tiene 50 desarrolladores a tiempo completo a bordo, ser minimalista tanto en características como en volumen de código es razonable y saludable para la gestión actual, pero también para el mantenimiento futuro. (KISS: keep it stupid simple). " [9419]: “3. Haz como el resto del mundo: claro, si todos se tiran por la ventana, tienes el derecho de no seguirlos, pero la mayoría de los problemas sobre la UI/UX de software ya se han resuelto en algún lugar y, en la mayoría de los casos, tiene sentido simplemente reutilizar esas soluciones, porque la mayoría de los usuarios ya estarán familiarizados con ellas. " [9420]: “5. La programación no es el objetivo: la programación es un medio para un fin, el fin es poder procesar un gran volumen de imágenes en un corto período de tiempo mientras se alcanza el aspecto deseado en cada imagen. Las tareas de programación deben considerarse gastos generales y deben mantenerse al mínimo, y el volumen de código es una responsabilidad para cualquier proyecto.1. Haz cosas que dominas: sí, es bueno aprender cosas nuevas, pero Ansel no es un sandbox, es un software de producción, y no es el lugar adecuado para recibir tu formación. " [9418]: “2. KISS y sé perezoso: Ansel no tiene 50 desarrolladores a tiempo completo a bordo, ser minimalista tanto en características como en volumen de código es razonable y saludable para la gestión actual, pero también para el mantenimiento futuro. (KISS: keep it stupid simple). " [9419]: “3. Haz como el resto del mundo: claro, si todos se tiran por la ventana, tienes el derecho de no seguirlos, pero la mayoría de los problemas sobre la UI/UX de software ya se han resuelto en algún lugar y, en la mayoría de los casos, tiene sentido simplemente reutilizar esas soluciones, porque la mayoría de los usuarios ya estarán familiarizados con ellas. " [9420]: “5. La programación no es el objetivo: la programación es un medio para un fin, el fin es poder procesar un gran volumen de imágenes en un corto período de tiempo mientras se alcanza el aspecto deseado en cada imagen. Las tareas de programación deben considerarse gastos generales y deben mantenerse al mínimo, y el volumen de código es una responsabilidad para cualquier proyecto. 2. KISS y sé perezoso: Ansel no tiene 50 desarrolladores a tiempo completo a bordo, ser minimalista tanto en características como en volumen de código es razonable y saludable para la gestión actual, pero también para el mantenimiento futuro. (KISS: keep it stupid simple). " [9419]: “3. Haz como el resto del mundo: claro, si todos se tiran por la ventana, tienes el derecho de no seguirlos, pero la mayoría de los problemas sobre la UI/UX de software ya se han resuelto en algún lugar y, en la mayoría de los casos, tiene sentido simplemente reutilizar esas soluciones, porque la mayoría de los usuarios ya estarán familiarizados con ellas. " [9420]: “5. La programación no es el objetivo: la programación es un medio para un fin, el fin es poder procesar un gran volumen de imágenes en un corto período de tiempo mientras se alcanza el aspecto deseado en cada imagen. Las tareas de programación deben considerarse gastos generales y deben mantenerse al mínimo, y el volumen de código es una responsabilidad para cualquier proyecto. 3. Haz como el resto del mundo: claro, si todos se tiran por la ventana, tienes el derecho de no seguirlos, pero la mayoría de los problemas sobre la UI/UX de software ya se han resuelto en algún lugar y, en la mayoría de los casos, tiene sentido simplemente reutilizar esas soluciones, porque la mayoría de los usuarios ya estarán familiarizados con ellas. " [9420]: “5. La programación no es el objetivo: la programación es un medio para un fin, el fin es poder procesar un gran volumen de imágenes en un corto período de tiempo mientras se alcanza el aspecto deseado en cada imagen. Las tareas de programación deben considerarse gastos generales y deben mantenerse al mínimo, y el volumen de código es una responsabilidad para cualquier proyecto. 5. La programación no es el objetivo: la programación es un medio para un fin, el fin es poder procesar un gran volumen de imágenes en un corto período de tiempo mientras se alcanza el aspecto deseado en cada imagen. Las tareas de programación deben considerarse gastos generales y deben mantenerse al mínimo, y el volumen de código es una responsabilidad para cualquier proyecto.


Translated from English by : ChatGPT. In case of conflict, inconsistency or error, the English version shall prevail.