Visual Studio 2012 esta a la vuelta de la esquina, para ser el primero en conocer las nuevas capacidades y caracteristicas que este producto contiene visite el sitio oficial:
http://www.visualstudiolaunch.com/vs2012vle/Home
Visual Studio 2012 esta a la vuelta de la esquina, para ser el primero en conocer las nuevas capacidades y caracteristicas que este producto contiene visite el sitio oficial:
http://www.visualstudiolaunch.com/vs2012vle/Home
Hace tiempo Microsoft anuncio la liberacion del codigo fuente del .Net Framework ademas de habilitar el soporte a la depuracion a traves de Visual Studio. A continuacion tratare de enlistar los pasos a realizar para poder configurar dicho soporte en Visual Studio 2010.
Pasos a realizar:
1. Como paso inicial es necesario descargar e instalar Visual Studio 2010 QFE. El cual al ser instalado habilitara las opciones necesarias.
2. Una vez instalado el parche, dentro de Visual Studio 2010, en el Menu Tools -> Options… -> Debugging -> General, deseleccionar la opcion «Enable Just My Code(Managed only)» y seleccionar la opcion «Enable source server support».

3. Por ultimo, es necesario especificar la localicacion de los fuentes, en la opcion Symbols, dentro de Debuggin se selecciona el Servidor, en caso de que no aparezca algun servidor se puede agregar http://referencesource.microsoft.com/symbols, ademas es necesario especificar la ruta para el cache la cual podria ser «C:UserselectrocucarachaSymbols».

