Cómo escribir g̶o̶o̶d no, gran código

Feb 09 2023
Una opinión no científica, completamente subjetiva de algún desarrollador aleatorio en línea.
¿Quién es este tipo que cree que es? ¿Qué sabe él acerca de escribir un código "excelente"? Tendrías 100% razón al pensar eso, y para ser completamente honesto... Tengo mucha, mucha más experiencia escribiendo código no excelente. no se escribe código excelente por muchas razones (algunas se enumeran a continuación) A pesar de mi profunda experiencia con código subóptimo, tengo casi una década de experiencia pidiéndole a la computadora (con la mayor amabilidad posible) que haga las cosas que yo y otros humanos queremos.
Live Oaks (Un hermoso organismo dinámico complejo) — Sitio histórico de Wormsloe, Savannah, GA, EE. UU. por Ryan Arnst

¿Quién es este tipo que cree que es? ¿Qué sabe él acerca de escribir un código "excelente"?

Tendrías 100% razón al pensar eso, y para ser completamente honesto... Tengo mucha, mucha más experiencia escribiendo código no excelente.

no se escribe un gran código por muchas razones (algunas se enumeran a continuación)

  1. Es dificil
  2. "genial" es subjetivo
  3. el software nunca se termina (no puede "ser" excelente, tiene que "permanecer" excelente)
  4. la calidad puede cambiar según los requisitos actuales
  5. mucho software que funciona no es bueno (malos modelos a seguir)
  6. las personas que quieren software a menudo no son ingenieros de software
  7. …

A pesar de mi profunda experiencia con código subóptimo, tengo casi una década de experiencia pidiéndole a la computadora (con la mayor amabilidad posible) que haga las cosas que yo y otros humanos queremos.

Durante este tiempo he llegado a apreciar varios conceptos y patrones, y también he aprendido a desconfiar profundamente de los demás.

En este artículo, resumiré algunos de los aspectos buenos y malos del software, y proporcionaré evidencia de respaldo de personas realmente inteligentes.

Bienvenido al paseo

Que es genial"

Comencemos por definir qué es "genial". Sin embargo, podría ser más fácil de definir indicando rápidamente lo que no es.

Gran código es

  1. no es dificil de leer
  2. no es difícil razonar sobre
  3. no hace que te odies a ti mismo hoy o 7 días después de escribirlo
  1. 90% estructura y 10% sintaxis
  2. una función de abstracción de información combinada con la gestión de recursos prevista
  3. un amigo de las matemáticas (específicamente la teoría de conjuntos/categorías)
  4. escrito para humanos, no para hardware

1. 90% estructura y 10% sintaxis

Todas estas ideas están inspiradas en temas mucho más amplios y profundos. En cuanto a la estructura, podemos mirar al paradigma de programación SOLID.

SOLID representa un conjunto de 5 "reglas" que deben seguirse para crear software mantenible. Conceptos enumerados a continuación

S - Single-responsiblity Principle
O - Open-closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D - Dependency Inversion Principle

Estos principios giran en torno al poder de la Programación Orientada a Objetos (lo aman o lo odian) y describen una forma elegante de dividir sus abstracciones en partes amigables con el software.

Siguiendo estos principios, puede evitar muchas complejidades desagradables que surgen en el software funcional.

Por ejemplo, con los principios SOLID, reducirá la huella de su código y centrará los archivos en torno a la funcionalidad común; facilitando la navegación y agregando/eliminando funciones sin afectar otras partes de su base de código.

Estos problemas se evitan por completo a nivel de estructura de su aplicación, en lugar de a nivel de código

La limpieza a nivel de estructura es una forma poderosa de hacer cumplir una organización duradera.

Artículo fácil de digerir sobre SOLID por Digital Ocean: aquí

Si eso no fuera suficiente, el tío Bob sigue lanzando éxitos .

Recomiendo encarecidamente su libro más reciente publicado en 2017 (y, sinceramente, todo lo más reciente también).

“Arquitectura limpia: una guía para artesanos sobre la estructura y el diseño del software” —https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/

Este libro explora cómo puede extender estos conceptos al nivel del sistema .

A medida que trasladamos más aplicaciones a “la nube” y aprovechamos los servicios distribuidos. Estos principios de diseño tienen cada vez más impacto en la grandeza de su código.

un gran código es solo una herramienta que llena la estructura del diseño de sus aplicaciones, su sistema debe expresarse a través de su estructura, no de sintaxis.

2. una función de abstracción de información junto con la gestión de recursos prevista

Um que. Realmente me perdiste con eso. una función de whaa?

Vamos a romperlo.

“una función de abstracción de información” es una forma concisa de expresar que nuestro código es el resultado de nuestras abstracciones .

En otras palabras, nuestro código es un reflejo de cómo decidimos dividir los conceptos de nuestra aplicación.

Más concretamente; si nos enfrentamos a un problema y decidimos que debemos crear "Usuarios" y "Sesiones", efectivamente hemos dividido nuestro problema en esas ideas abstractas de usuarios y sesiones.

