Subscribirse al RSS Feed
(CodeAR)

codeAR es un Agregador de Noticias que intenta capturar los blogs de los desarrolladores Argentinos. Para saber que piensan, que están desarrollando, que están leyendo, que están imaginando.
Si tenes un blog sobre desarrollo de sistemas o relacionado al tema, te invitamos a participar de este Planeta, envianos un mail con la dirección de tu blog.

July 30, 2010

Arte efímero

desde aurelianito por aurelianito (noreply@blogger.com)

Marcador al agua sobre pizarrón blanco
July 30, 2010

Feliz dia del Administrador de Sistemas

Hoy, como todos los años, el último viernes de Julio se festeja el día del administrador de sistemas. Feliz día para todo los amigos del rubro ! ©2010 Un Sanjuanino en Rio Cuarto. All Rights Reserved..


July 29, 2010

Aplicación de Port Knocking

El uso del concepto de Port Knocking es muy útil para los que son paranoicos ó requieren de tener un alta seguridad en los routers ó servidores. Un explicativo de como realizarlo con MikroTik está disponible en MKE Solutions en la sección artículos. Ahora tenemos una aplicación realizada por  Greg Sowell que permite enviar diferentes paquetes en [...]


July 29, 2010

Estrenos de Cine 2010

desde Hackelare por Iuga

Inception

(Ver Trailer)

Dom Cobb (DiCaprio) es el mejor del mundo en el arte de la extracción: apropiarse de los secretos del subconsciente justo en el momento en que la mente de la víctima es más vulnerable: durante el sueño. El extraño don de Cobb le ha convertido en un hombre muy codiciado en el mundo del espionaje corporativo, pero también le ha condenado a ser un fugitivo internacional costándole todo lo que alguna vez ha querido. Ahora tiene una oportunidad de redimirse y volver a tener la vida normal que anhela, pero para ello él y su equipo tendrán que realizar lo contrario a lo que realizan habitualmente: la incepción, que consiste en implantar una idea en el subconsciente en lugar de sustraerla….

Sucker Punch

(Ver Trailer)

Ambientada en los años 50, ‘Sucker Punch’ gira en torno a una chica que es internada por su padrastro en una institución psiquiátrica, donde tienen la intención de practicarle la lobotomía en cinco días. Mientras permanece allí, ella se imagina una realidad alternativa que la aleja de su dramática situación real. En ese mundo de fantasía, la joven comienza a preparar su fuga, para lo cual necesita robar cinco objetos que la ayudarán a escapar antes de que un hombre malvado la desvirgue

Tron Legacy

(Ver Trailer)

Secuela del clásico de culto de 1982, que vuelve a contar con Jeff Bridges en el papel de Kevin Flynn

The Expendables

(Ver Trailer)

Después de años de corrupción, asesinato de rehenes y de traición de la política exterior, Estados Unidos, con la ayuda de otras naciones, arma en secreto un equipo con su personal militar más capacitado para finalmente derrocar a un dictador que ha causado estragos en algún país de América latina, durante más de 20 años. La misión principal del equipo es terminar con la vida del dictador, pero recibiendo poca ayuda de las naciones, que tratan de mantener el secreto de la misión. Después de darse cuenta de esto, se basan en sus propias fuentes para combatir no sólo el ejército del dictador, sino también a los gobiernos que los respaldan.

Centurion

(Ver Trailer)

Bretaña, año 117 de nuestra era. Un grupo de soldados romanos lucha por salvar sus vidas después de que la legión se vea mermada tras un ataque de la guerrilla local. Los valientes soldados componían nada menos que la 9ª legión, la más legendaria por su dureza, pero las cosas no salieron como planeaban. Ahora tan solo quedan unos cuentos supervivientes, liderados por Quintus Dias (Michael Fassbender) y su misión es resistir hasta conseguir llegar a la frontera, antes que las hordas guerreras de la fiera y vengativa Etain (Olga Kurylenko) acabe con todos ellos.

Harry Potter and the Deathly Hallows

(Ver Trailer)

Primera parte de la adaptación al cine del último libro de la saga Harry Potter, “Harry Potter y las Reliquias de la Muerte”. La historia continúa desde el punto en el que terminó “El príncipe mestizo”: Una tarea casi imposible cae sobre los hombros de Harry: deberá encontrar y destruir los horrocruxes restantes para dar fin al reinado de Lord Voldemort…

The Last Airbender

(Ver Trailer)

Fantasía épica que adapta la serie “Avatar: The Last Airbender”. Aire, Agua, Tierra y Fuego son cuatro naciones enlazadas por el destino cuando la Nación del Fuego declara una brutal guerra a las demás Naciones. Tras un siglo de lucha, no parece haber esperanza de que algo pueda cambiar este entorno de destrucción.

The Sorcerer’s Apprentice

(Ver Trailer)

Balthazar Blake (Nicolas Cage) es un alto hechicero en el Manhattan de nuestros días que intenta defender la ciudad de su archi-enemigo Maxim Horvath (Alfed Molina). Balthazar no puede hacerlo solo, así que recluta -a su pesar- a Dave Stutler (Jay Baruchel), un chico normal pero que oculta un gran potencial, para que sea su protegido dándole un curso de inmersión en el arte de la antigua magia.


July 29, 2010

Ok, me ganaste Spring (por ahora)

desde Mundo Java por Pablo Frias (noreply@blogger.com)
No sé porqué dejé pasar tanto tiempo. Pero ahora me doy cuenta de que pasó algo importante y no pude estar a tiempo. Grrrrrrrr!! (me da bastante rabia....)

La cosa es que aunque un poco tarde, pero estoy decidido a aprender Spring. Cada vez ofrece más prestaciones, cada vez se usa más. Ya no basta con Struts o Struts 2. Pero lo bueno es que me encuentro motivado. Y esta motivación ha vuelto a la vida este blog!!

Así que lo más probable es que esté posteando cosas relacionadas a este "pequeño" framework.

Saludos
July 28, 2010

Introducción a IoC y DI: otro ejemplo web

desde Angel "Java" Lopez por lopez

Sigamos explorando Inversion of Control y Dependency Injection, dentro del Proyecto Hogwarts. Anteriores posts del tema:

Introducción a IoC y DI: Un ejemplo web
Introducción a IoC y DI: Hello, world flexible

Simplemente para ver otro ejemplo sencillo de programación con interfaces, veamos de agregar un objeto presenter en un ejemplo web. La forma de llenar la página con datos (dar datos a la vista) y la forma de atender comandos del usuario (un botón de aceptar en un formulario para grabar lo ingresado), lo separamos del "code behind" y le asignamos esa responsabilidad a un objeto Presenter:

Notemos que la vista que va a consumir no es una clase concreta, sino una interfaz. Eso nos va a permitir cambiar la vista, o probar a nuestro objeto presenter sin necesidad de darle una página web para operar, sino algún otro objeto más adecuado para nuestras pruebas.
El código de este ejemplo se puede bajar de PresenterExample.zip.

Esta vez, la solución tiene dos proyectos de librería de clases, y una aplicación web:

 

El primer proyecto se basa en nuestro anterior ejemplo: contiene el servicio, ayudado por repositorios.

El segundo proyecto define la interfaz que tiene que cumplir todas las vistas de lista de Customers, ICustomerListView:

namespace Customers.Presenters {  public interface ICustomerListView
   {
      IEnumerable<Customer> Customers { set; }
   }
}

El Presenter consume tanto a la vista como al servicio:

 public class CustomerPresenter  {
    private ICustomerService service;
    private ICustomerListView view;
    public CustomerPresenter(ICustomerService service, ICustomerListView view)
    {
       this.service = service;
       this.view = view;
    }
    public void Initialize()
    {
      this.view.Customers = this.service.GetCustomers();
    }
 }

Vean que el servicio también lo ve como una interfaz. Finalmente, el código de la página arma todos los objetos y se "conecta" con el Presenter para que éste la maneje. En nuestro ejemplo, sólo para llenar sus datos:

  public partial class _Default : System.Web.UI.Page, ICustomerListView
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                CustomerPresenter presenter = new CustomerPresenter(new CustomerService(new InMemoryCustomerRepository()), this);
                presenter.Initialize();
            }
        }
        public IEnumerable<Customer> Customers
        {
            set
            {
                this.grdCustomers.DataSource = value;
                this.grdCustomers.DataBind();
            }
        }
    }

Este ejemplo es un paso más hacia el tema de esta serie de post: Inversion of Control y Dependency Injection, términos que tenemos que definir. Pero, como en el post anterior, hay algo para mejorar: en el código de la página decidimos qué objetos concretos conectamos en un grafo de objetos colaboradores. Lo que quisiéramos mejorar es la definición de esos objetos concretos: tratar de no tenerlo de alguna forma fijo en el código, sino tener alguna otra manera de instanciarlos y de cambiar cuáles son las clases concretas a usar.

Este material será incluido en el curso online del Southworks Professional Improvement Program en http://pip.southworks.net/ (pueden ir ahí para ir explorando el curso de TDD ya publicado).

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

July 27, 2010

Imperdibles (Julio 26th – Julio 27th)

desde Hipertextos [desde La Plata] por Christian Silva

