
Pero para que quede claro lo que pretendemos, primero un ejemplo del resultado que vamos a conseguir:
La forma de conseguirlo es bastante sencilla. Basta con establecer, en las propiedades de estilo de los cuadros de edición una imagen de fondo con el icono que queremos incluir, y dejar un espaciado por la izquierda (padding-left) equivalente al ancho del mismo para que la introducción del texto comience a partir de ese punto.
Por ejemplo, si definimos las siguientes clases en el CSS de nuestra página (y suponiendo que la ruta de las imágenes sea correcta, claro):
.lupa
{
background: white url(icono_lupa.gif) no-repeat 2px center;
padding: 2px 2px 2px 18px;
}
.telefono
{
background: white url(icono_telefono.gif) no-repeat 2px center;
padding: 2px 2px 2px 18px;
}
Como se puede observar, se establece un fondo blanco con una imagen cuya URL se especifica (icono_xxxx.gif), mostrada sin repetición (no-repeat), posicionada en coordenada horizontal 2px y centrada verticalmente. El padding izquierdo será de 18px para que comience ahí el área de edición, a la derecha de la imagen.
Podremos utilizar después en nuestro HTML un código como el siguiente para conseguir que los cuadros de edición apararezcan "adornados" como nos interese en cada momento eligiendo para cada uno de ellos la clase CSS apropiada:
<input type="text" class="lupa" />
<input type="text" class="telefono" />
Espero que esto responda la duda, Joaquín.
Y por cierto, he utilizado esta técnica en el buscador del encabezado del blog, que lo tenía un poco soso...
Publicado en: www.variablenotfound.com.
Box2DFlashAS3 es un port para ActionScript 3.0 de una librería originalmente escrita para C++, Box2D. Ahí van unas demostraciones de sus posibilidades (pulsad las teclas izquierda y derecha para cambiar la demo, "R" para resetear la vista y también podéis arrastrar objetos con el ratón):
Hace unos meses se publicó su última revisión, la 4.1.3, y se distribuye bajo licencia zlib/libpng, lo que permite su libre utilización incluso con fines comerciales.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:01 p. m.
Etiquetas: curiosidades, desarrollo, motores de física

