aelena.com

31 March 2009

reflexiones sobre la cosa esta de los proyectos

Filed under: gestion de proyectos, metodologias, proyectos — admin @ 14:20

Es algo que ocurre en prácticamente todos los proyectos por los que paso. Nos quejamos de que los clientes no saben nunca lo que quieren, pero ¿es esto siempre así? Creo que estamos tan acostumbrados a ese modo de pensar que no siempre salimos de la caja para ver las cosas desde otro ángulo.

Si el cliente no sabe lo que quiere o no lo tiene demasiado claro, creo que sería la tarea del analista de negocio acompañar al cliente en el trabajo de dilucidar y concretar las necesidades del cliente para plasmarlas en una serie de requerimientos. Quizás cuando nadie tiene las cosas claras, ni el cliente ni los consultores / programadores externos, lo que en realidad está ocurriendo es que nadie ha vinculado el proyecto a un objetivo de negocio concreto y significativo. Nadie ha expresado en términos exactos y mensurables el objetivo del proyecto.

El papel del analista de negocios no es solamente el de acudir a reuniones a “recibir palos” o a tomar requisitos como el taquígrafo de un juzgado. Realmente, lo que debe hacer es ser capaz de orientar al cliente y de saber decir no cuando sea necesario.
Un ejemplo común sería “queremos que el sitio tenga un aspecto moderno”, frente a “queremos un sitio que cumpla con los estándares de usabilidad y que atraiga un 20% más de tráfico estando bien posicionado con técnicas SEO.” Este último objetivo es mucho más mensurable y concreto para todo el mundo que el primero. Pero para llegar aquí muchas veces hay que hacer un trabajo previo con el cliente que, por desgracia, tiende a considerarse “poco productivo.” Y es que existe una innegable cultura de la urgencia por ambas partes, cliente y consultor externo, por empezar a generar código desde el día uno, como si ese fuera el único “deliverable” o lo único que importa. Si se hace esta tarea previa de análisis y se toma la vía de concretar todos y cada uno de los objetivos es difícil no refinar el producto y acabar teniendo algo que se acerca mucho más a lo que el cliente quiere y necesita realmente.
Esto nos lleva a la importancia que puede tener en muchos casos la creación de “mockups” iniciales o prototipos como herramienta de análisis y definición de requisitos. Y no hay que tener miedo a hacer ofertas a precio cerrado por unos mockups o prototipos antes de empezar o como parte inicial del proyecto. El valor indudable de estos recursos es el de no tener que rehacer partes mucho mas significativas del desarrollo posterior.

Además, a partir de estos prototipos es bastante más facil hacer una “ingeniería inversa” para obtener requisitos de negocio. Tras esto, es más fácil conseguir cerrar un acuerdo con los requisitos exactos que se van a plasmar. Es más fácil definir una gestión del cambio, es más seguro para el contratado definir cuantas revisiones dentro de coste se pueden afrontar, porque se conoce mejor el coste de cada una de estas piezas. Este es el mejor valor añadido que puede aportar un analista que tiene el margen suficiente para hacer su trabajo, porque por desgracia no siempre es posible hacer las cosas de esta manera, por esa cultura de la urgencia que todos padecemos, que a veces no nos permite ni evaluar las herramientas con las que tenemos que trabajar, aunque ese es otro tema.
Y si el cliente finalmente no escucha, es terco, o quiere una solución de 60000 euros por 15000, solo hay dos opciones, o decir que no, o darle una solucion de 15000. Pero primero se debe hacer los deberes.

30 March 2009

¿Hora de salir corriendo?

Filed under: General, España, Trabajo, Europa, Economía — admin @ 21:08

el artículo en cuestión.

24 March 2009

El mejor post que he leido en mucho tiempo

Filed under: General, profesional, Trabajo — admin @ 15:59

sobre el entorno que nos encontramos muchos consultores cuando vamos a cliente.

No tiene desperdicio. Certero y bien expresado. Para nada extremo.
Saludos

23 March 2009

Enlaces de trabajo

Filed under: General, Employment, Trabajo, Jobs, Careers, Europa — admin @ 20:33

Una lista con un buen montón de enlaces a sitios para encontrar / explorar posibilidades de trabajo por toda Europa. Para los que soñamos con esto y no nos atrevemos del todo, o para el que está deseando irse:

http://richardmclaughlin.biz/europe-job-and-career-resources/

Saludos

6 March 2009

Script para fusionar dos tablas

Filed under: SQL Server, T-SQL — admin @ 10:41

Este script nos permite fusionar dos tablas que ya comparten algunas columnas. La situación es que tenemos una tabla A con, por ejemplo, 50 columnas y una tabla B con 15, algunas de las cuales ya coinciden con algunas de las 50 columnas de la tabla A.