Algunos vínculos interesantes que voy coleccionando en Delicious

  • Relación entre lectura y nuevas tecnologías (Piglia) – La enseñanza de la literatura está conectada con un saber que es el del desciframiento de signos. Por eso, la literatura tiene un grado de densidad o de complejidad tal que si uno aprende a enfrentarlos, luego es muy apto para leer con mucha mayor soltura los lenguajes políticos, económicos, o cualquiera que sean los otros usos del lenguaje. Incluso el desciframiento de los signos todavía sigue siendo la clave de cualquiera de los modos nuevos y de las nuevas tecnologías (frente a las cuales, desde luego, uno tiene que tener una actitud auspiciosa).
  • Son boleta (Guillermo Saccomanno) – No creo que muchos escritores se le animen a una clase de escuela media del conurbano. Pero que los hay, los hay. Es que no es sencillo encarar las aulas de la marginalidad, esos pibes que vienen de pobreza, violencia, droga, alcohol. A algunos les cuesta expresarse con algo más que un ininteligible fraseo primal. Estos son los pibes a quienes los docentes deben transmitirle el amor a la lectura. Pero, ¿cómo transmitir ese amor cuando no se lo siente? Más de una vez en los colegios planteo que los docentes no leen. “Los adolescentes, querrá decir”, me quiso enmendar una maestra. “No, le dije. Entendió bien: dije los docentes.” La mujer, como varias de sus colegas, me miró con odio. “A ver, cuéntenme qué leyeron anoche”, les pregunto. Silencio.
  • 50 Tecnicas y plugins en Javascript y jQuery – A través de noupe.com hemos visto esta fantástica recopilación de técnicas en Javascript y jQuery listos para utilizar en Diseño de páginas web. Esta recopilación cuenta con Snippets, librerías, artículos, herramientas y recursos listos para usar que mejorarán la experiencia de usuario en tu Sitio Web ofreciendo un mayor dinamismo, productividad y presencia.
  • How To Mix Your Own Music – In this episode, Gigafide will show you free resources that will help you mix your own customized music.
  • Desde Buenos Aires se crea el Movimiento de Diseño Inclusivo – Con el principal propósito de generar y hacer cumplir algunas buenas prácticas relacionadas con el diseño de un sitio web o de un producto interactivo, se creó en Buenos Aires, Argentina, el Movimiento de Diseño Inclusivo. Marcando así un importante precedente frente a los esfuerzos, que se vienen realizando en algunos países, de acercar la tecnología a un mayor número usuarios y reducir la brecha digital.
  • El arte tecnológico del Pompidou se despliega en Buenos Aires – Es increíble, pero cierto, y hay que aprovecharlo: por primera vez se muestran en Argentina obras de algunos grandes artistas, claves en cuanto al arte realizado con nuevas tecnologías en el siglo XX.
July 27, 2010

Nueva fecha de entrenamiento MikroTik RouterOS

Debido a que cupo del curso programado para el 9 al 13 de agosto ya se ha completado, se ha abierto una nueva jornada de entrenamiento y capacitación de MikroTik RouterOS del 16 al 20 de agosto con las mismas opciones que el anterior. El entrenamiento se impartirá con el temario para la preparación de [...]


July 26, 2010

Emulador de PlayStation para Android

desde Hackelare por Iuga

La verdad que vi este video en UbuntuLife y me quede bastante sorprendido con las capacidades de android


July 26, 2010

Imperdibles (Julio 23rd – Julio 26th)

desde Hipertextos [desde La Plata] por Christian Silva

Algunos vínculos interesantes que voy coleccionando en Delicious

  • How To Use CSS3 Media Queries To Create a Mobile Version of Your Website – CSS3 continues to both excite and frustrate web designers and developers. We are excited about the possibilities that CSS3 brings, and the problems it will solve, but also frustrated by the lack of support in Internet Explorer 8. This article will demonstrate a technique that uses part of CSS3 that is also unsupported by Internet Explorer 8. However, it doesn’t matter as one of the most useful places for this module is somewhere that does have a lot of support — small devices such as the iPhone, and Android devices.
  • Chrome Experiments: galería Javascript de vanguardia – Los estándares web están teniendo una transformación, como es el caso de HTML5 vs Flash, es por de más cierto que HTML5 tiene mucho potencial para establecerse como estándar oficial y que quizás cuando eso pase Flash tendrá que haber encontrado un mercado de nicho propio. Mientras eso sucede los invito a visitar esta interesante galería de Javascript de alto nivel, Chrome Experiment que tienen como objetivo recoger los mejor de Javascript y de estándares abiertos como HTML5, Canvas, SVG.
  • Gephi, Free Graph Exploration Software – I do not often get to play with networks, yet I find them fascinating and full of knowledge gathering potential. The data visualization works of Moritz Stefaner, Jer Thorp, and Mark Lombardi captivate me. I am intrigued by relationships, how we perceive them, and how we can understand them. Gephi, the "Open Graph Viz Platform", is not just for the hobbiest node nerd. It is a hardcore, professional tool for network researchers and other smarty pants. If you know the difference between Yifan Hu and Fruchterman Reingold, then you can use this tool effectively. But you do not need to be rich, as the software is completely free to download and use.
  • Gephi – Graph exploration and manipulation software. Gephi is an interactive visualization and exploration platform for all kinds of networks and complex systems, dynamic and hierarchical graphs.
  • Top 10 Ways to Tweak Your WordPress Theme – The vast selection of free and commercial themes is what makes WordPress so attractive. But the theme is often only a starting point for further customizations. Web developers and DIY website owners like to start with a great theme and tweak it to perfectly suit their (or their client’s) needs.
  • Daniel Johnston – Si tecleas Daniel Johnston en cualquier buscador de Internet accederás a cientos de webs sobre el más increíble fenómeno pop y artista visual “outsider” americano. La carrera de Johnston se extiende a lo largo de más de 3 décadas. Durante sus últimos veinticinco años ha sacado a la luz sus desgarradoras historias de amor no correspondido, contratiempos cósmicos, y tormentos existenciales para un cada vez mayor número de fans. Todo esto le ha hecho ser aclamado y comparado con el blues-man Robert Johnson y la leyenda del country Hank Williams.
  • Letras de película – Presentación audiovisual en torno al comportamiento expresivo de la tipografía a lo largo de la historia del cine. Mediante la revisión de las apariciones de la letra en forma de luz, principalmente en las secuencias de créditos cinematográficos, se explora la evolución de las corrientes artísticas contemporáneas y la influencia de estas en el diseño gráfico. Particularmente en el diseño tipográfico y su integración en las piezas de títulos cinematográficos contribuyendo a los estereotipos de los géneros en el cine.
July 25, 2010

Researchers Warn of Geotagging Dangers - Are You Concerned?

netFlux
Researchers Warn of Geotagging Dangers - Are You Concerned? - http://www.readwriteweb.com/archive...
July 25, 2010

Un diario hecho 100% con Youtube

netFlux
Un diario hecho 100% con Youtube - http://www.amphibia.com.ar/un-diar...
July 25, 2010

Handy Ruby one liners by David Thomas

netFlux
Handy Ruby one liners by David Thomas - http://axonflux.com/handy-r...
July 24, 2010

Diccionario bidireccional en Python

desde Vientos de Libertad por Juanjo

Bidirectional dict o Injective mapping es una estructura de datos muy útil.

Por lo general cuando usamos un diccionario o tabla hash, tenemos un valor asociado a una clave:

>>> d = {1:'uno', 2:'dos'}
>>> d[1]
'uno'

Pero algunas veces también resulta útil indexar por el valor y obtener la clave.

>>> d['uno']
1

Por ejemplo, en un programa tengo un archivo de configuración que contiene un diccionario dónde las claves son strings de 3 caracteres representando un edificio (‘SFE’, ‘GDP’, …) y las claves números de puerto (5007, 5008, …). En algunas partes el programa requiere conocer el edificio a partir del número de puerto y en otras el puerto a partir del edificio.

¿Cómo obtenemos este comportamiento?

Pregunté en StackOverflow y si bien me apuntaron a una implementación, la solución que más me gustó fue esta:

>>> d.update( dict((d[k], k) for k in d))

Así se ve d ahora: {1: 'uno', 2: 'dos', 'uno': 1, 'dos': 2}

Y podemos efectivamente indexar por clave o por valor:

>>> d[1]

'uno'

>>> d['uno']

1

Advertencias

No se pueden usar objetos mutables

En los diccionarios de Python solo objetos inmutables pueden ser clave de diccionarios, por lo tanto, en nuestro diccionario bidireccional, tanto las claves como los valores deberán serlo.

Actualizaciones

Otra limitación de este enfoque son las desincronizaciones que puede sufrir al modificar el bidict luego de realizar la transformación; hay que tener cuidado!

  • Luego de agregar un nuevo elemento debemos volver a ejecutar la línea mágica para que cree la entrada inversa.
  • No podemos agregar un par que tenga como clave algo que ya existía como valor o que tenga como valor algo que ya existía como clave.
  • Si borramos una entrada, hay que también borrar su inversa.

Conclusión personal

Como les contaba antes, yo estaba usando el diccionario original en un archivo de configuración, por lo que no toco la estructura de datos durante la ejecución del programa, así que esta solución compacta y elegante… como dijo el filósofo: me viene al pelo!

Espero a alguien más le sirva.

July 23, 2010

Varias nuevas de MikroTik

Hoy se ha anunciado una gran noticia para el mundo del wireless y es que MikroTik ha incorporado un nuevo protocolo wireless llamado Nv2 que está basado en TDMA, información que está disponible en MKE Solutions. Además de la noticia anterior, que por cierto es muy importante ya que abre un nuevo escenario en la [...]


