September 2007 - Posts
Ya visité algunas características nuevas de VB.NET 9, que viene integrado en el Visual Studio 2008. Estoy usando una beta 2. El artículo anterior es:
Lo nuevo en Visual Basic.NET (Parte 1)
El ejemplo de hoy está para descargarse en VbNetNew2.zip
Usa la misma clase Supplier. Investiguemos dos nuevos métodos del tipo extension methods:
Imports System.Runtime.CompilerServices
Module Extensions
<Extension()> _
Public Function Append(Of T)(ByVal a As T(), ByVal b As T()) As List(Of T)
Dim result = New List(Of T)(a)
result.AddRange(b)
Return result
End Function
<Extension()> _
Public Sub Show(ByVal suppliers As IEnumerable(Of Supplier))
For Each supplier As Supplier In suppliers
Console.WriteLine("Supplier {0} {1} ({2})", supplier.SupplierId, supplier.Name, supplier.City)
Next
End Sub
End Module
Recordemos: los extension methods son métodos que se pueden adosar a instancias de clases ya existentes, justamente, extendiendo su funcionalidad.
En VB.NET, se escriben como métodos de un módulo, marcados con el atributo <Extension()> . El primer parámetro indica la clase a la cual adosarle este método.
En el método Append de arriba, lo nuevo es que se puede usar generics. Es un método que se aplica a todo arreglo, de cualquier tipo T. Y devuelve una lista tipada del mismo T.
El método Show, se usa adosa a todo IEnumerable de Suppliers, no importa la clase concreta que implemente esa interfaz.
Esto demuestra la flexibilidad del concepto de extension methods.
En el Main, se usa tanto el Append, para unir dos listas, como el Show, para mostrar una lista de proveedores:
1 Sub Main()
2 Dim suppliers() As Supplier = New Supplier() { _
3 New Supplier(1) With {.Name = "John Madison", .City = "Washington"}, _
4 New Supplier(2) With {.Name = "Ann Arbor", .City = "Ohio"}, _
5 New Supplier(3) With {.Name = "Don Johnson", .City = "Miami"}, _
6 New Supplier(4) With {.Name = "Bill Clinton", .City = "Washington"} _
7 }
8
9 Dim suppliers2() As Supplier = New Supplier() { _
10 New Supplier(5) With {.Name = "John Smith", .City = "New Jersey"}, _
11 New Supplier(6) With {.Name = "Mary Dupinsky", .City = "Los Angeles"}, _
12 New Supplier(7) With {.Name = "Ronald Reagan", .City = "Washington"}, _
13 New Supplier(8) With {.Name = "Brad Shapiro", .City = "Dallas"} _
14 }
15
16 Dim allsuppliers = suppliers.Append(suppliers2)
17
18 Console.WriteLine("All Suppliers")
19 allsuppliers.Show()
20
21 Dim suppliers3 = allsuppliers.FindAll(Function(s) s.City = "Washington")
22
23 Console.WriteLine()
24 Console.WriteLine("Suppliers In Washington")
25
26 suppliers3.Show()
27
28 Dim suppliers4 = From s In suppliers _
29 Where s.City = "Washington" _
30 Select s
31
32 Console.WriteLine()
33 Console.WriteLine("Suppliers In Washington")
34
35 suppliers4.Show()
36
37 Console.ReadLine()
38 End Sub
39
En la línea 21, se aplica un método de extensión ya definido en LINQ, para aplicar ubicar todos los elementos de una lista que cumplan con un predicado. Aparece el nuevo Function para especificar un predicado ahí mismo.
En la línea 28, se ve que podemos usar también LINQ directamente en el lenguaje. Como en el caso examinado en otro post con C Sharp, el from va primero, y al final, el select. Esto le facilita a la IDE que pueda determinar qué tido de datos puede seleccionar, habiéndole primero indicado cuál es el tipo que se recupera.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
En post anteriores:
Lo nuevo de CSharp (Parte 1)
Lo nuevo de CSharp (Parte 2)
había escrito sobre algunas características nuevas que aparecen en el CSharp 3, que vendrá integrado en el Visual Studio 2008, y que estoy probando en la beta 2 de esta IDE.
Veamos ahora un ejemplo en VB.NET 9 (como se lo llama), disponible en VbNetNew1.zip
Es un simple programa de consola, que utiliza una clase Supplier:
Public Class Supplier
Private mSupplierId As Integer
Private mName As String
Private mCity As String
Public Sub New(ByVal id As Integer)
mSupplierId = id
End Sub
Public Property SupplierId() As Integer
Get
Return mSupplierId
End Get
Set(ByVal value As Integer)
mSupplierId = value
End Set
End Property
Public Property Name() As String
Get
Return mName
End Get
Set(ByVal value As String)
mName = value
End Set
End Property
Public Property City() As String
Get
Return mCity
End Get
Set(ByVal value As String)
mCity = value
End Set
End Property
End Class
No encontré que el nuevo VB.NET tuviera propiedades automáticas, como en el nuevo CSharp. Así que en este ejemplo, el código de la clase no muestra nada nuevo.
En la rutina Main:
1 Sub Main()
2 Dim suppliers() As Supplier = New Supplier() { _
3 New Supplier(1) With {.Name = "John Madison", .City = "Washington"}, _
4 New Supplier(2) With {.Name = "Ann Arbor", .City = "Ohio"}, _
5 New Supplier(3) With {.Name = "Don Johnson", .City = "Miami"} _
6 }
7
8 For Each supplier As Supplier In suppliers
9 Console.WriteLine("{0} {1}", supplier.SupplierId, supplier.Name)
10 Next
11
12 Dim c = New With {.Name = "John Doe", .City = "Everywhere"}
13
14 Console.WriteLine("{0} lives in {1}", c.Name, c.City)
15
16 For Each supplier As Supplier In suppliers
17 supplier.Print()
18 Next
19
20 Console.ReadLine()
21 End Sub
22
comienza a aparecer algunas características nuevas. En la línea 2, vemos la creación e inicialización de un arreglo, con el uso de llaves. En la línea 3, 4 y 5, aparece la creación de objetos con uso de With. Esto permite, llamar a un constructor, como Supplier(1), y luego completar las propiedades, con punto más el nombre de la propiedad.
En la línea 12, podemos crear una variable con un tipo implícito. Vemos que el new no refiere a ninguna clase en particular, pero en el with se colocan las propiedades que va a tener ese objeto.
Automáticamente, el IDE "arma" el tipo de la variable c, y me permite usar c.Name y c.City en la línea 14. La IDE hace inferencia de tipo.
En la línea 17, Print no es un método de la clase Supplier. Está definido en otra "clase":
Imports System.Runtime.CompilerServices
Module Extensions
<Extension()> _
Public Sub Print(ByVal supplier As Supplier)
Console.WriteLine("Supplier {0} {1}", supplier.SupplierId, supplier.Name)
End Sub
End Module
Es un extension method: un método que se puede definir para las instancias de una clase, fuera de la misma definición de la clase. En CSharp, vimos que se usaban clases estáticas. Acá se utilizan módulos. Para que el método fuera de extensión, en CSharp se colocaba un this adornando al primer parámetro. Acá se usa el atributo <Extension()> al método, un atributo que está en el namespace System.Runtime.CompilerServices.
Ya vendrá otro post con otras características.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Gracias a una iniciativa del bueno de Omar del valle Rodriguez comencé a escribir un ejemplo con AjGenesis, para generar código .NET que use NHibernate (ver Generando código para NHibernate (Parte 1)). Ya tenía ejemplos con y sin NHibernate (ver ....) pero esta vez, Omar pidió un modelo con herencia. Pueden descargar esta primera versión como AjOmar-v1.0.zip desde los ejemplos del proyecto en Codeplex.
Usé la versión 0.5 de AjGenesis, a descargar desde CodePlex. Si Ud. tiene la versión 0.4.3, debería funcionar sobre este ejemplo, pero no la he probado.
El modelo
Ahora tengo una primera versión de lo pedido por Omar. El "leit-motiv" del AjGenesis, es basarse en un modelo definible libremente, y desde ahí, ir generando código, scripts de base de datos, artefactos de textos, archivos de solución, proyectos, lo que uno quiera.
En el modelo Projects\AjOmar\Project.xml he definido:
<Project>
<Name>AjOmar</Name>
<Description>Example AjOmar for (N)Hibernate</Description>
<Prefix>AjOm</Prefix>
<Domain>com.ajomar</Domain>
<CompanyName>ajomar</CompanyName>
<Model>
<Entities>
<Entity Source="Entities/Client.xml"/>
<Entity Source="Entities/Company.xml"/>
<Entity Source="Entities/User.xml"/>
</Entities>
</Model>
</Project>
Para entender algo más sobre el modelo y la generación, ver Hello World con AjGenesis.
En el modelo coloqué tres entidades: Client, Company, User, que es lo que pedía Omar. En Client, tengo:
<Entity>
<Name>Client</Name>
<Description>Client Entity</Description>
<SetName>Clients</SetName>
<Descriptor>Client</Descriptor>
<SetDescriptor>Clients</SetDescriptor>
<SqlTable>clients</SqlTable>
<Properties>
<Property>
<Name>Id</Name>
<Type>Id</Type>
</Property>
<Property>
<Name>PhysicalAddress</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
<Property>
<Name>ContactEmail</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
<Property>
<Name>RegisterDate</Name>
<Type>DateTime</Type>
<SqlType>datetime</SqlType>
</Property>
<Property>
<Name>Active</Name>
<Type>Boolean</Type>
<SqlType>bit</SqlType>
</Property>
</Properties>
</Entity>
Los campos son los pedidos por Omar, pero todavía con tipos y nombres SQL que elegí yo. Client es la clase madre de Company y de User. En el Company.xml tenemos:
<Entity>
<Name>Company</Name>
<Description>Company Entity</Description>
<SetName>Companies</SetName>
<Descriptor>Company</Descriptor>
<SetDescriptor>Companies</SetDescriptor>
<SqlTable>companies</SqlTable>
<Inherits>Client</Inherits>
<Properties>
<Property>
<Name>CompanyName</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
<Property>
<Name>ContactName</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
</Properties>
</Entity>
Para los que vieron anteriores ejemplos, lo nuevo es el <Inherits>Client</Inherits>. Esto indica que esta entidad "hereda" de la entidad Client, en el dominio a generar. Lo mismo puse en User.xml:
<Entity>
<Name>User</Name>
<Description>User Entity</Description>
<SetName>Users</SetName>
<Descriptor>User</Descriptor>
<SetDescriptor>Users</SetDescriptor>
<SqlTable>users</SqlTable>
<Inherits>Client</Inherits>
<Properties>
<Property>
<Name>FirstName</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
<Property>
<Name>LastName</Name>
<Type>Text</Type>
<SqlType>varchar(200)</SqlType>
</Property>
</Properties>
</Entity>
En el subdirectorio Projects\AjOmar\Technologies, encontramos los archivos CSharp2Nh.xml y VbNet2Nh.xml. Veamos el primero:
<Technology>
<Programming>
<Dialect>CSharp2Nh</Dialect>
</Programming>
<Database>
<Dialect>MsSql</Dialect>
<Name>AjOmar</Name>
<Username>sa</Username>
<Prefix>ajom_</Prefix>
<Host>(local)</Host>
</Database>
<NHibernate>
<Dialect>NHibernate.Dialect.MsSql2000Dialect</Dialect>
</NHibernate>
</Technology>
Vean que ahí se establece el usuario y contraseña para usar contra un SQL Server. Si quieren, lo modifican acá. Sino, como alternativa, pueden luego modificar el web.config de la solución generada. El ejemplo también instala base, pero esto es opcional: genera un archivo con los scripts de creación, que Uds. puede correr en cualquier momento manualmente contra el SQL Server que elijan.
Generando el código
Para generar el código, seguir los siguientes pasos:
- Editar los parámetros del SQL Server que están en los archivos de tecnología mostrados arriba
- Ir a la línea de comando.
- Agregar al PATH el directorio \bin del AjGenesis 0.5 bajado
- Ir al directorio AjOmar del ejemplo bajado
- Ejecutar
GenerateProject AjOmar CSharp2Nh
para generar el ejemplo en C Sharp 2.
- Ejecutar
DeployDatabase AjOmar CSharp2Nh
para crear la base en el SQL Server local (en caso de querer hacerlo manualmente ver el código generado para crear la base en Build\AjOmar\CSharp2Nh\Sql)
- Si desea generar el código para VB.NET 2, ejecutar
GenerateProject AjOmar VbNet2Nh
La solución generada
En ambos casos, VB.NET o C Sharp, se generan directorios dentro de Build\AjOmar:
Si vemos el ejemplo C Sharp, queda un archivo de solución en Build\AjOmar\CSharp2Nh\Src, que al abrirlo en el Visual Studio 2005 queda:
Hay varios proyectos de librerías de clases:
- AjNHibernate: contiene las clases para el manejo de las llamadas al NHibernate, como configuración, factoría y obtención de sesiones.
- AjOmar.Data: acá están los DAO (Data Access Objects, aunque son clases con métodos estáticos) y el .hbm de mapeo, codificado como recurso embebido en el proyecto.
- AjOmar.Entities: las entidades del dominio.
- AjOmar.Services: simplemente una capa de servicio delgado.
Veamos como ejemplo la entidad Company en AjOmar.Entities:
/*
* Project AjOmar
* Example AjOmar for (N)Hibernate
* Entity Company
* Company Entity
*
*/
using System;
namespace AjOmar.Entities {
public class Company : Client {
// Private Fields
private string companyName;
private string contactName;
// Default Constructor
public Company() {
}
// Factory Methods
public static Company Create(
string companyname ,
string contactname
) {
Company company;
company = new Company();
company.CompanyName = companyname;
company.ContactName = contactname;
return company;
}
// Public Properties
public string CompanyName
{
get {
return companyName;
}
set {
companyName = value;
}
}
public string ContactName
{
get {
return contactName;
}
set {
contactName = value;
}
}
}
}
Gracias al ejemplo inicial que me envió Omar, pude generar un .hbm con subentidades:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="AjOmar.Entities.Client, AjOmar.Entities" table="ajom_clients">
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="PhysicalAddress" type="String" name="PhysicalAddress" length="255"/>
<property column="ContactEmail" type="String" name="ContactEmail" length="255"/>
<property column="RegisterDate" type="DateTime" name="RegisterDate" length="255"/>
<property column="Active" type="Boolean" name="Active" length="255"/>
<joined-subclass name="AjOmar.Entities.Company, AjOmar.Entities" table="ajom_companies">
<key column="Id" />
<property column="CompanyName" type="String" name="CompanyName" length="255"/>
<property column="ContactName" type="String" name="ContactName" length="255"/>
</joined-subclass>
<joined-subclass name="AjOmar.Entities.User, AjOmar.Entities" table="ajom_users">
<key column="Id" />
<property column="FirstName" type="String" name="FirstName" length="255"/>
<property column="LastName" type="String" name="LastName" length="255"/>
</joined-subclass>
</class>
</hibernate-mapping>
Hay un proyecto web AjOmar.WebClient, con una página inicial, un tema, un master page, y un directorio con páginas de navegación y actualización del modelo:
Desde el menú de administración pueden actualizarse los datos:
No es un "qué bruto, qué página", pero algo funciona... Jeje, lo mío no es el diseño gráfico. :-)
Noten que en web.config, coloqué la configuración del NHibernate:
<nhibernate>
<add
key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"
/>
<add
key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect"
/>
<add
key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"
/>
<add
key="hibernate.connection.connection_string"
value="server=(local);database=AjOmar;uid=sa;pwd="
/>
</nhibernate>
y un HttpModule para manejar la sesión:
<httpModules>
<add type="AjNHibernate.SessionHttpModule, AjNHibernate" name="NHSessionModule" />
</httpModules>
Próximos pasos
Quedan para encarar en la próxima versión
- Utilizar la última versión de NHibernate (con esquema 2.2)
- Ver de poner los tipos SQL que pedía Omar
- Probar contra SQL Server 2005
- Ver de agregar "lazy" en las joined subclasses del mapeo
- Generar para VB.NET 1.x/CSharp 1.x
- Generar con conceptos de Domain-Driven Design (capa Presentation+Application+Domain+Infrastructure).
- Generar código para Java con Hibernate y MySql
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com
El bueno de Rodolfo Finochietti me avisa de este tipo de sitios, busquen en Google GUI Gallery. Uno que aparece es:
http://toastytech.com/guis
Donde encontraran una historia de las distintas interfaces gráficas de usuario que tuvimos en la historia de la computación. Arriba unas "screenshots" de una Xerox Star.
Hay ejemplos de Xerox, Visi On, GEM, Deskmate, GEOS, Desqview/X, AmigaOS, RISC OS, BeOS, QNX, OS/2, Apple, Linux/Unix, Windows, Win Shells, otras GUIs, una "timeline" de GUIS, y enlaces a sitios sobre GUIs.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Les quería avisar de un nuevo curso de robótica, por aquí, en Buenos Aires, dictado por Roberto Dhios.
Pueden ver más detalle y costos en:
http://www.clubdeprogramadores.com/cursos/CursoMuestra.php?Id=326
Extraído de ahí:
La robótica móvil es un área de la ingeniería que se caracteriza, entre otras cosas, por ser multidisciplinaria. Para construir un robot, por pequeño que sea, es necesario aplicar conocimientos de electrónica, programación y mecánica.
Este curso pretende dar una visión general de todas las áreas de conocimiento relacionadas con el diseño de pequeños robots móviles autónomos sin profundizar en ninguna pero obteniendo una visión global.
El curso está pensado con un enfoque eminentemente práctico dejando los desarrollos matemáticos complejos y las demostraciones para los cursos donde se tratan estos temas en profundidad.
En el desarrollo del curso se intentará que las clases sean participativas y se fomentará el trabajo en equipo en las diferentes actividades que se organicen.
Roberto es un profesional en sistemas con mas de 20 años de experiencia, principalmente dedicado al desarrollo de sistemas embebidos. Ha trabajado en proyectos de automatización, control automático, electro-medicina y comunicaciones.
Pueden visitar su sitio:
http://www.roboticar.com.ar/
y el de Jorge Dhios
http://www.bairesrobotics.com.ar/
para aprender más sobre robótica. Vean los enlaces:
RobotIA
Robotica educativa
Rasti
CAFR
Todo Robot
Robotic Spot
RoboLiga
Robotica en Mendoza
Azteca
Johnny 5
www.miprimerrobot.com.ar
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
El bueno de Augusto Alvarez (una especie de jugador de la NBA, que me dobla en altura, y que cumple con el "mindset" "no sea canuto"...;-), me alcanza este enlace:
http://interviewhelper.blogspot.com/
un blog con preguntas y respuestas de entrevistas para informáticos, donde encontramos:
SQL Server Interview Questions
.NET Interview Questions
JAVA Interview Questions
Database
SQL Server
Software Testing
Basic .NET Framework
SAP Interview Questions
ABAP Interview Questions
C++ interview Questions
C Interview Questions
PHP Interview Questions
ASP.net Interview Questions
Java Interview Questions
Aparte de preguntas técnicas, me gustaron:
Points to remember
Salary Negotiation
Resume Preparation Guidelines
Yo agregaría, parafraseando a Ortega: "yo soy yo y mi blog". Gente, vayan preparando blogs, de lo que estudian, conocen, hacen. "Su blog es su CV" puede ser algo exagerado, pero no mucho.
Debe ser leído:
Cómo la revolución de la web 2.0 y los blogs abre la posibilidad de nuevas prácticas de reclutamiento y formación profesional
Curioso:
The Bloggers Business School
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Ayer, viernes 14, comencé mi segunda semana sabática del año: una semana sin cursos, visitas a clientes, dedicada a estudiar, investigar, leer, escribir, pensar, organizar y crear. Una semana donde espero plantearme algunos temas, iniciar algunos trabajos, para luego ir completándolos durante el año. Es una semana "larga": abarca hasta el lunes 24 inclusive.
Siempre me ha parecido importante dedicar un periodo a alejarse de las actividades cotidianas, y sumergirse con tiempo disponible en tópicos que nos interesan. Recomiendo que vayan pensando, si todavía no lo hacen, en tener este tipo de periodos en su año.
Dentro del ámbito del desarrollo de software, mi plan es, durante esta semana:
- Programar funcionalidad de AjGenesis, escribir ejemplos y postear sobre temas del proyecto.
- Revisar el estado de otros proyectos de código abierto que tengo en carpeta.
- Estudiar el estado actual de algunos frameworks y tecnologías, de Java, .NET, Smalltalk y más.
- Pasar en limpio y postear sobre la última reunión de Smalltalking.
- Mejorar ejemplos y material que presento en mis cursos.
- Investigar sobre concurrencia y grid computing, para un proyecto que se inicia.
Me gusta tener semanas sabáticas, y a veces, quisiera reorientar todas mis actividades para que el resto de mis semanas sean de este tipo.
Para actividades fuera del desarrollo de software, ver mi semana sabática en mi blog no técnico.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Sigo "jugando" con algunas características del nuevo CSharp, que puedo probar desde el Beta 2 de Visual Studio 2008. En el anterior post Lo nuevo de C Sharp (Parte 1) había escrito sobre Extension Methods. Sigamos en este ejemplo, explorando alguna de las posibilidades.
El ejemplo de este "post" pueden bajarlo desde CSharpNew2.zip
Encontraran que el ejemplo de consola, tiene al comienzo:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
Esto no tuve que escribirlo, sino que el Visual Studio ya lo coloca al comienzo de la clase. LINQ es como que ya viene.
Recordemos que los Extension Methods se escriben dentro de clases estáticas.
En la clase estática Extensions, hay dos métodos
1 static class Extensions
2 {
3 public static List<T> Append<T>(this List