Como mejora de la implementacion anterior y estudio de C#, sobretodo en las mejoras incoorporadas en la version 4, me decidi a implementar una nueva version de esta suma. Basicamente los cambios agregados fue la suma por bloques y la suma de ceros, que pienso yo que reduce la cantidad de operaciones, por lo menos unas 19 veces ya que es el bloque de numeros que toma.
Habria que hacer un profundo analisis en revisar la cantidad de codigo usado si este mejora el performance del algoritmo.
StringInteger.cs
...
public static readonly int MAX_ULONG_LENGTH = ulong.MaxValue.ToString().Length;
...
public static StringInteger operator +(StringInteger lhs, StringInteger rhs)
{
//Validaciones
String tmpX = lhs.Container, tmpY = rhs.Container;
ulong x, y, result = 0;
int limit = lhs.Container.Length > rhs.Container.Length ? lhs.Container.Length : rhs.Container.Length;
StringBuilder tmp = new StringBuilder(limit);
do
{
if (IsTheOnlyOperand(ref tmpX, ref tmpY, (int)result))
{
result = 0;
tmp.Insert(0, tmpX + tmpY);
}
else
{
x = RetrieveNextNumber(ref tmpX);
y = RetrieveNextNumber(ref tmpY);
result += x + y;
if (result.ToString().Length == MAX_ULONG_LENGTH)
{
tmp.Insert(0, result.ToString().Substring(1));
result = 1;
}
else
{
tmp.Insert(0, result);
result = 0;
}
}
} while (!(string.IsNullOrEmpty(tmpX) && string.IsNullOrEmpty(tmpY)));
tmp.Insert(0, result);
return new StringInteger(tmp.ToString());
}//operator+
private static bool IsTheOnlyOperand(ref string firstOperand, ref string secondOperand, int carry)
{
bool response = false;
firstOperand = SanitizeStringInput(firstOperand);
secondOperand = SanitizeStringInput(secondOperand);
if (string.IsNullOrEmpty(firstOperand) && !string.IsNullOrEmpty(secondOperand))
{
secondOperand = secondOperand.Substring(0, secondOperand.Length - 1) +
Convert.ToChar(Convert.ToInt32(secondOperand[secondOperand.Length - 1]) + carry);
response = true;
}
else if (string.IsNullOrEmpty(secondOperand) && !string.IsNullOrEmpty(firstOperand))
{
firstOperand = firstOperand.Substring(0, firstOperand.Length - 1) +
Convert.ToChar(Convert.ToInt32(firstOperand[firstOperand.Length - 1]) + carry);
response = true;
}
return response;
}//IsTheOnlyOperand
private static string SanitizeStringInput(string input)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
input = input.TrimStart('0').Trim();
if ("".Equals(input))
{
input = "0";
}
Regex pattern = new Regex(@"^d+$");
if (!pattern.IsMatch(input))
{
throw new ArgumentException("The string value " + input + " is not a integer value");
}
return input;
}//SanitizeStringInput
private static ulong RetrieveNextNumber(ref string stringNumber)
{
int length = stringNumber.Length > MAX_ULONG_LENGTH - 1 ? MAX_ULONG_LENGTH - 1 : stringNumber.Length;
int index = stringNumber.Length - length;
ulong number = length > 0 ? ulong.Parse(stringNumber.Substring(index, length)) : 0;
stringNumber = stringNumber.Remove(index, length);
return number;
}//RetrieveNextNumber
Continuando con la serie de operaciones con numeros grandes, desarrollo la implementacion de una suma de valores contenidos en una cadena, la cual nos puede evitar el desboramiento de bufer. Realizando un ligero analisis encontramos que seguimos limitados por el manejo de indices de arreglos, ya que solo nos permite indexarlos con numeros enteros.
Suma.java
...
private static String sumar(String a, String b) {
//Validaciones
...
int x, y, result = 0;
int limite = a.length() > b.length() ? a.length() : b.length();
char[] tmp = new char[limite + 1];
for (int i = 1; i <= limite; i++){
x = i <= a.length() ? a.charAt(a.length() - i) - '0' : 0;
y = i <= b.length() ? b.charAt(b.length() - i) - '0' : 0;
result += x + y;
tmp[tmp.length - i] = (char) ((result % 10) + '0');
result /= 10;
}
if ( result > 0){
tmp[0] = (char) ((result % 10) + '0');
return String.valueOf(tmp);
}
return String.valueOf(tmp, 1, tmp.length -1);
}
Esta implementacion surgio de la necesidad de implementar una solucion para la multiplicacion de numeros grandes, me refiero a numeros que su resultado causaran el desboramiento de bufer. Mi propuesta se baso en la utilizacion de cadenas para su representacion y manejo de datos, pienso que la solucion que encontre es relativamente buena y quizas tenga muchos puntos a mejorar, lo cual se aceptan sugerencias.
Quiza una de las mayores limitantes que tengo es que el tipo de valor para el indice de los arreglos solo puede ser entero, esto reduce la cantidad de digitos con los cuales puedo trabajar.
Multiplicacion.java
...
private static String multiplicar(String a, String b) {
//Validaciones
...
StringBuffer result = new StringBuffer();
int x = a.length();
int y = b.length();
int i;
int j;
long[][] results = new long[x][y];
List sum = new LinkedList();
long tmp;
for (i = 0; i < x; i++) {
for (j = 0; j < y; j++) {
results[i][j] = (a.charAt(i) - '0') * (b.charAt(j) - '0');
}
}
x--;
y--;
tmp = 0;
while (true) {
j = y;
i = x;
while (j >= 0 && i < a.length()) {
tmp += results[i][j];
i++;
j--;
}
sum.add(tmp % 10);
tmp /= 10;
if (x > 0) {
x--;
} else if (y > 0) {
y--;
} else {
if(tmp > 0){
sum.add(tmp);
}
break;
}
}
Collections.reverse(sum);
for (long l : sum) {
result.append(l);
}
return result.toString();
}