July 23, 2010

Talk: Taint Mode for Python via a Library (video)

desde Vientos de Libertad por Juanjo

OWASP have just published the video of my talk in OWASP App Sec Research 2010 in Stockholm.

First talk in English ever.
Fue mi primer charla en inglés.



Slides and text are also avaliable.

July 23, 2010

Proyecto Hogwarts: Sitio en línea, Southworks Professional Improvement Program

desde Angel "Java" Lopez por lopez

Después de haber publicado varios posts de avance sobre el Proyecto Hogwarts, finalmente pudimos hacer pública la versión beta (yo imagino que en beta constante) del material del curso de introducción a TDD, como parte del como parte del Southworks Professional Improvement Program. Pueden registrarse gratuitamente en:

http://pip.southworks.net/

Tienen lecciones en línea, con código, videos, ejercicios, explicaciones de conceptos, bibliografía, enlaces. Como comentaba al principio, para mí está en beta constante. Si hay algo que no se entiende o no queda claro, tienen un foro para plantear dudas. Si tienen una sugerencia, también puede dejarla ahí.

Está soportado en la plataforma open source de Moodle, con PHP y MySQL.

Tenemos otro curso en desarrollo: Inversion of Control y Dependency Injection (van a ver ahí que está dado de alta, incompleto). Próximos cursos a incluir: Mocks (como una continuación de TDD), principios S.O.L.I.D.

Ayer jueves 22, los buenos de @MartinSalias y @sebarenzi dictaron un taller presencial de TDD con máquinas acá en Buenos Aires, basado en el material del curso. La idea es que cada curso también tiene contrapartida de cursos, talleres presenciales. Esperamos redondear la idea, para organizar cómo darlos en otros lugares. Por ejemplo, ahora estamos probando que un instructor de una empresa, dicte el curso de introducción a TDD en su equipo.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

July 22, 2010

Imperdibles (Julio 20th – Julio 22nd)

desde Hipertextos [desde La Plata] por Christian Silva

Algunos vínculos interesantes que voy coleccionando en Delicious

  • Convocatoria de presentaciones para "Diseño interactivo para todos: usable y accesible" – El evento se realizará el día 29 de octubre de 2010 en la Universidad Tecnológica Nacional en el marco del Festival de Diseño de Buenos Aires. Lo organiza la Asociación de Profesionales de la Usabilidad (UPA Argentina), la Asociación de Diseño de Interacción (IXDA Buenos Aires), Internet Society (ISOC Argentina) y profesionales independientes. El objetivo es difundir nuevas ideas y metodologías relacionadas con diseño inclusivo, que permitan una mejor integración de todos, independientemente de sus capacidades, conocimientos y posibilidades económicas.
  • Dancing Typography – In this experiment/new visual effect, the letters from a lyric of a popular song – Never Gonna Give You Up — are repositioned to compose the images of its singer — Rick Astley — dancing in fluid motion. Take a look of it here. It is an evolution of an experiment I did a month ago where text compose a static image. In this case, I modified the algorithm to achieve the smooth motion by making the letters move the less as possible to be adapted to the next frame in the video.
  • La educación entre la cultura hacker – Es interesante ver cómo ciertos emergentes sociales reaparecen luego de décadas de olvido. Si bien el mundo ha cambiado mucho, sobre todo al advertir que “en los 60 se quería cambiar el mundo” y hoy “se quiere cambiar el auto”, también resurgen movimientos remedializados con ideales que encontraron su camino de propagación entre generaciones. Este es el caso del punk.
  • 6 razones por las que una empresa debería motivar sus trabajadores para estar presente en redes sociales – Una empresa debe motivar el uso de redes sociales por sus trabajadores. Para sacar el máximo provecho tiene que encontrar vías para aprovechar las posibles ventajas que puede obtener a través de su plantilla.
  • 7 maneras más de visualizar Twitter – Como continuación a 20 Maneras distintas de visualizar Twitter tenía pendiente esta entrada con 7 maneras más para añadir a la lista, que sin duda, seguirá creciendo con el paso del tiempo y la creación de nuevas herramientas de visualización y/o monitorización de Twitter.
July 22, 2010

Pilas y colas en Python

desde Vientos de Libertad por Juanjo

La forma más directa de tener pilas y colas en Python es usando listas, una de las poderosas estructuras de datos que vienen con el lenguaje.

Una pila es una estructura de datos secuencial en la que el último elemento insertado es el primero en retirarse (LIFO) y puede implementarse directamente con los métodos append y pop.

Una operación común en las pilas es top, que devuelve el elemento en el tope de la pila, pero sin quitarlo; esta operación se puede emular indexando por -1.

>>> pila = [6,7,8]
>>> pila.append(9)
>>> pila
[6, 7, 8, 9]
>>> pila.pop()
9
>>> pila.pop()
8
>>> pila[-1]
7

Implementar una cola requiere algo más. En las colas, a diferencia de las pilas, el primer valor insertado es el primero en quitarse (FIFO).

Un primer intento es implementarla con append y pop(0) que obtiene el primer elemento (o con insert insertando al principio y pop). Pero las listas de Python, si bien están optimizadas para insertar al final y quitar del final, no lo están para insertar al principio o quitar del principio. La solución es utilizar collections.deque que si está implementada con estas operaciones optimizadas.

>>> from collections import deque
>>> cola = deque([1,2,3])
>>> cola.append(4)
>>> cola
deque([1, 2, 3, 4])
>>> cola.popleft()
1
>>> cola.popleft()
2
>>> cola
deque([3, 4])

July 21, 2010

RT @newsycombinator: Flipboard: A social magazine for your iPad http://bit.ly/ayKo4P

netFlux
RT @newsycombinator: Flipboard: A social magazine for your iPad http://www.flipboard.com/
July 21, 2010

Introducción a IoC y DI: Un ejemplo web

desde Angel "Java" Lopez por lopez

Sigo posteando material de lo que se está produciendo en el Proyecto Hogwarts. Esta vez, sobre el tema de Inversion of Control y Dependency Injection. Dentro de poco, estará disponible un sitio en línea con un curso de TDD, y otros en construcción. En el anterior post:

Introducción a IoC, DI: Hello, world flexible

había planteado un ejemplo simple, veamos alguno apenas más complejo. Y veamos de plantearla con interfaces.

Lo que vimos en ese ejemplo es que:

- Un objeto A puede necesitar la ayuda de otro objeto B, pero conociendo la interface, sin ligarse a una clase en concreto

- Al objeto A alguien le provee el objeto B

Lo que vamos explorar ahora, es un ejemplo donde al objeto A le damos alguna vez un objeto B1, y otras veces el objeto B2. Para que no sea sólo una aplicación de consola, veamos de levantar el alcance, y hagamos un ejemplo web.

Sea una simple aplicación web, donde tenemos una página para presionar dos enlaces para leer y mostrar los clientes:

La idea es tener DOS implementaciones de una interface que se haga responsable de implementar un repositorio de clientes (digamos, una lista de clientes). Si presionamos en el primer enlace, se usará un repositorio en memoria:

 

Si presionamos en el segundo enlace, usaremos el repositorio de base de datos:

Pueden bajarse el ejemplo desde mi Skydrive CustomersExample.zip. Contiene una solución .NET y los scripts para crear la base de datos en SQL Server.

En este ejemplo, vamos a usar un servicio que se ayudará de un repositorio para conseguir los objetos que necesita la presentación. Veamos cómo se implementó.

Tenemos entonces, un servicio que necesita consumir un repositorio. Como en el ejemplo de Hello, world, el objeto consumidor no referencia a una clase concreta, sino a una interfaz:

Esa interfaz está definida como:

namespace Customers
{
 public interface ICustomerRepository
 {
 Customer GetById(int id);
 void Insert(Customer customer);
 void Update(Customer customer);
 void Delete(Customer customer);
 IQueryable<Customer> GetAll();
 }
}

Luego tenemos dos implementaciones de esta interfaz:

Una es la implementación del repositorio en memoria, parte del código:

 public class InMemoryCustomerRepository : ICustomerRepository
 {
 private IList<Customer> customers = new List<Customer>();
 public InMemoryCustomerRepository()
 {
 for (int k = 1; k <= 10; k++)
 {
 customers.Add(new Customer()
 {
 Id = k,
 Name = string.Format("Customer {0}", k),
 Address = string.Format("Address {0}", k),
 Notes = string.Format("Notes {0}", k)
 });
 }
 }
//....
 }

La otra implementación de la interfaz accede a una base de datos, código parcial:

 public class DatabaseCustomerRepository : ICustomerRepository
 {
 private string connectionstring;
 public DatabaseCustomerRepository(string connectionstring)
 {
 this.connectionstring = connectionstring;
 }
 public Customer GetById(int id)
 {
 SqlConnection conn = new SqlConnection(this.connectionstring);
 SqlCommand cmd = new SqlCommand("select Id, Name, Address, Notes from Customer where Id = @Id", conn);
 cmd.Parameters.Add(new SqlParameter("@Id", id));
 conn.Open();
 SqlDataReader reader = cmd.ExecuteReader();
 Customer customer = null;
 if (reader.Read())
 customer = this.GetCustomer(reader);
 reader.Close();
 conn.Close();
 return customer;
 }
///...
 }

Lo que se usó en este ejemplo es que al crear el objeto servicio le pasamos en los argumentos del constructor cuál implementación de repositorio queremos usar. Así, en la acción de ver por memoria, el código es:

