¿Qué subconjunto de C ++ se usa con mayor frecuencia?

C ++ es un lenguaje grande con muchas partes diferentes. Dependiendo del problema que se resuelva, diferentes subconjuntos del lenguaje C ++ tienen sentido.

Hay 2 razones principales para elegir un subconjunto del idioma:

  1. Razones relacionadas con el valor comercial
  2. Falta de disponibilidad de ciertas características del lenguaje

Ambas razones están muy relacionadas con el concepto de deuda técnica.
Algunos subconjuntos del lenguaje que he visto:

“C con clases”:
Desafortunadamente, este es un enfoque bastante común que he visto con desarrolladores de C ++ menos experimentados. Algunas personas esencialmente escriben código C en C ++. Puede haber pequeños cambios, como el uso de new en lugar de malloc e iostreams en lugar de printf y similares, pero el código es realmente un código C idiomático aparte de eso.
Una buena señal de esto es cuando las personas no usan los contenedores STL en circunstancias apropiadas y solo tienen matrices sin procesar en todas partes.

Esto suele indicar una mala calidad de C ++, ya que se pierde muchas de las cosas buenas de C ++ sin el beneficio de tener la simplicidad de C. No lo consideraría un buen subconjunto del lenguaje, pero es algo común.

Codificación de subconjuntos estándar:
A veces puede exigir su propio estándar de codificación que tiene varias restricciones sobre qué partes del lenguaje se utilizan. Qué subconjunto es mejor dependerá de su equipo y qué problemas está tratando de resolver. El costo / beneficio de ciertas características dependerá de su proyecto o negocio y, por lo tanto, es difícil decir algo concreto que se aplique a todos.

Ciertas características del lenguaje pueden agregar complejidad adicional y sobrecarga de mantenimiento que agregan a un proyecto. Algunas veces esto valdrá la pena desde un punto de vista de productividad general y otras no. Las características que elija utilizar dependerán del proyecto y del equipo que tenga trabajando en él. Un ejemplo común de una característica que se evita son algunas de las técnicas de metaprogramación de plantillas. Estos son difíciles de corregir y pueden ser difíciles de mantener debido a que las cadenas de herramientas tienen un soporte deficiente para ellos (por ejemplo, los horrendos mensajes de error que recibe). Este problema se exacerba en revisiones anteriores del estándar C ++ que tienen menos soporte para plantillas. Como resultado, he visto a muchos equipos evitar esta parte del lenguaje.

A veces, es posible que desee dar a los desarrolladores más jóvenes del equipo un subconjunto más restringido del lenguaje que los desarrolladores senior. Un desglose común de responsabilidades es tener el código de administración de memoria desarrollado por un grupo central de personas (generalmente el más antiguo) y luego tener interfaces más fáciles de usar disponibles para todos los demás. Al encapsular algunas de las administraciones de memoria más desagradables, puede permitir que el equipo tenga los beneficios de esto sin necesidad de conocer todos los detalles.

Sistemas embebidos:
Los sistemas integrados cubren mucho terreno, pero a los fines del ejemplo me refiero a entornos con recursos limitados. En este entorno, tiene algunas características de lenguaje que no son deseables y otras que simplemente no están disponibles. Scott Meyers tiene un buen material sobre el uso de C ++ en un entorno incrustado aquí: http://www.aristeia.com/c++-in-e…

Indeseable:
Por lo general, no tendrá un buen acceso a la administración de memoria dinámica en dicho entorno. Es posible que cosas como new y malloc en sus implementaciones de biblioteca estándar no existan o introduzcan una cantidad inaceptable de fragmentación de memoria o sobrecarga administrativa para su plataforma. Es posible que desee crear su propio esquema de administración de memoria utilizando algo como una ubicación nueva, pero el costo de su proyecto puede ser demasiado alto.

Indisponible:
A veces, algunas características del lenguaje pueden faltar por completo como su compilador o plataforma o ambas no tienen soporte para ciertas partes del idioma.