![[ING] ASP.NET Page Life Cycle en blog de Kris Van Der Mast](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT5f1ddJsQrs3L6f6WkA0piXPTgq-nmnSEi1vOjm4ICrWJpFQVEbH-Qb050rcuvTn9Q_711qoUE7YLLj78DghBPF40_BJjx1qA8R2A8w1roSidzUwUl1CVw_kOk3zzxsO90sFTmg/s400/aspnetpagelifecycle.png)
Entre otras cosas, se pone de manifiesto la simplicidad de este modelo frente al complejo ciclo de vida de una página utilizando la tecnología Webforms.
Y por cierto, podéis descargar la presentación completa que realizaron en el DevConnections, aunque eso sí, en inglés.
Publicado en: www.variablenotfound.com.
![[ING] Ir al sitio web de jQuery](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9HX3lmL5_rFpuxL5fKsuGpa8t5IWmEFyfB6iow00W8BI2XA8s5EVgZnwTZaGJBy9ItMXS0GunTmbCsz89Ou6N4qCsGnRLgPRJUpw3XuoMP_TOt_OT-tmwRjRW3NZ0SgptAjHy2g/s400/jQuery-logo.gif)
Como ya sabemos los PageMethods son métodos estáticos definidos dentro de la clase de una página, es decir, en su codebehind, y que son accesibles desde cliente utilizando Ajax (en minúsculas!).
Hace más de un año ya estuve comentando cómo hacerlo utilizando la propia infraestructura de ASP.NET Ajax y sus librerías de scripting para hacerlo muy fácilmente. De forma muy breve, todo consistía en crear el método estático al que se deseaba acceder, decorarlo con el atributo
WebMethod
, e incluir en la página un ScriptManager
con estableciéndole la propiedad EnablePageMethods=true
; a partir de ese momento, podíamos invocarlo desde cliente usando javascript de forma muy directa.Sin embargo, el uso de estándares como JSON hace posible la invocación de WebMethods desde scripting sin necesidad de recurrir a la magia del
ScriptManager
. De hecho, y como vamos a ver más adelante, vamos a realizar la llamada al método utilizando Ajax desde una página HTML pura, sin controles de servidor ni otros edulcorantes proporcionados por ASP.NET.Desarrollaremos un ejemplo completo (esta vez en VB.NET, por cambiar un poco), que demuestre cómo podemos crear un
PageMethod
en una página (default.aspx), e invocarlo desde otra (pagina.htm) usando la librería jQuery para comunicar ambos componentes. 1. Definición del PageMethod
Como ya comenté en el post al que hacía referencia antes, un PageMethod se define en la clase asociada a una página .aspx (su code-behind) y es un método normal y corriente, aunque obligatoriamente será estático y público. Además, debe presentar el atributoWebMethod()
, que lo identifica como accesible a través llamadas HTTP.El siguiente código muestra el PageMethod que vamos a utilizar. Se supone que partimos de una página Default.aspx totalmente vacía (de hecho, no vamos a crear nada más dentro), y que el siguiente código corresponde al archivo Default.aspx.vb:
Imports System.Web.Services
Partial Public Class _Default
Inherits System.Web.UI.Page
<WebMethod()> _
Public Shared Function Saludame(ByVal Nombre As String) As String
Return "Hola a " + Nombre _
+ " desde el servidor, son las " _
+ DateTime.Now.ToString("hh:mm:ss")
End Function
End Class
Se puede observar que el método recibirá un parámetro, el nombre del destinatario del mensaje de saludo. Una vez que lo tenemos definido de esta forma, siempre que el proyecto esté correctamente configurado, el método es accesible en la dirección "Default.aspx/Saludame" para todo aquél que quiera utilizarlo, siempre que siga ciertas reglas.
2. Creamos la página "cliente"

En lugar de mostrar el código fuente de la página HTML (pagina.html) completo, voy a hacerlo por partes, y saltándome algunas porciones que no tienen demasiado interés. En primer lugar va la correspondiente al interfaz, que es bastante simple:
<body>
<form>
<input type="text" id="nombre" />
<input type="button" value="¡Pulsa!"
onclick="llamar();" />
<br />
<strong>Mensajes obtenidos:</strong><br />
<label id="lblMensajes" />
</form>
</body>
Como se puede intuir, la función
llamar()
, invocada al hacer click sobre el botón, será la que realice la conexión con el servidor, le envíe el nombre contenido en el cuadro de edición, e introduzca la respuesta en la etiqueta lblMensajes
, que actuará como contenedor.Vamos ahora con la porción de página donde se desarrolla la acción. Primero se incluye jQuery en la página, y acto seguido creamos la función
llamar()
que hemos comentado anteriormente:<script type="text/javascript"
src="scripts/jquery-1.2.6.min.js" ></script>
<script type="text/javascript">
function llamar()
{
$.ajax({
type: "POST",
data: "{ Nombre: '" + $("#nombre").val() + "'}" ,
url: "Default.aspx/Saludame",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#lblMensajes").append(msg);
$("#lblMensajes").append("<br />");
},
error: function(msg) { alert("Algún problema debe haber..."); }
});
}
</script>
Los parámetros de llamada a la función ajax() de jQuery son los siguientes:
type
, la petición HTTP es de tipo POST. Es obligatorio para acceder a los PageMethods por motivos de seguridad.data
contiene una representación JSON de los parámetros enviados al método. En este caso, vemos que se compone de forma dinámica inyectándole el valor del cuadro de edición (obtenido a su vez utilizando un selector jQuery y el método val()). Fijaos que esta representación define un objeto anónimo cuyas propiedades deberán coincidir con los parámetros del método; para este ejemplo, un valor correcto dedata
sería"{ Nombre: 'Juan' }"
.url
contiene la dirección del método. Observad que es el nombre de la página seguido del nombre del método.- El
content-type
indica el tipo de contenido que enviamos al servidor; en este caso, dado que le vamos a enviar JSON codificado en utf-8 debe ser "application/json; charset=utf-8". - Con
dataType
indicamos al servidor qué tipo de respuesta estamos esperando. Dado que la trataremos también desde script, será más sencillo si es JSON. success
contiene una función anónima que recibe como parámetro la respuesta del servidor. En este caso, hemos implementado su inclusión en la etiqueta que habíamos preparado para mostrar los mensajes del servidor.- de la misma forma, en
error
implementamos lo que queremos que haga el sistema cuando se produzca un problema. En este caso sólo avisamos.
Y... ¡listo para funcionar!
Fijaos en un detalle importante: nada impide la invocación de PageMethods desde páginas distintas a donde se han definido, cosa que con el comportamiento estándar del
ScriptManager
y su EnablePageMethods=true
sería imposible.Finalmente, recordar que para que todo esto funcione el proyecto web debe estar correctamente configurado para trabajar con las extensiones Ajax. Las plantillas de proyectos de Visual Studio 2008 ya vienen preparadas de forma predeterminada, pero si usas VS2005 deberás crear el proyecto usando las plantillas para aplicaciones Web con Ajax, o retocar a mano el web.config.
Puedes descargar el proyecto de prueba para VS2005.
Publicado en: www.variablenotfound.com.

