miércoles, 22 de junio de 2011

Inferencia de tipos con sentido común

La inferencia de tipos es una de las características que más me gustan de framework de .net. Cuando llegó con el framework 3.0 mucha gente pensaba que era el resurgir del tipo variant de VB6 al ver código de este estilo:

 var programmer = new Developer { Name = "Jorge", Technology = "Java" };
var text = new StringBuilder();

Al definir una variable con var, el compilador analiza el resto de la expresión y detecta el tipo de la variable, de tal manera el código IL que se genera está tipado.
Usar esta característica del framework nos permite reducir la cantidad de código, lo que hace más sencillo la lectura del mismo. Pero el abuso de esta característica puede provocar el efecto contrario.

Creo que solo deberíamos utilizar var para definir variables cuando al hacer la asignación podemos ver el tipo que va a recibir. Tambien considero correcto utilizar la inferencia en el foreach ya que el tipo es el de la colección. Por ejemplo:


public class Developer
{
public string Name { get; set; }
public string Technology { get; set; }
}

static void Main(string[] args)
{

var text = new StringBuilder();

var developers = new List<developer> {
new Developer {Name = "Pedro", Technology = "Java"},
new Developer {Name = "Manel", Technology = ".NET"},
new Developer {Name = "Oscar", Technology = ".NET"},
new Developer {Name = "Noe", Technology = "Java"},
new Developer {Name = "Elias", Technology = "Java"}
};

var programmer = new Developer { Name = "Jorge", Technology = "Java" };
developers.Add(programmer);

foreach (var developer in developers)
{
Console.WriteLine("{0} es un programador", developer.Name);
}
}

En algunas ocasiones es tentador el uso del var porque aunque no vemos directamente el tipo se puede entender claramente en el código, por ejemplo:


var today = DateTime.Today; //Tipo DateTime
var developer = DevelopersDao.GetDeveloperById(2); //Tipo Developer

Pero en otras ocasiones, el uso de la inferencia complica la legibilidad del codigo, al no saber que tipo devuelven las funciones o puede causar dudas a la hora de inicializar una variable, como en estos casos:


var programmers = DevelopersDao.GetDevelopers(); //¿Qué tipo devuelve?
var number = 5 * 3; //¿int, smalint, decimal?

Hace no mucho, un compañero de dijo que la inferencia de tipos incitba al uso de malas prácticas. No creo que sea así, tan solo debemos de pensar que si la finalidad de esta característica es hacer código más legible, pues la debemos de usar con esa finalidad. Como casi siempre eso depende del sentido común, que suele ser el menos común de los sentidos.