protected void lnkMemory_Click(object sender, EventArgs e)
 {
 CustomerService service = new CustomerService(new InMemoryCustomerRepository());
 this.grdCustomers.DataSource = service.GetCustomers();
 this.grdCustomers.DataBind();
 }

La otra opción es por base de datos:

 protected void lnkData_Click(object sender, EventArgs e)
 {
 CustomerService service = new CustomerService(new DatabaseCustomerRepository("server=.\SQLEXPRESS;database=Customers;integrated security=true"));
 this.grdCustomers.DataSource = service.GetCustomers();
 this.grdCustomers.DataBind();
 }

Notemos que al servicio le "inyectamos" su ayudante, esta vez usando un parámetro de su constructor (en el ejemplo Hello World, habiamos inyectado usando propiedades).

Esto nos muestra:

- La capacidad de abstraer lo que necesitamos (la interfaz de repositorio) de cómo lo implementamos
- Nos permite cambiar la implementación y que todo siga funcionando igual

Acá usamos las DOS implementaciones al mismo tiempo. Pero es más común usar solo una.

Podríamos haber codificado el acceso a los clientes en el propio servicio. Pero lo separamos para:

- Poder mejorar el servicio (p.ej., en temas de seguridad) separando esas otras funcionalidades de la más simple de recuperación de clientes.

- Poder cambiar el ayudante, sin necesidad de cambiar el servicio y sus consumidores.

Hasta podemos ir armando una aplicación de demostración, usando durante semanas la implementación del repositorio en memoria. Mientras, en un desarrollo ágil, vamos iterando, mejorando nuestro dominio, SIN tener una base de datos por debajo. El cliente final va viendo nuestro avance, y solamente cuando tenemos algo más definido, vamos definiendo la base de datos subyacente y operando sobre ella.

También, este "approach" nos permite cambiar la implementación de la base de datos. Ahora, la implementación va contra SQL Server, pero si mañana necesitamos ir contra Oracle, cambiamos la implementación, y ni servicio y otros se enteran de ese cambio.

Y por último, veremos, más adelante en otro curso (Mocks con TDD), que podemos usar implementaciones de repositorios que no vayan contra la base, para alivianar nuestros tests del servicio.

Y todo, por haber programado contra la interfaz, y segregado responsabilidades.

Tenemos que avanzar en un sentido: no queremos tener que cambiar el código de creación del servicio, para que una vez use una implementación del repositorio (en memoria) y otra vez use una distinta (en base de datos). Quisiéramos que el cambiar esa relación NO IMPLIQUE tener que cambiar el código. Esa es la idea que subyace en lo que tenemos que definir en los próximos post de este tema: qué es Inversion of Control, qué es Dependency Injection, y contenedores de IoC.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

July 20, 2010

sex.py

desde Bunker Blog por Bunker Blog (escuelaint@gmail.com)
Necesitaba limpiar una carpeta llena de archivos .txt, una Maildir en realidad, repletos de encabezados de rebotes y explicaciones de los majordomos y mailer-daemons. Es decir, recorrer esta marabunta de archivos, y volcar las direcciones de correo que allí figuraran.

Y me encontré con este tremendo programa, sex.py

http://dandies.org/files/d4674f917898c54c537378d5fb7cad6e-46.html

Actualización: Antes de ejecutarlo, suministrarle una librería necesaria:
sudo aptitude install python-dnspython

Ejemplo:

python sex.py -sr Maildir/ rebotados.txt

Es prácticamente una aspiradora de direcciones de correos, y puede ser apuntado hacia cualquier cosa, una url, un archivo, una carpeta, comparando con servidores dns por direcciones de correo validas, ordenando, quitando duplicados, volcando resultados a otro archivo, tremendo.

Y por cierto, una vez extraidas las direcciones de correo rebotadas, quería compararlas con mi mailing-list, y crear un nuevo archivo de direcciones validas:

for i in `cat mailing-list.txt`; do echo $i|grep -v -f rebotados.txt; done > limpitos.new

Ojo que este for puede demorarse bastante. Chequear en otra terminal mediante un

tail -f limpitos.new

Listo, ahora me aseguro de no sobreexigir el smtp con rebotes innecesarios (que siempre son la mayoría). Además, es de unos amigos, y no quiero abusarme.
July 20, 2010

Imperdibles (Julio 14th – Julio 19th)

desde Hipertextos [desde La Plata] por Christian Silva

Algunos vínculos interesantes que voy coleccionando en Delicious

  • 40 Excellent Examples of Single Page Websites – Several months ago, we published a list showcasing 40 Inspiring Single Page Websites, and as we had a lot of comments and everybody really loved the post, we decided to gather a new list, showing some new and fresh examples to inspire you. Single page websites are still a big hit this year, and we see new examples of this trend popping up everyday. To put this list together I was able to find many great examples on One Page Love, which is a great source for those who like to stay tuned in on the single page world. So enjoy the list…
  • Editor WYSIWYG HTML5 gratuito – Cuando escribí hace tiempo la entrada con los editores WYSIWYG gratuitos todavía HTML5 no era demasiado cercano, pero hoy en día, y con el furor que esta causando en la comunidad de desarrolladores, no podía pasar demasiado tiempo hasta que aparezca un editor que aproveche estas mejoras. Y es asi que nace Aloha Editor.
  • CSS Type Set – We hope that you have found CSS Type Set useful. We are always looking for ways to improve the tool, so we’ve set up this section to help us (as well as yourselves) keep track of feature requests. Through the News section, we will be announcing when new versions are out or are upcoming out and what will be included in them. We encourage you to comment — though you are still free to email us — with any feedback.
  • Programación en la Educación Escolar – Existe actualmente un consenso general dentro de la comunidad educativa mundial sobre la necesidad de superar el tipo de enseñanza basada en la transmisión de contenidos para apuntarle en su lugar al desarrollo de capacidades. Investigaciones y estudios recientes proponen diversos conjuntos de habilidades que la educación debe fomentar para que los estudiantes puedan tener éxito en el mundo digital y globalizado en el que van a vivir [1]. Este planteamiento exige, sin dilaciones, implementar estrategias que contribuyan efectivamente en el desarrollo de esas habilidades planteadas como fundamentales para la educación en el Siglo XXI
  • Videojuegos y comunicación: hacia el lenguaje del videojuego – Revista incluida en la base de datos ISOC del CSIC y en LATINDEX (Sistema regional de información en línea para revistas científicas de América Latina, El Caribe, España, y Portugal). Número 7
July 20, 2010

Google Voice Recognition en el Motorola Milestone

desde Desarrollando Ideas por The Doctor

Como algunos de ustedes (sino todos) pueden haber leído en Twitter, desde el viernes soy el feliz poseedor de un Motorola Milestone, un celular con Android al que le tenía ganas hace rato.

Obviamente, de entrada empecé a instalar y probar aplicaciones, entre las que se encontraban algunas de reconocimiento de voz. El problema fue que cuando quería utilizar estas últimas, me salía un aviso diciendo que no tenía instalado Google Voice Recognition. Después de investigar un poco, descubrí que esta utilidad no está disponible en ciertos países, como Alemania, Italia y Argentina (ni por defecto en el celular, ni mediante el market).  Por suerte no me tomó mucho tiempo encontrar un foro donde daban la solución.

Lo único que hay que hacer es instalar desde el market una app llamada “Speak n’ send“, la cual al momento de intentar utilizarla nos dirá que no tenemos instalado Google Voice Recognition, luego de lo cual nos dará dos opciones: instalarlo desde el market (cosa que no podemos hacer) o descargarlo directo desde la página. Seleecionamos la segunda opción y tendremos instalado el reconocedor de voz de Google, que funciona muy bien :)

Espero que les haya servido este “tip” para poder activar el reconocimiento de voz en sus Milestone.

Casi me olvido; una vez que tengan instalaco el voice recognition, no dejen de probar la app TalkToMe Keyboard, les puede facilitar mucho la vida ^^


July 19, 2010

Un experimento sobre tecnología y transparencia gubernamental

desde Millón de Monos por manuel

La transparencia gubernamental es un tema de moda. Fue uno de los pilares de la innovadora campaña electoral de Barack Obama, donde la tecnología jugó un papel central. Una de las formas en las que Obama materializó estas promesas de transparencia es el proyecto data.gov, donde se brinda acceso a más de 40.000 conjuntos de datos “crudos” generados por agencias del gobierno federal. Hay estadísticas de accidentes aéreos o la lista de quienes visitaron la Casa Blanca en los últimos meses. Lo destacable de esta iniciativa, que está siendo implementada por otros países, es que los datos se publican en formatos legibles por computadoras. Esto es, la información puede ser usada en herramientas de análisis de datos (una planilla de cálculo, por ejemplo) o usados para construir mashups, aplicaciones que combinan varias fuentes de información. Un buen ejemplo es OilMoney, que muestra los aportes monetarios que hacen las compañías petroleras a las campañas electorales.

En Argentina, el panorama es bastante desolador. No hay ley de acceso a la información pública; apenas tenemos el decreto 1172/03 que tiene bastantes problemas en su aplicación (ver acá o acá). Algunos organismos que publican información en la web, lo hacen en formatos ilegibles para las máquinas. Una imagen que contiene un documento impreso escaneado, como las declaraciones juradas de los funcionarios municipales de Bahía Blanca, es invisible para los buscadores. Esto también es un problema para la transparencia: en esta época de sobreabundancia de información, en la que los filtros son imprescindibles para encontrar lo que se busca, los documentos deben ser publicados en formatos apropiados.

