miércoles, 25 de octubre de 2017

El secreto de la felicidad…

Ya tengo mis años en estas andanzas me quedan dos años para alcanzar mi 40va primavera (aunque también he tenido mis inviernos), son casi 17 años de vida profesional, y desde que comencé este camino he tenido claro una cosa que, muy honestamente y sin tratar de engarme a mismo (más de una vez me he sorprendido tratando de engañarme), ha logrado mantenerme feliz: Hago lo que me gusta, simple y llanamente.

Desde muy temprana edad, en la época de chiquillo de escuela, conocí las computadoras. Aquellos cajones con letras en verde chillón o ámbar en fondo negro, me cautivaron, me enamoraron. Unos cursos gratuitos de Logo y Logowriter que vinieron a ofrecer del Liceo León Cortés Castro (Grecia) a mi escuela rural de distrito, fueron el disparo de salida para sumergirme en lo que iba a ser el resto de mi vida…

Había que ir y venir en bus, en tiempo fuera de horario escolar. Para un niño sumamente tímido y retraído aquello era todo un reto, casi una hazaña;  pero ver moverse aquella tortuguita digital formando figuras a partir de los comandos que yo creaba, bien valían la pena: era feliz.

Computadora no había en casa, con costo había un televisor a blanco y negro y un atún para repartir entre cinco más algo de arroz y frijoles. En esa época era impensable contar con una. Pero yo sabía que, tarde o temprano, yo me iba a dedicar a trabajar con computadoras sí o sí.

Un amigo, de más musculo económico, adquirió una. Aquella era una maravilla, no solo tenía verde, sino hasta 8 colores ¡8 colores! No existía nada en el mundo mejor que jugar Test Drive. Pasaba cada vez que podía, y, aunque los turnos para usarla eran largos, yo era feliz.

Llegué al colegio, al mismo liceo de los cursos, y salvo un brevísimo periodo de coqueteo con la biología (en parte por culpa de una joven y bonita profesora sustituta) mi ruta era clara, estar cerca del laboratorio de informática y  llevar computación como materia técnica. Me gustaba aprender, no únicamente de computadoras, y mientras aprendía era feliz.

Llegué a la universidad decido a estudiar informática, aunque no tuviera “machete”. Pero mi padre y madre, quiénes con mucho esfuerzo habían logrado hacerse de un lotecito, lo sacrificaron para comprarme mi primer computadora. Jamás nunca podré pagarles ni agradecerles lo suficiente.

Aún recuerdo las palabras de recibimiento de la directora de carrera, quien, además, impartía el curso de lógica: “Aquí no vienen a aprender a digitar, ni a usar ni paquetes ofimáticos, aquí van a aprender a programar una computadora”. Éxtasis…

Todos los cursos de programación los pasé con muy buenas notas, mas no todo fue fácil, muy a mi pesar también repetí un par de cursos. Pero no importaba, estar ahí y saber cómo funciona un programa, como decirle a una computadora que hacer en PASCAL o en FOX-DOS, era simplemente demasiado bueno para ser cierto. Era muy feliz.

Al final de la carrera universitaria las oscuras garras de la duda intentaron sujetar mi voluntad. ¿Y si no consigo trabajo? ¿Y si no es cómo lo imagino? ¿Y si no cumplo las expectativas? ¿Y si no gano lo suficiente? Y muchas otras preguntas asaltaban mi cabeza, algunas eran dudas razonables otras eran estúpidos miedos queriendo convertirse en excusas para tomar pésimas decisiones.

Al final, posterior a una en la práctica empresarial que me dejó un mal sabor, aunque fue experiencia al fin y al cabo, y luego de una única entrevista de trabajo, en Julio de 2001 llegué a mi segunda casa, a mi segundo hogar. ¡Y nada era como lo imaginaba! Todo es más difícil y excepcionalmente gratificante.

Desde entonces he programado casi siempre, algunas veces con más otras con menos responsabilidades, con muchos colegas al mismo tiempo o autogestionándome completamente solo y, aunque también se hacen muchas otras tareas de la forma más profesional posible como reuniones con clientes, levantamiento de requisitos, diseño, documentación, manuales, ayuda, aspectos gráficos, presentaciones de productos, etc… para mí lo importante es que tarde o temprano termino programando y eso me hace feliz.