Con este script podemos realizar una “migración” controlada de la tabla A a la B.

   1:  – dos variables para meter los nombres de las tablas
   2:   
   3:  DECLARE @tabla1 varchar(100)
   4:  DECLARE @tabla2 varchar(100)
   5:   
   6:  – tabla origen
   7:   
   8:  SET @tabla1 = N‘tablaOrigen’
   9:   
  10:  – tabla a la que vamos a añadir las columnas
  11:   
  12:  SET @tabla2 = N‘tablaDestino’
  13:   
  14:  – primero la consulta para averiguar las columnas
  15:   
  16:  SELECT
  17:  clmns.name AS [Nombre],
  18:   
  19:  usrt.name AS [DataType],
  20:  ISNULL(baset.name, N‘’) AS [SystemType],
  21:  CAST(CASE WHEN baset.name IN (N‘nchar’, N‘nvarchar’)
  22:  AND clmns.max_length <> -1
  23:  THEN
  24:  clmns.max_length/2
  25:   
  26:  ELSE
  27:   
  28:  clmns.max_length END AS int) AS [Length],
  29:  CAST(clmns.precision AS int) AS [NumericPrecision]
  30:  – tabla temporal donde vamos a guardar los resultados de la consulta
  31:  INTO #_DIFFS
  32:  FROM sys.tables AS tbl
  33:  INNER JOIN
  34:  sys.all_columns AS clmns
  35:  ON clmns.object_id = tbl.object_id
  36:  LEFT OUTER JOIN
  37:  sys.types AS usrt
  38:  ON usrt.user_type_id = clmns.user_type_id
  39:  LEFT OUTER JOIN
  40:  sys.types AS baset
  41:  ON
  42:  baset.user_type_id = clmns.system_type_id
  43:  and
  44:  baset.user_type_id = baset.system_type_id
  45:  WHERE
  46:  clmns.name not in
  47:  (
  48:   
  49:  /* discriminamos auqellas columnas que ya existen en nuestra tabla destino */
  50:  SELECT clmns.name FROM sys.tables as tbl
  51:  INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
  52:  WHERE tbl.[Nombre]=@tabla2
  53:  )
  54:  AND
  55:  – aqui nos ceñimos a ‘dbo’ solamente aunque sería facil
  56:  – de modificar para configurar el esquema como parámetro
  57:  (tbl.name=@tabla1 and SCHEMA_NAME(tbl.schema_id)=N‘dbo’)
  58:  ORDER BY
  59:  clmns.column_id ASC;
  60:   
  61:  – declaramos una serie de variables para el cursor
  62:  DECLARE @columnName VARCHAR(100)
  63:  DECLARE @dataType VARCHAR(100)
  64:  DECLARE @dataLength VARCHAR(100)
  65:  DECLARE @numPres VARCHAR(100)
  66:   
  67:  – y otra variable para un alter table que vamos a usar
  68:  – para añadir la(s) nueva(s) columna(s) a la tabla destino
  69:  DECLARE @alterStatement NVARCHAR(1000)
  70:   
  71:  – declaramos el cursor para la tabla temporal de antes donde hemos
  72:  – guardado el resultado de la consulta
  73:   
  74:  DECLARE _cursor CURSOR FOR
  75:  SELECT [Nombre], DataType, Length, NumericPrecision
  76:  FROM #_DIFFS
  77:   
  78:  – abrimos el cursor
  79:  OPEN _cursor
  80:  FETCH NEXT FROM _cursor INTO
  81:  @columnName, @dataType, @dataLength, @numPres
  82:   
  83:  WHILE (@@FETCH_STATUS <> -1)
  84:  BEGIN
  85:  IF (@@FETCH_STATUS <> -2)
  86:  BEGIN
  87:   
  88:  – en esta variable vamos a ir concatenando una sentencia de sql
  89:  – para crear un ‘alter table add’ que nos permita añadir la nueva columna con — el tipo adecuado
  90:   
  91:  SET @alterStatement = N‘ALTER TABLE ‘ + @tabla2 + N‘ ADD [’
  92:  + @columnName + ‘] ‘ + @dataType
  93:   
  94:   
  95:  – en el caso de que sea VARCHAR o NVARCHAR, indicamos la precisión
  96:  – si fuera decimal o Money o cualquier otro tipo con precisión que — – haya — que indicar también habría que hacerlo, pero — queda como ejercicio ;-) 
  97:  – por eso vemos si el tipo de dato que tenemos guardado en @datatype
  98:  – es VARCHAR o NVARCHAR y realizamos la concatenación adecuada
  99:   
 100:  IF UPPER(@dataType) = ‘VARCHAR’ OR UPPER(@dataType) = ‘NVARCHAR’
 101:  BEGIN
 102:      SET @alterStatement = @alterStatement + ‘(’ + @dataLength + ‘)’
 103:  END
 104:   
 105:  
 106:  – si se quiere ver la concatenación…
 107:  – PRINT @alterStatement;
 108:   
 109:  – finalmente ejecutamos la sentencia
 110:   
 111:  exec sp_executesql @alterStatement;
 112:   
 113:  END;
 114:   
 115:  – y recogemos la siguiente fila
 116:   
 117:  FETCH NEXT FROM tablesize_cursor INTO @columnName, @dataType, @dataLength, @numPres
 118:  END;
 119:   
 120:  
 121:  – finalmente cerramos y limpiamos el cursor
 122:  CLOSE tablesize_cursor;
 123:  DEALLOCATE tablesize_cursor;
 124:  – tiramos la tabla temporal que hemos usado
 125:  DROP TABLE #_DIFFS
 126:   
 127:  

Este script o uno similar nos puede salvar mucho tiempo cuando tengamos que integrar dos bases de datos diferentes con considerables diferencias entre las tablas de una y otra. Quizás haya otras maneras, como SSIS, pero a mí me gusta tener el control y aquí podemos tener el control al 100 por 100 de una manera sencilla y rápida.

 

Simplemente parametrizando los nombres de las tablas al principio podemos reutilizar el script en múltiples situaciones. Y la lógica dentro del cursor es muy sencilla de adaptar a cualquier necesidad.

 

Saludos