Reflexiones sobre C ++ moderno y desarrollo de juegos

El nuevo año para los desarrolladores de juegos comenzó con una ola de críticas que cayó sobre el comité de estandarización de C ++ después de la publicación de las Quejas de Aras Prankevichus sobre Modern C ++ . Surgió una pregunta seria: ¿el comité de estándares realmente perdió contacto con la realidad, o es al revés, y estos desarrolladores de juegos están separados del resto de la comunidad de C ++?

Le ofrecemos una traducción de la popular publicación de Ben Dean, un veterano de la industria del juego , que trabajó durante mucho tiempo en Blizzard, Electronic Arts y Bullfrog como desarrollador de C ++ y líder de equipo, en el que responde a las críticas desde la perspectiva de su propia experiencia.
TL; DR: El Comité de Normalización de C ++ no tiene un objetivo oculto de ignorar las necesidades de los desarrolladores de juegos, y C ++ "moderno" no se convertirá en un lenguaje "depurado".
Durante la semana pasada , hubo una discusión activa en Twitter , durante la cual muchos programadores, especialmente aquellos que trabajan en el campo del desarrollo de juegos, hablaron de que el vector de desarrollo actual de "C ++ moderno" no satisface sus necesidades . En particular, desde el punto de vista de un desarrollador de juegos ordinario, todo parece como si se ignorara el rendimiento de depuración en el lenguaje, y la optimización del código se vuelve esperada y necesaria.

Debido a que en 2019 logré trabajar en la industria del juego durante más de 23 años, tengo mi propia opinión basada en observaciones sobre este tema en relación con el desarrollo del juego, que me gustaría compartir. ¿La depuración es importante para los desarrolladores de juegos y por qué? ¿Cuáles son los problemas asociados con él?

Para empezar, una pequeña digresión en la historia.

Muchos desarrolladores de juegos de C ++ trabajan en Microsoft Visual C ++. Históricamente, se ha formado un gran mercado de juegos alrededor de las plataformas de Microsoft, y esto ha afectado la experiencia típica de un programador de juegos ordinario. En los años 90 y 2000, la mayoría de los juegos se escribieron teniendo en cuenta estas circunstancias. Incluso con el advenimiento de consolas de otros fabricantes y la creciente popularidad de los juegos móviles, los activos de muchos estudios AAA y numerosos programadores de juegos actuales son herramientas hechas por Microsoft.

Visual Studio es posiblemente el mejor depurador para C ++ del mundo. Además, Visual Studio realmente se destaca más en términos de depuración de programas, más que con su front-end, back-end, implementación de STL o cualquier otra cosa. En los últimos cinco años, Microsoft ha logrado avances significativos en el desarrollo de herramientas de desarrollo de C ++, pero incluso antes de eso, el depurador en Visual Studio siempre ha sido muy bueno. Entonces, cuando está desarrollando en una PC con Windows, siempre tiene a mano un depurador de clase mundial.

Dado lo anterior, veamos el proceso de obtención de código en el que no habrá errores; oportunidades que tenemos desde el punto de vista de un programador que no maneja juegos; así como las limitaciones que enfrentan los desarrolladores de juegos. Si reformula el argumento principal a favor del "vector de desarrollo de C ++ moderno", se reducirá a tipos, herramientas y pruebas. Siguiendo este pensamiento, el depurador debería ser la última línea de defensa . Antes de lograrlo, tenemos las siguientes opciones.

Oportunidad No. 1: Tipos


Podemos utilizar la mayor cantidad de tipeo fuerte que sea necesario para eliminar clases enteras de errores en tiempo de compilación. La tipificación fuerte es, sin duda, una oportunidad que nos ha brindado la evolución reciente de C ++; por ejemplo, comenzando con C ++ 11, logramos:

  • extensión significativa de los type traits de type traits ;
  • innovaciones tales como nullptr y scoped enum para combatir el patrimonio C: escritura débil;
  • GSL y herramientas auxiliares;
  • conceptos en C ++ 20.