Aunque he tenido y sé que habrá días en que hubiera sido mejor no salir de la cama (porque para todos existen esos días) y que habrá problemas que solucionar y situaciones difíciles que enfrentar, laborales y personales. El secreto para ser feliz la mayor parte de mi existencia ha consistido y consiste aún, en haber encontrado lo que realmente me gusta (afortunadamente muy temprano) y haber tomado la decisión de dedicarme a eso como forma de vida. Hacer lo que me gusta, dedicarme a lo me gusta es mi secreto para ser feliz.


Leia Mais…

domingo, 29 de noviembre de 2015

Listas y Linq

Linq definitivamente es una herramienta que necesitamos dominar, son muchos los escenarios en los que podemos aprovechar su potencia para simplificar las tareas que otrora nos tomaría varias líneas de código. Aquí unas pequeñas pinceladas con arreglos y listas.

Supongamos que tenemos dos arreglos de enteros y necesitamos saber si ambos se intersecan y cuáles son los números que comparten. Con Linq sería algo así:

static void Main(string[] args)
{
    int[] x = { 1, 2, 3, 4, 5 };
    int[] y = { 2, 4, 6 };
    int[] z = x.Intersect(y).ToArray();
    System.Diagnostics.Debug.WriteLine("Resultado: " + 
    string.Join(",", z.Select(s => s.ToString())));
}
¡Simple!
Otro ejemplo
Supongamos que tenemos la siguiente clase
public class Empleado
{
    public int idEmpleado { get; set; }
    public string nomEmpleado { get; set; }
    public decimal mtoSalario { get; set; }
}
Tenemos un array de enteros y queremos inicializar una lista de empleados únicamente con los id a partir del array, procedemos así;
static void Main(string[] args)
{
    int [] ids =  { 1, 2, 3, 4, 5 };
    List<Empleado> empleados = ids
        .Select(i => new Empleado() { idEmpleado = i })
        .ToList();
    System.Diagnostics.Debug.WriteLine("Cantidad: " + empleados.Count);
}
Una más. Supongamos que adicionalmente a la clase anterior de tenemos otra correspondiente a clientes
public class Cliente
{
    public int idCliente { get; set; }
    public string nomCliente { get; set; }
}
Supongamos que comparten un mismo origen, de manera que un cliente y empleado con la misma id, son la misma persona, teniendo dos listas: una de empleados y otra de clientes, queremos saber cuáles empleados también son clientes, entonces:
static void Main(string[] args)
{
    //Clientes
    List<Cliente> clientes = new List<Cliente> (){
        new Cliente() {idCliente=1, nomCliente= "María"}, 
        new Cliente () {idCliente=2, nomCliente="Jose"},
        new Cliente() {idCliente=3, nomCliente="David"}, 
        new Cliente() {idCliente=4,nomCliente="Ana"} 
    };

    //Empleados
    List<Empleado> empleados = new List<Empleado>(){
        new Empleado() {idEmpleado=2, nomEmpleado="Jose", mtoSalario=3500},
        new Empleado() {idEmpleado=4, nomEmpleado="Ana", mtoSalario=5500},
        new Empleado() {idEmpleado=6, nomEmpleado="Carlos", mtoSalario=3500}
    };

    //ids de clientes
    List<int> idsClientes = clientes.Select(s => s.idCliente).ToList();

    //Empleados que son Clientes
    List<Empleado> empleadosClientes = empleados
        .Where(e => idsClientes.Contains(e.idEmpleado))
        .ToList();

    System.Diagnostics.Debug.WriteLine("Empleados y Clientes: " + string.Join(", ", empleadosClientes.Select(c => c.nomEmpleado.ToString())));
}
Como podemos ver son muchas las posibilidades que nos ofrece Linq, o sus Extension Methods para ayudarnos en nuestra labor.

Leia Mais…

sábado, 24 de octubre de 2015

RPAD y LPAD en TSQL

