El código es más fácil de escribir que de leer – otra estupidez

Hace aproximadamente 15 años que vengo escuchando gente repetir esta estupidez como una verdad revelada. No sé si quienes lo dicen realmente lo piensan o solo lo repiten, aunque creo que a quienes hacen copy/paste desde la cabeza de otro sin ningún filtro, poco se les puede pedir.

El código no es difícil de leer per se. Si hay código difícil de leer es porque quien lo escribió no sabía como escribirlo de una mejor manera. Así las cosas, el código es más difícil de escribir que de leer ya que cualquiera con algo de esfuerzo y tiempo puede entender una pieza de mal código pero no todos pueden tomarla y, no ya reescribirla correctamente sino tan solo mejorarla un poco. ¿Se entiende?

Si las recetas de los médicos son más difíciles de leer que de escribir es tan solo porque estos profesionales le dedican el suficiente empeño en hacer su peor letra (o bien porque son unos tarados) pero a nadie se le ocurriría afirmar que “las recetas médicas son más fáciles de escribir que de leer”.

Veamos, este es un método cualquiera que asigna algún permiso a una cuenta dada:

internal void Grant(Account toAccount, string right, Account authorizedBy)
{
    try
    {
        VerifyThatAuthorizerHasRightForOperation(authorizedBy);
        GrantTrusted(toAccount, right);
        LogChanges("granted", toAccount, right, authorizedBy);
    }
    catch (UnathorizedOperationException ue)
    {
        Logger.Info(
            string.Format("failed attempt by {0} to grant [{1}] right to {2}.",
                ue.Authorizer.Name, right, toAccount.Name));
        throw;
    }
    catch (NotPersistedException npe)
    {
        Logger.Info(
            string.Format("{0} must exist before grant a right.", ((Account)npe.Persistable).Name));
        throw;
    }
}

¿A alguien le duele el cerebro al tratar de entender que hace el método de arriba?. Yo creo que no.

Sin categoría