Por suerte, están apareciendo iniciativas particulares en la dirección correcta. La ONG Poder Ciudadano desarrolló dos herramientas interesantes. Una base de datos sobre las pautas publicitarias oficiales y el sitio Dinero y Política. Son un recurso para facilitar la búsqueda y el acceso a datos provenientes de organismos estatales, que no se destacan por producir sitios web de calidad.

Gasto Público Bahiense

La Municipalidad de Bahía Blanca publica en su sitio web las órdenes de compra adjudicadas a proveedores. La herramienta de consulta dista del ideal, pero afortunadamente los datos están publicados en una página web común y silvestre; tienen cierta estructura y por lo tanto, un programa de computadora podrá interpretarlos. La Municipalidad sólo publica los listados de las órdenes de compra: cuándo y a quién se compró tal o cual cosa y a qué repartición fue destinada la compra. Vista así, poco es el aporte de esa información. Entonces, motivado por el interés de probar algunas herramientas informáticas y por la curiosidad acerca de la transparencia y la tecnología, construí Gasto Público Bahiense.

Gasto Público Bahiense facilita el acceso a los datos de compras publicados por la MBB. Permite consultar la lista completa de proveedores y de dependencias municipales, ver las órdenes de compra por repartición o por proveedor, obtener montos totales por período y buscar en el contenido de las órdenes de compra. Puede verse el gasto de la Secretaría de Gobierno en el primer semestre de este año y comparar con el mismo período de la Dirección de Fortalecimiento Humano.

¿Y para qué?

Los gobernantes son responsables de informar sus acciones a los ciudadanos, al fin de cuentas están ahí gracias al voto popular. No pueden desaprovechar la oportunidad que ofrece la web para brindar esa información y mostrarla de manera concisa y clara. Muchas veces, el supuesto costo de este tipo de proyectos es argumento para no implementarlos. La única inversión para construir GPB fue 1 semana de mi tiempo. Tampoco hubo costos de licencias de software; todos los componentes que usé para el desarrollo son software libre o de uso gratuito. A su vez, GPB también es software libre.

Los datos son materia prima para la discusión. Con GPB, tengo la esperanza de que algún bahiense se alarme o se alegre por el dinero invertido en una cosa u otra y que se produzca la discusión que motive acciones transformadoras.

July 19, 2010

Radius Manager v3.8.0 disponible

El día 16 de Julio se ha publicado la versión v3.8.0 del servidor radius de DMA Softlab, Radius Manager. Los archivos de instalación pueden ser descargados si se tiene una suscripción activa y desde el portal. El licenciamiento a partir de ésta versión han cambiado por una nueva política de precios. Los cambios son: FEATURE LIST *** [...]


July 19, 2010

[SOLUTION] Slow framerate with fglrx

desde Buanzolandia por Buanzo

If you run glxinfo and get something around 60FPS (300 in 5 seconds), then you have the vertical sync set to QUALITY.

Open the AMD control center with amdcccle
Go to the “More Settings” item inside the “3D” Page on the left. Change “Wait for vertical refresh” to “Performance”.

Done.

I get this:

buanzo@murray:~$ fgl_glxgears
Using GLX_SGIX_pbuffer
10617 frames in 5.0 seconds = 2123.400 FPS
10988 frames in 5.0 seconds = 2197.600 FPS
10852 frames in 5.0 seconds = 2170.400 FPS

July 17, 2010

Resultado de ALT.NET Hispano VAN sobre NoSQL

desde Angel "Java" Lopez por lopez

Gracias a la gente de la comunidad ALT.NET Hispano, pude participar de una VAN (des-conferencia) sobre NoSQL, hace ya unas semanas, el 22 de mayo pasado. Había escrito adelantando la presentación en:

ALT.NET Hispano VAN sobre NoSQL

Eso fue un sábado, y ya al lunes siguiente, el video de la VAN estuvo publicado, pueden verlo, junto con unas notas, en:

VAN NoSQL

En estas semanas que pasaron, estuve ocupado con mi mudanza, mi consolidación de libros, y sigo ordenando cajas y volúmenes. Y luego alguna gripe. Pero ya pude hacerme algo de tiempo para pasar en limpio el material que utilicé para la VAN.

La presentación la pueden bajar desde mi Skydrive NoSqlVan2010.pptx

Enlaces sobre NoSQL:

Un panorama de NoSQL en el artículo de la Wikipedia.
A brief history of NoSQL interesante que nombrara a Pick, como hice en la presentación.
Java development 2.0: NoSQL una intro de IBM
NoSQL Architecture
MyNoSQL Blog activo sobre NoSQL
NoSQL Databases – Part 1 – Landscape
NoSQL: scaling to size and scaling to complexity
http://nosql-database.org/
What is NoSQL?
The NoSQL alternative
NoSQL Summer, list of papers
BASE: an Acid alternative
Errors in database systems, eventual consistency and the CAP theorem
Scalable Datastores: comparison nosql, and some scalable RDBMS
NoSQL el movimiento en contra de las bases de datos (yo no lo veo en contra, es complementario)
Diff SQL NoSQL
Choosing a NoSQL data store according to your data set
John P. Wood NoSQL posts
Databases: relational vs object vs graph vs document
NoSQL: no necesitas ACID
NoSQL and SQL anti-patterns
Learning NoSQL from Twitters experience

Eventual Consistency:

http://www.allthingsdistributed.com/2008/12/eventually_consistent.html
http://queue.acm.org/detail.cfm?id=1466448
http://devblog.streamy.com/tag/eventual-consistency

Teorema CAP

http://www.julianbrowne.com/article/viewer/brewers-cap-theorem
http://www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf
There is no free lunch with distributed data

Enlaces sobre Google BigTable:

http://labs.google.com/papers/bigtable.html

Enlaces sobre Hypertable:

http://hypertable.org/
Hypertable NoSQL (pdf)

Enlaces sobre Amazon Dynamo:

Amazon Dynamo (original paper)

Enlaces sobre Cassandra:

http://cassandra.apache.org/
http://wiki.apache.org/cassandra/ArticlesAndPresentations
Cassandra by example (Twitter-like one)
http://github.com/ericflo/twissandra
WTF is a supercolumn Cassandra model
Cassandra NoSQL Database
Apache Cassandra
NoSQL Live Dynamo derivatives: Cassandra
http://github.com/suguru/cassandra-webconsole
Tutorial: Getting started with Cassandra
NoSQL in Twitter
Twitter, Facebook and Cassandra, and Open Source
Cassandra and Twitter: interview with Ryan King
(Twitter está reviendo si usa NoSQL o no)

Enlaces sobre Voldemort:

http://project-voldemort.com/
Voldemort design
The NoSQL that must not be named
Product project Voldemort Distributed Database

Enlaces sobre CouchDB:

http://couchdb.apache.org
CouchDB Introduction
CouchDB Overview

Enlaces sobre SimpleDB

http://awsdocs.s3.amazonaws.com/SDB/latest/sdb-gsg.pdf
http://awsdocs.s3.amazonaws.com/SDB/latest/sdb-dg.pdf

Enlaces sobre Redis

http://code.google.com/p/redis/
Twitter alike example
Add NoSQL Data Storage to your PHP development with Redis

Nombré en algún momento a Memcached:

http://memcached.org/

Sobre NoSQL tipo graph

InfoQ: Graph NoSQL Neo4j
Graph databases: A special case of document databases

Otros temas relacionados:

Scalability of the Hadoop distributed file system
MapReduce Hadoop algorithms in academic papers

Enlaces sobre MongoDB:

NoSQL with MongoDB, NoRM, and ASP.NET, part 1
NoSQL with MongoDB, NoRM, and ASP.NET, part 2
Master Slave in MongoDB
Choosing a non relational database: Why we migrated from MySQL to MongoDb
MongoHQ - The cloud-based hosted database solution for MongoDB.
http://github.com/azamsharp/SKOOL Ejemplo MongoDB, VS2010, ASP.NET MVC, TDD, BDD
On distributed consistency

El ejemplo que mostré de MongoDB (instalar, levantar el servidor, consumirlo desde .NET con un driver) siguió la línea explicada en el primer artículo de Ted Neward:

Going NoSQL with MongoDB
Going NoSQL with MongoDB (Part 2)
Going NoSQL with MongoDB (Part 3)

Código de ejemplo, ASP.NET MVC con MongoDB (apenas unas páginas) (ver de referenciar al driver que deje compilado en Libraries)

MongoDbMvcApplication1.zip

Para esos ejemplos tuve que descargar:

http://github.com/samus/mongodb-csharp
http://www.mongodb.org/display/DOCS/Downloads

Mis enlaces sobre los temas tratados:

http://delicious.com/ajlopez/mysql
http://delicious.com/ajlopez/mongodb
http://delicious.com/ajlopez/cassandra
http://delicious.com/ajlopez/couchdb

En especial, buscar presentaciones, tutoriales, ejemplos y “reviews”, como en:

http://delicious.com/ajlopez/mysql+tutorial
http://delicious.com/ajlopez/mysql+presentation
http://delicious.com/ajlopez/mysql+example
http://delicious.com/ajlopez/mysql+review

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

July 16, 2010

Asimov sobre Inteligencia Artificial

desde Vientos de Libertad por Juanjo