Es posible que a algunos de ustedes no les guste la metaprogramación de plantillas; otros pueden no gustarle el estilo de codificación que usa auto casi universalmente. Independientemente de estas preferencias, el motivo principal para usar los estilos enumerados en C ++ se traza claramente aquí: este es el deseo de ayudar al compilador para que, a su vez, pueda ayudarnos, usando al mismo tiempo lo que mejor sabe: el sistema de tipos.

Si hablamos de programación de juegos, la tipificación fuerte aquí es un campo amplio para la investigación, y es utilizada activamente por programadores de juegos que conozco, que están interesados ​​en mejorar sus habilidades de aplicación C ++ en la práctica. Aquí hay dos cosas importantes que preocupan: el efecto sobre el tiempo de compilación y el efecto sobre la legibilidad del código.

Francamente, puede ignorar fácilmente el tiempo de compilación, pero solo con la condición de que sea un programador en una empresa muy grande que no juega juegos y que tenga una infraestructura interna establecida y una potencia informática infinita para compilar cualquier código que pueda escribir . Estas grandes empresas están preocupadas por el costo de la compilación, por lo tanto, usan módulos, pero, por regla general, esto no causa dolor a los desarrolladores individuales. Al mismo tiempo, para la mayoría de los programadores de juegos, este no es el caso. Los desarrolladores independientes no tienen granjas para construir; Los desarrolladores de juegos AAA a menudo usan algo como Incredibuild , pero dado el hecho de que pueden trabajar fácilmente con una base de código que tiene 10 años o más, el proceso de compilación aún puede tomar de 15 a 20 minutos.

Podemos discutir sobre el costo relativo de agregar hardware versus el costo del tiempo del programador, y estoy de acuerdo con la opinión de que el hardware es más barato, sin embargo:

  • El hardware es un gasto real de una sola vez que se asignará al presupuesto del trimestre actual, en contraste con los gastos no tan tangibles en tiempo / contratación / y similares, que se asignarán por un período de tiempo más largo. La gente no hace frente a la decisión a favor de tal compromiso, y las empresas están especialmente construidas de tal manera que optimizan las ganancias a corto plazo.
  • La infraestructura requiere soporte, y casi nadie entra en la industria del juego para convertirse en un ingeniero de lanzamiento. En comparación con otras áreas donde se usa C ++, el salario de los desarrolladores de juegos no es tan alto, y los que no son ingenieros de juegos reciben un salario aún menor.

También se puede especular sobre el hecho de que el tiempo de compilación nunca debería haber alcanzado tal estado; Y de nuevo estoy de acuerdo contigo. El precio de esto es la vigilancia constante, una vez más, proveniente de un ingeniero de lanzamiento, e, idealmente, alguna herramienta automatizada que le permite rastrear los cambios en el tiempo requerido para construir la construcción. Afortunadamente, con el advenimiento de los sistemas de CI, este objetivo se puede lograr mucho más fácilmente hoy.

Oportunidad No. 2: Herramientas


Deberíamos utilizar el máximo de las herramientas disponibles: advertencias, análisis estático, desinfectantes, herramientas de análisis dinámico, perfiladores y otros.

Mi experiencia es que los desarrolladores de juegos usan estas herramientas siempre que sea posible, pero aquí la industria en su conjunto tiene varios problemas:

  • Estas herramientas tienden a funcionar mejor en plataformas que no son de Microsoft y, como se mencionó anteriormente, este no es un escenario típico de desarrollo de juegos.
  • La mayoría de estas herramientas están destinadas a trabajar con C ++ "estándar". De CStaticVector admiten std::vector , pero no mi clase CStaticVector de un motor hipotético. Por supuesto, culpar a las herramientas es inútil, pero esta sigue siendo una de las barreras para su uso que los desarrolladores tienen que superar.
  • La creación y el mantenimiento de una cadena de CI que ejecute todas estas herramientas requiere la presencia de ingenieros de lanzamiento y, como se mencionó anteriormente, contratar personas para trabajos de ingeniería que no están directamente relacionados con los juegos es un problema sistémico para la industria del juego.