Con frecuencia, es posible que no tenga un buen medio para lidiar con el manejo de excepciones y si lo tiene disponible, es posible que no tenga los recursos para hacer que el manejo de excepciones sea una buena opción para su proyecto. Además, pueden faltar otras características del lenguaje, por ejemplo, en la implementación AVR-GCC de C ++, es posible que no tenga acceso a funciones virutales puras sin tener que implementarlas usted mismo. Es posible que desee escribir su propio controlador __cxa_pure_virtual o tal vez no.

Para resumir la mayoría de las veces, el mejor subconjunto del idioma dependerá de su proyecto y su equipo. Ningún subconjunto del idioma es el mejor en todos los casos, tome una decisión informada en función de sus requisitos / especificaciones del proyecto.

La otra cosa que escuchas de los ingenieros es que cada grupo de ingenieros tiene su propio subconjunto. Google tiene un subconjunto que Sergey Zubkov cree que es estúpido, por ejemplo. No tengo suficiente experiencia en el uso de C ++ actual para tener una opinión bien formada, excepto que no quisiera tener que trabajar en pre-C ++ 11 solo por la cantidad de caracteres que tiene que escribir en ausencia de instalación “auto”.

El subconjunto que no es C (por lo que no hay malloc / free, punteros sin procesar, conversiones en C o limpieza explícita, pocos bucles explícitos, etc.) tal vez estadísticamente no es “la mayoría de las veces”, pero ciertamente reduce la cantidad de problemas potenciales al usar las mejores instalaciones de C ++. Solo puede subconjuntar significativamente un idioma si hay alternativas superiores disponibles para todo lo que se niega a usar.

Supongo que acceder a bases de datos y limitar las cosas a std :: strings, ints y las colecciones integradas. Le ofrece los beneficios de velocidad de C ++ sin necesidad de una gran cantidad de experiencia interna para plantillas, administración de memoria y manejo adecuado de excepciones.

Obtienes mucho dinero por esto con esto. Además, la programación de lógica empresarial pura no necesita ninguna de las características avanzadas. Debe ser comprensible para todos los desarrolladores que contrate y ese subconjunto se encarga de eso.

En algunos casos, los subconjuntos se definen de manera bastante directa, variando desde las limitaciones relativamente informales en la guía de estilo de Google hasta las mucho más formales (y a menudo más estrictas) de MISRA C ++ o el proyecto Joint Strike Fighter ( http: // www .stroustrup.com / JSF-AV-rules.pdf ).

Sin embargo, no creo que la mayoría de las personas realmente intente definir un subconjunto formalmente; simplemente aprenden algunas partes lo suficientemente bien como para sentirse cómodas al usarlas, y no se molestan en hacerlo con otras partes.

Parte de la pregunta se reduce exactamente a por qué estás abogando / usando un subconjunto en primer lugar. Si lo está haciendo porque necesita admitir algunos compiladores de destino específicos, entonces su subconjunto más grande posible está definido por los compiladores que necesita apuntar; Si un compilador al que necesita apuntar le falta una característica específica, tiene una razón clara y objetiva para evitar esa característica.

En algunos otros casos, las personas evitan las técnicas con las que se sienten personalmente cómodos porque otros en su equipo no se sienten cómodos con ellos. En tal caso, se convierte en gran medida en una cuestión de costo versus beneficio. Es difícil justificar escribir código que es muchas veces más largo y engorroso solo porque una persona es demasiado perezosa para molestarse con él. Por otro lado, usar una técnica completamente nueva que solo una persona conoce solo porque podría (teóricamente) reducir el esfuerzo de codificación en un 8%, probablemente también sea difícil (¿imposible?) De justificar.

También hay diferencias entre (por ejemplo) técnicas que son conceptualmente difíciles, pero fáciles de leer una vez que comprende el concepto (por ejemplo, recurrencia), y técnicas que son difíciles de entender y descifrar incluso para aquellos que están íntimamente familiarizados con las técnicas. involucrado (por ejemplo, muchos trucos de plantilla C ++).

En pocas palabras: no hay un subconjunto fácilmente identificable que tenga un uso particularmente amplio. Muchos de los subconjuntos poco definidos en el uso más amplio (p. Ej., “C con clases”) probablemente se ignoren mejor de todos modos; estos generalmente se usan por alguna combinación de ignorancia y pereza, en lugar de decisiones bien informadas sobre costos y beneficios.