En El monstruo subatómico, un libro de difusión, Isaac Asimov habla sobre Iteligencia Artificial. Hace más o menos dos años que lo leí y tenía la intención de transcribir el artículo para que esté disponible en Internet. Casi lo olvidé, hasta que hoy alguien lo mandó en la lista de PyAr. Copio y pego a continuación.

Capítulo 11
Más pensamientos acerca del pensamiento

Podés leerlo en http://www.librosmaravillosos.com/elmonstruosubatomico/capitulo11.html
Gracias a Diego Avendaño, Patricio Barros y Antonio Bravo.

July 16, 2010

desde Blog de UsabilidadWeb.com.ar por Carlos (noreply@blogger.com)

Chile, el primer país del mundo en declarar la "neutralidad" en la web


Se trata de una ley que prohíbe la persecución de contenidos, la discriminación de usuarios y obliga a la transparencia en el servicio. Busca proteger a los consumidores

Mientras otros países se preguntan hasta qué punto es buena la neutralidad, el país vecino dio el paso clave y aprobó la primera ley del mundo al respecto. Los proveedores de internet "no podrán interferir, discriminar o entorpecer de cualquier forma contenidos, aplicaciones o servicios", según el periódico chileno Diario Financiero.

La norma chilena, que deriva de una propuesta de 2007, también contempla que los usuarios puedan introducir control parental en su conexión, eligiendo qué contenidos quieren bloquear para tener un sistema protegido a medida.

Es que dentro de la reforma de la Ley General de Telecomunicaciones, la Cámara de Diputados chilena introdujo este principio. Su objetivo es, según el ministro de Transportes, Felipe Morandé, lograr "transparentar los servicios de internet y proteger al usuario".

Quieren impedir que los operadores intervengan en la velocidad de transmisión de datos en función de los contenidos sin permitir escoger al consumidor.

En cuanto a los límites impuestos, la ley recoge el fomento del empleo de medidas de control parental que permiten a los adultos controlar el material al que tienen acceso los menores.

Los Estados Unidos, la Unión Europa y Japón son pioneras en la búsqueda de esta regulación que permite a las compañías cortar o reducir la velocidad de acceso a internet a los usuarios que, por ejemplo, utilicen redes P2P, pero aún no llegan a una legislación.

Diferente a lo que se esperaría, no todas las multinacionales están en contra de esta medida; compañías de servicios en la red como Google, Microsoft y Amazon, así como ciertos operadores de internet, apoyan la normativa.

Con otros términos, Finlandia también garantiza el acceso teórico a la red de todos sus ciudadanos mediante la declaración de la banda ancha como un derecho humano.

Otros gobiernos, como el francés, se han pronunciado en términos contrarios, al afirmar que internet no es un derecho fundamental.

Fuente: infobae.com
July 16, 2010

Armando una aplicación usando AjGenesis (Parte 4)

desde Angel "Java" Lopez por lopez

En este post, generaremos, desde el mismo modelo, archivos de texto para C#, Java, y VB.NET. Anteriores post:

Building An Application Using AjGenesis (Part 1)
Armando una Aplicación usando AjGenesis (Parte 1)
Building An Application Using AjGenesis (Part 2)
Armando una Aplicación usando AjGenesis (Parte 2)
Building an Application Using AjGenesis (Part 3)
Armando una Aplicación usando AjGenesis (Parte 3)

El código de este post puede bajarse desde AppExampleStep04.zip.

Necesitamos los binarios últimos de AjGenesis. Podemos bajarlo desde AjGenesisTrunkBinaries.zip. (el código fuente completo está en el repositorio de AjGenesis en Codeplex). Tienen que agregar el directorio bin al path, para ejecutar los ejemplos de este post.

El ejemplo ahora tiene más estructura:

Projects\AjApp es el folder conteniendo el modelo del ejemplo, en Project.xml:

<Project>
	<Name>AjApp</Name>
	<Description>Building an Application using AjGenesis</Description>
	<Model>
		<Entities>
			<Entity Source="Entities/Customer.xml"/>
			<Entity Source="Entities/Supplier.xml"/>
		</Entities>
	</Model>
</Project>

Podría, entonces, agregar más carpetas, con otros proyectos, si lo necesitara.

En el directorio inicial, tenemos tres comandos:

GenerateCSharp.cmd
GenerateJava.cmd
GenerateVbNet.cmd

Los tres comandos tienen un contenido similar. Por ejemplo, veamos el de GenerateCSharp.cmd:

AjGenesis.Console Projects\AjApp\Project.xml Projects\AjApp\Technologies\CSharp.xml Tasks\Complete.ajg Tasks\Generate.ajg

Notemos que hay dos modelos que se cargan en modelo: Project.xml es como en los anteriores posts, tiene el modelo independiente de la tecnología. El nuevo, CSharp.xml, describe la tecnología a usar:

<Technology>
	<Name>CSharp</Name>
</Technology>

Por ahora, contiene solo el nombre del lenguaje a usar. Podría extender este modelo, en próximos posts, para que contenga la base de datos a usar, el webserver a usar, etc…  Entonces: Project.xml es el modelo abstracto. Technologies\CSharp.xml, Technologies\VbNet.xml, Technologies\Java.xml son los modelos que describen la tecnología a usar. Cada uno de los comandos Generate*.cmd carga el modelo abstracto, Y uno de los tecnológicos.

La tarea Complete.ajg:

' Set Build Directory
if not Project.BuildDirectory then
	Project.BuildDirectory = "Build/${Project.Name}/${Technology.Name}"
end if
FileManager.CreateDirectory(Project.BuildDirectory)
IncludeCode "Tasks/Complete${Technology.Name}.ajg"

Noten el uso de un nuevo truco: incluir el código a ejecutar desde otro archivo, usando un string dinámico. Si Technology.Name == “CSharp”, la tarea de arriba termina ejecutando CompleteCSharp.ajg:

' Some functions
' Name to use for variables
function CSharpVariableName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToLower() & name.Substring(1)
end function
' Name to use for Classes, Properties..
function CSharpName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToUpper() & name.Substring(1)
end function
function CSharpType(type)
	type = type.ToLower()
	
	if type="text" then
		return "string"
	end if
	
	if type="integer" then
		return "int"
	end if
	
	return type
end function
' Set namespace to use in CSharp code
if not Project.CSharp.Namespace then
	Project.CSharp.Namespace = CSharpName(Project.Name)
end if
' Complete Entities
for each Entity in Project.Model.Entities
	' Set the variable name to use for an entity
	if not Entity.CSharp.VariableName then
		Entity.CSharp.VariableName = CSharpVariableName(Entity.Name)
	end if
	
	for each Property in Entity.Properties
		' Set the CSharp to use in each property
		if not Property.CSharp.Type then
			Property.CSharp.Type = CSharpType(Property.Type)
		end if
	end for
end for

Hay tareas escritas similares a la de arriba, para otras tecnologías: CompleteVbNet.ajg, CompleteJava.ajg. Estas tareas completan el modelo en memoria (asignando namespaces, packages, nombres para usar en las variables y propiedaes, el directorio a usar para dejar lo generado, etc…)

La segunda tarea es Generate.ajg:

IncludeCode "Tasks/Generate${Technology.Name}.ajg"

De nuevo, el viejo truco de un include de código dinámico. Esta es la subtarea GenerateCSharp.ajg:

for each Entity in Project.Model.Entities
	TransformerManager.Transform("Templates/CSharp/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.cs", Environment)
end for

Compare, con CompleteJava.ajg:

' Some functions
' Name to use for variables
function JavaVariableName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToLower() & name.Substring(1)
end function
' Name to use for Classes, Properties..
function JavaName(name)
	firstletter = name.Substring(0,1)
	
	return firstletter.ToUpper() & name.Substring(1)
end function
function JavaType(type)
	type = type.ToLower()
	
	if type="text" then
		return "String"
	end if
	
	if type="integer" then
		return "int"
	end if
	
	return type
end function
' Set package to use in Java code
if not Project.Java.Package then
	Project.Java.Package = JavaName(Project.Name).ToLower()
end if
' Complete Entities
for each Entity in Project.Model.Entities
	' Set the variable name to use for an entity
	if not Entity.Java.VariableName then
		Entity.Java.VariableName = JavaVariableName(Entity.Name)
	end if
	
	for each Property in Entity.Properties
		if not Property.Java.VariableName then
			Property.Java.VariableName = JavaVariableName(Property.Name)
		end if
		
		' Set the Java to use in each property
		if not Property.Java.Type then
			Property.Java.Type = JavaType(Property.Type)
		end if
	end for
end for

y el GenerateJava.ajg:

for each Entity in Project.Model.Entities
	TransformerManager.Transform("Templates/Java/EntityClass.tpl", "${Project.BuildDirectory}/${Entity.Name}.java", Environment)
end for

Hay templates para cada tecnología. Ejemplo, este es el EntityClass.tpl para CSharp:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace ${Project.CSharp.Namespace} {
	public class ${Entity.Name}
	{
<#
	for each Property in Entity.Properties
#>
		public ${Property.CSharp.Type} ${Property.Name} { get; set; }
<#
	end for
#>
	}
}

y éste es el de Java EntityClass.tpl:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
package ${Project.Java.Package};
public class ${Entity.Name}
{
<#
	for each Property in Entity.Properties
#>
		private ${Property.Java.Type} ${Property.Java.VariableName};
<#
	end for
	for each Property in Entity.Properties
#>
		public ${Property.Java.Type} get${Property.Name}()
		{
			return this.${Property.Java.VariableName};
		}
		public void set${Property.Name}(${Property.Java.Type} value)
		{
			this.${Property.Java.VariableName} = value;
		}
<#
	end for
#>
}