…está bien Creo que cubrimos la “función de abstracción de información”.

A continuación, combinamos eso con la "gestión de recursos prevista", que es una forma elegante de decir que los ingenieros de software tienen la tarea de poder ver el futuro y construir sistemas que puedan soportar cambios futuros

Si no lo sabía, es su culpa como programador que no usó el marco más nuevo un año antes de que se creara. ¿¡Cómo es que no lo sabes!? (Lea como sarcasmo, prometo que esto no es personal).

Entonces, para resumir; la calidad de nuestro código no siempre es su complejidad computacional, número de líneas o nombres de variables elegantes.

Es la capacidad de dividir eficazmente su problema en fragmentos abstractos que resistirán los cambios imprevisibles del mañana.

Sí, sí, sí, lo sé; eso no parece posible. Bueno, no lo es, y es nuestro trabajo como desarrollador administrar las cosas que sabemos y las cosas que sabemos que no sabemos.

Es un ejercicio de evaluación de riesgos y planificación de costos. No sabía que te habías inscrito en eso, ¿verdad?

Sin embargo, ¡hay esperanza!

Al seguir conceptos confiables (más por venir en breve) podemos fortalecernos a nosotros mismos y las aplicaciones para un mundo cambiante.

Antes de entrar en las cosas realmente buenas, podemos reconocer algunas ideas dignas de "confianza" aquí.

  • Organismos de estándares (hay personas que ya lo han pensado profundamente, y realmente apreciarían si haces uso de su gran trabajo. Esto se aplica especialmente a los algoritmos, la seguridad, la plataforma cruzada y otras cosas realmente importantes como los códigos QR).
  • Lenguajes estáticos y fuertemente tipados (honestamente, esto no se trata realmente de los problemas de seguridad de bajo nivel que evitará. Se trata de la naturaleza centrada en el ser humano de los tipos. uno, si viola el tipo en su código, el compilador le gritará, y dos, otros desarrolladores realmente sabrán lo que está haciendo su código).
  • Poesía (menos sobre las palabras y más sobre la capacidad de comunicar un significado complejo con pocos símbolos. Su código es poesía, aunque una audiencia muy poco imaginativa, pero aún así debe leerse breve y dulce).

Si bien es posible que no lo sea, su código debe ser amigo de las matemáticas.

Sí, lo sé: las matemáticas son aburridas y nunca has usado una derivada en la vida real.

Pero…. Lo prometo, puede ser muy útil. En realidad, es la herramienta más confiable que tenemos.

Es confiable porque tiene una larga historia de contribuciones de código abierto y han resuelto la mayoría de los errores en el software principal. Ahora los desarrolladores (matemáticos) están ocupados descubriendo cosas locas como la física cuántica.

Podemos confiar en cosas útiles como la criptografía para asegurar nuestras cuentas bancarias y comunicaciones. Podemos confiar en la teoría de conjuntos para aplicar el sistema de tipos de [AGREGAR LENGUAJE DE PROGRAMACIÓN FAVORITO AQUÍ]. Incluso podemos llegar a confiar en el álgebra lineal para optimizar nuestra ruta en los mapas de Google y ChatGPT para seguir siendo tonterías.

Es importante recordar que detrás de toda la interfaz de usuario elegante y la pantalla brillante, nuestras computadoras son solo eso; informáticos.

Si eliminas todas las complejidades, te quedas con los aspectos básicos de la suma y la resta.

Tal vez, solo tal vez... hay una forma en que podemos expandir todo ese poder a nuestro propio código.

Vamos a sumergirnos un poco más profundo

Haré una suposición descabellada y asumiré que usted (el lector) está familiarizado con la Programación Orientada a Objetos,

Y... también iré tan lejos como para suponer que ha oído hablar de la programación funcional, pero decidió que era algo sobre lo que aprendería otro día.

Si está en ese campo, es posible que no sea consciente de la belleza y la elegancia de los lenguajes de programación que siguen más de cerca la semántica de las matemáticas tradicionales.

Nosotros (las personas normales) estamos mimados con las abstracciones que brindan los lenguajes principales. Esperamos poder crear variables cuando queramos y construir flujos de control complejos con torres de ifyelse

Sin embargo, nosotros (las personas normales) deberíamos tomar nota de nuestra contraparte de programación funcional más inteligente.

Hay superpoderes ocultos en lenguajes simples y restrictivos. Proporcionan métodos comprobables ( ⚡️ impulsados ​​por matemáticas ) para demostrar que su código cubre todos los casos, o que se puede dividir en piezas de trabajo discretas que se pueden distribuir en máquinas infinitas.

Infinity y Proofs son ideas difíciles para el programador promedio, pero cualquier matemático se las come en el desayuno.

Por ejemplo, uno de estos superhéroes en el video a continuación, muestra cómo modelar un sistema puede proporcionar formas de encontrar instrucciones paso a paso para explotar errores complejos increíbles sin mirar una línea de código real

El secreto está en el poder de las matemáticas formales aplicadas al diseño de sistemas.

Si se aplica correctamente (y no, esto no requiere reescribir todo en un lenguaje funcional), obtendrá todos los beneficios de las matemáticas de forma gratuita.

Estos beneficios incluyen pero no se limitan a

  • generación automática de pruebas para todas las formas posibles en que se podría usar su programa
  • explorar las implicaciones de agregar componentes o sistemas a su aplicación
  • esté 100% seguro de que el código funcionará. Quiere estar realmente seguro de que el software del tren de aterrizaje de su avión funciona, ¿no es así?
  • otras cosas más complejas que los ponentes de este vídeo pueden enseñarte. Ah, y si realmente quieres aprender esto, echa un vistazo a TLA+

Tal vez podamos usar algunos de esos conceptos asombrosamente aburridos para hacer que nuestro código sea aburridamente asombroso.

un gran código debería aspirar a tener ideas tan concretas que esas mismas ideas sean válidas dentro de más de 1000 años

Pathagotem ideó un gran software para triángulos en ~570 aC…. eso es como hace 1500 años!

Tal vez deberíamos aprender o usar las matemáticas cuando sea posible: es la mejor manera que los humanos conocemos para expresar abstracciones duraderas.

4. escrito para humanos, no para hardware

Está bien lo suficiente en las cosas de matemáticas. Cuando hablamos de software, tanto como tratamos de evitar a los humanos. Siempre entran en la mezcla.

Hablemos de humanos. ¿Cómo encajan los humanos?

Bueno... ellos son los que quieren el software en primer lugar, y en realidad son los que idearon estos lenguajes.

Además, ellos son los que se preocupan por todo esto: las computadoras no tienen opiniones sobre el código que ejecutan.

La gente hace. La gente define lo que está “funcionando” y lo que no.

Entonces, ¿supongo que deberíamos orientar todo por el derecho humano?

¡Sí! y eso no solo significa que necesitamos una interfaz de usuario bonita y aplicaciones móviles ergonómicas.

Necesitamos extender la humanidad al desarrollo de software. Deberíamos sentir esto en muchos niveles.

La humanidad debe estar en la experiencia del desarrollador en todos los niveles. Las siguientes son algunas preguntas centradas en el ser humano.

  • Las personas se incorporan a las bases de código. ¿Su documentación facilita eso?
  • ¿Cuántas herramientas/comandos o pasos de configuración especiales debo seguir?
  • ¿Cómo se ve agregar una nueva prueba? una nueva característica?
  • ¿Cuántos frameworks/lenguajes impone tu proyecto? ¿Puede ser menos?
  • ¿Cuánto esfuerzo supone pasar de completamente nuevo a totalmente en producción?
  • ¿Cómo se ve la rotura? y tendré que despertarme para arreglarlo?

Pero un pequeño equipo de buenos desarrolladores es mayor que la suma de sus partes (cuando se hace correctamente).

Entonces, ¿cómo obtenemos un gran código de un equipo?

Algunas soluciones son más fáciles que otras. Por ejemplo, uno fácil pero efectivo es estandarizar todo: eliminar toda personalidad de las contribuciones individuales.

Si bien eso suena duro, un sistema sólido tendrá formas/tipos/patrones específicos para hacer las cosas. Debe haber muy poca personalización y creatividad dentro de la sintaxis del código.

¿Por qué es esto algo bueno? Alivia enormemente la carga mental del desarrollador. Si hay una “manera” de hacer algo, entonces debe hacerse de esa “manera”.

Esto mueve efectivamente la solución del nivel de código al nivel de estructura (mencionado anteriormente). Dado que debemos confiar en las decisiones y patrones a nivel del sistema en lugar de en los personalizados.

En pocas palabras, todos los desarrolladores deben compartir tipos comunes. Esto elimina la personalización y hace que sea mucho más fácil integrar el trabajo de varios desarrolladores.

Esta idea debería extenderse mucho más allá de los tipos y tantos conceptos que puedan estandarizarse efectivamente a nivel del sistema cuanto mayor sea su código.

El gran código está tan bien escrito que las contribuciones de diferentes miembros del equipo a menudo no se distinguen de otras partes de la base de código. Además, no debería poder ver dónde comenzó una persona y terminó otra.

En el siguiente video, se exploran en detalle las estrategias para formar equipos y aumentar la productividad a medida que un sistema se vuelve más complejo.

Este es un tema fascinante ya que las ideas del diseño de sistemas complejos están fuera del alcance de las computadoras y tocan fenómenos naturales como la biología animal/vegetal, las interacciones sociales y los planetas.

Nosotros, simples mortales/desarrolladores, tenemos mucho poder en nuestras manos. Podemos construir montones masivos de mierda compleja e inútil, y con esas mismas manos podemos construir nuestros propios sistemas dinámicos complejos que no difieran del planeta en el que escribo esto.

Hasta la próxima, sigue codificando, difunde amor y paz ✌️