viernes, 28 de mayo de 2010

Competitividad en el sector TIC de servicios informáticos

A continuación voy a exponer 3 puntos que permitirían ofrecer mejores precios para que los clientes vieran viables las inversiones en nuevos servicios y que reducirían los costes significativamente, aumentando el beneficio en el sector de los servicios informáticos:

1. Opensource: Esta es la evidente y más clara, presentar una oferta en la que el cliente debe hacer un desembolso en licenciamiento en estos tiempos tira para atrás cualquier tipo de nueva implantación. De muestra, un botón, aquí podéis comprobar las tarifas que tiene Oracle.

2. Commodity Hardware: Con el desembolso que el cliente realizará en servidores de medio rango y mainframes se pueden desplegar infraestructuras basadas en commodity hardware utilizando las técnicas de computación distribuida que permitirán una mayor escalabilidad, mejor rendimiento y un descenso significativo en la inversión a realizar. Esto sólo tiene sentido si se utilizan soluciones opensource, porque el coste de licenciamiento sería desproporcionado.

3. Remote work: La oficina debe ser un centro de reunión para tratar temas concretos, con las infraestructuras de telecomunicaciones domésticas existentes actualmente los empleados pueden ejercer su trabajo desde su casa probablemente en condiciones de mayor productividad y aprovechamiento del tiempo que en la propia oficina. Este punto quizá sea el más difícil de implantar dada la cultura empresarial y laboral que existe, en la que se mide a la gente por cuando entra o cuando sale, en lugar de fijar objetivos muy concretos de cumplimiento. El ahorro de costes en emplazamientos sumados a un estricto control de los objetivos supondría también un incremento sustancial del beneficio.

jueves, 27 de mayo de 2010

Tutorial de Erlang (1) Básico


Este es el primero de una serie de guías esquemáticas que realizaré mientras me introduzco en el apasionante mundo de Erlang:




1. Funciones y módulos

Con este primer programa veremos como se desarrolla con erlang:

test1.erl:
---------------------------------------------
-module(test1).
-export([sumar/2, restar/2, factorial/1]).

% Funcion sumar
sumar(X, Y) ->
X + Y.
% Funcion restar
restar(X, Y) ->
X - Y.

% Funcion factorial
factorial(1) ->
1;
factorial(X) when X > 0 ->
X * factorial(X - 1).
---------------------------------------------


Situar el fichero test1.erl en el bin donde reside el programa erl (erl.exe en windows).

---------------------------------------------
C:\Program Files\erl5.7.5\bin>erl.exe
Eshell V5.7.5 (abort with ^G)
1> c(test1).
{ok,test1}
2> test1:sumar(3,5).
8
---------------------------------------------

Con c(test1). realizamos la compilación del módulo.


Elementos que hemos visto:

- module(test1)
Nombre del módulo. El fichero que lo contenga debe llamarse igual que el módulo con la extensión .erl. Para llamar a las funciones que exporte el módulo la sintaxis es modulo:funcion(param1, param2).

-export([sumar/2, restar/2]).
Exportación de funciones del módulo al exterior con el número de parámetros esperados

factorial
Define dos comportamientos en función del parámetro de enrada para limitar la recursividad, el ";" separa las múltiples definiciones de la misma función.

%
Comentario, acaban con el retorno de carro


2. Variables, Atomos, Tuplas y Listas


Variables
Empiezan por mayúscula, pueden asignarse, pero sólo una vez.

Atomos
Comienzan por minúscula y se reducen a un literal que podrá ser utilizado en el programa.

Tuplas:
Compone un tipo de dato mediante un número fijo de términos:
{Term1,...,TermN}
Cada término en la tupla se llama elemento. El número de elementos es el tamaño de la tupla.
Hay funciones predefinidas para manejarlas (BIFs: built-in functions).

Examples:

1> P = {adam,24,{july,29}}.
{adam,24,{july,29}}
2> element(1,P).
adam
3> element(3,P).
{july,29}
4> P2 = setelement(2,P,25).
{adam,25,{july,29}}
5> tuple_size(P).
3
6> tuple_size({}).
0