10 comentarios:

  1. Siguiendo en mi línea, creo que esto de la inferencia de tipos sólo ayuda a que la gente que no sabe programar monte esborigorcios y que el código sea menos legible.

    Los que saben programar se sienten perfectamente cómodos tipando.

    Lo que sí que es útil es el uso de genéricos, pero esto no lo veo.

    Además, parece que choca frontalmente con el diseño por contrato. ¿Dónde va el contrato? Adios patrones. <trailer> Viva el patrón zurullo </trailer> .

    ResponderEliminar
  2. Desde mi casi total desconocimiento de .net (así que acepto correcciones), sólo me parece vagamente interesante en el ejemplo del foreach, pero sólo usándolo para iterar el foreach y no en la definición de la lista (¿es esto posible?). Estoy de acuerdo con Pedro, el tipado fuerte es útil y no es confuso.

    Eso sí, declarar las variables así ofrece dos ventajas:
    1) Tecleas unas pocas letras menos al poner "var" que, p.ej., "Developer".
    2) Es un hábil movimiento de Microsoft para atraer a los programadores de Javascript ;)

    ResponderEliminar
  3. Creo que no he conseguido transmitir lo que indica la palabra reservada var.

    Con var el tipado sigue siendo fuerte, lo saca del contexto. No es como poner object, siempre tienes el tipo.

    No veo donde choca la inferencia de tipos con el diseño por contrato. Puedes definir las interfaces y no puedes definir un método con var.

    Y sí, la ventaja no es que me ahorra poner el tipo, porque el tipo lo voy a poner en la asignación.

    Lo que quería decir en el post es que la inferencia me parece comodoa pero no se puede usar siempre, en caso de duda no usarlo.

    Y no el hábil movimiento de M$ para atraera a los programadores de Javascript es el tipado dinamico incluido en el framework 4 :P

    Al menos estamos deacuerdo en que lo importante es la legibilidad del código, donde veo un tened cuidad con esto, vosotros veis una puerta abierta al caos.

    Aunque en el 90% de las veces vb es más verboso que c#, en ocasiones me parece más conciso será porque en vb.net no se escribe dos veces el tipo:
    dim pepe as new Developer()
    Quizás por eso me gusta var "less code do more"

    ResponderEliminar
  4. Creo que no me expliqué bien.

    Si el fin es teclear menos, la 'magia negra' de Microsoft es cojonuda. Una tabla con un link a la conexión de base de datos, y pista. Arrastra. Arrastra. Suela. Linka. ODBC. Listo.

    Si yo fuese un programador que no sé lo que hago y tengo que usar un API, cogería todas las variables, les pondría 'var' a todas, y esperaría a que el IDE me autocompletase los métodos disponibles.

    Sé que lo estoy viendo desde el punto de vista 'profesional' y pensando siempre en proyectos en los que voy a tener programadores inexpertos. Está claro que si yo hago un proyecto, yo me lo guiso y yo me lo como. Pero si tengo que trabajar con otra gente, mi sentido común está siempre enfrentado al de los otros. Así que hago todos los esfuerzos posibles para evitar que el sentido común de programadores inexpertos lleve a soluciones creativas ante problemas estándar.

    Eso si, puede que en cierto momento en un proyecto mío, en un entorno controlado, y para según qué cosas, acabase usando la inferencia de tipos.

    ResponderEliminar
  5. Hablo desde el punto de vista de la herramienta.
    ¿Debe el equipo condicionar la tecnología? eso es otro post que me estaba guardando.
    Como decían en Conan: "pero eso es otra historia" :P

    ResponderEliminar
  6. No tengo experiencia en desarrollo de empresa, pero intuyo que son los típicos problemas de desarrollo ;)

    Prefiero las cosas fuertemente tipadas (y eso que programo en PHP).
    Por los ejemplos intuyo que ese 'var' simplemente añade el significado 'soy local' a la variable que acompaña.

    Ventajas: para desarrollar rápido donde quieren cosas rápidas (menos pulsaciones de teclas, claro). Para código donde sólo lo toca uno.

    Desventajas: en desarrollo en grupo donde un ajeno al proyecto ve el código por primera vez y sin documentación, o en código que puede pasarse 2 años sin tocar (nunca confíes en la memoria, o al menos no confíes en la memoria del resto de la gente).

    Porque el código mostrado está genial como ejemplo, pero imaginemos que quiero buscar los métodos de... ooooh:

    foreach (var line in contentEnsemble)
    {
    line.???
    }

    vaya, a darle vueltas al código para ver de dónde vienen las cosas.

    Obviamente en mi ejemplo el problema es una mala elección de nombres de variables (o el hecho de no tener todo el modelo de datos y estructura de la aplicación en mente); desgraciadamente, es algo probable y esperable que ocurra.
    Simplemente con:

    foreach (Track line in contentEnsemble)

    ya tengo algo por lo que buscar sin romperme mucho la cabeza.
    Y que conste que yo no sé .NET, pero ya he hecho unas cuantas búsquedas en google con ".net List orderby" satisfactorias tras leer una simple línea de código.

    Todo desde el punto de vista de alguien que tiene que mantener código ajeno, claro.

    ResponderEliminar
  7. @Manel: "¿Debe el equipo condicionar la tecnología?"

    Por supuesto. Si resulta que con un equipo no puedes usar una tecnología, y dicha tecnología es obligatoria, tienes 2 opciones:

    - Formar al equipo
    - Cambiar el equipo

    Si el equipo es obligatorio:

    - Cambiar la tecnología

    Es como la física: todo depende de la variable que esté fija.

    ResponderEliminar
  8. Estoy pensando que es altamente probable que el IDE informe del tipo de una variable al pasar el ratón por encima.

    Me iré comiendo mis palabras: ñam,ñam,ñam, gronf, gronf, ñam.

    ResponderEliminar
  9. En este caso veo más plausible que se llegue a las malas prácticas que comenta Manel, así que no veo muy recomendado hacer uso de la inferencia de tipos...

    ResponderEliminar
  10. El IDE informa del tipo de la variable y autocompleta sus métodos, pero no veo lógico el tener que andar pasando con el ratón por encima de las variable para ver los tipos.

    El 'var' quiere decir " Soy demasiado vago para molestarme en escribir el tipo del objeto al que le hago new aquí al lado y que todo el mundo puede ver. Compilador, míralo tú " .

    Lo malo es cuando el 'var' quiere decir " Soy demasiado vago como para tipar esta variable local del foreach que recorre una colección que me ha devuelto este método y te vas a joder y poner el ratón encima para mirar su tipo o ir a mirarlo en la definición " .

    Todo es relativo. Yo prefiero leer código tipado.

    ResponderEliminar