Entonces, dado que estas herramientas funcionan tan bien con C ++ estándar, ¿por qué los desarrolladores de juegos no usan STL?

¿Dónde comenzar la respuesta a esta pregunta? Quizás, de la próxima excursión a la historia del desarrollo del juego:

  • Hasta principios de los 90, no confiamos en los compiladores de C, por lo que escribimos juegos en ensamblador.
  • Desde el comienzo hasta mediados de los 90, comenzamos a confiar en los compiladores de C, pero aún no confiamos en los compiladores de C ++. Nuestro código era C, que usaba comentarios de estilo C ++, y ya no necesitábamos escribir typedefs para nuestras estructuras todo el tiempo.
  • Alrededor de 2000, la revolución C ++ tuvo lugar en el mundo del desarrollo de juegos. Fue una era de patrones de diseño y grandes jerarquías de clases . En ese momento, el soporte STL en las consolas dejaba mucho que desear, y las consolas gobernaban el mundo en ese momento. En PS2, estamos atrapados para siempre con GCC 2.95.
  • Alrededor de 2010, se lanzaron dos revoluciones más. El dolor de usar grandes jerarquías de clase estimuló el desarrollo de un enfoque de componentes para el código. Este cambio continúa su evolución hoy en forma de arquitecturas Entity-Component-System. De la mano de esta fue la segunda revolución: un intento de aprovechar las arquitecturas multiprocesador.

Durante estos cambios de paradigma, las plataformas de desarrollo de juegos en sí estaban cambiando constantemente, y estaban cambiando seriamente. La memoria segmentada ha dado paso a un espacio de direcciones plano. Las plataformas se han convertido en multiprocesador, simétricas y no muy. Los desarrolladores de juegos, acostumbrados a trabajar con arquitecturas Intel, tuvieron que acostumbrarse a MIPS (Playstation), luego a un hardware especial con CPU heterogéneas (PS2), luego a PowerPC (XBox 360), luego a una heterogeneidad aún mayor (PS3) ... La nueva plataforma viene con nuevas características de rendimiento para procesadores, memoria y unidades. Si quería lograr un rendimiento óptimo, se vio obligado a reescribir su antiguo código, y muchas veces. Ni siquiera mencionaré cuánto influyeron los juegos por la aparición y el crecimiento de la popularidad de Internet, así como las restricciones que los titulares de la plataforma impusieron a los desarrolladores.

Históricamente, las implementaciones de STL en plataformas de juego han sido insatisfactorias. No es un secreto que los contenedores STL no son adecuados para los juegos. Si empuja al desarrollador del juego a la pared, entonces tal vez él admite que std::string está bastante bien, y std::vector es una opción predeterminada razonable. Pero todos los contenedores contenidos en el STL tienen un problema de control de asignación e inicialización. Muchos juegos tienen que preocuparse por las limitaciones de memoria para diversas tareas, y para aquellos objetos para los cuales la memoria probablemente tendrá que asignarse dinámicamente durante el juego, a menudo se usan asignadores de losas o arena . El tiempo constante amortizado no es un buen resultado, ya que la asignación es potencialmente una de las cosas más "costosas" que pueden suceder durante la ejecución del programa, y ​​no quiero omitir un marco solo porque sucedió cuando no lo esperaba . Como desarrollador de juegos, debo administrar mis requisitos de memoria por adelantado.