Listas:
Compone un tipo de datos mediante un número variable de términos
[Term1,...,TermN]
Cada término de la lista se llama elemento. El número de elementos es la longitud de la lista.

Examples:

37> L = [a, b, {1, 2}].
[a,b,{1,2}]
38> [H|T] = L.
[a,b,{1,2}]
39> H.
a
40> L.
[a,b,{1,2}]
41> T.
[b,{1,2}]
42> length(H).
** exception error: bad argument
in function length/1
called as length(a)
43> length(T).
2
44> length(L).
3
45> L2 = [a, b | T].
[a,b,b,{1,2}]
46> L2.
[a,b,b,{1,2}]
47> T.

test2.erl:
---------------------------------------------
-module(test2).
-export([contar_lista/1, invertir_lista/1]).

% Funcion contar_lista
contar_lista([]) ->
0;
contar_lista([H|T]) ->
1 + contar_lista(T).

% Funcion invertir_lista interfaz
invertir_lista(L) ->
invertir_lista(L, []).

% Funcion invertir_lista implementacion con variable auxiliar de arrastre
invertir_lista([H|T], Lista_Invertida) ->
invertir_lista(T, [H | Lista_Invertida]);
invertir_lista([], Lista_Invertida) ->
Lista_Invertida.
---------------------------------------------


3. Salida por el terminal


1> io:format("salida").
salidaok
2> io:format("salida~n").
salida
ok
3> io:format("salida ~w~n", [hola]).
salida hola
ok
4> io:format("salida ~w ~w ~w~n", [hola, adios, 1]).
salida hola adios 1
ok


4. Control de flujo (if/case)

test3.erl:
---------------------------------------------
-module(test3).
-export([encontrar_elemento/2, encontrar_elemento_case/2]).

% Funcion encontrar_elemento
encontrar_elemento(A, []) ->
false;
encontrar_elemento(A, [H|T]) ->
if
A == H ->
true;
% El else aqui seria true ->
A =/= H ->
encontrar_elemento(A, T)
end.
encontrar_elemento_case(A, []) ->
false;
encontrar_elemento_case(A, [H|T]) ->
case A of
H ->
true;
_Else ->
encontrar_elemento_case(A, T)
end.
---------------------------------------------

5. Expresiones


5.1. Comparación de términos

Expr1 op Expr2
op Descripción
---------------------------
== igual
/= distinto
=< menor o igual
< menor
>= mayor o igual
> mayor
=:= exactamente igual
=/= exactamente distinto


5.2. Operadores aritméticos

op Expr
Expr1 op Expr2

op Descripción Tipo de arg
-----------------------------------------------
+ operador unario + number
- operador unario - number
+ number
- number
* number
/ división en coma flotante number
bnot not unario a nivel de bit integer
div división entera integer
rem resto entero de X/Y integer
band and a nivel de bit integer
bor or a nivel de bit integer
bxor xor a nivel de bit integer
bsl desplazamiento a la izq. integer
bsr desplazamiento a la dcha. integer


5.3. Expresiones booleaneas

op Expr
Expr1 op Expr2

op Descripción
---------------------
not unario not
and and lógico
or or lógico
xor xor lógico


5.4. Expresiones (short-circuit) evaluación perezosa

Sólo se evalúa la 2 si es estrictamente necesario.

Expr1 orelse Expr2
Expr1 andalso Expr2


5.5. Operaciones sobre listas

Expr1 ++ Expr2
Concatenación de listas
1> [1,2,3]++[4,5].
[1,2,3,4,5]

Expr1 -- Expr2
Substracción, elimina la primera aparición de cada elemento de la segunda lista de la primera, opera en modo foreach
1> [1,2,3,2,1,2]--[2,1,2].
[3,1,2]


5.6. Guard Sequences (secuencias de guardia)