El concepto es parecido a los antipatrones de programación, aunque funcionan a un nivel todavía más sutil, pues no describe situaciones completas sino indicios. De hecho, el uso de esta metáfora sensorial respecto a un código, es decir, que éste desprenda cierto tufillo, indica que sería conveniente realizar una revisión en profundidad para ver si hay que refactorizar, pero no implica que necesariamente haya algo incorrecto. Además, dado que trata de algo tan personal y específico como el código fuente, a veces las señales son bastante subjetivas y dependientes de lenguajes y tecnologías concretas.
Existen multitud de listas y clasificaciones, aunque es muy interesante la realizada por Mika Mäntylä, investigador de la universidad de Helsinki, ha creado una taxonomía que agrupa code smells relacionados en cinco categorías en función del efecto que pueden provocar:
- The bloaters (los infladores), que agrupa 'aromas' que indican el crecimiento excesivo de algún aspecto que hacen incontrolable el código.
- Long method (método extenso) que precisa de su reducción para ser más legible y mantenible.
- Large class (clase larga), con síntomas y consecuencias muy similares al caso anterior.
- Primitive obsession (obsesión por tipos primitivos), cuyo síntoma es la utilización de tipos primitivos para almacenar datos de entidades pequeñas (por ejemplo, usar un long para guardar un número de teléfono).
- Long parameter list (lista de parámetros larga), que incrementan la complejidad de un método de forma considerable.
- Dataclumps (grupos de datos), o uso de un cunjunto de variables o propiedades de tipos primitivos en lugar de crear una clase apropiada para almacenar los datos, lo que a su vez provoca el incremento de parámetros en métodos y clases.
- The Object-Orientation Abusers (los maltratadores de la orientación a objetos), que aglutina code smells que indican que no se está aprovechando la potencia de este paradigma:
- Switch statements (sentencias Switch), que podrían indicar una falta de utilización de mecanismos de herencia.
- Temporary field (campo temporal), que se salta el principio de encapsulamiento y ocultación de variables haciendo que éstas pertenezcan a la clase cuando su ámbito debería ser exclusivamente el método que las usa.
- Refused bequest (rechazo del legado), cuando una subclase 'rechaza' métodos o propiedades heredadas, atentando directamente contra uno de los principales pilares de la OOP.
- Alternative Classes with Different Interfaces (clases alternativas con distintos interfaces) indica la ausencia de interfaces comunes entre clases similares.
- The change preventers (los impedidores de cambios)
- Divergent Change (cambio divergente), que hace que sean implementadas dentro de la misma clase funcionalidades sin ninguna relación entre ellas, lo que sugiere extraerlas a una nueva clase.
- Shotgun surgery (cirujía de escopeta), ocurre cuando un cambio en una clase implica modificar varias clases relacionadas.
- Parallel Inheritance Hierarchies (jerarquías de herencia paralelas), paralelismo que aparece cuando cada vez que se crea una instancia de una clase es necesario crear una instancia de otra clase, evitable uniendo ambas en una úncia clase final.
- The Dispensables (los prescindibles), pistas aportadas por porciones de código innecesarias que podrían y deberían ser eliminadas:
- Lazy class (clase holgazana), una clase sin apenas responsabilidades que hay que dotar de sentido, o bien eliminar.
- Data class (clase de datos), cuando una clase sólo se utiliza para almacenar datos, pero no dispone de métodos asociados a éstos.
- Duplicate code (código duplicado), presencia de código duplicado que dificulta enormemente el mantenimiento.
- Dead code (código muerto), aparición de código que no se utiliza, probablemente procedente de versiones anteriores, prototipos o pruebas.
- Speculative generality (generalización especulativa), ocurre cuando un código intenta solucionar problemas más allá de sus necesidades actuales.
- The couplers (Los emparejadores), son code smells que alertan sobre problemas de acoplamiento componentes, a veces excesivo y otras demasiado escaso.
- Features envy (envidia de características), que aparece cuando existe un método de una clase que utiliza extensivamente métodos de otra clase y podría sugerir la necesidad de moverlo a ésta.
- Inappropriate intimacy (intimidad inapropiada), ocurre cuando dos clases de conocen demasiado y usan con demasiada confianza, y a veces de forma inapropiada, sus miembros (en la acepción POO del término ;-))
- Message Chains (cadenas de mensajes), aroma desprendido por código que realiza una cadena de llamadas a métodos de clases distintas utilizando como parámetros el retorno de las llamadas anteriores, como
A.getB().getC().getD().getTheNeededData()
, que dejan entrever un acoplamiento excesivo de la primera clase con la última. - Middle man (intermediario), que cuestiona la necesidad de tener clases cuyo único objetivo es actuar de intermediaria entre otras dos clases.
Aunque agrupadas bajo otros criterios, existe una interesante relación de code smells y la refactorización a aplicar en cada caso, que ayuda a determinar las acciones correctivas oportunas una vez se haya comprobado que hay algo que no va bien.
Y ahora, ¿piensas que tu código no huele a nada? ;-P
Publicado en: http://www.variablenotfound.com/.
Publicado por José M. Aguilar a las 10:12 p. m.
Etiquetas: buenas prácticas, desarrollo, programación

Y aunque pueda parecer similar a FxCop, Microsoft Source Analysis for C# se centra en el análisis de código fuente y no en ensamblados, lo que hace que pueda afinar mucho más en las reglas de codificación.
Incluye sobre 200 buenas prácticas, cubriendo aspectos como:
- Layout (disposición) de elementos, instrucciones, expresiones y consultas
- Ubicación de llaves, paréntesis, corchetes, etc.
- Espaciado alrededor de palabras clave y operadores
- Espaciado entre líneas
- Ubicación de parámetros en llamadas y declaraciones de métodos
- Ordenación de elementos de una clase
- Formateo de documentación de elementos y archivos
- Nombrado de campos y variables
- Uso de tipos integrados
- Uso de modificadores de acceso
- Contenidos permitidos en archivos
- Texto de depuración

Tras su descarga e instalación, que puede realizarse desde esta dirección, la herramienta se integra en Visual Studio 2005 y 2008, aunque también puede utilizarse desde la línea de comandos o MSBuild.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 12:49 p. m.
Etiquetas: buenas prácticas, c#, desarrollo, herramientas, vs2008