Se obtiene una historia similar para otras dependencias en general. Los desarrolladores de juegos quieren saber qué toma cada ciclo de procesador, dónde y cuándo y de qué es responsable cada byte de memoria, y también dónde y cuándo se controla cada hilo de ejecución. Hasta hace poco, los compiladores de Microsoft cambiaban ABI con cada actualización, por lo que si tenía muchas dependencias, reconstruirlas todas podría ser un proceso doloroso. Los desarrolladores de juegos generalmente prefieren pequeñas dependencias que son fáciles de integrar, hacen solo una cosa y lo hacen bien, preferiblemente con una API de estilo C, y son utilizadas por muchas compañías, son de dominio público o tienen una licencia gratuita que no requiere una indicación del autor. SQLite y zlib son buenos ejemplos de lo que los desarrolladores de juegos prefieren usar.

Además, la industria de los juegos C ++ tiene una rica historia de pacientes con el síndrome "No inventado aquí". Esto debería esperarse de la industria, que comenzó con entusiastas individuales que hicieron sus propias cosas con equipos completamente nuevos y no tenían otras opciones. La industria del juego, entre otras cosas, es la única en la que los programadores se indican en los créditos sin ningún orden en particular. ¡Escribir una variedad de cosas es divertido y ayuda a tu carrera! ¡Es mucho mejor construir algo propio que comprar ya hecho! Y dado que estamos tan preocupados por el rendimiento, podemos adaptar nuestra solución de tal manera que sea adecuada específicamente para nuestro proyecto, en lugar de tomar una solución generalizada que desperdicie recursos irreflexivamente. La hostilidad hacia Boost es el principal ejemplo de cómo tal pensamiento se manifiesta en el desarrollo del juego. Trabajé en proyectos que fueron de la siguiente manera:

  • Para comenzar, para resolver un problema en particular, conectamos una biblioteca de Boost al proyecto.
  • Todo funciona muy bien. Cuando necesita actualizar, se produce un pequeño dolor, pero no más que al actualizar cualquier otra dependencia.
  • Otro juego quiere usar nuestro código, pero el escollo es que usamos Boost, a pesar de que nuestra experiencia con Boost ha ido bastante bien.
  • Eliminamos el código usando Boost, pero ahora nos enfrentamos a un nuevo problema: debemos resolver el problema que la biblioteca de Boost en lugar de la nuestra resolvió antes.
  • Esencialmente copiamos las partes del código Boost que necesitamos en nuestros propios espacios de nombres.
  • Más tarde, inevitablemente y una y otra vez nos encontramos con el hecho de que necesitamos una funcionalidad adicional que ya estaría en el código original si no la hubiéramos descartado. Pero ahora somos los propietarios de este código, por lo que debemos continuar admitiéndolo.

No nos gusta algo enorme que está tratando de hacer muchas cosas al mismo tiempo o que puede afectar el tiempo de compilación, y esto es bastante razonable. Lo que la gente comete errores una y otra vez es que se oponen a aceptar el supuesto dolor hoy, mientras que debido a esta decisión enfrentarán un dolor muy real y mucho mayor con el apoyo de algo a expensas de alguien. el presupuesto que tendrán que experimentar en los próximos tres años. Lamentablemente, la presencia de evidencia en forma de juegos que utilizan con éxito un plato de STL y Boost, de ninguna manera puede afectar la psicología humana y convencer a los desarrolladores de juegos.

Por todas estas razones, muchas compañías de juegos han creado sus propias bibliotecas que cubren lo que hace STL, y aún más, al tiempo que admiten casos de uso específicos del juego. Algunas grandes compañías de juegos incluso pudieron dominar el desarrollo de su propio reemplazo de STL completo, casi completamente compatible con API, lo que posteriormente conllevó enormes costos para apoyar este proyecto.

Es aconsejable encontrar una alternativa mejorada a std::map , o aplicar una pequeña optimización del búfer en std::vector . Es mucho menos aceptable estar condenado a admitir sus propias implementaciones de algorithms o type traits , lo que hará poco bien. En cuanto a mí, es lamentable que para la mayoría de los desarrolladores, los STL sean solo contenedores. Dado que al aprender STL al principio, se les enseña exactamente eso, hablando de STL, la mayoría implica std::vector , aunque de hecho deberían pensar en std::find_if .