16 thoughts on “El código es más fácil de escribir que de leer – otra estupidez

  1. Bueno, yo estoy de acuerdo en que el código es general y en la realidad es más difícil de leer que de escribir.

    El código que has puesto de ejemplo es una función “tonta” de muy alto nivel en el que los nombres de los métodos son claros y que apenas tiene lógica visible. Habría que ver el interior de esos métodos que se llaman en el nivel de código real y no de llamadas a métodos hechos.

    Y en la realidad es que código claro hay muy, muy poco. En su inmensa mayoría, como tú dices, copy-paste, hacerlo rápido que nos pilla el toro y que quede como Dios quiera. En ese sentido si te doy la razón, hay muy poco código claro posiblemente porque es muy difícil de escribir, pero también y principalmente porque al 90% de la gente le trae sin cuidado el código que hace, la basta con que parezca que funciona.

    La realidad es que cuando te toca mirar código de otra persona, tienes un 95% de posibilidades de que ese código sea una pesadilla y no se parezca en nada al que has puesto.

    Se bueno.

  2. @chuidiang:
    estamos en sintonía. Si el código es dificil de leer es por su propia naturaleza sino porque no se ha escrito medianamente bien salvo exceptiones como fragmentos en perl, lisp o c++. Por otro lado, le método de ejemplo es real y no es tonto. Todo el proyecto es así y no tiene por qué tener 4 o 5 niveles de anidación para tener lógica, de hecho no necesita más que eso. No tengo el proyecto acá pero puedo pegar todos los métodos que quieran y van a ser siempre así de claros.

    @pregunton:
    No, esta entrada es de catarsis porque asistí a una presentación en la que el presentador comenzó diciendo: “como todos sabemos… el código es más facil de escribir que de leer…..” y todo el mundo asintió con la cabeza como si fuera un hecho cuando en realidad es una mentira.

    @Hadi:
    Muchos de mis lectores son personas que creen que lo saben todo… bienvenido!

    @Jorge:
    No Jorge, nada que ver… es por lo mismo que le respondo a preguntón. Si alguien no entendiese el método grant sería digno de lástima. Pero estos señores que se suben a los estrados a revolear idiotecez son peligrosos.
    El mensaje tal vez debería ser: “señores aprendan a escribir buen código porque de lo contrario nadie va a poder entenderlo”. Pero en lugar de ello se acpeta algo falso porque “como todos sabemos… “.
    La última es que escribir código es fácil….. lo dificil es entenderlo… por deus! me irrito de nuevo.

    Un saludo a todos y gracias por sus comentarios.

  3. Creo que este es un ejemplo más real de un código que para mucha gente puede ser más dificil de entender:

    public int LlenarTerceroPersonas(Personas personas)
    {
    try
    {
    int idTercero=-1; //Variable para almacenar el ID del tercero asignado
    int banderaValidacion=0;

    if ((personas.Persona[0].RolPersona != null) && (personas.Persona[0].EstadoPersona != null))
    {
    for (int i = 0; i < personas.Persona[0].RolPersona.Length; i++)//procese para cada uno de los roles de Tercero { int codigoHomologacionRolTerceroEstado = HomologarCodigo(Convert.ToInt32(personas.Persona[0].IDCore), 21, personas.Persona[0].EstadoPersona.IDEstado, "", ""); int codigoHomologacionRolPersona = HomologarCodigo(Convert.ToInt32(personas.Persona[0].IDCore), 31, personas.Persona[0].RolPersona[i].IDRolPersona, "", "");//homologar codigo del ROL if (codigoHomologacionRolTerceroEstado == -1)//si no puede homologar el estado de la persona y el Rol, genere inconsistencias { banderaValidacion = 1; IngresarInconsistenciaHomologacion(personas.Persona[0].IDPersona, Convert.ToInt32(personas.Persona[0].IDCore), 21, personas.Persona[0].EstadoPersona.IDEstado, "", ""); } if (codigoHomologacionRolPersona == -1) { banderaValidacion = 1; IngresarInconsistenciaHomologacion(personas.Persona[0].IDPersona, Convert.ToInt32(personas.Persona[0].IDCore), 31, personas.Persona[0].RolPersona[i].IDRolPersona, "", ""); } } if (banderaValidacion == 0)//se pudieron homologar todos los Roles y estado de personas. Inserte Tercero { ReferenciasDeTercerosServiceReference.ReferenciasDeTercerosServiceClient clientReferenciasDeTerceros = new MasterDataServices.ReferenciasDeTercerosServiceReference.ReferenciasDeTercerosServiceClient(); ReferenciasDeTercerosServiceReference.ReferenciasDeTerceros[] referenciasDeTercero = new MasterDataServices.ReferenciasDeTercerosServiceReference.ReferenciasDeTerceros[1]; TercerosServiceReference.TercerosServiceClient clientTerceros = new MasterDataServices.TercerosServiceReference.TercerosServiceClient(); TercerosServiceReference.Terceros tercero = new MasterDataServices.TercerosServiceReference.Terceros(); string comando="IdSistemaCore=" + personas.Persona[0].IDCore+ " AND IdPersonaUOrganizacion='" + personas.Persona[0].IDPersona + "'"; referenciasDeTercero = clientReferenciasDeTerceros.Find(comando); if (clientReferenciasDeTerceros.Find(comando).Length == 0)//si no existe el tercero, ingresar un nuevo registro en la tabla TERCEROS { //Insercion en la tabla TERCEROS según los datos de la persona tercero.Tipo = "Persona"; tercero.Fecha_Actualizacion = DateTime.Now; idTercero = clientTerceros.Insert(tercero); //Fin de la inserción en la tabla TERCEROS LlenarReferenciasDeTercero(idTercero, personas.Persona[0].IDPersona, Convert.ToInt32(personas.Persona[0].IDCore), "Persona", 1);//Llenar una referencia de Tercero } else//si existe el tercero, retornar el IdTercero que ya se tiene, y borrar la información que existe previa { tercero.Id_Tercero = referenciasDeTercero[0].IdTercero; tercero.Tipo = "Persona"; tercero.Fecha_Actualizacion = DateTime.Now; EliminarInformacionTercero(referenciasDeTercero[0].IdTercero);//borrar informacion previa clientTerceros.Update(tercero);//Primero actualice la información del tercero. Se hace para los casos de intermediarios que se ingresaron sin NaturalezaJuridica. Aca se las adiciono. idTercero= referenciasDeTercero[0].IdTercero; } } return idTercero; }//si no vienen roles o estado de personas genere inconsistencias. else { if (personas.Persona[0].RolPersona == null) { IngresarInconsistenciaHomologacion(personas.Persona[0].IDPersona, Convert.ToInt32(personas.Persona[0].IDCore), 31, "No viene Rol de Tercero", "", ""); } if (personas.Persona[0].EstadoPersona == null) { IngresarInconsistenciaHomologacion(personas.Persona[0].IDPersona, Convert.ToInt32(personas.Persona[0].IDCore), 21, "No viene estado de la persona", "", ""); } return -1; //retorne -1 para saber que no se ingresó un registro para el tercero por error con los datos de entrada } } catch (FaultException q) { throw new FaultException(q.Message, q.Code, q.Action); } catch (Exception q) { throw new FaultException(q.Message); } finally { } } Creo que muchas veces es más dificil leerlo que volver a escribirlo. Depende del caso y de los desarrolladores anteriores. No se puede generalizar para ninguno de los dos lados.

  4. @Millan Sanchez:

    El punto es claro. Ahora, que abunde o que la generalidad del código sea malo no significa que el mismo sea por naturaleza más dificil de leer que de escribir.

    Voy a tener que usar un pensamiento racista para explicar algo tan elemental:

    “Si las carceles de los EEUU están llenas de negros y latinoamericanos es porque los negros y los latinoamericanos son mas criminales que los blancos”. Estoy seguro que nadie se anima a repetir esta facalia pero si lo hacen con el código.

    Por último, el código que haz pegado no es “más real” porque el que yo he pegado es abolutamente real solo que parece que he el reparto de proyectos y compañeros de trabajo he sido más afortunado que vos. Es solo eso.

    Saludos.

  5. Ok, en algún momento creo me perdí, no entendí o simplemente desvié mi atención, pues no me importa en absoluto el fragmento del código que coloquen, tal como dice Lucas es un tema de afirmar algo que es mentira, el código es fácil o difícil de entender incluso dependiendo del contexto.

    Sin entrar en cual método de codificación o lenguaje utilizamos la catarsis en bien válida por parte de Lucas, aprovechando la misma les recuerdo que nuestro trabajo como desarrolladores es uno de los más ingratos que existe, pues si algo funciona, pero se ve simple o “poco estético” resulta que “está bien”, pero si ven lago que gráficamente es llamativo seguramente será la “mejor opción” y “se puede arreglar en el camino”. Al menos ese es el pensamiento de muchos clientes.

    Ahora bien, si entre nosotros mismos (desarrolladores) vamos a discutir si es más fácil leerlo, escribirlo, dictarlo por teléfono o colgarlo de la pared creo estamos perdiendo el potencial de poder construir soluciones que simplifiquen inclusive nuestro propio trabajo en un futuro. Si como Lucas estamos conscientes o nos parece que una opinión de un expositor es equivoca simplemente no callemos y asintamos con la cabeza. Además (y de manera muy particular) me parece que no es la manera más adecuada para abrir una exposición.

  6. @Millan Sanchez
    Programando estructurado es muy típico encontrarlo. El código que has puesto claramente confirma lo que dice Lucas. “Es mas facil escribir código malo que un buen código” 🙂

  7. Amigo, q paso? el invierno o q?
    no voy a entrar sobre la frase de tu post, pero si a recomendar tener cuidado sobre aquellas personas que se suben a los estrados y sueltan verdades como puños. Eso ya es muy triste, pero más triste es, que como tu dices, haya 100 personas dando por válidas esas “verdades”.
    Vamos que es la versión informática de las iglesias “universales”.

    Salu2 y a no quemarse que la vida son 2 dias

  8. Hola Lucas, no puedo estar más en desacuerdo contigo, llevo más de 20 años escribiendo programas y puedo asegurarte que incluso hoy en día, después de algún tiempo reviso algunos de los programas que he realizado recientemente y a veces me cuesta incluso entenderlos a mí, hasta tal punto que dedicó gran parte de mi tiempo a refactorizar y mejorar mucho del código escrito con anterioridad, eso, que intentamos aplicar muchas buenas practicas, test unitarios, utilización de herramientas de ayuda como resharper, fxcop, reglas de estilo, inyección de dependencias, etc, aún así y con todo, muchas veces cometemos errores que al cabo de un tiempo, cuando nos toca volver a revisar parte del código nos damos cuenta de que no está del todo bien, de hecho si revisas mi código de solo un año atrás, este no tiene nada que ver con el que realizo ahora mismo, si trasladas esto mismo a otros desarrolladores que no tienen la misma experiencia y/o conocimientos, te das cuenta después de analizar los programas que escriben, que muchas veces resulta más costoso reescribir un pequeño programa que tratar de comprender como ha sido desarrollado, cuántas veces he dicho a algún programador: esto no hay quien lo entienda, simplifica el programa, refactorízalo, para que cualquiera podamos entenderlo con facilidad…

    En tu ejemplo, por decirte cosas que a mí me chocan en comparación a mi código, yo hubiera comprobado si los parámetros de entrada están vacíos o nulos, ya sé que lo puedes hacer antes o después, no hubiera encapsulado la llamada a tres métodos diferentes con un catch, puesto que creo que cada uno debería controlar sus excepciones de forma individual pero esto son formas de diferentes de abordar un problema y cuando escribes código la suma de todos estos pequeños detalles, pueden aumentar o disminuir la legibilidad de los programas. La utilización de expresiones lamba, herencia, utilización de interfaces, y otras técnicas se hacen difíciles de entender a programadores poco experimentados.

    Así que no puedo estar más de acuerdo con la frase, si bien no debemos generalizar con ella, pero estoy convencido al menos en mi experiencia que este problema se da muchas veces en equipos de desarrollo en los que cada miembro del equipo tiene unos conocimientos y habilidades diferentes.

    Te sorprendería saber el tiempo que puedes tardar en entender algunos de los programas que hemos escrito, te aseguro que en algunas ocasiones hubiéramos tardado mucho menos optando por rehacerlos de principio a fin.

    Un saludo.

  9. @Bruno:
    Un saludo enorme para vos. Perdón si el tono es fuerte, hoy lo hubiese escrito diferente… que digo, hoy no lo hubiese escrito.

    @Juan:
    El que veamos nuestro código anterior con asco es lo mejor. Eso significa que no nos hemos detenido y que seguimos aprendiendo. Yo también soy el primer crítico de mi código.
    Pero cuando veo que el nombre de los métodos son asquerosos, que no se entienden, que mezclo distintos niveles de abstracción en ellos, yo no culpo al código. Yo no me justifico con una mentira “no se entiende porque el código es así”, sino que me recrimino “en que estaba pensando? porque le puse ese nombre?”. Hombres necios que acusais al código sin razón! El pobre código no tiene la culpa de que su creador no haya sabido escribirlo él solo es lo que su creador lo hizo. El culpable es su creador, es decir, Yo. Y es justamente por eso que el código es más dificil de escribir que de leer.
    A lo que voy es que internamente todos lo sabemos: escribir código bueno es arduo, no es “la parte fácil”. Quien dice que escribir código es fácil no sabe mucho de esto. Ahora, que abunden los desarrolladores sin experiencia, que en su mayoría el código no sea tan bueno como uno desearía no hacen de “la afirmación una verdad”.
    Si quisieramos una afirmación verdadera deberiamos decir “como todos sabemos, el código nauseabundo es más fácil de escribir que de entender”… Yo sería el primero en aderir a esto.

    En cuanto a mi ejemplo, es claro que lo entendiste. Todo el que lo vió lo entendió a la primera. No lo escribí facilmente, me llevó muchísimo tiempo y es el resultado de muchísimo refacting. Este es el proyecto que se empezó con TDD así que refactoring cada 5 minutos. Por esta misma razón es que no se chequean los argumentos… porque no hay requerimientos para ello y porque este método es “internal” y no “public”. De la misma manera, el manejador está donde debe porque es aquí donde tiene el contexto necesario para loguear la info. Si bajamos el manejo de exceptiones un nivel tendríamos que pasarle esos valores por parámetros y no queremos pasar parámetros solo porque el manejador de excepciones nos lo requiere. Por último, ese try’catch es atómico por lo que solo loguea si todo estuvo bien.

  10. Yo cambiaría el título: el código es mas fácil de refactorizar que de escribirlo de nuevo.

    Yo creo que reescribir nuevo código si que es una estupidez, cuando el que hay seguro que es mas maduro, mas robusto, mas probado y mas testado, no será muy mantenible o legible pero funciona, lo que si se debe hacer es refactorizarlo. Reescribir nuevo código es un gran error.

    En dos palabras: RE, FACTORIZAR.

    Una perla de Joel Spolsky:

    http://www.joelonsoftware.com/articles/fog0000000069.html

    Saludos!

    Miguel

  11. Hola Lucas.
    Estaba a punto de poner mi punto de vista sobre tu aseveración, sin embargo en tu último comentario aclaras más tu idea con la cual comulgo. Por tal motivo solo me resta aportar la frase “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” ~Martin Fowler.

    Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *