Hay una cita popular de Jamie Zawinski :
Algunas personas, cuando se enfrentan a un problema, piensan "Lo sé, usaré expresiones regulares". Ahora ellos tienen dos problemas.
¿Cómo se supone que debe entenderse esta cita?
Hay una cita popular de Jamie Zawinski :
Algunas personas, cuando se enfrentan a un problema, piensan "Lo sé, usaré expresiones regulares". Ahora ellos tienen dos problemas.
¿Cómo se supone que debe entenderse esta cita?
Respuestas:
Generalmente, los programadores no comprenden bien algunas tecnologías de programación ( expresiones regulares , coma flotante , Perl , AWK , IoC ... y otras ).
Estas pueden ser herramientas increíblemente poderosas para resolver el conjunto correcto de problemas. Las expresiones regulares en particular son muy útiles para hacer coincidir los idiomas regulares. Y ahí está el quid del problema: pocas personas saben cómo describir un lenguaje regular (es parte de la teoría / lingüística de la informática que usa símbolos divertidos; puedes leer sobre él en la jerarquía de Chomsky ).
Cuando se trata con estas cosas, si las usa mal, es poco probable que haya resuelto su problema original. Usando una expresión regular para que coincida con HTML (una ocurrencia muy común), se entenderá que se pierda casos extremos. Y ahora, todavía tienes el problema original que no resolviste, y se ha introducido otro error sutil que utiliza la solución incorrecta.
Esto no quiere decir que las expresiones regulares no deberían usarse, sino que uno debería trabajar para comprender cuál es el conjunto de problemas que pueden resolver y no pueden resolver y usar con criterio.
La clave para mantener el software es escribir código mantenible. El uso de expresiones regulares puede ser contrario a ese objetivo. Al trabajar con expresiones regulares, ha escrito una mini computadora (específicamente un autómata de estado finito no determinista ) en un lenguaje específico de dominio especial. Es fácil escribir el equivalente de 'Hola mundo' en este idioma y ganar confianza rudimentaria en él, pero ir más allá debe ser moderado con la comprensión del lenguaje regular para evitar escribir errores adicionales que pueden ser muy difíciles de identificar y corregir (porque no son parte del programa en el que se encuentra la expresión regular).
Entonces ahora tienes un nuevo problema; elegiste la herramienta de la expresión regular para resolverla (cuando es inapropiada), y ahora tienes dos errores, los cuales son más difíciles de encontrar, porque están ocultos en otra capa de abstracción.
Las expresiones regulares, particularmente las no triviales, son potencialmente difíciles de codificar, comprender y mantener. Solo tiene que mirar la cantidad de preguntas en Stack Overflow etiquetadas [regex]
donde el interrogador ha asumido que la respuesta a su problema es una expresión regular y posteriormente se ha atascado. En muchos casos, el problema puede (y quizás debería) resolverse de una manera diferente.
Esto significa que, si decides usar una expresión regular, ahora tienes dos problemas:
Básicamente, creo que quiere decir que solo debes usar una expresión regular si no hay otra forma de resolver tu problema. Probablemente, otra solución sea más fácil de codificar, mantener y respaldar. Puede ser más lento o menos eficiente, pero si eso no es crítico, la preocupación principal debería ser la facilidad de mantenimiento y soporte.
Es sobre todo una broma irónica, aunque con un grano de verdad.
Hay algunas tareas para las que las expresiones regulares son una excelente opción. Una vez reemplacé 500 líneas de código de analizador de descenso recursivo escrito manualmente con una expresión regular que tardó alrededor de 10 minutos en depurar completamente. La gente dice que las expresiones regulares son difíciles de entender y depurar, pero las aplicadas adecuadamente no son tan difíciles de depurar como un analizador diseñado a mano. En mi ejemplo, me llevó dos semanas depurar todos los casos extremos de la solución no regex.
Sin embargo, parafraseando al tío Ben:
Con gran expresividad viene una gran responsabilidad.
En otras palabras, las expresiones regulares agregan expresividad a su lenguaje, pero eso le da más responsabilidad al programador para elegir el modo de expresión más legible para una tarea determinada.
Algunas cosas parecen inicialmente una buena tarea para las expresiones regulares, pero no lo son. Por ejemplo, cualquier cosa con tokens anidados, como HTML. A veces las personas usan una expresión regular cuando un método más simple es más claro. Por ejemplo, string.endsWith("ing")
es más fácil de entender que la expresión regular equivalente. A veces las personas intentan agrupar un gran problema en una sola expresión regular, donde es más apropiado dividirlo en pedazos. A veces las personas no pueden crear abstracciones apropiadas, repitiendo una expresión regular una y otra vez en lugar de crear una función bien nombrada para hacer el mismo trabajo (quizás implementado internamente con una expresión regular).
Por alguna razón, las expresiones regulares tienen una extraña tendencia a crear un punto ciego a los principios normales de ingeniería de software como responsabilidad individual y DRY. Es por eso que incluso las personas que los aman los encuentran problemáticos a veces.
Jeff Atwood saca una interpretación diferente en una publicación de blog que discute esta cita: Expresiones regulares: ahora tienes dos problemas (gracias a Euphoric por el enlace)
Analizando el texto completo de las publicaciones de Jamie en el hilo original de 1997, encontramos lo siguiente:
La naturaleza de Perl fomenta el uso de expresiones regulares casi con exclusión de todas las demás técnicas; son, de lejos, la forma más "obvia" (al menos para las personas que no conocen mejor) de llegar del punto A al punto B.
La primera cita es demasiado simple para ser tomada en serio. Pero esto, estoy completamente de acuerdo. Aquí está el punto que Jamie estaba tratando de hacer: no es que las expresiones regulares sean malas, per se, sino que el uso excesivo de expresiones regulares es malo.
Incluso si usted no entiende completamente las expresiones regulares, se encuentra con The Golden Hammer problema, tratando de resolver un problema con las expresiones regulares, cuando habría sido más fácil y más claro para hacer lo mismo con el código regular (véase también codinghorror: uso Regex vs. abuso de expresiones regulares ).
Hay otra publicación de blog que analiza el contexto de la cita y entra en más detalles que Atwood: Blog de Jeffrey Friedl: Fuente de la famosa cita "Ahora tienes dos problemas"
Hay algunas cosas que suceden con esta cita.
La cita es una reformulación de una broma anterior:
Cuando se enfrentan a un problema, algunas personas dicen "Vamos a usar AWK". Ahora ellos tienen dos problemas. - D. Tilbrook
Es una broma y una verdadera excavación, pero también es una forma de resaltar la expresión regular como una mala solución al vincularla con otras malas soluciones. Es un gran ja ja solo un momento serio .
Para mí, eso sí, esta cita está abierta a la interpretación a propósito, el significado es sencillo. Simplemente anunciar la idea de usar una expresión regular no ha resuelto el problema. Además, ha aumentado la complejidad cognitiva del código al agregar un lenguaje adicional con reglas que se distinguen del idioma que esté utilizando.
Aunque es divertido como una broma, debe comparar la complejidad de una solución no regex con la complejidad de la solución regex + la complejidad adicional de incluir expresiones regulares. Puede valer la pena resolver un problema con una expresión regular, a pesar del costo adicional de agregar expresiones regulares.
RegularExpressionsarenoworsetoremaintainthanother otherformatetedcontently; indeedaregexisprobablyeasieoreoreadthathispiece oftext here-but lamentablemente, tienen una gran reputación debido a que las implementacionesdeformacionesdeformanal y la gente en general no saben de ella.
(Las expresiones regulares no son peores de leer o mantener que cualquier otro contenido sin formato; de hecho, una expresión regular es probablemente más fácil de leer que este texto aquí, pero desafortunadamente tienen una mala reputación porque algunas implementaciones no permiten el formateo y la gente en general no sé que puedes hacerlo)
Aquí hay un ejemplo trivial:
^(?:[^,]*+,){21}[^,]*+$
Lo cual no es realmente tan difícil de leer o mantener de todos modos, pero es aún más fácil cuando se ve así:
(?x) # enables comments, so this whole block can be used in a regex.
^ # start of string
(?: # start non-capturing group
[^,]*+ # as many non-commas as possible, but none required
, # a comma
) # end non-capturing group
{21} # 21 of previous entity (i.e. the group)
[^,]*+ # as many non-commas as possible, but none required
$ # end of string
Ese es un ejemplo un poco exagerado (comentar $
es similar a comentar i++
), pero claramente no debería haber problemas para leer, comprender y mantener eso.
Siempre que tenga claro cuándo las expresiones regulares son adecuadas y cuándo son una mala idea, no hay nada de malo en ellas, y la mayoría de las veces la cita de JWZ realmente no se aplica.
*+
? ¿Cómo es eso diferente (funcionalmente) de justo *
?
*+
en este caso; todo está anclado y un autómata que puede contar hasta 22 puede emparejarlo en una sola pasada. El modificador correcto en esos conjuntos sin comas es simplemente antiguo *
. (Además, tampoco debería haber diferencias entre los algoritmos de correspondencia codiciosos y no codiciosos aquí. Es un caso extremadamente simple.)
Además de la respuesta de ChrisF : que las expresiones regulares "son difíciles de codificar, comprender y mantener", hay algo peor: son lo suficientemente poderosas como para engañar a las personas para que intenten usarlas para analizar cosas que no pueden, como HTML. Vea las numerosas preguntas sobre SO en "¿Cómo analizo HTML?" Por ejemplo, la respuesta más épica en todo SO!
Las expresiones regulares son muy poderosas, pero tienen un problema pequeño y uno grande; son difíciles de escribir y casi imposibles de leer.
En el mejor de los casos, el uso de la expresión regular resuelve el problema, por lo que solo tiene el problema de mantenimiento del código complicado. Si no obtiene la expresión regular correcta, tiene tanto el problema original como el problema con el código ilegible que no funciona.
A veces, las expresiones regulares se denominan código de solo escritura. Frente a una expresión regular que necesita corrección, a menudo es más rápido comenzar desde cero que tratar de comprender la expresión.
El problema es que regex es una bestia complicada, y solo resuelve su problema si usa regex perfectamente. Si no lo hace, terminará con 2 problemas: su problema original y expresiones regulares.
Afirma que puede hacer el trabajo de cien líneas de código, pero también podría argumentar que 100 líneas de código claro y conciso es mejor que una línea de expresión regular.
Si necesita alguna prueba de esto: puede consultar este SO Classic o simplemente peinar la etiqueta SO Regex
El significado tiene dos partes:
Como lo solicitó en 2014, sería interesante centrarse en las ideologías de los lenguajes de programación del contexto de 1997 en comparación con el contexto de hoy. No entraré en este debate aquí, pero las opiniones sobre Perl y el propio Perl han cambiado mucho.
Sin embargo, para permanecer en el contexto de 2013 ( de l'eau a coulé sous les ponts depuis), sugeriría centrarse en la recreación de citas utilizando un famoso cómic de XKCD que es una cita directa del de Jamie Zawinski :
Primero tuve problemas para entender este cómic porque era una referencia a la cita de Zawinski, y una cita de la letra de una canción de Jay-z, y una referencia de GNU program --help -z
flag 2 , por lo tanto, era demasiada cultura para mí entenderlo.
Sabía que era divertido, lo estaba sintiendo, pero realmente no sabía por qué. La gente a menudo hace bromas sobre Perl y expresiones regulares, especialmente porque no es el lenguaje de programación más moderno, realmente no sé por qué se supone que es divertido ... Tal vez porque los traficantes de Perl hacen cosas tontas .
Entonces, la cita inicial parece ser una broma sarcástica basada en problemas de la vida real (¿dolor?) Causados por la programación con herramientas que duelen. Al igual que un martillo puede lastimar a un albañil, programar con herramientas que no son las que un desarrollador elegiría si pudiera lastimar (el cerebro, los sentimientos). A veces, se producen grandes debates sobre qué herramienta es la mejor, pero es casi inútil porque es un problema de su gusto o del gusto de su equipo de programación , razones culturales o económicas . Otro excelente cómic de XKCD sobre esto:
Puedo entender a las personas que sienten dolor por las expresiones regulares, y creen que otra herramienta es más adecuada para lo que están diseñadas para las expresiones regulares. Como @ karl-bielefeldt responde a su pregunta con gran expresividad viene una gran responsabilidad , y las expresiones regulares están especialmente preocupadas por esto. Si a un desarrollador no le importa cómo maneja las expresiones regulares, eventualmente será una molestia para las personas que mantendrán el código más adelante.
Terminaré con esta respuesta sobre la recreación de citas mediante una cita que muestra un ejemplo típico de Perl Best Practices de Damian Conway (un libro de 2005).
Él explica que escribir un patrón como este:
m{'[^\\']*(?:\\.[^\\']*)*'}
... no es más aceptable que escribir un programa como este :
sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;
Pero se puede reescribir , todavía no es bonito, pero al menos ahora se puede sobrevivir.
# Match a single-quoted string efficiently...
m{ ' # an opening single quote
[^\\']* # any non-special chars (i.e., not backslash or single quote)
(?: # then all of...`
\\ . # any explicitly backslashed char
[^\\']* # followed by any non-special chars
)* # ...repeated zero or more times
' # a closing single quote
}x
Este tipo de código de forma rectangular es el segundo problema, no las expresiones regulares que pueden formatearse de forma clara, fácil de mantener y legible.
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
Si hay algo que debe aprender de la informática, es la jerarquía de Chomsky . Diría que todos los problemas con las expresiones regulares provienen de los intentos de analizar la gramática sin contexto. Cuando puede imponer un límite (o cree que puede imponer un límite) a los niveles de anidamiento en CFG, obtiene esas expresiones regulares largas y complejas.
Las expresiones regulares son más adecuadas para la tokenización que para el análisis a gran escala.
Pero, un conjunto sorprendentemente grande de cosas que los programadores necesitan analizar son analizables por un lenguaje regular (o, peor aún, casi analizable por un lenguaje regular y si solo escribe un poco más de código ...).
Entonces, si uno está habituado a "ajá, necesito separar el texto, usaré una expresión regular", es fácil seguir esa ruta, cuando necesita algo más cercano a un autómata pushdown, un analizador CFG o gramáticas aún más poderosas. Eso generalmente termina en lágrimas.
Entonces, creo que la cita no es tanto regexps de golpe, tienen su uso (y bien utilizados, son muy útiles), sino la excesiva dependencia de las expresiones regulares (o, específicamente, la elección acrítica de ellas) .
jwz simplemente está fuera de su rockero con esa cita. las expresiones regulares no son diferentes a las de cualquier característica del lenguaje: fáciles de fastidiar, difíciles de usar con elegancia, poderosas a veces, inapropiadas a veces, a menudo bien documentadas, a menudo útiles.
Lo mismo podría decirse de la aritmética de coma flotante, los cierres, la orientación a objetos, las E / S asíncronas o cualquier otra cosa que pueda nombrar. Si no sabes lo que estás haciendo, los lenguajes de programación pueden entristecerte.
Si cree que las expresiones regulares son difíciles de leer, intente leer la implementación del analizador equivalente para consumir el patrón en cuestión. a menudo las expresiones regulares ganan porque son más compactas que los analizadores completos ... y en la mayoría de los idiomas, también son más rápidas.
no se desanime de usar expresiones regulares (o cualquier otra característica del lenguaje) porque un blogger autopromocionado hace declaraciones sin reservas. pruebe las cosas por sí mismo y vea qué funciona para usted.
Mi respuesta favorita y profunda a esto la da el famoso Rob Pike en una publicación de blog reproducida de un comentario interno del código de Google: http://commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing- y.html
El resumen es que no es que sean malos , sino que se usan con frecuencia para tareas para las que no son necesariamente adecuados, especialmente cuando se trata de analizar y analizar algunas entradas.
Las expresiones regulares son difíciles de escribir, difíciles de escribir bien y pueden ser costosas en relación con otras tecnologías ... Los Lexers, por otro lado, son bastante fáciles de escribir correctamente (si no de forma tan compacta) y muy fáciles de probar. Considere encontrar identificadores alfanuméricos. No es demasiado difícil escribir la expresión regular (algo así como "[a-ZA-Z _] [a-ZA-Z_0-9] *"), pero en realidad no es mucho más difícil de escribir como un bucle simple. Sin embargo, el rendimiento del bucle será mucho mayor e implicará mucho menos código debajo de las cubiertas. Una biblioteca de expresiones regulares es una gran cosa. Usar uno para analizar identificadores es como usar un Ferrari para ir a la tienda a buscar leche.
Él dice mucho más que eso, argumentando que las expresiones regulares son útiles en, por ejemplo, la coincidencia de patrones desechables en editores de texto, pero rara vez se deben usar en código compilado, y así sucesivamente. Vale la pena leerlo.
Esto está relacionado con el epigrama # 34 de Alan Perlis:
La cadena es una estructura de datos rígida y en todas partes se pasa hay mucha duplicación de proceso. Es un vehículo perfecto para ocultar información.
Entonces, si elige la cadena de caracteres como su estructura de datos (y, naturalmente, el código basado en expresiones regulares como los algoritmos para manipularlo), tiene un problema, incluso si funciona: mal diseño en torno a una representación inapropiada de datos que es difícil de extendido e ineficiente.
Sin embargo, a menudo no funciona: el problema original no se resuelve y, en ese caso, tiene dos problemas.
Las expresiones regulares se utilizan ampliamente para el análisis de texto rápido y sucio. Son una gran herramienta para expresar patrones que son un poco más complejos que una simple coincidencia de cadenas.
Sin embargo, a medida que las expresiones regulares se vuelven más complejas, varias cuestiones plantean su cabeza.
Por lo tanto, es muy fácil comenzar con un problema de procesamiento de texto, aplicarle expresiones regulares y terminar con dos problemas, el problema original que estaba tratando de resolver y tratar con las expresiones regulares que intentan resolver (pero no resuelven correctamente) El problema original.