Oportunidad No. 3: Pruebas


Se argumenta que se deben realizar pruebas exhaustivas, TDD y / o BDD deben cubrir todo el código que se puede cubrir, y los errores deben abordarse escribiendo nuevas pruebas.

Por lo tanto, discutamos el tema de las pruebas.

A juzgar por mi experiencia, las pruebas automatizadas prácticamente no se utilizan en la industria del juego. Por qué

1. Porque la corrección no es tan importante, pero no hay una especificación real


Como un joven programador en la industria del juego, rápidamente me deshice de la idea de que debería esforzarme por simular algo de manera realista. Los juegos son humo y espejos y la búsqueda de caminos cortos. A nadie le importa cuán realista sea tu simulación; Lo principal es que sea divertido. Cuando no tienes otra especificación que "el juego debería sentirse bien", falta el tema de la prueba. Gracias a los errores, la jugabilidad puede incluso mejorar. Muy a menudo, un error entra en el lanzamiento, e incluso se gana el amor de los usuarios ( recuerda el mismo Gandhi de Civilization ). Los juegos son diferentes de otras áreas que usan C ++; aquí la falta de corrección no lleva al hecho de que alguien eventualmente pierda sus ahorros.

2. Porque es difícil


Por supuesto, le gustaría producir pruebas automatizadas siempre que pueda. Esto se puede hacer para algunos subsistemas para los cuales hay resultados finales claramente establecidos. Las pruebas unitarias en la industria del juego, por supuesto, están presentes, pero por regla general se limitan al código de bajo nivel: los análogos de STL mencionados anteriormente, los procedimientos de conversión de cadenas, los métodos de motor físico, etc. Los casos en que la sección ejecutable del código tiene resultados predecibles generalmente se prueban mediante pruebas unitarias, aunque TDD no se usa aquí, ya que los programadores de juegos prefieren simplificar sus vidas, y no al revés. Pero, ¿cómo se prueba el código de juego (ver punto uno)? Tan pronto como va más allá de las pruebas unitarias, inmediatamente se encuentra con otra razón por la cual probar juegos es tan difícil.

3. Porque el contenido está involucrado


Probando sistemas no triviales probablemente incluirá la provisión de contenido con el cual será implementado. La mayoría de los ingenieros no son muy buenos para producir este contenido por sí mismos, por lo que para obtener una prueba significativa, deberá atraer a alguien con las habilidades adecuadas para crear el contenido. Después de lo cual encontrará el problema de medir lo que obtiene en la salida; después de todo, esto ya no es una línea o un número, sino una imagen en la pantalla o un sonido que cambia con el tiempo.

4. Porque no lo practicamos


La prueba unitaria es una función para la que conozco las posibles entradas y salidas. Sin embargo, la jugabilidad es un comportamiento impredecible, que evoluciona dinámicamente, y no sé cómo se podría probar adecuadamente este fenómeno. ¿Qué puedo probar? Si, ​​por supuesto, obtengo permiso de mi gerente para dedicar suficiente tiempo a esto, esto es, por ejemplo, el rendimiento o las capacidades de alto nivel, como el emparejamiento, que puedo analizar. Tal trabajo de infraestructura puede ser emocionante para algunos programadores de juegos, pero para la mayoría simplemente no es interesante, y además requiere la aprobación y el apoyo del propietario de la billetera. Como programador de juegos, nunca tengo la oportunidad de practicar escribir exámenes de alto nivel.

5. Dado que [empresa] no ve la necesidad de realizar pruebas automatizadas