Ejecutando los tres comandos Generate*.cmds, se crea el directorio Build, con Build\AjApp, Build\AjApp\CSharp, Build\AjApp\Java, Build\AjApp\VbNet, un directorio por el proyecto, con subdirectorios por tecnología.

Veamos el Customer.cs generado:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
namespace AjApp {
	public class Customer
	{
		public string Name { get; set; }
		public string Address { get; set; }
	}
}

El Customer.vb generado:

' Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
Namespace AjApp
	Public Class Customer
		Private mName as String
		Private mAddress as String
		Public Property Name as String
			Get
				return Me.mName
			End Get
			Set(value as String)
				Me.mName = value
			End Value
		End Property		
		Public Property Address as String
			Get
				return Me.mAddress
			End Get
			Set(value as String)
				Me.mAddress = value
			End Value
		End Property		
	End Class
End Namespace

Y el Customer.java generado:

// Entity Class, generated with AjGenesis (http://ajgenesis.codeplex.com)
package ajapp;
public class Customer
{
		private String name;
		private String address;
		public String getName()
		{
			return this.name;
		}
		public void setName(String value)
		{
			this.name = value;
		}
		public String getAddress()
		{
			return this.address;
		}
		public void setAddress(String value)
		{
			this.address = value;
		}
}

Próximos pasos: generar proyectos C# o VB.NET, listos para cargar en Visual Studio, o un proyecto Eclipse para Java.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

July 14, 2010

Imperdibles (Julio 12th – Julio 14th)

desde Hipertextos [desde La Plata] por Christian Silva

Algunos vínculos interesantes que voy coleccionando en Delicious

  • Revisión del libro: "HTML5 for Web Designers" – La verdad es que pensé que el libro sería más largo pero apenas son 100 páginas. En el prólogo, Jeffrey Zeldman comenta que habrá otros libros sobre HTML5, más extensos, más técnicos, más tipo referencia, de 500 páginas o más pero que éste es un libro "real" para quien está día a día creando contenido, desarrollando interfaces.
  • 250 Quick Web Design Tips (Part 1) – As web professionals, we’re always looking for ways to improve our knowledge and skills. Tips, tricks and checklists are often one of the most underused yet potentially useful models of providing great, quick and easy to follow pieces of useful information.
  • Augmented Hyper-Reality: Immersing yourself in (Branded) Infographics – Augmented reality is all the hype know, in particular with the technology ditching the required goggles for cool mobile phones screens, and the like. The short movie below offers a future vision of augmenting your normal vision in the kitchen when commercial branding and infographics have all the freedom, and "above the fold" finally receives a meaning in physical reality.
  • Google Maps Slider – Google Maps has a JavaScript API now in it’s third version. I remember playing with some version of the API back in v2 and thought it was kinda cool but a bit obtuse. For one thing, v3 no longer requires applying for an API key which is nice.
  • Google lanza App Inventor, ahora todos pueden hacer apps para Android – Google ha anunciado en su blog oficial, el lanzamiento en versión beta de una nueva herramienta llamada App Inventor. El objetivo de esta herramienta es facilitar el proceso de creación de aplicaciones para Android, incluso para personas sin conocimientos en programación.
  • MultiBootISOs: Múltiples Live CD de Linux en tu USB – Existen muchas razones por las que un usuario puede llegar a necesitar un Live CD de una distro de Linux. Tal vez esté interesado en cambiar de distro y prefiera dar un vistazo antes de instalarla en su ordenador, o puede que se trate de una emergencia en la que se deben recuperar archivos y/o reparar una sección específica de otro sistema operativo. Sea cual sea el caso, MultiBootISOs permite copiar múltiples imágenes ISO a un pendrive, e iniciar cualquiera de ellas desde allí, como si fuera un Live CD.
  • Canvas en Html5 terminará con Flash de Adobe? – La inclusión de Canvas como una de las etiquetas nativas de Html5 está consiguiendo un gran número de entusiastas implementando Javascript para realizar juegos, vídeo. No es un novedad la implementación del Javascript en internet pero conseguir animaciones con la misma calidad que Flash si es una novedad.
  • 3D High Definition CAVE: Entorno inmersivo 3D para la investigación biomédica – Mientras soñamos con un entorno interactivo para juego al estilo Gamer, una empresa llamada Christie ya ofrece soluciones visuales para aplicaciones 3D/Realidad virtual en la investigación.
  • Firefox 4 Beta 1 – Mientras que la gente de Mozilla continúa mejorando y avanzando el desarrollo de la actual versión 3.6 de su navegador Firefox, al mismo tiempo ha puesto a disponibilidad del público la primera versión beta de lo que será Firefox 4. Como siempre sucede en estos casos, cualquier cosa que esté presente en una beta tan temprana debe ser tomada con pinzas, pero al menos ya es posible tener una idea de qué cambios podría llegar a experimentar el nuevo navegador, especialmente en lo que se refiere a su interfaz.
  • La realidad aumentada llega a la enseñanza – Esta tecnología, que existe desde hace unas dos décadas, hasta hace poco no ha llegado al gran público, primero a través de móviles y ordenadores de sobremesa para el sector del ocio, marketing y geolocalización. Pero ahora, hay un área estratégica que se beneficiará de esta tecnología: la educación. La realidad aumentada está mejorando los materiales didácticos de los alumnos como vemos a continuación.
July 12, 2010

Una pequeña delicia del JavaScript

desde aurelianito por aurelianito (noreply@blogger.com)
Qué valor debería dar el siguiente código:
"aDb".replace("D","$$")

Si pensaron "a$$b" se equivocaron. Da "a$b" (con un solo $).
Para que de el valor que esperaba ("a$$b") hay que hacer este hack:
"aDb".replace("D",function() { return "$$" })

¿Por qué?
Ni idea, pero anda así en rhino y V8, así que debe estar en la especificación.

Happy hacking,
Aureliano
July 11, 2010

Cómo cambiar el puerto de salida por defecto de ssh

desde Vientos de Libertad por Juanjo

Si en una terminal tipeamos:

ssh user@domain.com

el cliente ssh intentará contactarse al puerto 22 de domain.com. Cómo cambiamos ese puerto?

ssh -p 2222 user@domain.com

Pero qué pasa si no tenemos acceso a cambiar ese parámetro? Puede pasarnos esto? Sí, por ejemplo si accedemos a un repositorio cvs por ssh; cuando ejecutamos uno de los comandos cvs, el tunel ssh se hace sin que nos demos cuenta. Si el servidor al que nos queremos conectar escucha en un puerto distinto al por defecto, tenemos un problema.

Hoy no me acordaba cómo se configuraba esto y resultó bastante tedioso buscarlo en Internet (todas las respuestas a la búsqueda era sobre como cambiar el puerto en el que un servidor ssh escucha). Lo dejo aquí para futuras referencias.

La forma de configurar un puerto por defecto para un cliente ssh en GNU/Linux es editando el archivo .ssh/config y añadiendo la línea:

Port NNNN

dónde NNNN es el número de puerto.

July 11, 2010

Hibernate para ñoños IV : Relación one-to-one

desde Hackelare por Iuga

Supongamos por un momento que tenemos dos clases, y ambas se relacionan 1 a 1, pero sabemos que por ambas se relacionan solo con el mismo objeto, es decir la relación es uno a uno, por ejemplo:

En este caso cada “Persona” es única y está relacionada con un Domicilio de forma tal que un Domicilio solo se asocia con una Persona en particular y viceversa. ¿Se entiende?

Para este tipo de casos es que existe la relación one-to-one, así que vamos a ver un poco el XML:

El XML de Persona (Persona.hbm.xml)

Ésta es una asociación de clave primaria y como tal no necesitan una columna extra de la tabla. Si dos filas están relacionadas por la asociación entonces las dos filas de tablas comparten el mismo valor de clave principal. Esa es la esencia de este tipo de relaciones.

<hibernate-mapping>
  <!-- Defino la clase Padre -->
  <class name="modelo.Persona">
    <id column="ID_PERSONA" name="oid" type="integer" unsaved-value="null">
      <generator class="native"/>
    </id>
    <property column="NOMBRE" name="nombre" not-null="true" type="string"/>
    <property column="APELLIDO" name="apellido" not-null="true" type="string"/>
    <property column="EMAIL" name="email" type="string"/>
<!-- Indicamos el tipo de objeto que es y
      el nombre del atributo, solo eso -->
<one-to-one class="modelo.Domicilio" name="domicilio"/>
  </class>
</hibernate-mapping>

Como vemos la relación es muy simple y con una sola línea se lleva a cabo.

<one-to-one class="modelo.Domicilio" name="domicilio"/>

El XML de Domicilio (Domicilio.hbm.xml)

<hibernate-mapping>
<class name="modelo.Domicilio">

	<id column="ID_DOMICILIO" name="id" type="integer">
		<generator class="foreign"/>
	</id>

	<property column="CALLE" name="calle" type="string"/>
	<property column="NUMERO" name="numero" type="integer"/>

	<one-to-one name="persona" class="modelo.Persona" constrained="true"/>

  </class>
</hibernate-mapping>

