Como la mayoría de los proyectos usan una API de C ++, se ocupan de las restricciones de la API y las restricciones del proyecto en sí.
Soy un principiante en programación, no me gusta usar OOP en absoluto porque nadie logró explicarme claramente POR QUÉ es tan importante restringirse con un alcance privado para evitar que otros programadores rompan la consistencia de la organización de datos de algún tipo.
Todavía puedo estar bien con OOP, ya que todavía permite hacer cosas geniales como Qt y Ogre3D, pero esas son solo API, no aplicaciones, y esos códigos deben ser perfectos para que nadie pueda criticar el trabajo.
No entiendo por qué la mayoría de los programadores, ya que crean aplicaciones y no API, quieren hacer un código perfecto como si diseñaran una pieza de código genial, y pierden tiempo en esto.
fuente
Respuestas:
¿Alguna vez has escuchado el dicho "Ningún hombre es una isla" ?
Para la mayoría de los programadores esto es cierto. Casi nadie escribe código que sea "solo una aplicación". En muchas aplicaciones no triviales, un programador escribe la interfaz de usuario que un diseñador debe modificar fácilmente. También debe permitir un enlace claro de datos a la lógica de negocios (Controlador, ViewModel o como quiera llamarlo). Otro programador escribe ese controlador, que a menudo puede ser extremadamente complejo, pero debe ser lo suficientemente simple como para ser consumido fácilmente por el programador front-end. Ese codificador de lógica de negocios está consumiendo código de quien escribió la capa de datos (Modelo, Repositorio, etc.). No tiene que usar OOP, sin embargo, en lo que OOP es bastante bueno es que le permite encapsular la lógica detrás de una interfaz para que otras personas con las que trabaje puedan usar su código sin romperlo (¡suponiendo que haya probado esa interfaz!). La abstracción no es la bala de plata,
Entonces podría estar diciendo ahora "En serio, soy una excepción y nadie verá mi código ni trabajará con él en absoluto". Es justo, pero cuando necesite corregir un error en esa aplicación dentro de unos meses, o si desea agregar un par de características, probablemente verá que la persona que escribió ese código en ese momento y la persona que lo está modificando ahora están Dos personas totalmente diferentes. A menudo asumimos que recordaremos cosas, lo cual es el núcleo de por qué escribimos código descuidado, pero la verdad es que usted dentro de seis meses no recordará los hacks que ha puesto en su aplicación ahora. Tu futuro yo tendrá suficiente con lo que lidiar, así que ¿por qué no darle un descanso?
fuente
En pocas palabras, es por eso que quieres preocuparte por un código hermoso.
No escribes código para la computadora. La computadora solo entiende el código binario de todos modos (que se produce a partir de su código fuente a través de compiladores e intérpretes). No le importa la belleza o la claridad, ni siquiera si su código hace lo que se supone que debe hacer.
Escribes código para tus compañeros programadores. Y hacen lo mismo por ti. Si no puede entender un código escrito por otra persona, ¿cuál cree que es su oportunidad de encontrar y corregir un error o agregar una nueva funcionalidad?
fuente
Lo que otros han dicho como si nunca supieras si es posible que necesites tu código nuevamente en el futuro es correcto, por supuesto.
Pero para mí hay un punto importante, por qué siempre trato de escribir un código hermoso:
Es entrenamiento para mejorar.
Si aprendo algo nuevo sobre un lenguaje que uso o sobre algunos conceptos generales de programación, inmediatamente trato de usarlo, trato de hacerlo parte de mi flujo de trabajo diario y cadena de herramientas mentales.
Si solo lee sobre algo como OOP, lo olvidará en pocas semanas. Y nunca recibirá la capacitación sobre cómo aplicarlo adecuadamente a grandes problemas, siempre y cuando no se enseñe a sí mismo al aplicarlo a pequeños problemas.
Ejemplo:
¿Por qué es importante restringirse con un ámbito privado?
En proyectos pequeños no lo es. Algunos lenguajes (por ejemplo, Ruby) incluso desalientan este tipo de encapsulación hasta cierto punto. Pero hay usos para ello. Muchos.
Y usarlo viene con ciertos problemas y muchos detalles que tienes que aprender. Usarlo en pequeños proyectos te enseñará esto. Verá algunos mensajes de error de su compilador que son nuevos para usted y en un proyecto pequeño podrá encontrar la fuente del problema más fácilmente.
Aprenderá sobre espacios de nombres en C ++. No hay tanta necesidad de ellos en pequeños proyectos. Lo mismo ocurre con la estructura genaral de los archivos de encabezado e incluye. Puede aprender todo esto desde el principio en la protección de una pequeña base de código.
fuente
Se trata de tener que mantener el código heredado. Y en unos meses, el código que está escribiendo ahora se convertirá en un código heredado que también deberá mantener.
Codificación de psicos violentos
fuente
Lo que R0MANARMY dijo en su comentario. El código limpio y "hermoso" hace que sea más fácil de leer, comprender, mantener, cambiar y arreglar en el futuro, no solo para usted, sino también para los demás que vienen después de usted.
Algunas personas, cuando hacen algo, intentan hacerlo lo mejor posible, de la mejor manera posible, por lo que es "perfecto", o en este caso, "hermoso". Descubrí que hay una gran superposición entre este conjunto de personas y desarrolladores (¡incluido yo mismo!).
Sin embargo, tenga en cuenta que "bello", "limpio" o "elegante" son términos muy subjetivos que significan cosas diferentes para diferentes personas. Sin embargo, por lo que he visto, el código que es ampliamente considerado como hermoso, limpio y / o elegante,
fuente
Estoy de acuerdo con la mantenibilidad. Solo intente hacer un proyecto relativamente grande, y verá todo el desorden que ata sus manos a la corrección de errores, agregando nuevas características, etc. Pero para hablar de belleza:
fuente
En un equipo lo suficientemente pequeño con una base de código lo suficientemente pequeña que está realmente bien coordinada con buenos estándares (podría ser una sola persona), a menudo puede encontrar un software confiable que simplemente deja todos los datos a la vista para que cualquiera pueda tocar todos los campos de datos de una
struct
exposición abierta y con lastruct
definición abierta para cualquier persona que incluya ese encabezado para acceder. La ley de Murphy no siempre se aplica en esos casos.Pero he trabajado en el escenario opuesto de una enorme base de código con muchos millones de LOC que datan de los años 80 con un gran equipo de desarrolladores de todo el mundo donde solo nos reuníamos cara a cara cada pocos meses, coordinados de forma flexible, a veces apenas habla el mismo idioma, sin estándares de codificación, excepto el SDK que la gente a menudo no seguía de todos modos, sin pruebas de unidad / integración, usando SVN sin ramificación y a veces pasando 6 semanas sin registrar el código, solo para bombardearnos con errores, y No fue hasta entonces que realmente entendí el valor de ocultar información y mantener invariantes .
Me ocupé de errores en los que ni siquiera podía reproducir el problema de manera consistente en mi máquina, y a veces ninguno de nosotros podía hacerlo entre todo el equipo. Y cuando finalmente pude reproducir afortunadamente el problema informado por el usuario o algo que se parecía a él después de todo tipo de prueba y error (y la prueba y el error a menudo tomaron horas porque la ineficiencia de nuestro software se combinó con la ejecución de la depuración contra la producción del usuario final los datos a menudo tomaban más de 15 minutos solo para que los datos se cargaran), lo rastrearía a algo así como un
struct
tipo de cadena que tenía unlen
conjunto a un número negativo de basura, como una longitud de cadena de-921141282
.Eso nunca debería suceder, pero ¿quién lo hizo? Así que tuve que establecer puntos de interrupción de memoria y averiguarlo, y cuando finalmente lo hice, fue como una interacción en cascada de variables no inicializadas que se usan aritméticamente, que finalmente se sumaron a un
len
campo de cadena que se estableció en un número de basura negativo, y ese código no había sido modificado en años. Voló por debajo del radar.Y todo ese tiempo después de encontrar muchos errores como este, pensé para mí mismo, ¿cuánto más confiable sería nuestro software si solo se usara
getters
ysetters
? Los captadores y establecedores son generalmente indicativos de los peores tipos de diseños de interfaz posibles, pero un establecedor podría al menos desencadenar una falla de aserción si alguien intenta establecer la longitud de una cadena en un valor negativo. Podríamos haber atrapado ese error añosantes en el momento preciso en que se introdujo en segundos, no en la culminación de horas de esfuerzo de investigación. Y eso es solo pensar egoístamente como desarrollador; no cubre todas las horas de dolor que podría haber salvado a los usuarios y al equipo de control de calidad también. Usted sabe que su sistema está en un lugar bastante malo cuando sueña con lo mejor que podría ser si usara setters y getters frente a los últimos 35 errores que pasó toda la noche arreglando.Incluso tuvimos casos en los que
structs
se documentaron de manera tal que nadie más debería acceder a esos campos de datos, solo para encontrar lugares en el sistema que accedan a esos campos de datos.Así que estos son los tipos de cosas que realmente solo puedes apreciar al máximo enfrentando el peor de los casos, pero a menudo lo harás a menos que tengas la suerte de pasar el resto de tu vida trabajando en bases de código más pequeñas con equipos bien coordinados y Fuertes estándares de codificación.
Esa es una dificil. Todavía estoy tratando de resolver eso. La mayor parte del código que considero hermoso que he escrito a lo largo de los años, o al menos confiable y relativamente intemporal y estable (no necesita / quiere cambios) fue escrito en C y recientemente en Lua. Todavía me cuesta escribir código C ++ que parece pasar la prueba del tiempo hasta el punto de no reflexionar sobre eso unos años más tarde y al menos desearía poder cambiarlo. Siento que se ha vuelto más fácil desde C ++ 11, pero necesito algunos años para descubrir qué tan bien mi código se las arregla para sobrevivir sin necesidad de cambios para asegurarlo. Para mí, la "belleza" definitiva es la "estabilidad", como en el código que no necesita y ni siquiera tienta a ningún cambio adicional, pero sigue siendo relevante y útil en los años venideros, ya que '
fuente
Bueno, definir interfaces limpias y útiles ("hermosa" es un calificador deficiente) se trata de asegurarse de que:
Los puntos 1. y 2. requieren que piense mucho sobre el contrato que está haciendo con su usuario. Ese contrato, o protocolo, es la forma de comunicarle al usuario cómo puede usar su sistema. Por ejemplo, las funciones miembro de solo lectura (funciones miembro const) informan mucho sobre qué situaciones debería poder llamar a esa función. Del mismo modo, los atributos de cada función sumergen al usuario para recopilar y proporcionar la información mínima requerida para que el sistema funcione.
Todos los puntos juntos sugieren que sus interfaces solo deben mostrar servicios que sean útiles para el usuario. Primero, limitar el uso del sistema por parte del usuario solo para lo que se creó el sistema. En segundo lugar, evitando que manipule el estado interno de manera incorrecta. Por lo tanto, la forma más fácil en C ++ de lograr esto es poner a todos los miembros privados y declarar explícitamente qué servicios proporciona su sistema, utilizando funciones miembro o globales (en espacios de nombres). Otra forma es usar el idioma de PImpl.
Tercero, y lo más importante: su interfaz debe proporcionar una abstracción útil, lo que significa que el usuario no debería tener que entender la implementación. Cuando conduzco un automóvil o una lavadora, no quiero saber cómo está construido adentro (incluso si soy un geek tecnológico ...). Solo necesito usarlo y no tener que preocuparme por lo que hay dentro.
Es dificil.
Cualquier definición de protocolo, como el diseño de un lenguaje de programación o el diseño de una clase, no es tan obvio como puede haber pensado primero. Se requiere mucha experiencia para apreciar las sutilezas de diseñar interfaces.
Todo lo que no es revelador cuando se definen estructuras o clases que representan conceptos de muy bajo nivel. Cuanto más alto sea el hardware, más necesitará para tener interfaces limpias, claras y útiles.
fuente