Nuestro objetivo principal es lanzar el juego. Vivimos en una era de industria que avanza con éxitos que aprovechan al máximo su dinero en el primer mes de ventas, cuando los costos de comercialización de estos éxitos se maximizan. El ciclo de vida de las consolas nos enseñó que, en cualquier caso, el código no durará tanto. Si estamos trabajando en un juego en línea, lo más probable es que tengamos tiempo adicional para probar el emparejamiento o la carga del servidor. Dado que para el lanzamiento del juego necesitamos que su rendimiento esté en orden, al menos deberíamos realizar pruebas de rendimiento, pero no deberíamos automatizar este proceso. Para la administración en la industria del juego, las pruebas automatizadas no son más que una pérdida de tiempo y dinero. Para su implementación, es necesario contratar ingenieros experimentados que llevarán a cabo el trabajo, cuyo resultado será casi imperceptible. Se podría dedicar el mismo tiempo al desarrollo de nuevas funciones. A corto plazo, es mucho más rentable utilizar personal de control de calidad para probar el juego, lo que nos lleva al siguiente punto.

6. Porque, en general, las pruebas en juegos se clasifican como actividades de segundo orden


Me encantan los buenos profesionales de control de calidad. Para mí valen su peso en oro. Saben cómo mejorar tu juego rompiéndolo de una manera que nunca se te hubiera pasado por la cabeza. Son expertos especializados en tu juego en ese aspecto en el que no entiendes y casi nunca entiendes. Son mejores que un equipo de compiladores súper capaces para ayudarlo a hacer todo bien. Me alegra haber tenido la oportunidad de trabajar con varios maravillosos especialistas en control de calidad durante los años de mi trabajo.

Casi siempre tuve que luchar para asegurarme de que permanecieran en mi equipo.

En las grandes empresas AAA, una organización de control de calidad suele ser un departamento completamente separado de cualquier equipo de desarrollo, con su propia estructura organizativa y de gestión. Supuestamente, esto se hace para que puedan ser objetivos durante la prueba. En la práctica, todo está lejos de ser tan hermoso.

Son tratados como engranajes en un mecanismo enorme, que a menudo se lanzan entre proyectos sin previo aviso y generalmente se tratan como si alguien pudiera manejar su trabajo. Cuando el proyecto "se aleja" de la fecha límite, los ingenieros pueden sentir la crisis en su propia piel, pero el control de calidad se vuelve mucho más fuerte, porque tienen que trabajar en el turno de noche y los fines de semana, además de que también reciben noticias sombrías sobre la actualidad. estado de calidad del proyecto.

Están seriamente mal pagados. Los evaluadores más experimentados con años de experiencia en el área temática reciben menos de la mitad de lo que pagan a un desarrollador de nivel medio. Tuve que trabajar con los ingenieros de control de calidad más inteligentes que crearon proyectos para pruebas de rendimiento con seguimiento y alertas, crearon marcos para probar API y pruebas de estrés, y realizaron muchas otras tareas supuestamente indignas de la época de los "ingenieros reales". Estoy seguro de que estas personas más inteligentes obtendrían mucho más si trabajaran en cualquier otra gran empresa de tecnología.

No son de confianza. No es raro que los evaluadores se mantengan separados de otros desarrolladores, y sus credenciales les permiten acceder solo al piso del edificio donde trabajan ellos mismos, o incluso usar una entrada separada.

Se ven obligados a obedecer. A menudo se les dice a los evaluadores que no molesten a otros ingenieros. Cuando necesitan informar un error directamente, se les pide que se comuniquen con los ingenieros respetuosamente, como "la Sra. H." o "Sr. Y." A veces recibí una llamada de los jefes molestos de los departamentos de control de calidad, en esos casos cuando contacté a aquellos que descubrieron el error para una investigación conjunta.

Todo esto suena como una historia terrible, y que no todos tengan que lidiar con tales cosas, desafortunadamente esto sucede con bastante frecuencia; tan a menudo que los ingenieros comienzan a pensar, quizás bajo una carga de estrés constante, pero eso no los disculpa, que el trabajo de QA es buscar sus propios errores o, lo que es peor, comenzar a culpar a QA por los errores.