Es un elemento de circuito pasivo. Ha sido descrito como el cuarto elemento de los circuitos pasivos, junto con el capacitor, la resistencia y el inductor; su nombre es una palabra compuesta de memory resistor (resistencia-memoria). Y se cree que puede llevar a la creación de circuitos analógicos que podrían pensar como el cerebro humano.
El memristor fue predicho y descrito en 1971 por Leon Chua, de la Universidad de California, Berkeley. Durante 37 años, fue un dispositivo hipotético, hasta que en abril de 2008, una implementación física fue divulgada por un equipo de investigadores de HP Labs.
El concepto general es una matriz de cables (conductores), entre cada par de conductores de toda la matriz, existen llaves (interruptores) que en primera instancia se encuentran abiertos. Si conectamos una fuente de alimentación entre un par de conductores, al principio esta disposición no almacena o posee información alguna, pero si empezamos a cerrar algunos de estos interruptores podemos programar la matriz para que contenga una cantidad impresionante de información. Se puede abrir o cerrar cualquier interruptor particular, si queremos manejar otro interruptor solo debemos cambiar la conexión de la fuente.
Teóricamente se puede reemplazar 10 transistores con tan solo 1 memristor, las implicancias de esto son abismales, en modo simplista podríamos decir que aumentaríamos en 10 veces la capacidad de todos los circuitos electrónicos, y con ello las PC, celulares, tablets, etc
Los memristors de estado sólido de Williams pueden ser combinados para formar transistores, aunque son mucho más pequeños. Pueden también ser formados como memoria de estado sólido no volátil, que permitiría una mayor densidad de datos que los discos duros con tiempos de acceso similares a la DRAM, sustituyendo ambos componentes. Además, al ser un dispositivo analógico, no solo podría almacenar bits («1″s y «0»s), sino bytes o cadenas de bytes en el mismo espacio, solamente mejorando el dispositivo de control del memristor. Esto ofrece un futuro muy prometedor a largo plazo.
La Transferencia de Estado Representacional o REST, termino publicado por de Roy Fielding (uno de los principales autores de la especificación del protocolo HTTP) en el año 2000, el termino por si solo no define una arquitectura, sino una serie de reglas o restricciones que, cuando son aplicadas al diseño de un sistema, este crea un estilo de arquitectura. Despues de evaluar todos los recursos en la red y tecnologias disponibles para crear sistemas distribuidos y viendo que sin alguna restriccion, era dificil el mantenimiento y desarrollo de aplicaciones; Fielding definio una serie de restricciones definiendo el sistema RESTful:
br>
br>
Estas restricciones no dictan que tipo de tecnologia usar, solo definen como los datos son transferidos entre componentes y sus beneficios. Actualmente contamos con un ejemplo claro de un sistema RESTful funcionando, la Web. Antes que nada debemos puntualizar que significa que la Web sea RESTful, mas particularmente la web estatica, dicha web se apega a las restricciones de RESTful, su infraestructura web actual ofrece sistemas de cacheo, conexion stateless, y unicos hyperlinks para obtener recursos, donde los recursos son todos los documentos disponibles en cada sitio, siendo sus representaciones legibles por el explorador; por lo tanto la web estatica esta construida sobre la arquitectura de REST.
br>
Por otra parte las aplicaciones web dinamicas no siempre son RESTful, porque pueden no cumplir con alguna restriccion.
Para conocer mas acerca de la arquitectura de RESTful necesitamos comprender que son los recursos y sus representaciones, definiendo un recurso como cualquier cosa direccionable sobre la web, entendiendo por direccionable, como aquellos recursos que pueden ser accedidos y trasferidos entre cliente y servidor. Siendo el mapeo de un recurso unico, diferentes peticiones sobre el mismo pueden regresar la misma representacion binaria guardada en el servidor. Por otra parte, la representacion de un recurso, es el estado temporal de la informacion actual que es enviado de vuelta hacia los clientes, por lo tanto una representacion puede tomar varias formas, como una imagen, un archivo de texto, o un stream de XML o JSON, pero todos deben estar disponibles bajo la misma URI.
Durante la vida de cualquier proyecto, incluso en la vida diaria de cada programador, se debería tener como meta que el código creado no genere warnings, ya que dichos warnings fueron creados con el propósito de prevenir futuros errores o evitar confusiones en el código, siempre hay que pensar que el código que escribas hoy, podrá ser leído, modificado, corregido o aumentado el día de mañana por lo que se recomienda prestar atención a cada warning generado.
Por otra parte, y como toda regla, existen excepciones donde por una parte, no se recomienda modificar las reglas impuestas por el compilador ni tampoco el ignorar los warnings de manera tal que con el tiempo se acumulen. Para esos casos aislados, en los cuales necesitamos deshabilitar los warnings creados existe la instrucción #pragma warning que deshabilita la generación de warnings por parte del compilador; a continuación escribo un ejemplo de su uso.
ProgramExample.cs
namespace Electrocucaracha.Warnings
{
class ProgramExample
{
#pragma warning disable
private int unusedDisable;
#pragma warning restore
private int unusedEnable;
static void Main(string[] args)
{
}
}
}
Una propiedad de Hibernate la cual es muy útil y que nos permite visualizar las consultas realizadas sobre la base de datos, es show_sql la cual al activarse nos muestra las consultas HQL realizadas sobre la base de datos.
hibernate.properties
hibernate.show_sql = true
Aunque es una propiedad muy util, muchas veces es necesario conocer los valores que son enviados o recibidos por la base de datos; en muchos de estos servidores es posible configurarlos para generar trazas de las consultas realizadas, el problema de hacerlo de esta forma, es que para una base de datos muy concurrida, aun siendo de desarrollo, resulta complicado encontrar la consulta realizada.
Para obtener los valores enviados podemos utilizar dos frameworks, Log4j y P6Spy.
Cuando utilizamos el framework de Log4j solo se requiere la modificación de su configuración añadiendo una propiedad.
log4j.properties
log4j.logger.org.hibernate.type=trace
Lo cual nos muestra, de forma separada, el tipo y valor de cada parámetro enviado en la consulta.
Output
13:20:43,281 TRACE StringType:153 - binding 'root' to parameter: 1
13:20:43,296 TRACE BooleanType:153 - binding 'true' to parameter: 2
Otra forma y quizás mas elegante de mostrar las consultas que se realizan es utilizando P6Spy, para lo cual es necesario configurarla, con los siguientes pasos:
hibernate.properties
#hibernate.connection.driver_class = com.mysql.jdbc.Driver
hibernate.connection.driver_class = com.p6spy.engine.spy.P6SpyDriver
spy.properties
# mysql Connector/J driver
realdriver=com.mysql.jdbc.Driver
#specifies the appender to use for logging
appender=com.p6spy.engine.logging.appender.Log4jLogger
#the DriverManager class sequentially tries every driver that is
#registered to find the right driver. In some instances, it's possible to
#load up the realdriver before the p6spy driver, in which case your connections
#will not get wrapped as the realdriver will "steal" the connection before
#p6spy sees it. Set the following property to "true" to cause p6spy to
#explicitily deregister the realdrivers
deregisterdrivers=true
Dando como resultado en la siguiente salida:
Output
p6spy - 1275601495062|0|2|statement|select this_.iId as iId7_5_, ... , adeudos6_.mMonto as mMonto2_4_ from tblUsuario this_ left outer join tblTarjeta tarjetas2_ on this_.iId=tarjetas2_.iIdUsuario left outer join tblAbono abonos3_ on tarjetas2_.iId=abonos3_.iIdTarjeta left outer join tblAclaracion aclaracion4_ on tarjetas2_.iId=aclaracion4_.iIdTarjeta left outer join tblEntradasSalidas entradassa5_ on tarjetas2_.iId=entradassa5_.iIdTarjeta left outer join tblAdeudo adeudos6_ on tarjetas2_.iId=adeudos6_.iIdTarjeta where this_.vchUser=? and this_.bActivo=? order by this_.iId asc limit ?|select this_.iId as iId7_5_, ... , adeudos6_.mMonto as mMonto2_4_ from tblUsuario this_ left outer join tblTarjeta tarjetas2_ on this_.iId=tarjetas2_.iIdUsuario left outer join tblAbono abonos3_ on tarjetas2_.iId=abonos3_.iIdTarjeta left outer join tblAclaracion aclaracion4_ on tarjetas2_.iId=aclaracion4_.iIdTarjeta left outer join tblEntradasSalidas entradassa5_ on tarjetas2_.iId=entradassa5_.iIdTarjeta left outer join tblAdeudo adeudos6_ on tarjetas2_.iId=adeudos6_.iIdTarjeta where this_.vchUser='root' and this_.bActivo='true' order by this_.iId asc limit 1
Lo cual muestra la consulta original sin sustituir los valores, y la consulta creada por el framework sustituida por los valores utilizados.
Mas que nada quise postear sobre este patrón de diseño, ya que en un reciente proyecto donde el requerimiento era utilizar RMI, al usarlo me pareció estupendo, ya que en lugar de crear varias interfaces y estarlas registrando, solo fue necesario crear una sobre la cual se centraba y administraba la ejecución de acciones. En este patrón existen varias clases que juegan un papel importante: Invoker, o el cliente que realiza la petición de ejecutar la acción; CommandManager, quien administra y controla la ejecución de acciones; AbstractCommand, como clase común para todas las acciones concretas y por ultimo ConcreteCommand, que es la implemetancion de cada acción.
A continuación muestro el diagrama de clases utilizado
Sesion.java
public class Sesion {
...
public Parametro ejecutar(Parametro p) throws AvException {
try {
p.setUsername(usuario.getUser());
Parametro out = RemoteStubCache.getStubToRemoteObject(host).ejecutar(
p);
return out;
} catch (RemoteException e) {
throw new AvException(
"Ha occurrido un error al intentar ejecutar "
+ "la accion :" + p.getAccion(), e);
}
}// ejecutar
}//Sesion
Como CommandManager e implementando una interfaz para exponer métodos con RMI:
ServerRemoteImpl.java
public class ServerRemoteImpl implements ServerRemote, Unreferenced {
...
public Parametro ejecutar(Parametro param) throws RemoteException {
log.info("Inicio - ejecutar(Parametro param)");
BaseAccion accion = BaseAccion.getAccion(param.getAccion());
Parametro p = null;
if (accion != null) {
log.debug("Ejecutar : " + param.getAccion());
try {
p = accion.ejecutar(param);
} catch (AvException e) {
log
.error("Ha ocurrido un error al intentar ejecutar la accion");
throw new RemoteException("Ha ocurrido un error al intentar "
+ "ejecutar la accion", e);
}
} else {
log.warn("Accion no encontrada");
}
log.info("Fin - ejecutar(Parametro param)");
return p;
}// ejecutar
}// ServerRemoteImpl
En cuanto a AbstractCommand, cabe notar que agregue métodos para obtener las acciones y beans, estos métodos se basan en clases de Spring:
BaseAccion.java
public abstract class BaseAccion {
...
public static Object getBean(String bean) {
return getContext().getBean(bean);
}// getBean
public static BaseAccion getAccion(String accion) {
if (accion != null && accion.trim().length() > 0) {
return (BaseAccion) getContext().getBean(accion);
}
return null;
}// getAccion
public abstract Parametro ejecutar(Parametro parametro) throws AvException;
}// BaseAccion
Y por ultimo un ejemplo de alguna acción concreta o ConcreteCommand, que en este caso corresponde a la acción de agregar un usuario
AgregarAccion.java
public class AgregarAccion extends BaseAccion {
private static Logger log = Logger.getLogger(AgregarAccion.class);
@Override
public Parametro ejecutar(Parametro parametro) throws AvException {
log.info("Inicio - ejecutar(Parametro parametro)");
UsuarioLayer ul = (UsuarioLayer) getBean(UsuarioLayer.BEAN_NAME);
Usuario u = null;
if (parametro.getValor(Tipo.INPUT) instanceof Usuario) {
u = (Usuario) parametro.getValor(Tipo.INPUT);
ul.agregar(u);
parametro.setValor(Tipo.OUTPUT, u);
}
log.info("Fin - ejecutar(Parametro parametro)");
return parametro;
}// ejecutar
}// AgregarAccion