Bueno esto ya pasa a ser la clave de la relación y tenemos dos puntos principales, primero, el one-to-one está en ambas clases. El segundo y más importante, la clase de menor importancia tiene un generador de id del tipo “foreign”. Que si repasamos los generadores, toma el id de la otra tabla y usa el mismo.

La Clase Persona (Persona.java)

En sí, esta relación no es muy complicada, la clase java queda tal cual lo imaginaríamos con la POO:

public class Persona {

	private int oid;
	private String nombre;
	private String apellido;
	private String email;
	private String cuil;
	private Domicilio domicilio;

    public Persona() {
    }
    public Domicilio getDomicilio() {
        return domicilio;
    }
    public void setDomicilio(Domicilio domicilio) {
        this.domicilio = domicilio;
    }

// ACA SIGUEN LOS GETTERS Y LOS SETTERS ...

July 11, 2010

RT @newsycombinator: Google co-created video of an entire ride of the Trans-Siberian Railway http://bit.ly/aXKTqz

netFlux
RT @newsycombinator: Google co-created video of an entire ride of the Trans-Siberian Railway http://www.google.ru/intl...
July 07, 2010

Hibernate para ñoños III : Herencia

desde Hackelare por Iuga

Hibernate proporciona 4 formas de implementar la herencia, yo me voy a referir a una sola que creo que es la mejor, si te interesa conocer las demás te recomiendo que leas la documentación en el “Capítulo 9 – Mapeo de herencias”.

Tabla por subclase

Supongamos que tenemos una clase Persona (que contiene los datos generales) y heredan 2 un Empleado y un Capacitador, para esta estrategia se necesitarían 3 tablas, una para Persona, otra para Empleado y otra para Capacitador. Las dos tablas de subclase tienen asociaciones de clave principal a la tabla de superclase de modo que en el modelo relacional es realmente una asociación uno-a-uno.

El XML

El XML se vería así, lo documento sobre la marcha así se entiende mejor:

<hibernate-mapping>
 <!-- Defino la clase Padre -->
 <class name="modelo.Persona">
    <id column="ID" name="oid" type="integer" unsaved-value="null">
      <generator class="native"/>
    </id>
    <property column="NOMBRE" name="nombre" not-null="true" type="string"/>
    <property column="APELLIDO" name="apellido" not-null="true" type="string"/>
<!-- …. Sigo con todos los atributos … -->

<!-- AHORA VIENEN LAS HERENCIAS PRIMERO EL EMPLEADO-->
    <joined-subclass name="modelo.Empleado" table="EMPLEADO">
        <!-- Definio la PK de la tabla Empleado que se va a
             emparejar con la de Persona -->
        <key column="LEGAJO"/>

        <!-- Defino las propiedades del Empleado -->
        <property column="FECH_ALTA" name="fechaAlta" not-null="true" type="date"/>
        <property column="FECH_BAJA" name="fechaBaja" type="date"/>

   </joined-subclass> 

<!-- SIGUEN LAS HERENCIAS TURNO DEL CAPACITADOR-->
    <joined-subclass name="modelo.Capacitador" table="CAPACITADOR">
         <key column="LEGAJO"/>
         <!-- Defino las propiedades … -->
   </joined-subclass> 

  </class>
</hibernate-mapping>

Como podemos ver lo que define una clase hija es el tag joined-subclassal que se le indica la tabla destino y el tipo de objeto. Para completar se tiene que definir el key que es el que empareja ambas PK en la base de datos siguiendo con los atributos de la clase, está de más aclarar que tenemos UN solo XML para la clase padre e hijas mientras que tenemos varios .java para cada una de las clases.

La Tabla Persona y la tabla Empleado

Como vemos automáticamente creo las referencias entre tablas y las claves primarias para emparejar la herencia.

Los JAVA

No hay nada raro en esto si sabes algo de herencia básica de java, pero manos a la obra, primero la clase Persona:

public class Persona {
private int oid;
private String nombre;
private String apellido;
private Date fechadeNac;
private TipoDocumento tipoDoc;
private String nroDoc;
private String email;
private String cuil;
private Domicilio domicilio;

public Persona()
{  }

public int getOid() { return oid; }

public void setOid(int id) { this.oid = id; }

public String getApellido() { return apellido; }

public void setApellido(String apellido) { this.apellido = apellido; }

// .... etc etc ...

}

Ahora seguimos por la clase Empleado, la de capacitador la dejo de lado por considerarla similar:

public class Empleado extends Persona
{
private int legajo;
private String rango;
private EstadoEmpleado estado;

public int getLegajo() { return legajo; }

public void setLegajo(int legajo) { this.legajo = legajo; }

// ... etc etc ...

}

Como vemos la herencia no presenta un problema muy grande en hibernate, y en 5 minutos podemos tener marchando este tipo de relación sin tener dolores agudos de cabeza y tendencias suicidas.


July 07, 2010

Estrenando layout y versión de WordPress luego de 2 años

desde Santiago Lobos por admin

Luego de casi 2 años, slobos.com.ar he actualizado la versión de WordPress (tarea que tenia pendiente desde hace rato, pero no encontraba un momento para hacerlo) y de layout, si bien la disposición del diseño es muy similar al que solia utilizar, encontré este que realmente me agradó por lo limpio que es.

Así mismo notarán que integré algunos plugins como el de Facebook, que espero utilicen , twitter para replicar lo que posteo por ese medio en el sitio mientras no estoy frente a una pc y las ultimas fotitos que cargo a mi flickr para que de alguna forma quienes estan lejos y son medios vagos (lo digo por vos ceci) puedan vernos de algún modo.

No mucho más por decir, queda en ustedes darme su apreciación de que les parece.

Besos, abrazos y apretones de mano según corresponda.

July 05, 2010

Errores comúnes en Hibernate (Anexo 1)

desde Hackelare por Iuga

Éste anexo creo que es más importante que todo el manual en sí, ya que lamentablemente, cuando trabajen con hibernate más alla de las clases y los XML, van a trabajar integramente y de la mano con los errores. Sueno pesimista, pero así es, cada error por más chico que sea va a dar una excepción irrecuperable que debemos ser capaces de analizar y de lograr resolver las causas que lo generaron.

Aunque soy algo optimista y espero que cuando se tome más conocimiento de la plataforma, se pueda trabajar sin ver las malditas lineas rojas en el Output.

Este anexo es para no perder tanto tiempo tratando de ver que tenemos mal y dar un par de ideas de que nos puede estar pasando y como solucionarlo de una manera rápida y explicada, o lo que se pueda XD.

java.lang.ClassCastException: org.hibernate.collection.PersistentSet cannot be cast to java.util.HashSet

Tipo de Error: En los .java
A Revisar:
Manejo de colecciones

Ignoro qué significa este error, surge de la utilización de una Collection y puede solucionarse así.

Supongamos que tenemos un Empleado “e” que tiene un Set de capacitaciones, La llamada para usar las capacitaciones con error sería:

HashSet listaCaps = (HashSet)e.getCapacitaciones();

Esto da error así que lo tenemos que reemplazarlo por algo como:

HashSet listaCaps = new HashSet(e.getCapacitaciones());

java.sql.SQLException: Excepción de E/S: The Network Adapter could not establish the connection

Tipo de Error: software – hardware
A Revisar: Base de datos y conexiones físicas

Este error es el más simple de todos, se refiere a que Hibernate no pude abrir la conexión con la base de datos, ¿el motivo? Bueno, o la base de datos está caída/apagada, o bien que no se puede llegar al servidor, Empieza por comprobar el estado del servicio de la BD y luego por ver las conexiones, si es localhost mira los firewalls o antivirus por si cortan la conexión.

Could not parse mapping document from resource xxx. hbm.xml

Tipo de Error: En los xml
A Revisar: Revisar semánticamente y conceptualmente los xml

Este es uno de los errores más comunes a la hora de estar armando los XML de mapeo, en otras palabras significa, que tenemos un error en el XML, pero un error de escritura. Por ejemplo puede ser que nos olvidamos de cerrar un tag “/>”, o que tenemos etiquetas que no existen, o está mal escrito un atributo, etc etc. Tienen que verificar el XML en cuestión línea por línea para ver que tienen semánticamente o conceptualmente mal.

Si depuramos un poco más, podemos ver  un poco más del detalle, por ejemplo:

Error parsing XML: XML InputStream(14) The element type "property"
must be terminated by the matching end-tag "</property>".
 

Por ejemplo, acá vemos que nos olvidamos de cerrar un tag “property”, la solución es ver cada uno y comprobar que estén correctamente cerrados.
Otro error común es:

XML InputStream(37) The content of element type "set" must match
"(meta*,subselect?,cache?,synchronize*,comment?,key,
(element|one-to-many|many-to-many|composite-element|many-to-any)
,loader?,sql-insert?,sql-update?,sql-delete?,sql-delete-all?,filter*)".
 

Vemos que en el xml, en alguno de los Sets, tenemos una tag, que no corresponde, osea tenemos alguna propiedad que no es nativa de los sets y por ello nos da error (Por ejemplo tener declarado un <index column… que es propio de los lists). También puede darse el caso de que nos falte un atributo obligatorio, ver la documentación por si nos estamos olvidando de algo (puede ser que en un list, nos olvidemos de <index column …).


July 05, 2010

Feliz cumpleaños, Fabio

desde Blog de Javier Smaldone por Javier
Fabio

Gracias, mi muchacho, por sorprenderme todos los días. ¡Felices diez años!

Construido con Eco v0.1