Según la especificación del lenguaje C#, un identificador (de una variable, clase, propiedad...) puede ser una de las palabras clave del lenguaje (for, if, int, string...) si va precedida por una arroba, permitiendo aberraciones como la siguiente:
class @class
{
public static void @static(bool @bool)
{
if (@bool)
System.Console.WriteLine("true");
else
System.Console.WriteLine("false");
}
}
En fin, dudo mucho que vaya a utilizar esta posibilidad alguna vez, pero está bien saber que existe.
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 8:45 p. m.
Etiquetas: c#, desarrollo, programación, trucos
Todos los lenguajes de programación facilitan la inclusión de texto libre, no estructurado, con objeto de que el programador explique a futuros mantenedores del software los principales aspectos del código fuente que está observando, el por qué de determinadas decisiones, o, en definitiva, aclarar lo que considere oportuno. Sin embargo, esta libertad y falta de normalización acarrea una serie de inconvenientes que deben ser tenidos en cuenta, y que comentó Chad Myer hace unas semanas.
En primer lugar, es importante ser conscientes de que estos textos están fuertemente ligados al código que comentan y, obviamente, al no ser comprobados por ningún sistema automático (como un compilador), es fácil que contengan errores:
// Retorna la suma de a y b
public int multiplica(int a, int b)
{
...
Tampoco puede asegurarse que los comentarios sean útiles; de hecho, parte de los comentarios que leemos son obviables y totalmente innecesarios, auténticos insultos a la inteligencia, del tipo:
if (a > 5) // Si a es mayor que cinco, ...
counter = 0; // ... ponemos el contador a cero
...
La inclusión de este tipo de comentarios no harían sino añadir "ruido" a un código perfectamente inteligible de forma directa.
Y hablando de comentarios prescindibles, es curioso ver su utilización como vía de escape y desfogue de algunos programadores, que no dudan en añadir todo tipo de artillería a sus creaciones, como las mostradas en el Contador de palabrotas del Kernel de Linux, arremetiendo contra los usuarios, colegas o todo aquél que pase por delante en el momento apropiado.
Otro hecho bastante frecuente es que los comentarios sean introducidos al crear un código pero que no sean actualizados de forma paralela a éste, lo que da lugar a textos obsoletos y sin sentido en su contexto. Y no hablo sólo de actualizaciones tiempo después de su creación, también las realizadas minutos u horas después de la programación inicial como consecuencia de optimizaciones y refactorizaciones, incluso realizadas por el mismo desarrollador.
// Si x es true, retorna a+b
// Si no, retorna a-b
public int calcula(int a, int b)
{
...
A pesar de todos estos problemas, normalmente generados por falta de rigor durante su creación y actualización, los comentarios son absolutamente necesarios para el futuro mantenimiento de un sistema y deben tratarse como parte fundamental en una pieza de código y prestarle la misma atención que a éste. Recordemos la famosa frase de Martin Fowler:
"Cualquier tonto puede escribir código que entienden las computadoras. Los buenos programadores escriben código que entienden las personas"
Para ello, como dice Bernhard Spuida en su magnífico documento The Fine Art of Commenting, hay que luchar contra actitudes negativas como:
- el orgullo del programador ("no me hacen falta comentarios para entender lo que hace cualquier código", "yo escribo código que entiende cualquiera"). No te engañes, un código medianamente complejo te llevará tiempo entenderlo en cuanto hayan pasado unos meses incluso a tí mismo, así que imagina a otro desarrollador.
- la pereza y procrastinación ("ya comentaré el código más adelante"). No te engañes, no lo harás; además, se estima que el tiempo necesario para añadir comentarios útiles a un código se duplica (como mínimo) si no se realiza en el momento de la codificación.
- la excusa del deadline ("el proyecto va demasiado apurado como para ponerme a comentar el código"). No te engañes, los minutos de tardarás en comentar apenas afectarán a los plazos, y sí añadirán mantenibilidad al sistema.
Y es que, citando a Ryan Campbell en su post Successful Strategies for Commenting Code,
"comentar el código es como limpiar el cuarto de baño; nadie quiere hacerlo, pero el resultado es siempre una experiencia más agradable para uno mismo y sus invitados"
Publicado en: Variable Not Found.
Publicado por José M. Aguilar a las 8:35 p. m.
Etiquetas: buenas prácticas, comentarios, desarrollo, programación
En pocas palabras, el uso de interfaces fluidos es un estilo cada vez más frecuente de programación, también llamado a veces "encadenamiento de métodos" (method chaining), que promueve la eliminación de código innecesario y engorroso para la realización de tareas frecuentes, sustituyéndolo por una secuencia natural, intuitiva y fluida de instrucciones que se encadenan de forma casi mágica.
Pero veámoslo con un ejemplo. Y ojo, que aunque lo codificaremos en C#, el concepto es perfectamente válido para otros lenguajes orientados a objetos, salvo por los aspectos sintácticos.
Imaginemos la clase
Calculator
, con un diseño como el mostrado a la izquierda, que es capaz de mantener un único valor (entero) y que soporta cinco operaciones: Get
(para obtener el valor actual de la calculadora), Set
(para establecerlo), y Add
, Substract
y Multiply
(para sumarle, restarle y multiplicarle un valor respectivamente).La forma habitual de operar con esta calculadora para obtener el resultado de un cálculo sería algo parecido a:
Calculator calc = new Calculator();
calc.Set(0);
calc.Add(10);
calc.Multiply(2);
calc.Subtract(4);
Console.WriteLine("Resultado : " + calc.Get());
Como podemos observar, para realizar unas operaciones muy simples hemos necesitado demasiadas líneas de código, y además bastante repetitivas.
Veamos ahora cómo utilizando la técnica de interfaces fluidos podemos dejar este código en:
Console.WriteLine("Resultado: " +
new Calculator().Set(0).Add(10).Multiply(2)
.Substract(4).Get()
);
El truco consiste en hacer que métodos que normalmente no devolverían ningún valor (métodos void, como los de la clase Calculator anterior) retornen referencias hacia el propio objeto, es decir, acaben con un
return this;
. De esta forma, la llamada a la función podrá ir seguida de otra llamada sobre el mismo objeto, que a su vez lo devolverá para el siguiente y así sucesivamente. Y de ahí el término "fluido": fijaos en el ejemplo anterior como la instancia de Calculator que es retornada por el constructor se utiliza directamente en la llamada Set(0)
, que a su vez la devuelve y es utilizada por Add(10)
... ¿no es eso fluir, aunque el término suene algo poético?Otro ejemplo, donde se utiliza la misma técnica, pero esta vez combinando instancias de distintas clases (fijaos que nada impide en la mayoría de lenguajes dividir las líneas de código como se muestra, facilitando así la lectura):
new Surface()
.Clear()
.Fill("white")
.CreateText()
.SetMessage("Hi, all!")
.SetColor("blue")
.Draw()
.CreateCircle(100, 100, 10)
.Fill("green")
.Draw()
.Border("red")
.Draw()
Este código muestra tres aspectos importantes. Primero, que es posible crear un pseudo-lenguaje de programación utilizando esta técnica, de hecho los fluent interfaces son muy utilizados en los DSL (Lenguajes Específicos de Dominio). En el ejemplo se puede intuir un lenguaje para el dibujo de figuras sobre una superficie.
Segundo, que la devolución de los métodos no tiene por qué limitarse a una única clase. En el código anterior, los métodos
CreateText()
y CreateCircle()
retornan referencias a nuevas instancias de clases que representan estas figuras, que también hacen uso de interfaces fluidos. Los métodos Draw()
de ambas retornan de nuevo una referencia a la instancia de la superficie (Surface
) sobre la que están dibujando.Tercero, se deja entrever la dificultad de desarrollar clases que permitan utilizar esta técnica, pues cada método debe devolver una referencia al objeto oportuno para facilitar el encadenamiento con el método posterior. Una elección incorrecta de la clase de devolución hará que la fluidez se rompa.
Finalmente, decir que los interfaces fluidos no son algo nuevo. Hay quien habla de su uso en SmallTalk antes de la década de los noventa (!), aunque el concepto se extendió a partir de la inclusión de una entrada en la Bliki de Martin Fowler comentándolo hace un par de años.
Hay también quien opina que los interfaces fluidos son algo más que el encadenamiento de métodos, que también existe en un código como
name.Trim().ToUpper()
, pues aporta una interfaz comprensible e intuitiva.En cualquier caso, hace algún tiempo que esta técnica me llamó la atención y cada vez lo veo utilizado en más ocasiones, especialmente en contextos de frameworks y para implementar DSLs (como Quaere).
Publicado por José M. Aguilar a las 8:48 p. m.
Etiquetas: desarrollo, dsl, fluent interfaces, interfaces fluidos, patrones, programación
Sin embargo, si querías usar los controles de servidor en todo su esplendor te veías obligado a meter tareas completas dentro de una misma página; así, aquellas que presentaban funcionalidades relativamente complejas se convertían en batiburrillos donde se incluían formularios de entrada de datos, código de validaciones, formularios de salida de información, etc. Por ejemplo, podíamos tener en un mismo Webform paneles de introducción de criterios de búsqueda, paneles de información o errores, paneles con un grid para mostrar los resultados e incluso otro panel para mostrar una vista ampliada de un registro concreto, y jugar con las visibilidades para mostrar unos u otros en función de los pasos dados por el usuario.
Desde ASP.Net 2.0 es posible realizar los llamados "Cross Page PostBacks", o PostBacks hacia páginas distintas de la inicial, permitiéndonos separar funciones y hacer nuestro código un poco más legible, estructurado y reutilizable. El ejemplo anterior podría ser diseñado en tres páginas independientes, separando las distintas vistas, una solución mucho más limpia:
- en la primera estaría el formulario de introducción de criterios.
- en la segunda podríamos simplemente tomar los parámetros de la anterior y mostrar un listado con los resultados obtenidos, o bien un mensaje de información si no hay coincidencias.
- en la tercera podríamos montar una ficha con los datos detallados de un elemento, que habría sido seleccionado por el usuario en la página anterior.
En primer lugar, hay que modificar el comportamiento de los botones de acción (o similar, de hecho también podría ser ImageButtons o LinkButtons) para que realicen el envío a otra página, indicándole su URL en la propiedad PostBackUrl. Eso hará que, tras su pulsación, el control sea enviado inmediatamente al archivo .aspx que se defina en la misma.
Un aspecto muy a tener en cuenta es el término "inmediatamente": el control es transferido a la nueva página sin ejecutar posibles validaciones en servidor, por lo que podrían llegar gazapos a la segunda. Sin embargo, si los validadores son en cliente, se ejecutarán con normalidad (si el usuario no tiene desactivado Javascript, of course!).
Ya en la página destino, hay varias opciones para recuperar el valor de los controles de la página invocadora. La primera de ellas, la más sencilla, consiste en usar la propiedad PreviousPage de la clase Page para obtener una referencia hacia la página de origen y obtener sus controles de la siguiente forma:
if (PreviousPage != null)
{
TextBox txt =
(TextBox)PreviousPage.FindControl("TextBox1");
Label1.Text = txt.Text; // Por ejemplo
}
Sin embargo, no es una solución aconsejable, puesto que un simple cambio de nombre del control en la página origen provocaría un error en tiempo de ejecución, puesto que FindControl no sería capaz de encontrarlo con el nombre "TextBox1".
Hay otra forma mucho más potente, que consiste en especificar en la página destino un tipado fuerte para la de origen usando en su archivo .aspx la siguiente directiva:
<%@ PreviousPageType VirtualPath="~/PaginaOrigen.aspx" %>
De esta forma, cualquier referencia a PreviousPage en la página destino se considerará automáticamente del tipo de la página de origen, pudiendo acceder a sus propiedades de forma directa, sin necesidad de castings ni nada parecido. Sin embargo, todo sea dicho, debido a que el nivel de visibilidad de los controles de un Webform son protected, no podemos acceder directamente a su contenido, debemos usar accesores o propiedades públicas para ello.
Por ejemplo, podríamos definir en la clase (codebehind) de la página de origen una propiedad como la siguiente como accesor al contenido de un control TextBox llamado txtTexto:
public string Texto
{
get {return txtTexto.Text; }
}
Y en la página destino, una vez introducida la directiva descrita anteriormente especificando la URL de la página de origen, podríamos hacer lo siguiente:
if (PreviousPage != null)
{
Label1.Text = PreviousPage.Texto; // Por ejemplo
}
En resumen, esta técnica permite estructurar mucho mejor nuestras aplicaciones web, aunque sea a cambio de realizar un sobreesfuerzo en el desarrollo. En mi opinión puede valer la pena su uso en páginas que generen demasiadas vistas diferentes para ser introducidas en un único Webform sin comprometer la mantenibilidad, o cuando resulte interesante de cara a la reutilización de páginas.
No es conveniente, a mi entender, su utilización indiscriminada en formularios simples, pues precisamente los PostBacks fueron introducidos en ASP.Net para evitar la proliferación innecesaria de páginas sueltas (.aspx) y facilitar el mantenimiento del estado en la inherentemente desconectada tecnología Web.
Publicado por José M. Aguilar a las 11:38 p. m.
Etiquetas: asp.net, c#, desarrollo, mono, programación, web
Asimismo, se han vuelto a comentar las principales ventajas de utilizar este nuevo marco para el desarrollo de sistemas web:
- Separación clara de lógica, presentación y control.
- Utilización de URLs limpias y amigables.
- Control absoluto sobre el marcado y emisión de XHTML puro.
- Extensibilidad total, todos los componentes pueden ser reemplazados por otros de terceros.
- Ventajas sobre Monorail (o incluso Ruby on Rails), como la perfecta integración con VS2008 (intellisense, plantillas, depuración...), o el uso de parte de la infraestructura ASP.NET (aunque se abandonen los postbacks).
En fin, que en breve tendremos diversión asegurada.
1. Lanzamiento
Visual Studio 2008 y .NET framework 3.5 serán lanzados oficialmente juntos el próximo febrero. Sin embargo, estará disponible para desarrolladores a finales de noviembre de 2007.
Afortunadamente, estarán disponibles las versiones Express de C#, VB, C++ y Web, así como las Profesionales (¡con soporte de testeos unitarios!), Estándar y ediciones de equipos de desarrollo. La novedad será Visual Studio 2008 Shell, de carácter gratuito, que permitirá crear lenguajes y herramientas de desarrollo más verticalizadas.
Daniel comenta también que bajo Windows Vista, VS2008 será espectacular, e incluirá mejoras para la depuración de múltiples hilos. Ya no hay excusa para quedarnos con WXP ;-P
2. Compatibilidad hacia atrás
.NET framework 3.5 continúa la línea iniciada por Fx3.0 en cuanto al mantenimiento del CLR. Por tanto, y dado que lo único que hace es añadir ensamblados a las librerías presentes con las versiones 2.0 y 3.0 del framework, las aplicaciones actuales no se verán afectadas. Eso sí, necesitará los Service Packs 1 de ambas plataformas.
3. Generación multiplataforma
Visual Studio 2008 incluye la capacidad de crear proyectos para múltiples plataformas .NET, es decir, la 2.0, 3.0 y 3.5, desde el mismo entorno. Por tanto, no será necesario tener VS2005 instalado para generar ensamblados para .NET 2.0.
4. Multitud de novedades en C# 3.0 y VB9
Propiedades automáticas, delegados "relajados", inicializadores de objetos, inferencia de tipos, tipos anónimos, métodos de extensión, funciones lambda y métodos parciales, entre otros.
Pero no sólo eso... dado el punto 3 (generación multiplataforma), podremos usar estas nuevas características de nuestros lenguajes favoritos y generar para .NET 2.0.
5. LINQ
Se trata de una de las grandes revoluciones que nos aportará este nuevo conjunto de herramientas. Language INtegrated Query es un nuevo método de acceso a datos totalmente integrado en nuestro lenguaje habitual y de una forma muy independiente de la fuente de donde provengan (colecciones, XML, motores de bases de datos, etc.).
6. Novedades para ASP.NET
Visual Studio, así como el nuevo framework, ya incluirán ASP.NET AJAX de serie, así como 3 nuevos controles (ListView, DataPager y LinqDataSource). Además, el IDE ha sido muy mejorado e incluye soporte para intellisense y depuración de Javascripts, ¡también para ASP.NET 2.0!, y un nuevo diseñador que permite anidar páginas maestras.
7. Para el desarrollo en cliente
VS2008 incluirá nuevas plantillas de proyectos, así como un diseñador para WPF integrado con soporte para la comunicación WPF-WinForms. También se ha añadido el soporte para Firefox de la tecnología ClickOnce y XBAP (XAML Browser Applications).
8. Para el desarrollador de Office
Se ofrece soporte total para la personalizaciones (customisations) de Office 2007, así como para las plantillas de Office 2003.
9. Para desarrollo en servidor
Se han incluido nuevas plantillas para WCF y WF, y se han introducido mejoras interesantes en el primero, como el modelo de programación HTTP (sin SOAP) o serialización JSON.
10. Para el desarrollo en dispositivos móviles
Hay decenas de nuevas características, como el soporte para las versiones compactas de LINQ y WPF, o, a nivel de IDE, Unit Testing for Devices.
11. (punto extra) Código del framework
Pues sí, como ya es sabido, podremos depurar nuestras aplicaciones siguiendo el rastro por el interior de las clases y métodos del framework
Más información en la fuente: The Moth.