1 puntos por GN⁺ 3 시간 전 | 1 comentarios | Compartir por WhatsApp
  • La cerca de Chesterton es un consejo de no cambiar a la ligera código cuya razón se desconoce, pero el código y el historial de commits que no dejan registrada esa razón trasladan la misma carga al desarrollador que viene después
  • En este repositorio, el cuerpo de los commits de los últimos 13 años suma apenas 295 líneas según el conteo por comandos, y si se excluyen los cuerpos relacionados con dependabot, revert y typos, se reduce a 167 líneas
  • Los títulos de los commits, incluso en cambios grandes, no dan contexto con cosas como “fix page A”, y casi no hay documentación aparte ni comentarios en el código, por lo que es difícil rastrear el motivo de los cambios
  • En el código quedan refactorizaciones inconclusas, restos de funciones eliminadas, funciones agregadas pero no conectadas ni usadas, y funciones que aparentemente nadie usa
  • Los mensajes de commit y la documentación deberían dejar al menos qué se cambia, por qué se cambia y por qué es una buena solución; si no se deja nada, el costo para los desarrolladores que vienen después crece

La carga que deja un código sin razones

  • La cerca de Chesterton es una metáfora que dice que, si no entiendes por qué algo está así, no deberías cambiarlo a la ligera
    • En programación también puede pasar que “arregles” código que se ve raro y después descubras que esa rareza tenía una razón de ser
  • En este caso aparece el problema del lado contrario
    • Hay mucho código y decisiones extrañas, pero no hay registros que permitan saber por qué terminaron así
    • Después de que todos los desarrolladores anteriores se fueron, ya no hay a quién preguntarle
  • El historial de commits del repositorio casi no aporta contexto real
    • El cuerpo de los commits de los últimos 13 años suma 295 líneas en total
    • Si se excluyen manualmente los cuerpos de commits de dependabot, “revert commit” y “fix typo”, quedan 167 líneas
    • Eso equivale más o menos a una línea por mes
  • Los títulos de los commits también suelen ser insuficientes para explicar cambios grandes, con cosas como “fix page A”
  • No hay documentación separada y casi no hay comentarios en el código
  • Esta situación se parece más a un dedo medio de Chesterton: “hicimos muchas cosas raras, pero no vamos a decir por qué”

El registro mínimo que un desarrollador debe dejar

  • En la base de código quedan varios tipos de código incompleto o residual
    • Refactorizaciones inconclusas
    • Restos de funciones eliminadas
    • Funciones agregadas pero no conectadas ni usadas
    • Funciones que parece que nadie usa
  • En general, también parece grave el problema de la brecha de Chesterton
    • Algo como “todavía no hay una cerca, así que pongamos una”, sin preguntarse si de verdad hace falta una cerca
  • Escribir bien es difícil, pero no es difícil dejar una explicación apenas suficiente para pasar
  • Un registro de cambios debería responder básicamente tres preguntas
    • Qué se cambia
    • Por qué se cambia
    • Por qué esta solución es buena
  • A veces “Implement new feature X” puede ser suficiente, pero en la mayoría de los casos hay algo que decir sobre por qué o cómo se agregó una función de esa manera
  • En correcciones de bugs, refactorizaciones y cambios sustanciales, normalmente se puede dejar al menos uno o dos párrafos explicando el cambio y su motivo
  • Esto no es opcional, sino parte del trabajo de un desarrollador de software
    • No hace falta que sea elegante
    • No hace falta que sea inglés perfecto
    • No hace falta que sea un ensayo grandilocuente
    • Aunque falten cosas, sigue siendo muchísimo mejor que no dejar nada
  • Si no dejas nada, terminas trasladando el problema a todas las personas que vengan después

