Programación: ¿Cuál es la mejor manera de leer el código de otro programador?

Depende mucho del proyecto y del estilo de codificación, por lo que es difícil dar un enfoque específico, pero aquí están las reglas generales:

  • Primero apunte a una comprensión de arriba hacia abajo de lo que se supone que debe hacer el código y por qué, mientras ignora cómo inicialmente. Por ejemplo, el código de Data Science a menudo tomará conjuntos de datos (como tablas o archivos CSV) como entrada y salida, para que pueda comprender cada parte de la tubería al observar qué datos se leen y qué se produce. Luego puede continuar observando de dónde proviene la entrada o para qué se utiliza la salida. Las pruebas unitarias y la documentación son otras buenas formas de comprender qué se supone que debe hacer el código.
  • Obtenga una idea de los patrones de diseño utilizados en la base de código: por ejemplo, ¿está escrito en un estilo principalmente funcional u orientado a objetos? Una vez que tenga una idea de cómo está organizado el código, úselo para descubrir cuáles son los principales componentes específicos del código y cómo los navegaría.
  • En este punto, debe comenzar a hacer cosas con el código: escriba algunas pruebas y refactorice algunas cosas que espera que no hagan la diferencia. Luego, cambie algunas cosas que espera que marquen la diferencia y vea si las cosas que suceden son lo que predijo. Intente asegurarse de tener iteraciones muy rápidas: poder realizar cambios en 30 segundos le permitirá tener una idea del código mucho más rápido que los cambios que tardan 5 minutos en probar.

Trabajo como consultor revisando el código de otras personas y viendo cómo mejorarlo, refactorizarlo, ver dónde está mal y aunque estoy de acuerdo en que sería bueno comenzar con comentarios y pruebas unitarias, todavía tengo que encontrar un proyecto que tenga ellos y fueron útiles. Puede ser que, por lo general, el código que tengo que mirar es lo que se considera “código heredado”.

Así que tomo cada pieza de funcionalidad como uno de esos laberintos que vienen en los periódicos y diseccionan el código.

Uno comienza con una pieza de funcionalidad y estudia la entrada, por ejemplo, en una aplicación web, generalmente es fácil, ya que uno puede mirar las páginas y las solicitudes que se envían a la aplicación. Luego se analiza el resultado de la solicitud, la respuesta, y comienza a avanzar desde la solicitud y / o hacia atrás desde la respuesta para conectar todos los puntos.

Si lee los comentarios, descubrirá qué dicen los comentarios que hace la aplicación. Y citando al Dr. House, “todos mienten”. Lo mismo ocurre con los nombres de funciones / variables / módulos. DEBEN reflejar el propósito y tener el significado adecuado … pero no se sorprendan si no lo hacen.

Si observa las pruebas, verá lo que las pruebas esperan de la aplicación, pero no cómo llega allí.

Averigua qué hace el código al mirar el código, y aunque uno podría intentar leer toda la base de código e intentar extraer la imagen, me resulta más fácil seguir la funcionalidad, ya que verás exactamente lo que hace. para hacer el trabajo Y a partir de ahí, puede retroceder la mayor parte del funcionamiento y la configuración de la aplicación.

No digo que los comentarios y las pruebas sean inútiles. Las pruebas le muestran la funcionalidad y generalmente son repetibles, por lo que puede usarlas para rastrear la funcionalidad, repitiéndolas tantas veces como sea necesario para ver todos los caminos que se siguen. Sin embargo, necesitaría buenas pruebas para eso, por lo que uno no puede realmente solo con eso.

Una vez que tenga experiencia con la tecnología, se puede omitir un poco e ir directamente a algunas partes, como si está buscando una aplicación con un marco que conoce, puede ir directamente a los archivos de configuración o los lugares donde el negocio La lógica suele ubicarse y mirar allí.

Es un trabajo detectivesco interesante, pero también suele ser desafiante y frustrante. También se necesita una mente abierta porque las cosas se pueden hacer de muchas maneras diferentes y si espera que las cosas se hagan a su manera, o incluso “de la manera correcta”, estará buscando en los lugares equivocados durante mucho tiempo. Al principio uno debe mirar los hechos, el cómo y preguntar por las razones, el por qué, más tarde.

Así es como lo abordo y hasta ahora me ha funcionado bastante bien. Los desarrolladores exitosos encuentran su propio método, ya que no hay una bala de plata.

Primero hago un chequeo de cordura: ¿Hay comentarios razonables y describen la intención del código? Si no, generalmente me detengo allí.

Para el código no trivial, primero trato de obtener el panorama general: la estructura modular. A menudo, dibujaré un cuadro. Examinaré cada módulo y las funciones principales e intentaré tener una idea de lo que hacen, en lugar de prestar atención al código de detalle. Esto me permite entender el “entorno” del código.

Después de hacer eso, generalmente tengo una idea de cuál es la “pieza clave del código”. Que luego diseccionaré, tanto leyéndolo como tal vez esquematizando el algoritmo utilizado, si corresponde. Lo que estoy buscando es entender el pensamiento sobre el problema que resuelve el código.

A veces, noto un estilo o enfoque para escribir código o resolver pequeños problemas de detalle al leer el código. Estos los guardaré en un álbum de recortes (mantengo un dokuwiki personal para ese propósito) junto con un vínculo de retroceso a la fuente de la observación. Estos vínculos de retroceso me han sido increíblemente útiles a lo largo de los años.

A veces me encuentro con un algoritmo o referencia que nunca he encontrado (es un gran mundo con muchos ojos expertos) y tomo nota de eso. Como ejemplo, el otro día leí en Quora sobre el rápido algoritmo inverso de raíz cuadrada. Ha estado en uso durante décadas, sin embargo, nunca me había encontrado con este maravilloso código.