En los mejores equipos con los que tuve que trabajar, insistimos en que nuestros equipos tengan sus propios ingenieros de control de calidad que trabajarían con nosotros. Sin embargo, no perdieron su objetividad o deseo de lograr un mejor resultado. Les complació recibir ayuda de los programadores para redactar pruebas automatizadas. Lo que ciertamente no dudo es que sería útil para la industria del juego hacer la automatización con más frecuencia.

Rendimiento de depuración


Dado todo lo anterior, los hábitos de depuración, la plataforma para las API y las herramientas que aún están creciendo, y la complejidad (combinada con la falta de cultura) de las pruebas automatizadas, queda claro por qué los desarrolladores de juegos insisten en las capacidades de depuración.

Pero al mismo tiempo, sigue habiendo problemas con la depuración en sí misma y problemas con la forma en que los desarrolladores de juegos hacen frente al vector de desarrollo actual de C ++.

El principal problema con la depuración es que no se escala. Entre los desarrolladores de juegos de desarrolladores que leen esta publicación, hay quienes deciden que los fenómenos que describí no están de acuerdo con lo que observaron en su práctica. Posiblemente, esto se deba al hecho de que tarde o temprano ellos mismos tuvieron que lidiar con el problema de la escalabilidad de la depuración, y encontraron una forma de evitarlo.

En otras palabras, queremos tener una depuración productiva, porque para detectar errores, a menudo necesitamos poder ejecutar aplicaciones con conjuntos de datos suficientemente grandes y representativos. Pero, de hecho, cuando llegamos a este punto, el depurador generalmente se convierte en una herramienta demasiado grosera para usar, independientemente de si es productiva o no. Por supuesto, establecer puntos de interrupción en los datos ( puntos de interrupción de datos) puede ser útil para detectar problemas de tamaño mediano, pero ¿qué sucede si encontramos errores reales, los que quedan después de que parece que lo hemos solucionado todo? Con los que surgen bajo la carga de la red, o en el caso de una falta de memoria, o que trabajan al límite de las capacidades de subprocesamiento múltiple, o que suceden solo para un pequeño subconjunto no identificado en el contexto de un millón de otros jugadores, o surgen solo en versiones de disco del juego, o solo en la asamblea en alemán, o después de pasar tres horas en pruebas de estabilidad ( prueba de remojo )?

Rasgo dos, podemos confiar solo en el depurador. En este caso, hacemos lo que siempre hicimos. Estamos tratando de aislar el problema, hacer que suceda con más frecuencia; agregamos el registro y tamizamos nuestro programa a través de él; ajustamos temporizadores y configuraciones de flujo; utilizamos búsqueda de compilación binaria; estudiamos volcados de núcleos y registros de fallos; intentamos reproducir el problema recortando el contenido al mínimo; reflexionamos sobre lo que podría estar causando el problema y lo discutimos.

A menudo, hasta que lleguemos a la causa real del accidente, tendremos tiempo para arreglar algunas otras cosas. En otras palabras, resolvemos problemas y, al final, usar un depurador es solo una pequeña parte de este proceso. Entonces sí, la velocidad de depuración es una buena adición, pero su falta no nos impide seguir siendo ingenieros. Todavía necesitamos nuestras otras habilidades, como la capacidad de analizar los volcados del núcleo y leer el ensamblador optimizado.

Cuando uso "C ++ moderno", uso el depurador de la misma manera que de costumbre. Reviso el código recién escrito; Pongo puntos de interrupción en los datos que me interesan; Yo uso un depurador para explorar código desconocido. Con el advenimiento del "C ++ moderno", nada de esto cambia, y sí, aunque el STL usa identificadores _ feos _, esto no hace que el STL sea mágico. A veces es útil ver qué hace el STL "debajo del capó" o pasar por encima; o, como puede hacer ahora, use el depurador para ocultarme el código de la biblioteca .

