Estoy teniendo una discusión con un compañero de trabajo en Linq, copiaré aquí:
Compañero de trabajo: seamos honestos aquí. La sintaxis de Linq apesta. Es confuso y no intuitivo.
Yo: oh, vamos, ¿más confuso que T-SQL?
Compañero de trabajo: uh, sí.
Yo: tiene las mismas partes básicas, seleccionar, dónde y de
Compañero de trabajo: Linq, para mí, es una bastarización de relacional + OO. Compañero de trabajo: No me malinterpreten, es increíblemente poderoso, pero reutilizaron SQL para usar colecciones de objetos.
Soy de la opinión de que usar Linq + Lamda's es muy poderoso (él está de acuerdo), y también hace que el código sea más fácil de leer (no está de acuerdo en ese punto):
pickFiles = from f in pickFolder.GetFiles("*.txt")
where ValidAuditFileName.IsMatch(f.Name)
select f;
o
var existing = from s in ActiveRecordLinq.AsQueryable<ScannedEntity>()
where s.FileName == f.FullName && s.DocumentType != "Unknown"
select s;
o (código VB aquí)
Dim notVerified = From image In images.AsParallel
Group Join verifyFile In verifyFolder.GetFiles("*.vfy").AsParallel.Where(
Function(v) v.Length > 0
).AsParallel
On image.Name.Replace(image.Extension, ".vfy") Equals verifyFile.Name
Into verifyList = Group
From verify In verifyList.DefaultIfEmpty
Where verify Is Nothing
Select verify
Para mí esto es limpio y fácil de leer (al menos más fácil que las alternativas), ¿cuáles son sus opiniones al respecto?
fuente
Respuestas:
Ya no puedo encontrar la publicación correcta, pero Eric Lippert (y posiblemente varios otros softwares) han opinado en varias ocasiones sobre cómo Linq es declarativo , lo que, para varias clases de problemas, es mucho más intuitivo que la sintaxis imperativa .
Linq le permite escribir código que expresa la intención , no el mecanismo .
Me dices cuál es más fácil de leer. Esta:
¿O esto?
O incluso esto?
El primer ejemplo es solo un montón de repeticiones sin sentido para obtener los resultados más simples. Cualquiera que piense que es más legible que las versiones de Linq necesita que le examinen la cabeza. No solo eso, sino que el primero desperdicia memoria. Ni siquiera puedes escribirlo usando
yield return
la clasificación.Tu compañero de trabajo puede decir lo que quiera; personalmente, creo que Linq ha mejorado la legibilidad de mi código de manera inconmensurable.
Tampoco hay nada "relacional" sobre Linq. Puede tener algunas similitudes superficiales con SQL, pero no intenta de ninguna forma implementar el cálculo relacional. Es solo un conjunto de extensiones que hacen que sea más fácil consultar y proyectar secuencias. "Consulta" no significa "relacional", y de hecho hay varias bases de datos no relacionales que usan una sintaxis similar a SQL. Linq está puramente orientado a objetos, simplemente funciona con bases de datos relacionales a través de marcos como Linq to SQL debido a un vudú de árbol de expresión y un diseño inteligente del equipo de C #, lo que hace que las funciones anónimas se conviertan implícitamente en árboles de expresión.
fuente
Linq is purely object-oriented
+1 por esto. Esta es también la razón por la cual nuestra guía de estilo de equipo impone el uso de la sintaxis fluida sobre la sintaxis de la consulta. Me parece que hace que la naturaleza OO del enlace sea más obvia para alguien acostumbrado a objetar la notación en lenguajes tipo C.GetVipCustomers()
, lo que, como su propio nombre sugiere, solo devolverá una colección de clientes VIP, en un orden arbitrario. Para los casos excepcionales en los que el orden es importante, como la salida a la pantalla, deje que la persona que llama clasifique la colección.No se puede discutir con esa crítica. Para su compañero de trabajo, es una mierda . No pudimos diseñar una sintaxis que, para ellos, fuera clara e intuitiva. Ese es nuestro error, y puedes transmitir mis disculpas a tu compañero de trabajo. Me complace tomar sugerencias sobre cómo mejorarlo; ¿Qué encuentra específicamente su compañero de trabajo confuso o poco intuitivo?
Sin embargo, no puedes complacer a todos. Mi opinión personal, y la opinión de la mayoría de las personas con las que he hablado sobre el tema, es que la sintaxis de comprensión de consultas es mucho más clara que la sintaxis imperativa equivalente. Claramente, no todos están de acuerdo, pero afortunadamente no requerimos el consenso de todos los millones de nuestros clientes cuando hacemos el diseño del lenguaje.
Sin embargo, sobre el tema de lo que es "intuitivo", recuerdo la historia del lingüista inglés que estudió muchos idiomas diferentes y finalmente concluyó que el inglés era el mejor de todos los idiomas porque en inglés, las palabras vienen en el mismo orden en que usted Piensa en ellos . A diferencia del francés, donde constantemente dicen cosas como "el perro blanco come la carne roja". ¡Qué difícil debe ser para los franceses pensar las palabras en el orden correcto y luego tener que decirlas en el orden francés ! ¡El francés es tan poco intuitivo! Es sorprendente que los franceses logren hablarlo. ¿Y alemán? donde piensan que "el perro se come la carne" pero luego tienen que decir "¡el perro se come la carne"!
A menudo, lo que es "intuitivo" es simplemente una cuestión de familiaridad. Me llevó meses trabajar con LINQ antes de dejar de comenzar mis consultas con la cláusula "select". Ahora es una segunda naturaleza, y el orden SQL parece extraño.
¡Cual es! Las reglas de alcance están desordenadas en SQL. Algo que quizás desee señalar a su compañero de trabajo es que LINQ fue cuidadosamente diseñado para que (1) la introducción de variables y ámbitos ocurra de izquierda a derecha (*), y (2) el orden en que aparece la consulta en la página es El orden en que se ejecuta. Es decir, cuando dices
la c aparece en el alcance a la izquierda y permanece en el alcance a la derecha. Y el orden en que suceden las cosas es: primero se evalúa a los "clientes". Luego se evalúa el "dónde" para filtrar la secuencia. Luego, la secuencia filtrada se proyecta mediante la "selección".
SQL no tiene esta propiedad. Si usted dice
entonces "Nombre" se pone en alcance por algo a su derecha, no a su izquierda, y la consulta se ejecuta en un orden completamente desordenado; la cláusula intermedia se evalúa primero, luego la última cláusula y luego la primera cláusula. Eso ahora me parece loco y poco intuitivo, ya que he trabajado únicamente con LINQ durante tanto tiempo.
(*) Las reglas de alcance son un poco extrañas en LINQ con cláusulas de unión. Pero aparte de eso, los ámbitos anidan muy bien.
fuente
c.
el IDE ya conoce el tipoc
y puede darle IntelliSense. En LINQ usted dice "de c en clientes donde c". y boom, obtienes IntelliSense ayudándote al enumerar los miembros deCustomer
. En SQL, cuando escribe "SELECCIONAR nombre DE clientes", no puede obtener ninguna ayuda de IDE para decirle que "nombre" es una buena opción porque escribióname
antescustomers
.Como cualquier otra cosa en el mundo de la programación, debes acostumbrarte a la sintaxis, y luego es (potencialmente) más fácil de leer.
Como cualquier otra cosa en el mundo de la programación, existe el potencial para el código de espagueti u otros abusos.
Como cualquier otra cosa en el mundo de la programación, puedes hacerlo de esta manera o de otra.
Como cualquier otra cosa en el mundo de la programación, su kilometraje puede variar.
fuente
Vi un comentario / comentario donde decía algo, en relación con LINQ / lambda, en la línea de: "Escribe código legible para los humanos, en lugar de legible para tu computadora".
Creo que esta declaración tiene mucho mérito, sin embargo, considere al desarrollador (como yo) que ha pasado por toda la gama de lenguajes de desarrollo desde Assembly, procesales, OO, gestionados, aprovechando soluciones paralelas de tareas de alto rendimiento .
Me he enorgullecido de hacer que mi código sea lo más legible y reutilizable posible y de adoptar muchos de los principios del patrón de diseño de GOF para ofrecer sistemas y servicios de calidad de producción en una gran cantidad de sectores comerciales dispares.
La primera vez que me encontré con la expresión lambda pensé: "¡¿Qué demonios es eso ?!" Fue inmediatamente contra-intuitivo a mi sintaxis declarativa explícita familiar (y por lo tanto cómoda). ¡Los chicos menores de 5 años en el trabajo, sin embargo, lo lamieron como si fuera maná del cielo!
Esto se debe a que, durante años, pensar como una computadora (en sentido sintáctico) se tradujo muy fácilmente en sintaxis de codificación directa (independientemente del lenguaje). Cuando haya tenido esa mentalidad computacional durante alrededor de 20 años (más de 30 en mi caso), debe apreciar que el shock sintáctico inicial de la expresión lambda puede traducirse fácilmente en miedo y desconfianza.
¿Quizás el compañero de trabajo en el OP provenía de un entorno similar al mío (es decir, había estado en la cuadra varias veces) y era contra-intuitivo para ellos en ese momento? Mi pregunta es: ¿qué hiciste al respecto? ¿Intentó reeducar a su compañero para que comprenda los beneficios de la sintaxis en línea, o los ridiculizó / excluyó por no "estar con el programa"? El primero probablemente habría visto a su compañero de trabajo acercarse a su línea de pensamiento, el último probablemente los haría desconfiar aún más de la sintaxis de LINQ / lambda y exacerbar así la opinión negativa.
Por mi parte, tuve que reeducar mi propia forma de pensar (como Eric infiere anteriormente, no es un cambio mental insignificante, y tuve que programar en Miranda en los años 80, así que he tenido mi parte de experiencia en programación funcional) pero una vez que pasé por ese dolor, los beneficios fueron obvios pero, lo que es más importante, donde su uso se usó en exceso (es decir, por el simple hecho de usarlo), más complejo y repetitivo (considerando el principio DRY en ese caso).
Como alguien que no solo todavía escribe mucho código, sino que también tiene que revisar técnicamente mucho código, era imperativo que entendiera estos principios para poder revisar los artículos de manera imparcial, aconsejar dónde el uso de una expresión lambda puede ser más eficiente / legible, y también para que los desarrolladores consideren la legibilidad de expresiones lambda en línea altamente complejas (donde una llamada a un método, en esos casos, haría que el código sea más legible, mantenible y extensible).
Entonces, cuando alguien dice que "no tienen lambda?" o la sintaxis LINQ, en lugar de calificarlos como un ludito, intente ayudarlos a comprender los principios subyacentes. Después de todo, pueden tener antecedentes de "vieja escuela" como yo.
fuente
Lambda Expressions conduce a un código menos legible si las consultas son demasiado largas. Sin embargo, es mucho mejor que demasiados bucles anidados .
Es mejor con una mezcla de los dos .
Escríbalo en Lambda si es más rápido (necesita que sea rápido) o más fácil de leer.
fuente
Creo que depende en la mayoría de los casos (excepto cuando se hace algo muy extraño) si quieres decir "legible" como si alguien tuviera la idea de lo que está sucediendo o si puede encontrar fácilmente todos los pequeños detalles.
Creo que el enlace ayuda con el primero, pero a menudo (especialmente cuando se depura) perjudica al segundo.
En mi humilde opinión, cuando estoy mirando el código que no estoy familiarizado con el primero es mucho más importante que el segundo, por lo que me parece mucho más legible.
fuente
where e.FirstName == "John"
y la traduce en una consulta SQL. Lo hace al observar la expresión no compilada (pero analizada), al ver que es una comparación de una propiedad invocadaFirstName
en una entidad persistente, y se compara con una cadena, etc. Están sucediendo muchas cosas.Encuentro que la sintaxis de LINQ es intuitiva y fácil de leer, especialmente porque pusieron el FROM al comienzo donde pertenece en lugar de en el medio, como en SQL. Pero las lambdas de la OMI son confusas y hacen que el código sea más difícil de leer.
fuente
\x -> x * x
) o F # (fun x -> x * x
)?Estoy de acuerdo con usted en que la sintaxis de Linq no es significativamente diferente de T-SQL. Creo que su compañero de trabajo realmente podría estar objetando que las cosas relacionales se mezclen en su código OO agradable y brillante. Por otro lado, la programación funcional requiere un poco de tiempo para acostumbrarse y la voluntad de acostumbrarse.
fuente
Depende. Obviamente, T-SQL proporciona de forma exclusiva algunas soluciones relacionales de base de datos. Obviamente, LINQ ofrece de manera única algunas soluciones OO.
Sin embargo; "más confuso que T-SQL?" - se discute / pregunta en la pregunta inicial. Esto implica claramente algunas características que ninguna de las respuestas existentes aborda, en su lugar, acusa al crítico (obviamente familiarizado con SQL) de estar atrapado en el pasado.
Entonces, aunque aprecio LINQ por ciertas cualidades, y no estoy muy en desacuerdo con las respuestas existentes aquí, siento que el contrapunto merece representación:
Años después de familiarizarme con LINQ, realizar ciertos tipos de operaciones grupales, uniones externas y no equijoins, trabajar con teclas compuestas y otras operaciones en LINQ todavía me da escalofríos. (Especialmente cuando se dirige a un back-end relacional con preguntas sensibles al rendimiento).
Si crees que es intuitivo, más poder para ti. ;)
fuente
Probablemente haya una razón por la cual Linq apesta, solo trate de hacer ejemplos del mundo real, en lugar de estos ejemplos de libros de texto.
intente mostrar esta función en linqlamdathings y verá que toda la belleza se ha ido, mientras que la forma clásica sigue siendo legible. Sin mencionar los problemas de ejecución diferida y el establecimiento de puntos de interrupción.
La verdad es que LinqLambdaThings son muy útiles en algunos casos y no se cree que reemplacen toda la ingeniosa orientación a objetos que ustedes nunca entendieron
fuente
source.Where(c => c.IsVip && c.FirstName == "Aaron" || c.SecondName == "Aaron").Take(maxCount).OrderBy(d => d.LastName);
pero es difícil leer el tuyo, así que puede que haya cometido un error;)