Son un par de funciones que los que algún día estuvimos trabajando con Oracle estrañamos en SQL Server, Básicamente permiten rellenar a la izquierda o derecha con un caracter dado. Aquí una implementación de ambas en T-SQL

--Permite rellenar con un caracter dado a la izquierda hasta completar
-- la longitud deseada
CREATE FUNCTION [dbo].[fnPADL](
 @strOrigen VARCHAR(50), --String original
 @intlen INT,            --longitud a completar
 @chrCaracter CHAR)      --Caracter con el que se rellena
 RETURNS VARCHAR(50)
 AS 
 BEGIN
    DECLARE @len INT = LEN(@strOrigen)
    RETURN (
        CASE 
            WHEN @len < @intlen THEN REPLICATE(@chrCaracter, @intlen - @len) + @strOrigen 
            ELSE  @strOrigen
        END)
END

--Permite rellenar con un caracter dado a la derecha hasta completar
-- la longitud deseada
CREATE FUNCTION [dbo].[fnPADR](
 @strOrigen VARCHAR(50), --String original
 @intlen INT,            --longitud a completar
 @chrCaracter CHAR)      --Caracter con el que se rellena
 RETURNS VARCHAR(50)
 AS 
 BEGIN
    DECLARE @len INT = LEN(@strOrigen)
    RETURN (
        CASE 
            WHEN @len < @intlen THEN  @strOrigen + REPLICATE(@chrCaracter, @intlen - @len)
            ELSE  @strOrigen
        END)
END
Ambas funciones se aseguran que si la longitud de la palabra es mayor o igual a la longitud a cubrir devuelva la misma palabra.

Su forma de utilización sería
SELECT DBO.fnPADL ('HOLA',6,'X')
--devuelve: XXHOLA

SELECT DBO.fnPADR ('HOLA',6,'X')
-- devuelve: HOLAXX

SELECT DBO.fnPADL ('HOLA',2,'X')
-- devuelve: HOLA

Es muy muy importante a tener en cuenta que aunque estén disponibles las UDF (User-Defined Function) que devuelven escalares (como las que acabamos de definir) no es muy recomendable su uso, principalmente con grandes conjuntos de datos, En otro post intentaré ahondar mas en el por qué, quizás con algunas comparativas pero de momento el consejo sería: siempre que sea posible usar la lógica "in line" o dentro de la misma sentencia SQL, por ejemplo es más eficiente esto
SELECT REPLICATE('X',6 - LEN(miColumna)) + miColumna
FROM miTabla
en lugar de esto:
SELECT  DBO.fnPADL (miColumna,6,'X')
FROM miTabla

Obviamente con una cantidad de datos significativa, Además para usar la primera sentencia tenemos que estar seguros que la longitud de miColumna no es mayor a 6.

En todo caso recordar que si vamos a usar UDF escalares debemos realizar pruebas con buenos volúmenes de datos.

Leia Mais…

viernes, 18 de septiembre de 2015

Error en instalación de SQL Server 2014 en Windows 10


Hace ya un tiempo que migré de Windows 8.1 a Windows 10 pro. En el proceso instalé Visual Studio  2013 sin ningún problema pero al tratar de instalar el SQL server 2014 comenzaron los problemas:




Intenté varias soluciones, todas sin ningún efecto. Luego de revisarlo incluso con técnicos de Microsoft y a pesar de que ellos tampoco lograron resolver el problema, si me pusieron en la dirección correcta.

Aquí dejo los pasos con los que logré solventar la situación:

Primero se intentó instalar Visual C++ 2005, sin embargo este a su vez producía un error similar al que producía la instalación de SQL Server solo que en lugar de Microsoft.VC80.CRT era Microsoft.VC80.ATL por lo que determinamos que el problema era más profundo.

Lo siguiente fue levantar un command promp con privilegios de administrador y ejecutar el siguiente comando:

sfc /scannow

Este arrojó lo siguiente:
There is a system repair pending which requires reboot to complete. Restart Windows and run sfc again.”

Fue aquí cuando relacioné con el problema una circunstancia que no había tomado en cuenta anteriormente: cada vez que apagaba o reiniciaba mi laptop el Windows me indicaba que habían actualizaciones pendientes por descargar y/o instalar, yo simplemente dejaba que terminase siempre sin darle mayor relevancia.