Cuando me encuentro con problemas de rendimiento de depuración, generalmente no es que el "C ++ moderno" me frene, el hecho es que en este momento ya estoy tratando de hacer demasiado. El uso del depurador no se escala , a diferencia de los tipos, herramientas y pruebas.

Yo mismo estaba preocupado por el problema de que el código C ++ necesitaba más y más optimización, y estaba interesado en la opinión de los desarrolladores de compiladores sobre esto. El hecho es que no hay una respuesta única. Ya estamos en el continuo, y tenemos la oportunidad de avanzar más en esta dirección sin dañar la capacidad de depurar código. Hoy, nuestros compiladores realizan copias de elisión para objetos temporales., incluso si no les pedimos que realicen esta optimización. Esto no afecta nuestra capacidad de depurar aplicaciones. Dudo que nos quejemos de que las compilaciones de depuración comenzaron a incluir NRVO u otra media docena de optimizaciones que se pueden hacer de tal manera que no las notaremos durante la depuración. Sospecho que C ++ se está moviendo en esa dirección.

Epílogo: El camino de C ++ moderno


Si trabajas como programador en el campo del desarrollo de juegos y no te gusta hacia dónde se dirige C ++, entonces básicamente tienes dos opciones para posibles acciones adicionales.

1. No hacer nada


Suponiendo que todavía va a escribir código C ++, simplemente puede continuar usando el lenguaje de la misma manera que lo hizo antes. No es necesario comenzar a usar ninguna función nueva si no desea hacerlo. Casi todo lo que usa ahora continuará siendo compatible, y al hacerlo, en los próximos años continuará cosechando los beneficios de mejorar el compilador.

Esta es una estrategia de comportamiento completamente apropiada para quienes trabajan para sí mismos o con un equipo de personas de ideas afines. C ++ 98, junto con algunas características más nuevas, sigue siendo una buena opción para escribir juegos en él.

Sin embargo, si trabaja en una gran empresa, tarde o temprano tendrá que enfrentar cambios en el idioma, ya que tendrá que aumentar el equipo y contratar nuevas personas. A su vez, cuando contrata desarrolladores de C ++, esto significará contratar desarrolladores con C ++ "moderno". Ocurrirá un cambio de generaciones, como ya sucedió con el ensamblador, C y C ++ 98. Puede administrar el proceso si establece límites sobre lo que está permitido en su base de código y lo que no, pero esta solución no lo salvará a largo plazo. ¿Y qué debes hacer en este caso?

2. Participa


En lugar de ir a un solo GDC una vez al año, comience a visitar CppCon , donde obtendrá mucho más beneficio del dinero que su compañía gastó en un boleto. Participar en discusiones sobre estándares; unirse a grupos y suscribirse a boletines informativos; lea los borradores de normas y brinde retroalimentación a los autores. Si también puede asistir a las reuniones del comité, estará bien, pero incluso si no, aún puede hacer mucho para transmitir su punto de vista a los demás.

La membresía en el Comité C ++ está abierta a todos. Toda la información necesaria para aquellos que desean participar en el trabajo de SG14, SG7 o SG15, o cualquier otro grupo de trabajo relacionado con su área de interés,se puede encontrar en isocpp.org . El comité no tiene planes secretos; de hecho, ¿realmente crees que más de 200 programadores pueden ponerse de acuerdo sobre una agenda común? Aquí, incluso los "jefes" del comité a menudo no "empujan" sus ideas.

Si desea que se escuche su opinión, entonces debe comenzar a hablar donde se pueda escuchar su opinión, y no en Twitter o Reddit. Por favor tome este consejo. Espero con ansias nuestra discusión.

Source: https://habr.com/ru/post/es435036/


All Articles