Nota para el moderador
Esta pregunta ya ha recibido diecisiete respuestas . Antes de publicar una nueva respuesta, lea las respuestas existentes y asegúrese de que su punto de vista no esté cubierto adecuadamente.
He seguido algunas de las prácticas recomendadas en el libro "Clean Code" de Robert Martin, especialmente las que se aplican al tipo de software con el que trabajo y las que tienen sentido para mí (no lo sigo como un dogma) .
Sin embargo, un efecto secundario que he notado es que el código "limpio" que escribo es más código que si no siguiera algunas prácticas. Las prácticas específicas que conducen a esto son:
- Condicionales encapsulantes
Entonces en lugar de
if(contact.email != null && contact.emails.contains('@')
Podría escribir un pequeño método como este
private Boolean isEmailValid(String email){...}
- Reemplazar un comentario en línea con otro método privado, de modo que el nombre del método se describa a sí mismo en lugar de tener un comentario en línea encima
- Una clase solo debe tener una razón para cambiar
Y algunos otros. El punto es que lo que podría ser un método de 30 líneas, termina siendo una clase, debido a los pequeños métodos que reemplazan los comentarios y encapsulan los condicionales, etc. Cuando te das cuenta de que tienes tantos métodos, entonces "tiene sentido" poner toda la funcionalidad en una clase, cuando realmente debería haber sido un método.
Soy consciente de que cualquier práctica llevada al extremo puede ser dañina.
La pregunta concreta para la que busco una respuesta es:
¿Es este un subproducto aceptable de escribir código limpio? Si es así, ¿cuáles son algunos argumentos que puedo usar para justificar el hecho de que se han escrito más LOC?
La organización no está preocupada específicamente por más LOC, pero más LOC puede dar lugar a clases muy grandes (eso, de nuevo, podría ser reemplazado por un método largo sin un montón de funciones auxiliares use-once por razones de legibilidad).
Cuando ve una clase que es lo suficientemente grande, da la impresión de que la clase está lo suficientemente ocupada y que su responsabilidad ha sido concluida. Por lo tanto, podría terminar creando más clases para lograr otras funciones. El resultado es muchas clases, todas haciendo "una cosa" con la ayuda de muchos métodos de ayuda pequeños.
ESTA es la preocupación específica ... esas clases podrían ser una sola clase que aún logre "una cosa", sin la ayuda de muchos métodos pequeños. Podría ser una sola clase con quizás 3 o 4 métodos y algunos comentarios.
fuente
Respuestas:
Estas personas han identificado correctamente algo: quieren que el código sea más fácil de mantener. Sin embargo, donde se equivocaron es asumir que cuanto menos código haya, más fácil será mantenerlo.
Para que el código sea fácil de mantener, entonces debe ser fácil de cambiar. Con mucho, la forma más fácil de lograr un código fácil de cambiar es tener un conjunto completo de pruebas automáticas que fallarán si su cambio no funciona. Las pruebas son código, por lo que escribir esas pruebas aumentará su base de código. Y eso es algo bueno.
En segundo lugar, para determinar qué necesita cambiar, su código debe ser fácil de leer y de razonar. Es muy poco probable que el código muy breve, de tamaño reducido para mantener la cuenta regresiva de la línea, sea fácil de leer. Obviamente, hay que llegar a un compromiso ya que el código más largo tomará más tiempo para leer. Pero si es más rápido de entender, entonces vale la pena. Si no ofrece ese beneficio, entonces esa verbosidad deja de ser un beneficio. Pero si el código más largo mejora la legibilidad, nuevamente esto es algo bueno.
fuente
Sí, es un subproducto aceptable, y la justificación es que ahora está estructurado de manera que no tenga que leer la mayor parte del código la mayor parte del tiempo. En lugar de leer una función de 30 líneas cada vez que realiza un cambio, está leyendo una función de 5 líneas para obtener el flujo general, y tal vez un par de funciones auxiliares si su cambio toca esa área. Si se llama a su nueva clase "extra"
EmailValidator
y sabe que su problema no es con la validación de correo electrónico, puede omitir la lectura por completo.También es más fácil reutilizar piezas más pequeñas, lo que tiende a reducir el recuento de líneas para su programa general. Se
EmailValidator
puede usar en todo el lugar. Algunas líneas de código que validan el correo electrónico pero se combinan con el código de acceso a la base de datos no se pueden reutilizar.Y luego considere lo que debe hacerse si alguna vez es necesario cambiar las reglas de validación de correo electrónico, que preferiría: una ubicación conocida; o muchos lugares, posiblemente faltan algunos?
fuente
iterations < _maxIterations
a un método llamadoShouldContinueToIterate
es estúpido .A Bill Gates se le atribuyó la famosa frase: "Medir el progreso de la programación por líneas de código es como medir el progreso de la construcción de aeronaves por peso".
Estoy humildemente de acuerdo con este sentimiento. Esto no quiere decir que un programa deba esforzarse por obtener más o menos líneas de código, sino que, en última instancia, esto no es lo que cuenta para crear un programa que funcione y funcione. Es útil recordar que, en última instancia, la razón detrás de agregar líneas de código adicionales es que, en teoría, es más legible de esa manera.
Se pueden tener desacuerdos sobre si un cambio específico es más o menos legible, pero no creo que se equivoque al hacer un cambio en su programa porque cree que al hacerlo lo está haciendo más legible. Por ejemplo, hacer un
isEmailValid
podría considerarse superfluo e innecesario, especialmente si la clase que lo define lo llama exactamente una vez. Sin embargo, preferiría verisEmailValid
una condición en lugar de una serie de condiciones AND con las cuales debo determinar qué verifica cada condición individual y por qué se está verificando.Cuando te metes en problemas es cuando creas un
isEmailValid
método que tiene efectos secundarios o comprueba otras cosas además del correo electrónico, porque esto es peor que simplemente escribirlo todo. Es peor porque es engañoso y puedo perder un error debido a eso.Aunque claramente no estás haciendo eso en este caso, entonces te animo a que continúes como lo estás haciendo. Siempre debe preguntarse si al hacer el cambio es más fácil de leer, y si ese es su caso, ¡hágalo!
fuente
Se trata de perder de vista el objetivo real.
Lo que importa es reducir las horas dedicadas al desarrollo . Eso se mide en tiempo (o esfuerzo equivalente), no en líneas de código.
Esto es como decir que los fabricantes de automóviles deberían construir sus automóviles con menos tornillos, porque lleva una cantidad de tiempo distinta de cero colocar cada tornillo. o no tiene Por encima de todo lo demás, un automóvil debe ser eficiente, seguro y fácil de mantener.
El resto de la respuesta son ejemplos de cómo un código limpio puede generar ganancias de tiempo.
Inicio sesión
Tome una aplicación (A) que no tiene registro. Ahora cree la aplicación B, que es la misma aplicación A pero con registro. B siempre tendrá más líneas de código y, por lo tanto, debe escribir más código.
Pero mucho tiempo se dedicará a investigar problemas y errores, y descubrir qué salió mal.
Para la aplicación A, los desarrolladores se quedarán atrapados leyendo el código y teniendo que reproducir continuamente el problema y recorrer el código para encontrar la fuente del problema. Esto significa que el desarrollador tiene que probar desde el principio de la ejecución hasta el final, en cada capa usada, y necesita observar cada pieza lógica utilizada.
Tal vez tenga suerte de encontrarlo de inmediato, pero tal vez la respuesta estará en el último lugar en el que piense en buscar.
Para la aplicación B, suponiendo un registro perfecto, un desarrollador observa los registros, puede identificar inmediatamente el componente defectuoso y ahora sabe dónde buscar.
Esto puede ser cuestión de minutos, horas o días guardados; dependiendo del tamaño y la complejidad de la base de código.
Regresiones
Tome la aplicación A, que no es SECA en absoluto.
Tome la aplicación B, que es SECA, pero terminó necesitando más líneas debido a las abstracciones adicionales.
Se presenta una solicitud de cambio, que requiere un cambio en la lógica.
Para la aplicación B, el desarrollador cambia la lógica (única, compartida) de acuerdo con la solicitud de cambio.
Para la aplicación A, el desarrollador tiene que cambiar todas las instancias de esta lógica donde recuerda que se está utilizando.
Esto puede conducir a una enorme pérdida de tiempo. No solo en desarrollo, sino también en la caza y búsqueda del error. La aplicación puede comenzar a comportarse de manera errática de una manera que los desarrolladores no pueden comprender fácilmente. Y eso conducirá a largas sesiones de depuración.
Intercambiabilidad del desarrollador
El desarrollador A creó la aplicación A. El código no es limpio ni legible, pero funciona de maravilla y se ha estado ejecutando en producción. Como era de esperar, tampoco hay documentación.
El desarrollador A está ausente durante un mes debido a vacaciones. Se presenta una solicitud de cambio de emergencia. No puede esperar otras tres semanas para que Dev A regrese.
El desarrollador B tiene que ejecutar este cambio. Ahora necesita leer toda la base de código, comprender cómo funciona todo, por qué funciona y qué intenta lograr. Esto lleva años, pero digamos que puede hacerlo dentro de tres semanas.
Al mismo tiempo, la aplicación B (que creó el desarrollador B) tiene una emergencia. Dev B está ocupado, pero Dev C está disponible, aunque no conoce la base de código. qué hacemos?
Dev A regresa de sus vacaciones y ve que B no entendió el código y, por lo tanto, lo implementó mal. No es culpa de B, porque usó todos los recursos disponibles, el código fuente simplemente no era legible adecuadamente. ¿A ahora tiene que pasar tiempo arreglando la legibilidad del código?
Todos estos problemas, y muchos más, terminan perdiendo el tiempo . Sí, a corto plazo, el código limpio requiere más esfuerzo ahora , pero terminará pagando dividendos en el futuro cuando se deban abordar errores / cambios inevitables.
La gerencia necesita comprender que una tarea corta ahora le ahorrará varias tareas largas en el futuro. No planificar es planificar el fracaso.
Mi explicación general es preguntarle a la gerencia qué preferirían: una aplicación con una base de código 100KLOC que se pueda desarrollar en tres meses, o una base de código 50KLOC que se pueda desarrollar en seis meses.
Obviamente elegirán el tiempo de desarrollo más corto, porque la administración no se preocupa por KLOC . Los gerentes que se enfocan en KLOC están microgestionando mientras no están informados sobre lo que están tratando de manejar.
fuente
Creo que debe tener mucho cuidado al aplicar prácticas de "código limpio" en caso de que conduzcan a una mayor complejidad general. La refactorización prematura es la raíz de muchas cosas malas.
Extraer un condicional a una función conduce a un código más simple en el punto donde se extrajo el condicional , pero conduce a una mayor complejidad general porque ahora tiene una función que es visible desde más puntos en el programa. Agrega una ligera carga de complejidad a todas las demás funciones donde esta nueva función ahora es visible.
No estoy diciendo que no debas extraer el condicional, solo que debes considerarlo cuidadosamente si es necesario.
En todo lo anterior, esta es una razón para la extracción más allá de ser simplemente "código limpio". Además, probablemente ni siquiera estaría en duda si fuera lo correcto.
Diría que, en caso de duda, elija siempre el código más simple y directo.
fuente
Señalaría que no hay nada inherentemente malo en esto:
Al menos suponiendo que se use esta vez.
Podría tener problemas con esto muy fácilmente:
Algunas cosas que miraría por:
Si se usa una vez, es fácil de analizar y toma menos de una línea, dudaría la decisión. Probablemente no sea algo que llamaría si no fuera un problema particular de un equipo.
Por otro lado, he visto métodos que hacen algo como esto:
Ese ejemplo obviamente no es SECO.
O incluso esa última declaración puede dar otro ejemplo:
El objetivo debe ser hacer que el código sea más legible:
Otro escenario:
Es posible que tenga un método como:
Si esto se ajusta a la lógica de su negocio y no se reutiliza, no hay ningún problema aquí.
Pero cuando alguien pregunta "¿Por qué se guarda '@', porque eso no está bien!" y decide agregar una validación real de algún tipo, ¡luego extráigala!
Se alegrará de haberlo hecho cuando también necesite dar cuenta de la segunda cuenta de correo electrónico de los presidentes Pr3 $ sid3nt @ h0m3! @ Mydomain.com y decida simplemente hacer todo lo posible y tratar de apoyar RFC 2822.
Sobre legibilidad:
Si su código es así de claro, no necesita comentarios aquí. De hecho, no necesita comentarios para decir qué hace el código la mayor parte del tiempo, sino más bien por qué lo hace:
Si los comentarios sobre una declaración if o dentro de un pequeño método son para mí, pedante. Incluso podría argumentar lo contrario de útil con buenos comentarios dentro de otro método porque ahora tendría que navegar a otro método para ver cómo y por qué hace lo que hace.
En resumen: no midas estas cosas; Concéntrese en los principios a partir de los cuales se construyó el texto (SECO, SÓLIDO, BESO).
fuente
Whether the comments above an if statement or inside a tiny method is to me, pedantic.
Este es un problema de "gota que colmó el vaso". Tienes razón en que esta cosa no es particularmente difícil de leer directamente. Pero si usted tiene un método grande (por ejemplo, una gran importación), que cuenta con decenas de estos pequeños evaluaciones, teniendo éstos encapsulado en nombre de los métodos de lectura mecánica (IsUserActive
,GetAverageIncome
,MustBeDeleted
, ...) se convertirá en una notable mejora en la lectura del código. El problema con el ejemplo es que solo observa una gota, no el paquete completo que rompe la espalda del camello.if (contact.email != null && contact.email.contains('@'))
tiene errores. Si el if es falso, ninguna de las otras líneas if puede ser verdadera. Esto no es visible en absoluto en elLooksSortaLikeAnEmail
bloque. Una función que contiene una sola línea de código no es mucho mejor que un comentario que explica cómo funciona la línea.Clean Code es un libro excelente y vale la pena leerlo, pero no es la autoridad final en tales asuntos.
Por lo general, es una buena idea dividir el código en funciones lógicas, pero pocos programadores lo hacen en la medida en que Martin lo hace: en algún momento obtienes rendimientos decrecientes al convertir todo en funciones y puede ser difícil seguirlo cuando todo el código está en minúsculo piezas.
Una opción cuando no vale la pena crear una función completamente nueva es simplemente usar una variable intermedia:
Esto ayuda a mantener el código fácil de seguir sin tener que saltar mucho por el archivo.
Otro problema es que Clean Code se está volviendo bastante viejo como un libro ahora. Una gran cantidad de ingeniería de software se ha movido en la dirección de la programación funcional, mientras que Martin se esfuerza por agregar estado a las cosas y crear objetos. Sospecho que habría escrito un libro muy diferente si lo hubiera escrito hoy.
fuente
Teniendo en cuenta el hecho de que la condición "es válida por correo electrónico" que tiene actualmente aceptaría la dirección de correo electrónico muy inválida "
@
", creo que tiene todos los motivos para resumir una clase EmailValidator. Aún mejor, use una buena biblioteca bien probada para validar las direcciones de correo electrónico.Las líneas de código como métrica no tienen sentido. Las preguntas importantes en ingeniería de software no son:
Las preguntas importantes son:
Nunca he pensado en LoC cuando escribo código para cualquier propósito que no sea Code Golf. Me he preguntado "¿Podría escribir esto de manera más sucinta?", Pero con fines de legibilidad, facilidad de mantenimiento y eficiencia, no simplemente longitud.
Claro, tal vez podría usar una larga cadena de operaciones booleanas en lugar de un método de utilidad, pero ¿debería?
Su pregunta en realidad me hace pensar en algunas cadenas largas de booleanos que he escrito y me doy cuenta de que probablemente debería haber escrito uno o más métodos de utilidad.
fuente
En un nivel, tienen razón: menos código es mejor. Otra respuesta citó Gate, prefiero:
En resumen, cuanto menos código tenga, menos puede salir mal. Si algo no es necesario, córtalo.
Si hay un código demasiado complicado, simplifíquelo hasta que los elementos funcionales reales sean todo lo que queda.
Lo importante aquí es que todos estos se refieren a la funcionalidad y solo tienen el mínimo requerido para hacerlo. No dice nada sobre cómo se expresa eso.
Lo que estás haciendo al intentar tener un código limpio no va en contra de lo anterior. Está agregando a su LOC pero no agrega funcionalidad no utilizada.
El objetivo final es tener un código legible pero sin extras superfluos. Los dos principios no deben actuar uno contra el otro.
Una metáfora sería construir un automóvil. La parte funcional del código es el chasis, el motor, las ruedas ... lo que hace que el automóvil funcione. La forma en que divide eso es más como la suspensión, la dirección asistida, etc., hace que sea más fácil de manejar. Desea que su mecánica sea lo más simple posible mientras realiza su trabajo, para minimizar la posibilidad de que las cosas salgan mal, pero eso no le impide tener buenos asientos.
fuente
Hay mucha sabiduría en las respuestas existentes, pero me gustaría agregar un factor más: el idioma .
Algunos idiomas requieren más código que otros para obtener el mismo efecto. En particular, aunque Java (que sospecho que es el lenguaje en la pregunta) es extremadamente conocido y generalmente muy sólido, claro y directo, algunos lenguajes más modernos son mucho más concisos y expresivos.
Por ejemplo, en Java podría tomar fácilmente 50 líneas para escribir una nueva clase con tres propiedades, cada una con un getter y setter, y uno o más constructores, mientras que puede lograr exactamente lo mismo en una sola línea de Kotlin * o Scala. (Incluso un mayor ahorro si también quería adecuados
equals()
,hashCode()
ytoString()
métodos).El resultado es que en Java, el trabajo adicional significa que es más probable que reutilice un objeto general que realmente no encaja, para comprimir propiedades en objetos existentes o para pasar un montón de propiedades 'desnudas' individualmente; mientras que en un lenguaje conciso y expresivo, es más probable que escriba un mejor código.
(Esto resalta la diferencia entre la complejidad 'superficial' del código y la complejidad de las ideas / modelos / procesamiento que implementa. Las líneas de código no son una mala medida del primero, pero tienen mucho menos que ver con el segundo .)
Por lo tanto, el "costo" de hacer las cosas bien depende del idioma. ¡Quizás una señal de un buen lenguaje es una que no te hace elegir entre hacer bien las cosas y hacerlo de manera simple!
(* Este no es realmente el lugar para un enchufe, pero vale la pena echarle un vistazo a Kotlin).
fuente
Supongamos que está trabajando con la clase
Contact
actualmente. El hecho de que esté escribiendo otro método para la validación de la dirección de correo electrónico es evidencia del hecho de que la claseContact
no está manejando una sola responsabilidad.También está manejando parte de la responsabilidad del correo electrónico, que idealmente debería ser su propia clase.
Otra prueba de que su código es una fusión de
Contact
yEmail
clase es que no podrá probar el código de validación de correo electrónico fácilmente. Se requerirán muchas maniobras para alcanzar el código de validación de correo electrónico en un gran método con los valores correctos. Vea el método a continuación.Por otro lado, si tuviera una clase de correo electrónico separada con un método para la validación del correo electrónico, para probar la unidad de su código de validación, simplemente haría una simple llamada
Email.Validation()
con sus datos de prueba.Contenido adicional : la charla de MFeather sobre la profunda sinergia entre la capacidad de prueba y el buen diseño.
fuente
Se ha encontrado que la reducción en LOC se correlaciona con defectos reducidos, nada más. Suponiendo que cada vez que reduzca la LOC, haya reducido la posibilidad de defectos, esencialmente está cayendo en la trampa de creer que la correlación es igual a la causalidad. El LOC reducido es el resultado de buenas prácticas de desarrollo y no lo que hace que el código sea bueno.
En mi experiencia, las personas que pueden resolver un problema con menos código (a nivel macro) tienden a ser más hábiles que aquellos que escriben más código para hacer lo mismo. Lo que hacen estos desarrolladores expertos para reducir las líneas de código es usar / crear abstracciones y soluciones reutilizables para resolver problemas comunes. No pasan el tiempo contando líneas de código y agonizando sobre si pueden cortar una línea aquí o allá. A menudo, el código que escriben es más detallado de lo necesario, simplemente escriben menos.
Dejame darte un ejemplo. He tenido que lidiar con la lógica en torno a los períodos de tiempo y cómo se superponen, si son adyacentes y qué brechas existen entre ellos. Cuando comencé a trabajar en estos problemas, tenía bloques de código haciendo los cálculos en todas partes. Finalmente, creé clases para representar los períodos de tiempo y las operaciones que calculaban superposiciones, complementos, etc. Esto eliminó inmediatamente grandes extensiones de código y las convirtió en algunas llamadas a métodos. Pero esas clases en sí mismas no fueron escritas de manera escueta.
En pocas palabras: si está tratando de reducir la LOC intentando cortar una línea de código aquí o allá con más precisión, lo está haciendo mal. Es como tratar de perder peso reduciendo la cantidad de vegetales que come. Escriba código que sea fácil de entender, mantener, depurar y reducir LOC mediante la reutilización y la abstracción.
fuente
Ha identificado una compensación válida
Entonces, de hecho, hay una compensación aquí y es inherente a la abstracción como un todo. Cada vez que alguien intenta colocar N líneas de código en su propia función para nombrarlo y aislarlo, al mismo tiempo facilita la lectura del sitio de llamada (al referirse a un nombre en lugar de a todos los detalles sangrientos que subyacen en ese nombre) y más complejo (ahora tiene un significado que está enredado en dos partes diferentes de la base de código). "Fácil" es lo opuesto a "difícil", pero no es sinónimo de "simple", que es lo opuesto a "complejo". Los dos no son opuestos, y la abstracción siempre aumenta la complejidad para insertar una forma u otra de manera fácil.
Podemos ver la complejidad añadida directamente cuando algún cambio en los requisitos del negocio hace que la abstracción comience a filtrarse. Tal vez alguna lógica nueva hubiera sido más natural en el medio del código previamente abstraído, por ejemplo, si el código abstraído atraviesa algún árbol y realmente desea recopilar (y tal vez actuar) algún tipo de información mientras está atravesando el árbol. Mientras tanto, si ha extraído este código, puede haber otros sitios de llamadas, y agregar la lógica requerida en el medio del método podría romper esos otros sitios de llamadas. Mira, cada vez que cambiamos una línea de código solo necesitamos mirar el contexto inmediato de esa línea de código; cuando cambiamos un método, debemos Cmd-F todo nuestro código fuente buscando cualquier cosa que pueda romperse como resultado de cambiar el contrato de ese método,
El algoritmo codicioso puede fallar en estos casos
La complejidad también ha hecho que el código en cierto sentido sea menos legible en lugar de más. En un trabajo anterior, traté con una API HTTP que fue estructurada con mucho cuidado y precisión en varias capas, cada punto final es especificado por un controlador que valida la forma del mensaje entrante y luego lo entrega a algún administrador de "capa de lógica empresarial" , que luego solicitó alguna "capa de datos" que se encargó de realizar varias consultas a alguna capa de "objeto de acceso a datos", que se encargó de crear varios Delegados SQL que realmente responderían a su pregunta. Lo primero que puedo decir al respecto fue que algo así como el 90% del código era una copia repetitiva de copiar y pegar, en otras palabras, era sin operaciones. Entonces, en muchos casos, leer cualquier pasaje de código dado fue muy "fácil", porque "oh, este administrador simplemente reenvía la solicitud a ese objeto de acceso a datos".muchos cambios de contexto y búsqueda de archivos e intentar rastrear información que nunca debería haber estado rastreando, "esto se llama X en esta capa, se llama X 'en esta otra capa, luego se llama X' en esta otra otra capa ".
Creo que cuando lo dejé, esta API CRUD simple estaba en la etapa en la que, si la imprimía a 30 líneas por página, ocuparía de 10 a 20 libros de texto de quinientas páginas en un estante: era una enciclopedia completa de repetitivos código. En términos de complejidad esencial, no estoy seguro de que haya siquiera la mitad de un libro de texto de complejidad esencial allí; solo teníamos unos 5-6 diagramas de base de datos para manejarlo. Hacer un pequeño cambio fue una tarea gigantesca, aprender que era una tarea gigantesca, agregar nuevas funcionalidades resultó ser tan doloroso que en realidad teníamos archivos de plantilla repetitivos que usaríamos para agregar nuevas funcionalidades.
Así que he visto de primera mano cómo hacer que cada parte sea muy legible y obvia puede hacer que todo sea muy ilegible y no obvio. Esto significa que el algoritmo codicioso puede fallar. Conoces el algoritmo codicioso, ¿sí? "Voy a hacer cualquier paso a nivel local que mejore la situación más y luego confiaré en que me encuentro en una situación mejorada a nivel mundial". A menudo es un hermoso primer intento, pero también puede fallar en contextos complejos. Por ejemplo, en la fabricación, puede intentar aumentar la eficiencia de cada paso en particular en un proceso de fabricación complejo: hacer lotes más grandes, gritar a las personas en el piso que parecen no estar haciendo nada para ocuparse de otra cosa, y Esto a menudo puede destruir la eficiencia global del sistema.
Mejor práctica: use DRY y longitudes para hacer la llamada
(Nota: el título de esta sección es una broma; a menudo les digo a mis amigos que cuando alguien dice "deberíamos hacer X porque las mejores prácticas lo dicen ") el 90% del tiempo no hablan de algo como la inyección SQL o el hash de contraseñas o lo que sea, las mejores prácticas unilaterales, por lo que la declaración se puede traducir en ese 90% de las veces a "deberíamos hacer X porque yo lo digo ". Como si pudieran tener algún artículo de blog de alguna empresa que hizo un mejor trabajo con X en lugar de X ', pero generalmente no hay garantía de que su negocio se parezca a ese negocio, y generalmente hay algún otro artículo de otro negocio que hizo un mejor trabajo con X' en lugar de X. Por lo tanto, no tome el título también seriamente.)
Lo que recomendaría se basa en una charla de Jack Diederich llamada Stop Writing Classes (youtube.com) . Él hace varios puntos importantes en esa charla: por ejemplo, que puedes saber que una clase es realmente una función cuando solo tiene dos métodos públicos, y uno de ellos es el constructor / inicializador. Pero en un caso está hablando de cómo una biblioteca hipotética que ha reemplazado por cadenas para la charla como "Muffin" declaró su propia clase "MuffinHash", que era una subclase del
dict
tipo integrado que tiene Python. La implementación estaba completamente vacía: alguien acababa de pensar: "podríamos necesitar agregar una funcionalidad personalizada a los diccionarios de Python más tarde, introduzcamos una abstracción ahora por si acaso".Y su respuesta desafiante fue simplemente: "siempre podemos hacerlo más tarde, si es necesario".
Creo que a veces simulamos que vamos a ser peores programadores en el futuro de lo que somos ahora, por lo que es posible que deseemos insertar algún tipo de pequeña cosa que nos haga felices en el futuro. Anticipamos las necesidades futuras de nosotros. "Si el tráfico es 100 veces mayor de lo que creemos que será, ese enfoque no se ampliará, por lo que tenemos que poner la inversión inicial en este enfoque más difícil que se ampliará". Muy sospechoso.
Si tomamos ese consejo en serio, entonces necesitamos identificar cuándo ha llegado "más tarde". Probablemente lo más obvio sería establecer un límite superior en la longitud de las cosas por razones de estilo. Y creo que el mejor consejo restante sería usar DRY, no se repita, con estas heurísticas sobre las longitudes de línea para reparar un agujero en los principios SOLID. Basado en la heurística de 30 líneas que son una "página" de texto y una analogía con la prosa,
Como mencioné allí, probé estas estadísticas con el árbol fuente de Linux actual para encontrar esos porcentajes aproximados, pero también son lógicas en la analogía literaria.
fuente