Mi sugerencia: lea el código activamente, no pasivamente. Tome notas en cualquier forma que le permita encontrarlas meses después. De vez en cuando, busque esas notas.

Dibujando las lógicas en un diagrama de flujo.

Odiaba el diagrama de flujo cuando teníamos que usarlos en la universidad, y no me molesté en usarlo durante años después.

Luego comencé en un nuevo trabajo, y mi primer proyecto fue reescribir una API existente.

Mi compañero de trabajo me mostró lo que hace la API e incluso me dijo cuál es un buen punto de partida para la reescritura. Pero ese punto de partida era una función con cien líneas de código, mientras que empleaba muchas clases y llamaba a docenas de métodos que también tenían cien líneas de largo.

Intenté leer el código línea por línea, y me encontré olvidando qué método estaba haciendo qué y qué objeto pertenecía a qué clase. Comencé a anotar notas, pero eso pronto se convirtió en un desastre a medida que profundizo en cada método secundario.

Finalmente recordé el diagrama de flujo de la universidad. Tenía Microsoft visio y comencé a usarlo. Cada vez que la lógica se vuelve demasiado complicada y el diagrama de flujo se hace demasiado grande, lo refactorizo. Al final, obtuve un diagrama de flujo agradable y limpio que muestra el propósito principal de la función, mientras que cada parte se vincula a lógicas detalladas si es necesario.

No solo pude comprender completamente el código, también encontré áreas que necesitaban refactorización y errores ocultos.

Desde entonces, había estado usando muchos diagramas de flujo, para comprender el código de otras personas, para aclarar los requisitos, etc. Me ayudó a detectar muchas incógnitas que de otro modo se habrían pasado por alto.

La mejor manera de leer el código de otro programador es línea por línea. La mayoría de los programadores profesionales deben incluir comentarios en el código fuente de desarrollo para ayudar a otros programadores a leer su código. Aunque, sin los comentarios, tendrá que leer el código y entenderlo usted mismo, línea por línea. A medida que leas el código, sería beneficioso si colocas comentarios en él para que todo tenga sentido. Los comentarios que coloque a lo largo del código serán beneficiosos para usted u otro programador en el futuro cuando tenga que profundizar nuevamente en el código.

No soy un programador profesional y soy relativamente un novato, pero esta es mi experiencia leyendo códigos de otras personas:

Cuando es algo tan grande como Minecraft, cuando quieres aprender cómo funciona el código para hacer tus propias modificaciones, es suficiente leer el nombre de las clases. Si está interesado en cuál es esa clase, también puede leer los nombres y propiedades de los métodos. En general, debería poder usar eso sin mucho problema.

Pero, ¿qué sucede si llegas a un método que necesitas entender que está lleno de números aleatorios y multiplicación y operaciones bit a bit (eso es lo que sucedió cuando intenté leer la clase de brújula de Minecraft cuando quería hacer un artículo similar) sin comentarios? o palabras reales, o cualquier otra pista que no sea lo que está escrito allí? Obtener. Lejos.

También he tenido un amigo de donde he leído el código. Lo leí como cualquier otra cosa para leer. Primero una lectura superficial, y concéntrate en lo que me interesa. No leo todo el código. Llego a las partes interesantes que encuentro porque sus nombres y leo las partes más específicas que quiero saber. Si desea cambiar la esponjosidad de un gato, probablemente encontrará una variable de esponjosidad, un método setFluffiness, etc.

No es que el código fuera solo símbolos y no palabras reales.

Cuando se trata de leer ejemplos de código, como un ejemplo de xxxxsorting, diría que lo leí línea por línea más o menos. Porque cuando el código es cada una de las líneas importantes para el mismo objetivo, entonces no creo que deba perder ninguna línea. Los nombres de las variables ayudan mucho.

Entonces, en conclusión, leo principalmente código buscando palabras en inglés.

Al leer los comentarios junto con él (si el programador los ha proporcionado)

Es una manera muy simple de entender el código de otras personas leyendo los comentarios adjuntos.

Otra forma es leer cada línea, línea por línea. Este método puede demorar un poco, pero es un método muy efectivo para comprender el código de los demás.

Lo primero que hago es buscar las pruebas unitarias. Luego me aseguro de estar preparado para ejecutarlos. Es mejor que todos pasen .

Si no encuentro ninguna prueba unitaria, busco cualquier prueba existente que sea similar y la uso para iniciar un nuevo archivo de prueba. Solo estoy tratando de demostrar que puedo crear una nueva prueba y ejecutarla, suponiendo que aún no lo haya hecho en este proyecto.

Si el proyecto ni siquiera está configurado para pruebas unitarias, salgo a caminar. Paso unos 10 minutos revisando las principales opciones de vida que me llevaron a este momento.

Siempre es más fácil entender el código leyendo las pruebas. Asumamos que esa no es una opción. Pasaré unos minutos formateando el código a mano. En realidad es molesto cuando el código ya está perfectamente formateado. Si a usted (programador original) le importaba tanto la calidad, ¿dónde están las malditas pruebas?

Reformatear el código a mano me da la oportunidad de familiarizarme con el código. Es como darle al código un masaje en la oscuridad. Me gusta saber su tamaño y forma general. Las personas que usan formateadores automáticos se están perdiendo esta acción de TLC.

Finalmente, leeré los nombres de los métodos y los comentarios. No hay mucho más que se pueda hacer sin una lectura línea por línea.

Siempre abro cuando mis amigos piden ayuda cuando se atascan en la asignación de código. Me sentaré con ellos y ayudaré a depurar su código, encontraré cualquier falla allí y les diré qué puede estar mal. Me ayuda a comprender cómo codifican otras personas, lo que piensan, y a veces podría ver mejores soluciones para resolver los mismos problemas desde su perspectiva.