Lo que pasaba en realidad es que en alguna de estas instalaciones el sistema operativo no había podido finalizar el proceso adecuadamente y el archivo pending.xml en la carpeta del sistema, que es el cargado de manejar estos aspectos, se había corrompido.

Para arreglar este problema lo que se debe hacer es ir a la consola de recuperación (recovery console) de Windows y ejecutar cierto comando. Hago un paréntesis aquí para explicar cómo llegar a la consola re recuperación: 

Lo más sencillo es, usando la búsqueda de Windows (tecla de Windows + q), digitar “Recovey Settings”. Seleccionando la opción correspondiente nos llevará a una pantalla como la siguiente

Aquí seleccionamos “Restart Now”. El sistema se iniciará e ingresa a la consola de recuperación


 En esta seleccionamos la opción de "Troubleshoot"


Y en esta la opción de “Advanced options


Finalmente seleccionamos “Command Prompt


Ya estando en la ventana de comandos ejecutamos la siguiente línea:


dism.exe /image:C:\ /cleanup-image /revertpendingactions

Cuando nos indique que el proceso se ejecutó satisfactoriamente reiniciamos el equipo. 
Para asegurarnos que todo esté correcto volvemos a ejecutar, en un command prompt con permisos de administrador, el comando:

sfc /scannow

Esta vez nos debe indicar, una vez finalizado, que no hay ningún problema con la integridad del sistema.

Entonces procedemos a instalar el Visual C++ 2005 x64, en mi caso, ya sin ningún problema. Antes de proceder a la instalación de SQL SERVER vamos a la opcion“Turn Windows Features On of Off” y nos aseguramos que la casilla correspondiente a ."Net Framework 3.5 (Includes .Net 2.0 and 3.0)” este marcada (si no lo esta la marcamos y reiniciamos la máquina).


Finalmente podemos instalar SQL Server sin ningún problema


Leia Mais…

sábado, 25 de octubre de 2014

WHERE condicional

Las consultas a las base de datos son bastante poderosas, pero en algunos casos nos pueden parecer incomodas e incluso frustrantes. Uno de los casos  más comunes es donde necesitamos hacer una consulta donde dado un parámetro si este viene nulo devolver todos los registros pero si trae algún valor hay que devolver los registros filtrados por ese valor, básicamente un filtro condicional.


Luego de varias aproximaciones más o menos eficaces, encontré la que, posiblemente, sea la forma más eficiente de hacer esto sin dividir la consulta en dos (o en 'n' dependiendo de las condiciones) consultas.

Suponiendo que tengo una tabla de productos y que el store procedure recibe un código de categoría para filtrar los resultados, pero si este viene nulo retorna el listado completo de todos los productos, el resultado, usando SQL SERVER 2014,  seria el siguiente:
SELECT P.(...) FROM Producto P
WHERE (1 =  IIF(@pcocCategoria IS NULL, 1, 0) 
OR P.cocCategoria = @pcocCategoria)
En caso de no contar con la instrucción IIF de SQL Server 2014, entonces nos las arreglamos con un CASE:
SELECT P.(...)  FROM Producto P
WHERE (1 = (CASE WHEN @pcocCategoria IS NULL THEN 1 ELSE 0 END) 
OR P.cocCategoria = @pcocCategoria)
En otros caso podría ser dadas una fecha desde y fecha hasta como parámetros necesitemos retornar los registros en ese  rango pero si vienen nulas retornar todos los registros. Entonces utilizaríamos algo similar a esto:
SELECT P.(...)  FROM Producto P
WHERE (1=IIF(@fecDesde IS NULL, 1, 0) OR (P.fecIngreso >= @fecDesde))
AND (1=IIF(@fecHasta IS NULL, 1, 0) OR (P.fecIngreso <= @fecHasta))
Es siempre importante dejar claro que todo este tipo de "workarounds" tiene sus penalizaciones de rendimiento y se debería utilizar únicamente si no existiese alternativas. Siempre es mejor buscar consultas directas, procurando usar los campos índices y en el orden correcto, pero si no queda alternativa aquí queda este tip.


Leia Mais…