Una secuencia de guardia es una secuencia de guardias, separadas por punto y coma (;). La secuencia de guardia es true si al menos una de sus guardias (elementos) es true. Cuando una lo cumple, las restantes, si las hubiera, no son evaluadas:

Guard1;...;GuardK

Una guardia es una secuencia de expresiones de guardia separadas por coma (,). La guardia es true si todas las expresiones evaluadas son true

GuardExpr1,...,GuardExprN

Expresiones válidas de guardia son las siguientes:

El atom true, otras constantes (términios y variables establecidas), comparaciones de términos, expresiones aritméticas, booleanas y short-circuit, y las siguientes funciones predefinidas:

BIFs de chequeo de tipos
-------------------------
is_atom/1
is_binary/1
is_bitstring/1
is_float/1
is_function/1
is_function/2
is_integer/1
is_list/1
is_number/1
is_pid/1
is_port/1
is_record/2
is_record/3
is_reference/1
is_tuple/1

BIFs aritméticas
--------------------------
abs(Number)
bit_size(Bitstring)
byte_size(Bitstring)
element(N, Tuple)
float(Term)
hd(List)
length(List)
node()
node(Pid|Ref|Port)
round(Number)
self()
size(Tuple|Bitstring)
tl(List)
trunc(Number)
tuple_size(Tuple)


5.7. Funciones de orden superior

fun
(Pattern11,...,Pattern1N) [when GuardSeq1] ->
Body1;
...;
(PatternK1,...,PatternKN) [when GuardSeqK] ->
BodyK
end

Una función de orden superior (fun expression) empieza con la palabra reservada "fun" y acaba con la palabra reservada "end". Entre ellas aparece la declaración de la función, similar a una declaración de función estandar excepto que no aparece el nombre de la función especificado.

1> Fun1 = fun (X) -> X+1 end.
#Fun
2> Fun1(2).
3
3> Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end.
#Fun
4> Fun2(7).
gt

foreach y map son dos funciones estandar que operan de este modo, la primera aplica la función a cada elemento de la lista y la segunda genera una nueva lista como resultado de aplicar la función a cada elemento de la lista.

92> Add 3 = fun(X) -> X + 3 end.
#Fun
93> lists:map(Add 3, [1,2,3]).
[4,5,6]



6. Programación concurrente


6.1. Procesos

Los procesos Erlang son como los threads pero sin datos. La función predefinida "spawn" es utilizada para crear nuevos procesos.

spawn(Módulo, Función exportada, Lista de argumentos)

Retorna el identificador del proceso Pid.

test4.erl:
--------------------------------------------
-module(test4).
-export([start/1, funcion/2]).

funcion(Palabra, Proceso) ->
io:format("~w - ~w~n", [Palabra, Proceso]).

start(0) ->
done;
start(A) ->
Pid1 = spawn(test4, funcion, [hola, A]),
io:format("Proceso ~w arrancado~n", [Pid1]),
Pid2 = spawn(test4, funcion, [adios, A]),
io:format("Proceso ~w arrancado~n", [Pid2]),
start(A - 1).
--------------------------------------------


6.2. Paso de mensajes:

--------------------------------------------
-module(test5).
-export([start/0, funcion/0]).

funcion() ->
receive Mensaje ->
io:format("Proceso recibe el mensaje: ~w~n", [Mensaje]),
funcion()
end.

1>Pid = spawn(test5, funcion, []).

2>Pid ! hola
3>Pid ! adios
--------------------------------------------

Patrón de recepción de mensajes:

receive
patron1 ->
acciones1;
patron2 ->
acciones2;
....
patronN ->
accionesN
end.

Paso de mensaje: Pid ! mensaje

self(): Función que da el Pid del proceso actual


6.3. Registrar nombres de procesos

register(pong, spawn(tut16, pong, []))

pong ! mensaje

register(Name, Pid) Asocia un átomo con un Pid
registered() Retorna una lista de nombres registrados.
whereis(Name) Retorna el Pid del nombre buscado si está registrado


miércoles, 26 de mayo de 2010

Programadores vocacionales

