2010-10-08 13 views
7

Me doy cuenta de que esto es parcialmente subjetivo, pero en general tengo curiosidad por la opinión de la comunidad y no he podido encontrar con éxito una pregunta existente que aborde este tema.¿Cuándo hace demasiado un lambda en un método de extensión?

Estoy en un debate un tanto religioso con un compañero de trabajo sobre una determinada instrucción Select en una consulta L2EF.

.Select(r => 
{ 
    r.foo.Bar = r.bar; 
    r.foo.Bar.BarType = r.Alpha; 
    if (r.barAddress != null) 
    { 
     r.foo.Bar.Address = r.barAddress; 
     r.foo.Bar.Address.State = r.BarState; 
    } 
    if (r.baz != null) 
    { 
     r.foo.Bar.Baz = r.baz; 
     if (r.bazAddress != null) 
     { 
      r.foo.Bar.Baz.Address = r.bazAddress; 
      r.foo.Bar.Baz.Address.State = r.BazState; 
     } 
    } 
    return r.foo; 
}) 

Advertencias:

  • Esto es Linq-to-Entidades
  • Esto es después de el trabajo en el DB como han realizado y devuelto
  • El parámetro de entrada r es anónima

Personalmente, soy de la opinión en (a) la cláusula de selección no debería estar alterando valores, simplemente debería proyectarse. Su contra argumento es que no está alterando nada, solo se está asegurando de que todo se inicialice correctamente como resultado de la consulta DB. En segundo lugar, creo que una vez que empiece a entrar en bloques de código completos y declaraciones de devolución, es hora de definir un método o incluso un Func<T, U> y no hacer todo esto en línea. El complicador aquí es, una vez más, que la entrada es anónima, por lo que habría que definir un tipo. Sin embargo, aún estamos debatiendo el punto general, sino el específico.

Entonces, ¿cuándo una expresión lambda hace demasiado? ¿Dónde dibujas la línea borrosa en la arena?

+0

Parece que la complejidad del código sigue la complejidad del tipo anónimo; ¿Es un tipo anónimo tan complejo realmente necesario? –

+0

@Dan, la consulta real implica uniones a la izquierda que atraviesan 8 entidades diferentes, con el tipo anónimo que simplemente contiene los objetos de esas entidades. no es un tipo anónimo complejo, per se, simplemente no está definido. es como 'seleccionar nuevo {foo, bar, baz,/* etc. * /}' –

+0

Esto es obviamente un Seleccionar con efectos secundarios. No es la intención. Para eso, hay 'foreach();'. – Dykam

Respuesta

2

Mi primer instinto es estar de acuerdo con usted, principalmente en materia de tamaño y complejidad.

Sin embargo, se usa en un contexto donde se ejecutará (oa veces se ejecutará) como algo distinto al código .NET (especialmente si se convierte en parte de una consulta SQL), me convertiré en mucho más tolerantes

Por lo tanto, ahí es donde trazo la línea borrosa, y también por qué lo muevo de nuevo :)

1

También estoy de acuerdo a Seleccione() debería emplearse para la proyección. Prefiero ver el uso de la palabra clave "let" para hacer la verificación por adelantado para que esa proyección en el Select() pueda mantenerse limpia. Esto permitirá que Select() haga referencia a la (s) variable (s) configurada (s) usando "let".

1

No creo que sea una expresión larga de lambda, personalmente. Creo que verás lambdas mucho más complejas y anidadas en el futuro. Especialmente con algo como Rx.

En cuanto a los cambios de estado ... bueno, aquí está simplemente inicializando los valores. Sólo había preocuparme si se asigna un estado a alguna variable fuera de la lambda, pero esto es toda la inicialización de r, por lo que parece bien a mí.

1

tuve que mirar esto por un tiempo antes de ver lo que me está molestando.

  1. Esto necesita un refactor.

  2. El hecho de que me tomó tanto tiempo para leer la intención de un lambda.

no estoy seguro si puedo tomar un lado de su definición de la Selección de trabajo, pero estoy de acuerdo en que cuanto más corto que pueda mantener una lambda, mejor. Divídalo para volver a usarlo si la inicialización después de la búsqueda de dB es tan mala.

0

Hay que tener en cuenta sus otras alternativas ... ¿hay un mejor lugar para poner esa lógica. De cualquier forma, estás recorriendo cada entidad en LINQ, o en un bucle foreach, para hacer ese trabajo adicional ... A menos que quieras refactorizarlo en tu propio método de extensión, yo diría que lo dejes si funciona.

Visualmente, que no es tan complicado, por lo que es una ventaja. O bien, puede ver si la palabra clave let (básicamente una subconsulta) le compra algo más.

0

La longitud de la lambda no me molesta en absoluto. Pero estoy de acuerdo con la sensación de suciedad cuando asigna un valor dentro de su declaración seleccionada. Me gustaría factorizar las cosas de inicialización en una declaración justo debajo de la declaración de selección.

Cuestiones relacionadas