1 comentarios

 
GN⁺ 3 시간 전
Comentarios en Lobste.rs
  • A veces no está claro en el momento qué cosas van a volverse importantes después. Ayuda muchísimo que todo el proceso que llevó hasta un commit quede registrado públicamente, pero como todas las personas involucradas ya tienen mucho contexto, también hay cosas que se omiten por parecer “demasiado obvias”.
    Si la discusión no queda registrada, se vuelve mucho más difícil desenterrar el proceso de toma de decisiones como si fuera arqueología digital. Al final, a veces hay que lidiar con no saber por qué está esa cerca, y evaluarlo con base en el contexto actual y el conocimiento del sistema que tiene la gente de ahora.
    También ayuda mucho cuando hay alguien que lleva mucho tiempo en el proyecto y ha desarrollado comprensión e intuición sobre el sistema completo. Las organizaciones que ven a los desarrolladores como engranes reemplazables hacen que nadie se quede el tiempo suficiente, así que repiten los mismos errores y vuelven a inventar la rueda.

    • El mayor beneficio que obtengo del code review es que hace que otra persona lea el código y deje comentarios en cada parte donde la razón no es clara. Las partes que no me parecen claras ya las comento yo, así que ahora quedan comentarios en los lugares donde al menos una de dos personas sintió que hacía falta una explicación.
      Así, la siguiente persona que vea el código al menos tiene una probabilidad mayor que cero de entender por qué está hecho así.
    • Es parecido a las recetas de cocina antiguas que no anotaban ingredientes que “todo el mundo sabía dónde encontrar”, o a la música medieval, que asumía que “todos sabían” el ritmo y el compás. Ahora ya no podemos saber qué había ahí.
  • Nunca he entendido a los desarrolladores que en el mensaje del commit solo escriben cosas como “fix” o “WIP commit”. Supongo que nunca han hecho arqueología de código en serio, o ni siquiera habían pensado que eso era algo que se podía hacer.
    Yo siempre intento equivocarme del lado de dar demasiada información. Así, al menos existe la posibilidad de que mi yo del futuro, mi reemplazo, o la pobre persona a la que llamen cuando haya una caída, logre entender por qué algo terminó rompiéndose.

    • Probablemente eso puede deberse a que el tamaño de la unidad de trabajo está mal definido. Para algunos desarrolladores, un commit puede ser uno de cientos de pasos pequeños para construir una sola funcionalidad “vendible”.
      En esos casos, es difícil llevar en la cabeza qué cambió después de cada checkpoint o ponerle una explicación con sentido, y el commit termina tratándose más como el botón de “guardar” de un videojuego que como una forma de dividir el trabajo en unidades bien definidas.
      En cambio, si haces un commit grande como resultado de un refactor grande de una API, probablemente cualquier cosa que no sea una explicación casi al nivel de un documento de diseño se quede corta; y si no vas a hacer eso, el sentido de un mensaje largo también se vuelve ambiguo. Aun así, hay gente que toma esto como si fuera una medalla y empieza a poner en las notas de lanzamiento frases como “corrección de errores y mejoras de funcionalidades”, pero esa es claramente la conclusión equivocada.
  • Muchos desarrolladores olvidan con frecuencia que “la otra persona” que tendrá que leer y entender el contexto de un cambio puede ser su yo del futuro. A casi todo el mundo le resulta familiar esa situación de rascarse la cabeza frente a un bloque de código, correr git blame, y ver que su propio nombre le devuelve la mirada.
    He perdido la cuenta de cuántas veces un buen mensaje de commit me ha ahorrado horas, o incluso días, de buscar entre issues, correos y logs de chat para encontrar el por qué. Incluso en casos donde se suponía que yo debería poder responderlo de inmediato.
    Hay que ser amable con tu yo del futuro. Conviene volcar en el log de git todo lo que sabías, pensabas y se discutió. Nunca está claro qué cosas seguirán siendo obvias dentro de 5 años.

    • Claro, parte de ese conocimiento quizá encaja mejor en comentarios o en documentación de diseño, y no en el log de commits.
    • La parte de sorprenderme al ver mi nombre en git blame no me pasa tanto, al menos cuando hubo una razón detrás. Cuando se trata de algo aleatorio, como el comportamiento extraño de otra persona, es difícil dar una explicación útil si no puedes ver el proceso que siguió; pero si era algo que en su momento tenía sentido para mí, al releerlo por lo general vuelvo a entenderlo.
      Mi forma de aprender parece más bien por acumulación en capas de lava. Desde la preparatoria no he cambiado tanto; más bien he ido agregando continuamente cosas que sé y formas en que puedo usarlas.
  • Hace poco alguien sostuvo que, si un mensaje de commit pasa de una oración, por lo general es una pérdida de tiempo; quise rebatirlo con fuerza, pero resultó que no fui tan bueno como esperaba para demostrar lo contrario
    Una pregunta es qué información debería ir en el mensaje de commit y cuál debería ir en comentarios en línea, ADR u otros documentos de formato más largo
    Sigo intentando escribir buenos mensajes de commit, pero en el trabajo ya no hay esperanza, y ni siquiera en mis proyectos personales de juguete logro ser consistente

    • Para mí, los mensajes de commit son para el revisor. Le dicen por qué este cambio es necesario, qué corrige o por qué se quiere una nueva función, y le dan un marco para entender el cambio
      Pero el código final debería poder entenderse sin leer el mensaje de commit. Si hay algo en el código nuevo que necesita justificación, eso debería ir en un comentario
      Dicho de otro modo, el mensaje de commit explica por qué hicimos este cambio ahora, y los comentarios explican por qué el código, al terminar el cambio, quedó de esa manera
      Los cambios más grandes, en especial las funciones nuevas, deberían tener un documento de diseño en alguna parte. Si necesita revisión, puede ser un documento real dentro del repositorio o puede estar en el rastreador de issues
      El mensaje de commit debería apuntar a ese documento, y quizá también tenga que explicar los detalles que surgieron al bajar el diseño al código. Si es posible, conviene incluir también un resumen corto del documento de diseño. Esto es especialmente importante cuando hay varios posibles revisores: da una señal de quién debería prestar más atención y ayuda a detectar si faltó alguien que debió haber dado feedback en la etapa de diseño
    • Mi criterio para decidir qué poner en un mensaje de commit es que, por lo general, no veo los mensajes con git log o jj log, sino casi siempre a través de la vista de anotaciones por línea
      La línea de título suele ser muy útil para decidir si vale la pena profundizar más. Si el cuerpo contiene información sobre por qué se hizo el cambio, ayuda cuando esa razón no es intuitiva
      Por ejemplo, aunque haya bastante código, muchas veces basta con “admin: add impersonation”. Pero si dice “auth: shorten JWT timeouts”, sí quisiera ver una o dos oraciones sobre por qué había que acortar los tiempos de expiración
      Los mensajes de commit realmente largos, en la práctica, me parecen bastante poco útiles. Estoy en gran parte de acuerdo con las razones que señala el artículo. Ese formato parece venir de flujos de trabajo donde el mensaje de commit es también la descripción del PR, como los flujos basados en correo electrónico o Gerrit. En esos casos no diría que sea perjudicial, pero tampoco me convence que necesariamente aporte valor
    • Hace tiempo escribí un artículo justamente para responder esta pregunta. Organicé varios lugares de documentación como una jerarquía y resumí reglas prácticas para decidir dónde poner cada tipo de información
      Yo también estoy en una situación parecida. En el grupo más amplio de mi trabajo, los únicos que escribimos mensajes de commit detallados somos yo y otra persona
  • Aunque sepas por qué se construyó una cerca, puede que no sepas por qué sigue ahí ahora. Incluso si fuiste quien construyó la cerca de Chesterton, no necesariamente sabes si puedes derribarla
    El árbol de dependencias intencionales cuando se creó un sistema es solo un subconjunto del árbol de dependencias real en un momento dado. Así que, incluso si un desarrollador perfecto te explicara por completo por qué se construyó la cerca, su utilidad sería limitada
    Lo que saben es por qué la construyeron, no la respuesta a “¿qué se rompe si quito esta cerca?”. Basta con ver https://xkcd.com/1172/. Entre los casos de uso graciosos, algunos pueden parecer irrelevantes, pero siempre existen usos legítimos que ni el propio desarrollador original podía conocer
    Está bien saber qué pensaba el desarrollador original o qué se había fumado, pero esa información está en algún punto entre incompleta e irrelevante
    Como ejemplo inventado, supongamos que la cerca de Chesterton se levantó originalmente para mantener a los niños alejados de un charco cuando todavía había granjas a ambos lados. Ahora se construyó una autopista, y esa cerca podría haberse convertido accidentalmente en la única barrera que evita muertes masivas de animales y personas por choques entre ciervos y autos
    Nadie sabe esto. La combinación de autopista + ausencia de cerca no solo no se ha probado, sino que nunca ha existido, y ni quienes construyeron la autopista ni el ministerio de recursos naturales saben por qué hay tan pocos atropellamientos de fauna en esa carretera. En unos años, cuando todas las granjas se conviertan en viviendas y deje de ser un corredor principal de fauna, la cerca podría volverse inútil; o no
    Si esto te parece forzado o sientes que no aplica a tu caso, te envidio. En mi experiencia, salvo en empresas de cierto tamaño y que no sean demasiado viejas, así es como suelen funcionar las cosas
    La verdad es que todo lo que hacemos forma parte de un ecosistema, y depende de cosas con las que nunca acordamos interactuar explícitamente, y a la vez otras cosas dependen de ello. Se puede reducir la superficie del API y evitar que todos los detalles de implementación se vuelvan asunto del vecino, pero el acoplamiento no intencional se parece más a una ley universal, tan inevitable como el aumento de la entropía
    A algunas personas esto les suena nihilista y derrotista. Podrían decir que hay que luchar contra la entropía. Pero creo que el mejor uso del tiempo y el mejor retorno de inversión vienen de aceptar que esto, en el fondo, no es algo contra lo que se lucha, sino algo que se gestiona
    Asumir que siempre puedes conocer el estado del mundo es garantizarte el fracaso y la culpa propia. Igual que el 100% de uptime no existe y, para la mayoría de las cosas, es un objetivo equivocado
    Si aceptas que estás gestionando un proceso con cierto grado de incertidumbre heisenbergiana, puedes elegir cómo usar de forma efectiva el tiempo limitado que tienes cada día para producir mejores resultados. En particular, eso permite hacer concesiones inteligentes entre respuesta preventiva y reactiva, y entender que no se puede llevar la respuesta reactiva a cero, y que a veces no tiene sentido hacer un año de trabajo preventivo para evitar un solo día de trabajo reactivo
    Entonces, ¿cuánta documentación debería escribirse en un commit? ¿Cuántos documentos de diseño o planes de prueba debería haber? No lo sé. Pero si tengo que proponer una idea, sería esta: toda documentación se escribe para un lector
    Si cambias el codebase, la gente del equipo actual —y también quienes se incorporen después— debería poder entender, mediante investigación, qué hizo el cambio y por qué se hizo, y también debería haber algunas advertencias sobre trampas peligrosas o bugs que sostienen carga
    Esto normalmente no requiere prosa larga, sino más bien punteros hacia contexto adicional que ayude a preparar el escenario. Por ejemplo, algo como “Se exigió autenticación en este paso como parte de la política que requiere aprobación multipartita para todos los cambios. see: go/multiparty”

    • Incluso podría decirse que el aumento de la entropía y la aparición continua de acoplamientos no intencionales no son un defecto, sino una característica útil que evita que los sistemas queden atrapados en un estado permanente
      Los sistemas que buscan la perfección cuando tratan con humanos son realmente incómodos. Cosas como DRM, trusted computing, remote attestation, Faro Plague y smart contracts
      Son mucho mejores los sistemas que puedes reiniciar en modo servicio y arreglar. Porque no podemos predecir en qué dirección tendrá que evolucionar el software para ayudar de verdad a las personas. Es mejor hacerlo fácil de modificar que dejarlo bloqueado al 100%
  • Casi no escribimos cuerpos de commit, pero sí solemos escribir títulos bastante buenos. Si esa es la métrica, no tengo muy claro qué está midiendo
    En codebases grandes, código claro y suficiente cobertura de pruebas suelen ser mucho más útiles que la documentación

    • No estoy de acuerdo. A veces tanto el cambio real como la razón del cambio son sutiles. Cuando intentas entender por qué un código raro quedó así, mirar las pruebas modificadas en ese commit es un paso extra y no necesariamente te dice por qué cambió
      Puede ocurrir que se haya hecho un cambio completamente válido y que las pruebas se hayan actualizado en consecuencia, pero después siga siendo totalmente poco claro por qué ese cambio era necesario. Más aún si las líneas modificadas producen un comportamiento inesperado o adicional en producción
      Un simple revert puede no ser deseable, y en ese momento ayuda muchísimo tener el historial completo de por qué se hizo el cambio
      He visto muchos casos donde la idea era correcta, pero aparecieron consecuencias imprevistas. Si conoces la intención, puedes llegar a un cambio realmente correcto que también corrija el nuevo problema y preserve la razón original del cambio
      Si vas a insistir en commits de una sola línea, al menos incluye el número del ticket para que el historial pueda leerse ahí
  • Me gané bastante buen dinero durante 5 años recorriendo regiones exóticas para rescatar codebases como estos. @arp242, siempre sube tus tarifas y duerme con https://archive.org/details/working-effectively-with-legacy-code bajo la almohada

  • Por suerte, los generadores de porquería con IA sí escriben mensajes de commit gigantescos. A veces incluso tienen cierta relación con el cambio real, así que al menos esa parte ya estaría resuelta

    • ¿De verdad? Tal vez sirvan para resumir qué cambió, pero dudo que sean buenos para explicar por qué cambió