En las empresas de tecnología actuales hay una serie de personas, entre un 5/10% según Coding Horror que son programadores de élite. Según mi opinión este tipo de personas cumplen la mayor parte de los siguientes 10 puntos:

1. Programador
No necesitan etiquetarse de arquitectos, analistas o nada similar. Son PROGRAMADORES. Analizan, diseñan, codifican, prueban y despliegan. Concibiendo el desarrollo de software desde el sentido más amplio.

2. Generalista
Conocimiento de diferentes paradigmas y lenguajes de programación que le dan una perspectiva amplia para la conceptualización, resolución y detección de problemas. Utilizan la mejor opción para cada tarea (Best tool for the job), su perfil se lo permite. No están restringidos a la resolución de problemas en un sólo lenguaje o plataforma que limite su capacidad creativa.

3. Multiplataforma
Capacidad de manejo y administración sobre sistemas Unix y Windows. Conocimiento y administración de múltiples gestores de bases de datos. Entendimiento y configuración de elementos de red (firewalls, routers, gateways).

4. Agestión
No llevan gente, no delegan, su cometido es la resolución directa de problemas de alta complejidad.

5. Literatura
Los libros que leen se centran en temas directamente relacionados con el trabajo.

6. Autocrítica
Siempre ponen en tela de juicio su nivel de conocimiento, nunca es suficiente y hay que seguir alimentándolo. Jamás presumen de su conocimiento y no tratan a sus compañeros como si fuesen basura ignorante... este es otro perfil que veremos otro día... Al contrario que estos, suelen estar siempre dispuestos a echar un cable a quién lo necesite.

7. Autonomía
No preguntan si no es estrictamente necesario, utilizan su propio conocimiento para buscar la solución utilizando todos los medios a su alcance.

8. End2End
Conocimiento del entorno completo de despliegue. Diseñan, codidifican y prueban pensando en el entorno de producción. Son capaces de montar entornos completos desde cero, desde la instalación del sistema operativo, servidores de aplicaciones, bases de datos... lo que sea necesario.

9. Obsesión
Los problemas se convierten en retos personales que ocuparán su actividad mental hasta el momento de la resolución que es la mayor recompensa que pueden obtener.

10. Adaptación
Pueden ser productivos en nuevos entornos que desconocen completamente en menos de dos semanas, sin necesidad de formación.

La estructura de las carreras profesionales en las TIC españolas condena a este tipo de perfiles tan valiosos al ostracismo. Y sobreviven como soldados de fortuna ;-) en diferentes proyectos donde destacan por solventar marronazos de cuidado en "heroic mode" de cuando en cuando.

En otros mercados, la cosa es muy diferente, forman parte del staff de la compañía y son determinantes en el éxito de los proyectos, lanzamiento de nuevos productos e incremento sustancial de beneficios. Las compañías son conscientes de ello, son remunerados y reconocidos hasta niveles ejecutivos.

Pero aquí, donde lo que se factura es el calentamiento de silla y el reconocimiento no tiene nada que ver con los méritos, seguirán ocultos... esperando que algún día algo cambie y la profesión que tanto aman sepa reconocer y explotar su potencial.

miércoles, 5 de mayo de 2010

Bloom - Cloud programming


Cada año el MIT en su publicación Technology Review selecciona las 10 tecnologías emergentes más importantes según sus editores. Este año aparece Cloud programming basándose en los avances realizados en la Universidad de Berkeley por el grupo de Joseph Hellerstein y un nuevo lenguaje llamado Bloom.

Esperan tener una early release de la sintaxis y una beta del intérprete a finales de este año. Básicamente se trata de realizar un lenguaje centrado en el dato para simplificar la implementación de las tecnologías de computación distribuida con las que ya contamos, como: MapRedurce, HadoopFS y Paxos. Permitiendo centrarse en el problema del análisis de los datos y no en el microtratamiento de los mismos que tanta complejidad introduce en este tipo de sistemas.

Podéis leer una entrevista completa que le realizan en HPC in the Cloud