Acabo de escribir una función que abarca aproximadamente 100 líneas. Al escuchar eso, probablemente tengas la tentación de contarme sobre responsabilidades individuales y de instarme a refactorizar. Este es mi instinto también, pero aquí está el problema: la función hace una cosa. Realiza una manipulación de cadena compleja, y el cuerpo de la función consiste principalmente en una expresión regular detallada, dividida en muchas líneas que están documentadas. Si dividiera la expresión regular en múltiples funciones, siento que en realidad perdería legibilidad, ya que estoy cambiando de idioma de manera efectiva y no podré aprovechar algunas de las características que ofrecen las expresiones regulares. Aquí ahora es mi pregunta:
Cuando se trata de la manipulación de cadenas con expresiones regulares, ¿los cuerpos de funciones grandes siguen siendo un antipatrón? Parece que los grupos de captura con nombre tienen un propósito muy similar a las funciones. Por cierto, tengo pruebas para cada flujo a través de la expresión regular.
Respuestas:
Lo que está encontrando es la disonancia cognitiva que proviene de escuchar a las personas que favorecen la adhesión servil a las pautas bajo la apariencia de "mejores prácticas" sobre la toma de decisiones razonadas.
Claramente has hecho tu tarea:
Si alguno de esos puntos no fuera cierto, sería el primero en decir que su función necesita trabajo. Entonces hay un voto para dejar el código tal como está.
El segundo voto proviene de mirar sus opciones y lo que obtiene (y pierde) de cada una:
Esta decisión se reduce a lo que valoras más: legibilidad o duración. Caigo en el campamento que cree que la longitud es agradable, pero la legibilidad es importante y tomaré lo último sobre lo primero cualquier día de la semana.
En pocas palabras: si no está roto, no lo arregles.
fuente
Honestamente, su función puede "hacer una cosa", pero como usted mismo dijo
lo que significa que su código ex reg hace muchas cosas. Y supongo que podría desglosarse en unidades más pequeñas y comprobables individualmente. Sin embargo, si esta es una buena idea, no es fácil de responder (especialmente sin ver el código real). Y la respuesta correcta puede ser ni "sí" o "no", sino "todavía no, pero la próxima vez que tenga que cambiar algo en ese registro exp".
Y este es el punto central: tiene un fragmento de código escrito en un lenguaje regular . Este lenguaje no proporciona ningún buen medio de abstracción en sí mismo (y no considero que los "grupos de captura con nombre" reemplacen las funciones). Por lo tanto, la refactorización "en el lenguaje reg ex" no es realmente posible, y entrelazar los registros reg más pequeños con el idioma del host puede no mejorar la legibilidad (al menos, así lo siente , pero tiene dudas, de lo contrario no habría publicado la pregunta) . Así que aquí está mi consejo
muestre su código a otro desarrollador avanzado (tal vez en /codereview// ) para asegurarse de que otros piensen en la legibilidad como lo hace usted. Sea abierto a la idea de que otros pueden no encontrar un registro de 100 líneas tan legible como usted. A veces, la noción de "no se puede romper fácilmente en pedazos más pequeños" se puede superar con un segundo par de ojos.
observe la capacidad de evolución real: ¿su brillante registro aún se ve tan bien cuando llegan nuevos requisitos y tiene que implementarlos y probarlos? Mientras su registro exp funcione, no lo tocaría, pero cada vez que hay que cambiar algo, lo reconsideraría si realmente fuera una buena idea poner todo en este gran bloque, y (¡en serio!) Repensar si se divide en piezas más pequeñas no serían una mejor opción.
observe la capacidad de mantenimiento: ¿puede depurar efectivamente el registro en el formulario actual muy bien? Especialmente después de que tiene que cambiar algo, y ahora sus pruebas le dicen que algo está mal, ¿tiene un depurador de registros regulares que lo ayude a encontrar la causa raíz? Si la depuración se vuelve difícil, esa también sería una ocasión para reconsiderar su diseño.
fuente
A veces, una función más larga que hace una cosa es la forma más adecuada de manejar una unidad de trabajo. Puede acceder fácilmente a funciones muy largas cuando comience a consultar una base de datos (utilizando su lenguaje de consulta favorito). Hacer que una función (o método) sea más legible y limitarla a su propósito establecido es lo que consideraría el resultado más deseable de una función.
La longitud es un "estándar" arbitrario cuando se trata del tamaño del código. Cuando una función de 100 líneas en C # puede considerarse alargada, sería pequeña en algunas versiones de ensamblaje. He visto algunas consultas SQL que estaban bien en el rango de 200 líneas de código que devolvieron un conjunto de datos muy complicado para un informe.
Código completamente funcional , que es tan simple como razonablemente puede hacer que sea el objetivo.
No lo cambie solo porque es largo.
fuente
Siempre puedes dividir la expresión regular en sub-expresiones regulares y gradualmente componer la expresión final. Esto podría ayudar a la comprensión de un patrón muy grande, particularmente si el mismo subpatrón se repite muchas veces. Por ejemplo en Perl;
fuente
Yo diría romperlo si es rompible. desde el punto de vista de la mantenibilidad y quizás la resabilidad, tiene sentido romperlo, pero, por supuesto, debe tener en cuenta su función y la forma en que obtiene información y lo que va a devolver.
Recuerdo que estaba trabajando en analizar la transmisión de datos fragmentados en objetos, así que lo que hice básicamente fue dividirlo en dos partes principales, una fue construir una unidad completa de Cadena de texto codificado y en la segunda parte analizar esas unidades en el diccionario de datos y organizar ellos (podrían ser propiedades aleatorias para diferentes objetos) y que actualizar o crear objetos.
También podría dividir cada parte principal en varias funciones más pequeñas y más específicas, por lo que al final tenía 5 funciones diferentes para hacer todo y podría reutilizar algunas de las funciones en un lugar diferente.
fuente
Una cosa que puede o no haber considerado es escribir un pequeño analizador en el idioma que está usando en lugar de usar una expresión regular en ese idioma. Esto puede ser más fácil de leer, probar y mantener.
fuente
Las expresiones regulares gigantes son una mala elección en la mayoría de los casos. En mi experiencia, a menudo se usan porque el desarrollador no está familiarizado con el análisis (ver la respuesta de Thomas Eding ).
De todos modos, supongamos que desea apegarse a una solución basada en expresiones regulares.
Como no conozco el código real, examinaré los dos escenarios posibles:
La expresión regular es simple (muchas coincidencias literales y pocas alternativas)
En este caso, las funciones avanzadas que ofrece una expresión regular única no son indispensables. Esto significa que probablemente se beneficiará al dividirlo.
La expresión regular es compleja (muchas alternativas)
En este caso, no puede tener una cobertura de prueba completa de manera realista, porque probablemente tenga millones de flujos posibles. Entonces, para probarlo, debes dividirlo.
Puede que me falte imaginación, pero no puedo pensar en ninguna situación del mundo real en la que una expresión regular de 100 líneas sea una buena solución.
fuente