string s = "cadena";
Sin embargo, la declaración anterior es redundante. Si la constante "cadena" es un string, ¿por qué hace falta indicar que la variable s también lo es?Las variables locales implícitamente tipadas permiten obviar en su declaración el tipo que tendrán, dejando al compilador la tarea de averiguar cuál será en función de las variables o constantes que se usen al inicializarlo. Por tanto, será posible escribir código como:
var x = XmlDateTimeSerializationMode.Local;
Y será equivalente a:
XmlDateTimeSerializationMode x = XmlDateTimeSerializationMode.Local;
Creo que no hace falta decir cuál de ellas es más cómoda a la hora de programar, ¿no? Simplemente hemos indicado con la palabra var que preferimos que sea el compilador el que haga el trabajo sucio.
Otro contexto donde este tipo de variables pueden facilitarnos la vida de forma frecuente es en los bucles for, foreach y bloques using:
// Un ejemplo de bucle...
var chars = "Saludicos".ToCharArray();
foreach (var ch in chars)
{
Console.Write(ch); // ch es char
}
// Y ahora un bloque using...
using (var ctx = new AppContext())
{
// usamos ctx, que es de tipo AppContext
}
También es importante la existencia de esta nueva forma de declaración para posibilitar la creación de objetos de tipo anónimo, es decir, aquellos cuya especificación de clase se crea en el mismo momento de su definición. Por tanto, una declaración como la siguiente será válida:
var x = new { Nombre = "Juan", Edad = 23 };
Para no desviarme del objetivo de este post, otro día hablaremos más detenidamente de las clases anónimas, aunque adelantaré que una vez compilado el código anterior el resultado será algo parecido al siguiente:
class __Anonymous1
{
private string nombre ;
private int edad ;
public string Nombre { get { return nombre ; } }
public int Edad { get { return edad ; } }
public __Anonymous1(string nombre, int edad)
{
this.nombre = nombre;
this.edad = edad;
}
}
...
__Anonymous1 x = new __Anonymous1("Juan", 23);
Existen ciertas reglas de obligado cumplimiento para usar variables locales implícitamente tipadas:
- La declaración debe incluir un valor de inicialización. En otras palabras, no será posible usar en una línea
var i;
, puesto que el compilador no podría inferir el tipo en este momento. - El valor de inicialización debe ser una expresión evaluable como clase en tiempo de compilación. Expresamente prohibido el valor null, es decir, nada de
var n = null;
, puesto que el compilador no sabría de qué tipo se trata; eso sí, si fuera necesario, podría forzarse un castingvar str = null as string;
. - La declaración no puede incluir más de una variable. Una línea como
var i = 1, s = "hola";
generará un error en compilación. - El inicializador no puede referirse a la propia variable declarada, obviamente.
- Sólo pueden utilizarse como variables locales en bloques de código, en bucles for y foreach y como recurso de un bloque using.
Por último, me gustaría añadir un par de detalles que considero interesantes.
Primero, el hecho de utilizar la palabra "var" y no indicar de forma explícita el tipo puede hacernos pensar que estamos utilizando tipado dinámico en tiempo de ejecución, como lo hacemos con Javascript, sin embargo esto no es así. Como he comentado anteriormente, el compilador toma el tipo del lado derecho de la asignación de inicialización, por lo que si la variable no es inicializada se produce un error de compilación:
Implicitly-typed local variables must be initializedPor ello, un entorno como Visual Studio sabe en todo momento el tipo exacto de que se trata, y nos puede ofrecer las ayudas en la codificación, detección de errores sintáticos e intellisense, como se puede observar en la imagen.
(Las variables locales implícitamente tipadas deben ser inicializadas)
Segundo, y muy interesante. Como ya comenté en su momento, la nueva versión de Visual Studio permite la generación de ensamblados para versiones anteriores de la plataforma, es decir, que es posible escribir código C# 3.0 y generar un ensamblado para el framework 2.0. Esto, a efectos prácticos, implica que una vez demos el salto definitivo a VS2008 podremos usar las variables locales de tipo implícito, así como otras novedades del lenguaje, incluso en aplicaciones diseñadas para .NET 2.0.
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 9:47 p. m.
Etiquetas: .net, asp.net, buenas prácticas, c#, nivel medio, programación, vs2008
El invento utiliza un sistema en el que las solicitudes de captura de pantalla se distribuyen entre "factorías", máquinas de los propios usuarios de la comunidad, que prestan parte del ancho banda y capacidad de sus equipos para realizar estas tareas. De hecho, hay unas sencillas instrucciones para crear una nueva factoría de capturas de pantalla y apoyar así el proyecto.
Para enviar la solicitud de captura es necesario indicar la URL a comprobar, así como los navegadores y características de la captura, combinando entre los siguientes elementos:
- Navegadores:
- para Linux: Epiphany 2.14, Firefox 1.5, Firefox 2.0, Galeon 2.0, Iceweasel 2.0, Konqueror 3.5, NetFront 3.2, Opera 9.24, Opera 9.5
- para Windows: Firefox 1.5, Firefox 2.0, MSIE 5.5, MSIE 6.0, MSIE 7.0, Opera 9.24, Safari 3.0.
- para Mac OS: Firefox 2.0, Safari 1.3, Safari 2.0, Safari 3.0
- Anchos de pantalla: 640, 800, 1024, 1280, 1400 y 1600 pixels.
- Profundidad de color: 8, 16, 24 y 32 bits por pixel.
- Javascript: deshabilitado, habilitado, v1.3, v1.5, v1.6, v1.7, v2.0
- Java: deshabilitado o habilitado.
- Flash: deshabilitado o habilitado.
Una vez enviado el formulario con las características deseadas, el trabajo pasará a la cola de cada una de las factorías desde se generarán las capturas de pantalla. El tiempo de espera dependerá del número de solicitudes pendientes, pero podremos conocer una estimación global y detallada desde la misma página:
Conforme las factorías van terminando su trabajo, enviarán una copia de la captura al servidor central, que publicará en la misma página web las imágenes obtenidas. Simplemente recargando la página obtendremos información actualizada del proceso y podremos ampliar las imágenes obtenidas hasta el momento pulsando sobre ellas:
Es importante destacar que la solicitud que enviamos tiene una validez de 30 minutos. Si en ese tiempo no hemos obtenido los resultados deseados, debemos extender (hay un botón para ello en la página) este tiempo, pues de lo contrario expirará. De esta forma, los señores de ScreenShots.org pueden asegurar que estamos todavía en la página y que seguimos interesados en las capturas de pantalla que hemos solicitado previamente.
Las capturas generadas son de un tamaño y calidad excelente, suficientes para detectar problemas en el diseño o las habituales incompatibilidades entre los motores de renderizado de páginas web de los navegadores.
El único problema es el tiempo que puede llegar a tardar la realización de un conjunto completo de capturas. En distintas pruebas me he encontrado con colas de más de una hora, aunque, también he de decirlo, la mayoría de las capturas se han generado en los primeros diez minutos. Además, por una módica cantidad mensual (10€/15$) puedes adquirir un mes de prioridad en el servicio, por lo que, según aseguran, obtendrás todas las pantallas en menos de 3 minutos.
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 8:32 p. m.
Etiquetas: diseño, estándares, navegadores, servicios on-line, web
NiftyDotNet, para el que no lo conozca, es un componente ASP.Net para las plataformas Mono y Microsoft, que encapsula la librería javascript Nifty Corners Cube para conseguir redondear las esquinas de elementos de una página web de una forma realmente sencilla. Basta con arrastrar los controles sobre un Webform, indicarles los elementos que se verán afectados y listo.
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 1:12 p. m.
Etiquetas: asp.net, componentes, mono, niftydotnet, proyectos, software libre
Ahora, partiendo de estos consejos, la abundante literatura que hay sobre el tema y mi propia experiencia, he creado los 13 consejos para comentar tu código, que contribuirán a hacerlo más inteligible y por tanto a incrementar su mantenibilidad a lo largo del tiempo.
1. Comenta a varios niveles
Comenta los distintos bloques de los que se compone tu código, aplicando un criterio uniforme y distinto para cada nivel. Puedes, por ejemplo, seguir un modelo como:- En cada clase, incluir una breve descripción, su autor y fecha de última modificación
- Por cada método, una descripción de su objeto y funcionalidades, así como de los parámetros y resultados obtenidos
Obviamente, una solución bastante aceptable e incluso aconsejable es utilizar las convenciones y herramientas (como XML en C# ó Javadoc para el mundo Java) que ayudan y facilitan esta tarea.
2. Usa párrafos comentados
Como complemento al punto anterior, es recomendable dividir un bloque de código extenso en "párrafos" que realicen una tarea simple, e introducir un comentario al principio de forma que se guíe al lector, precediéndolos, además, de una línea en blanco que ayude a separar cada uno del anterior. ...
// Comprobamos si todos los datos
// son correctos
foreach (Record record in records)
{
if (rec.checkStatus()==Status.OK)
{
...
}
}
// Ahora pasamos a realizar las
// transacciones
Context ctx = new ApplicationContext();
ctx.BeginTransaction();
...
3. Tabula por igual los comentarios de líneas consecutivas
Si tenemos un bloque de líneas de código donde existe por cada una de ellas un comentario, es buena costumbre tabularlos todos a la misma posición, de forma que quedarán alineados y serán más sencillos de leer, sobre todo si forman parte de la misma frase. const MAX_ITEMS = 10; // Número máximo de paquetes
const MASK = 0x1F; // Máscara de bits TCP
Ojo a las tabulaciones. Hay editores que usan el carácter ASCII (9) y otros, en cambio, lo sustituyen por un número determinado de espacios, que suelen variar según las preferencias personales del desarrollador. Lo mejor es usar espacios simples o asegurarse de que esto es lo que hace el IDE correspondiente.
4. No insultes la inteligencia del lector
Debemos evitar comentarios absurdos como: if (a == 5) // Si a vale cinco, ...
counter = 0; // ... ponemos el contador a cero
...
Este exceso necesita mucho tiempo a la hora de su creación, lo necesitará para su mantenimiento y, además, la mayoría de las veces distraerá al lector con detalles que no es necesario conocer o que pueden ser deducidos echando un vistazo al código.
5. Sé correcto
Evita comentarios del tipo "ahora compruebo que el estúpido usuario no haya introducido un número negativo", o "este parche corrije el efecto colateral producido por la patética implementación del inepto desarrollador inicial".El uso de este tipo de comentarios no dice nada a favor de su creador, y, además, nunca se sabe quién los va a leer en el futuro. Emarts, en "Sapos, culebras y código fuente" muestra ejemplos de comentarios de este tipo.
Otro tema relacionado y, a mi entender, igualmente importante: cuida la ortografía. El hecho de que los comentarios no se vean desde el exterior no implican que puedas descuidarlos. Una ortografía correcta mejora la calidad de la expresión escrita y, por tanto, de la comunicación, que es de lo que se trata.
6. No pierdas el tiempo
No comentes si no es necesario, no escribas nada más que lo que necesites para transmitir la idea. Nada de diseños realizados a base de caracteres ASCII, ni florituras, ni chistes, ni poesías, ni chascarrillos.En resumen, mantén los comentarios simples y directos, pues de lo contrario harás perder tiempo a tu sucesor. Para entender el efecto negativo de una verborrea excesiva, no hay como echar un vistazo a Hyperverbosity, publicado en Worse Than Failure hace unos días.
7. Utiliza un estilo consistente
Hay quien opina que los comentarios deberían ser escritos para que los entendieran no programadores. Otros, en cambio, piensan que debe servir de ayuda para desarrolladores exclusivamente.En cualquier caso, coincidiendo con Ryan Campbell en su post Successful Strategies for Commenting Code, lo que importa es que siempre sea de la misma forma, orientados al mismo destinatario. Personalmente, dudo mucho que alguien de un perfil alejado a la programación vaya a acercarse al código, por lo que, para mi gusto, bastaría con cubrir el segundo caso de los expuestos anteriormente.
8. Para los comentarios internos usa marcas especiales
Y sobre todo, aunque no únicamente, cuando se trabaja en un equipo de programación en el que varias personas pueden estar tocando las mismas porciones de código. El ejemplo típico es el comentario TODO (to-do, por hacer), que describe funciones pendientes de implementar:
int calcula(int x, int y)
{
// TODO: implementar los cálculos
return 0;
}
En este caso los comentarios no se usan para explicar una porción de código, sino para realizar anotaciones sobre el mismo a las que hay que prestar especial atención. Eso sí, si usas esta técnica, recuerda que debes actualizarlos conforme las anotaciones dejen de tener sentido.
9. Comenta mientras programas
Ve introduciendo los comentarios conforme vas codificando. No lo dejes para el final, puesto que entonces te costará más de el doble de tiempo, si es que llegas a hacerlo. Olvida las posturas "no tengo tiempo de comentar, voy muy apurado", "el proyecto va muy retrasado"... son simplemente excusas. Si tu intención es comentar el código, no te engañes y ¡hazlo!Hay incluso quien opina que los comentarios que describen un bloque deberían escribirse antes de codificarlo, de forma que, en primer lugar, sirvan como referencia para saber qué es lo que hay que hacer y, segundo, que una vez codificado éstos queden como comentarios para la posteridad. Un ejemplo:
public void ProcesaPedido()
{
// Comprobar que hay material
// Comprobar que el cliente es válido
// Enviar la orden a almacén
// Generar factura
}
La codificación de cada una de las tareas descritas en el lenguaje correspondiente se realizaría justo debajo del comentario, quedando éste como encabezado de párrafo (como se describe en el consejo 2).
10. Comenta como si fuera para tí mismo. De hecho, lo es.
A la hora de comentar no pienses sólo en mantenimiento posterior, ni creas que es un regalo que dejas para la posteridad del que sólo obtendrá beneficios el desarrollador que en el futuro sea designado para corregir o mantener tu código.En palabras del genial Phil Haack,
"tan pronto como una línea de código sale de la pantalla y volvemos a ella, estamos en modo mantenimiento de la misma"
Como consecuencia, nosotros mismos seremos los primeros beneficiaros (o víctimas) de nuestro buen (o mal) hacer.
11. Actualiza los comentarios a la vez que el código
De nada sirve comentar correctamente una porción de código si en cuanto éste es modificado no se actualizan también los comentarios. Ambos deben evolucionar paralelamente, pues de lo contrario estaremos haciendo más difícil la vida del desarrollador que tenga que mantener el software, al facilitarle pistas incorrectas para comprenderlo.Atención especial a las refactorizaciones automáticas, que suelen introducir cambios en distintos puntos del código de un proyecto, dejando los comentarios obsoletos en ese mismo instante.
12. La regla de oro del código legible
He dejado para el final uno de los principios básicos para muchos desarrolladores: deja que tu código hable por sí mismo. Aunque se sospecha que este movimiento está liderado por programadores a los que no les gusta comentar su código ;-), es totalmente cierto que una codificación limpia puede hacer innecesaria la introducción de textos explicativos adicionales.Recordemos, por ejemplo, el código introducido en el post "Interfaces fluidos (fluent interfaces)", donde se muestra lo que esta técnica puede aportar a la claridad y autoexplicación en un desarrollo:
Console.WriteLine("Resultado: " +
new Calculator()
.Set(0)
.Add(10)
.Multiply(2)
.Substract(4)
.Get()
);
A la vista del ejemplo, ¿es necesario añadir algún comentario para que se entienda qué hace el código? El uso de nombres apropiados (aconsejo leer el clásico Ottinger's Rules), indentación correcta y la adopción de guías de estilo (podéis ver algunas en la wikipedia, o googleando un poco) facilitan enormemente la escritura homogénea e inteligibilidad directa del código.
El no cumplimiento de esta regla hace que a veces los comentarios puedan parecer una forma de pedir perdón al desarrollador que se encargará del mantenimiento del software.
13. Difunde estas prácticas entre tus colegas
Obviamente, aunque ya hemos comentado en el punto 10 que nosostros mismos nos beneficiamos inmediatamente de las bondades de nuestro código comentado, la generalización y racionalización de los comentarios y la creación código inteligible nos favorecerá a todos, y sobre todo en contextos de trabajo en equipo. No dudes, por tanto, en crear cultura de comentarios en tu entorno.Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 8:36 p. m.
Etiquetas: buenas prácticas, comentarios, desarrollo, programación
Acepto críticas (constructivas, eso sí ;-)), sugerencias y opiniones.
PD: ¡Gracias, Javi!
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 7:16 p. m.
Etiquetas: autobombo, blogger, blogging, diseño, variablenotfound, variablenotfound.com
Pues bien, llevo tiempo observando que hay muchas personas que preguntan a Google algo similar a "anular postback en botón", es decir, se tienen dudas sobre cómo evitar el disparo del postback al pulsar un botón de un formulario ASP.Net. El tema me ha parecido tan interesante que intentaré dar una respuesta a la duda estudiando algunas de las distintas posibilidades que pueden darse. Eso sí, si echáis en falta algún caso, no dudéis en comentarlo y lo trataremos lo antes posible.
I. ¿Hablamos de botones con lógica exclusivamente en cliente?
La primera cuestión es preguntarse para qué queremos un botón que no realice un postback al ser pulsado. Pensad que si todas las acciones desencadenadas por la pulsación del botón se realizarán en cliente es posible que no necesitemos un control ASP.Net. Imaginemos, por ejemplo, un botón que queremos que haga un cálculo en el cliente y muestre un cuadro de alerta con el resultado... ¿es necesario que sea un control de servidor (runat="server")? Seguro que no.Para este caso lo más apropiado es incluir en el .aspx un HTML INPUT de los de toda la vida:
<input id="Button1" type="button" value="button"
onclick="hacerAlgo();" />
Si eres de los que prefieren arrastrar y soltar, puedes hacer exactamente lo mismo utilizando los controles incluidos en la pestaña HTML de Visual Studio, en este caso el llamado Input(Button). El resultado visual será idéntico al de un Button (un botón de servidor) y estaremos aligerando tanto la página enviada al cliente como la carga del servidor.
II. Anular el postback en un botón de servidor
Otra posibilidad es que vayas a usar un control de servidor (un Button, por ejemplo) y sólo bajo determinadas circunstancias quieras anular el postback desde el cliente. Obviamente, estas circunstancias serían calculadas/obtenidas por script, por lo que podríamos aplicar un patrón como el siguiente:
...
<asp:Button ID="Button1" runat="server"
Text="Pulsa"
OnClientClick="return comprueba();" />
...
<script type="text/javascript">
function comprueba() {
return confirm("Confirme el postback");
}
</script>
Como se puede observar, se ha modificado la propiedad OnClientClick del botón para hacer que retorne el resultado de la llamada a la función comprueba(). Si ésta retorna cierto, se realizará el postback, mientras que si retorna falso, no lo hará. En el ejemplo anterior se permite al usuario decidir si desea enviar el formulario al servidor o no.
III. Anular la posibilidad de envíos múltiples
Hay otras ocasiones, sin embargo, en las que estamos utilizando un botón de servidor de forma normal y simplemente queremos evitar duplicidades en el envío del formulario, es decir, bloquear el botón correspondiente una vez el usuario lo haya pulsado la primera vez.Esto es muy habitual debido a la falta de feedback: el usuario envía el formulario, se impacienta esperando la respuesta o no está seguro de haberlo enviado, y cual poseso, inicia un ataque implacable sobre el botón de envío. ¿A que os suena?
El comportamiento típico, adoptado por la mayoría de sitios web, es deshabilitar el botón y seguir con el postback. Sin embargo, esto que podría ser realmente sencillo mediante scripting, causa algún que otro problema cuando el botón es de tipo Submit, puesto que en determinados navegadores (por ejemplo IE6) no realizará el envío si lo está generando un botón deshabilitado. Una forma de evitar este problema es hacer que el botón no sea de tipo submit e incluir un pequeño script:
<asp:Button ID="Button2" runat="server"
Text="Pulsa"
OnClientClick="this.disabled=true"
UseSubmitBehavior="False"/>
Si el botón debe ser obligatoriamente de tipo submit, se deben utilizar soluciones alternativas. Googleando un poco he encontrado varias, como deshabilitar el botón pasadas unas décimas de segundo mediante un timer, o retocar los estilos del botón para, simplemente, hacerlo desaparecer y mostrar en su lugar un mensaje informativo. La mejor, para mi gusto, consiste en capturar el evento onsubmit del formulario web, así:
...
<form id="form1" runat="server" onsubmit="deshabilita()">
...
<script type="text/javascript">
function deshabilita()
{
var btn = "<%= Button1.ClientID %>";
if (confirm("Confirme postback"))
{
document.getElementById(btn).disabled = true;
return true;
}
return false;
}
</script>
Este último ejemplo lo he aprovechado para, además, mostrar cómo es posible realizar la captura del envío justo antes de que se produzca, en el evento OnSubmit, e introducir las confirmaciones de envío y deshabilitado de botones.
Publicado en Variable not found.