tag:blogger.com,1999:blog-57008995175596647732024-03-05T13:18:00.995-03:00Deploshark - Tech Blog#sysadmin, #devops, #python y #erlangGonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.comBlogger81125tag:blogger.com,1999:blog-5700899517559664773.post-87448627781150728822015-12-13T01:42:00.000-03:002015-12-13T01:42:22.924-03:00Erlang - Sintaxis en funciones <b>Que sucede con el if?</b><br />
El condicional if actúa como las guardas y comparte con ellas la sintaxis pero fuera de la clausula cabecera de la funcion. Las clausulas if son llamada Patrones de Guardas. Los IFs en Erlang son diferentes de los ifs que encuentras en la mayoria de los lenguajes. Cuando entrás al pais de Erlang deberías dejar en la puerta todo lo que sabes acerca de los ifs<br />
<br />
Para ver que tan similar a las guardas es la expresión if, mira lo siguiente.<br />
<br />
-module(what_the_if).<br />
-export([heh_fine/0]).<br />
<br />
heh_fine()-><br />
if 1 =:= 1 -><br />
works<br />
end,<br />
if 1=:= 2; 1 =:= 1-><br />
works<br />
end,<br />
if 1 =:= 2, 1=:= 1 -><br />
fails<br />
end.<br />
<br />
<br />
guarda esto como what_the_if.erl y probemos.<br />
<br />
1> c(what_the_if).<br />
./what_the_if.erl:12: Warning: no clause will ever match<br />
./what_the_if.erl:12: Warning: the guard for this clause evaluates to 'false'
{ok,what_the_if}<br />
2> what_the_if:heh_fine().<br />
** exception error: no true branch found when evaluating an if expression<br />
in function what_the_if:heh_fine/0<br />
<br />
<br />
Bueno, el compilador nos informa que hay un error en la linea 12 que informa que esa linea siempre se evalua como falso. Recuerda, que en Erlang, todo debe retornar algo y la expresión if no es una excepción a la regla. De esta manera cuando Erlang no puede encontrar una manera de tener una guarda exitosa, este se rompe: no puede no devolver algo. Así que necesitamos agregar una rama que capture todo haciendo que siempre sea exitoso de cualquier manera.<br />
<br />
En cualquier lenguaje esto es llamado un "else". En Erlang usamos "true" (esto explica por que la VM lanza el error "no hay rama verdadera")<br />
<br />
oh_god(N) -><br />
if N =:= 2 -> might_succeed;<br />
true -> always_does<br />
end.<br />
<br />
Y ahora si nosotros testeamos esta función (la parte anterior seguirá lanzando esos warnings)<br />
<br />
3> c(what_the_if).<br />
./what_the_if.erl:12: Warning: no clause will ever match<br />
./what_the_if.erl:12: Warning: the guard for this clause evaluates to 'false'
{ok,what_the_if}<br />
4> what_the_if:oh_god(2).<br />
might_succeed<br />
5> what_the_if:oh_god(3).<br />
always_does
<br />
<br />
<br />
Seguramente serás alguno de los programadores que se sorprende por el uso de atomo true en vez de else para el control de flujo, despues de todo es más familiar. Como dice Richard O'Keefe básicamente usar el true es capturar todas las otras posibilidades y estos ejemplos que dá él mismo deberián solucionar nuestra confusión.<br />
<br />
<pre> by
if X > Y -> a() if X > Y -> a()
; true -> b() ; X =< Y -> b()
end end
if X > Y -> a() if X > Y -> a()
; X < Y -> b() ; X < Y -> b()
; true -> c() ; X ==Y -> c()
end end </pre>
<pre> </pre>
<br />
Las ramas "else" o "true" deberián ser evitadas ambas. Los ifs son usualmente más fácil de leer cuando cubres todas los extremos lógicos que cuando confias eso a una clausula "captura-todo".<br />
<br />
<b>En caso ... de</b><br />
<br />
Si la expresión if es como una guarda una expresión <b>case ... of </b>es como la cabecera de la función completa: puede tener una compleja coincidencia de patrones para cada argumento, y puedes tener guardas encima de él.<br />
<br />
Probablemente estás familiarizado con la sintaxis, no necesitaremos demasiados ejemplos. Para esto, escribiremos una función para agregar elementos a un conjunto (una colección de valores únicos) que podremos representar como una lista desordenada. Esta posiblemente sea la peor implementación en términos de eficiencia. Aquí la sintaxis.<br />
<br />
insert(X, []) -&gt<br />
[X];<br />
insert(X,Set) -&gt<br />
case lists:member(X,Set) of<br />
true -&gt Set;<br />
false -&gt [X|Set]<br />
end.<br />
<br />
Si enviamos una lista vacia y un término x para ser agregado, entonces nos retornará una lista solo conteniendo el valor x. De otra manera la función lists:member/2 verifica si un elemento es parte de un lista y retorna true si existe o false si no lo está. En caso de que ya exista el elemento en el conjunto entonces no lo modificamos. Sino, agregamos x al conjunto como el primer elemento de la lista.<br />
<br />
En este caso la coincidencia de patrones, fue realmente simple. Aquí una más compleja,<br />
<br />
beach(Temperature) -&gt<br />
case Temperature of<br />
{celsius, N} when &gt= 20, N =&lt 45 -&gt<br />
'favorable';<br />
{kelvin, N} when N &gt= 293, N =&lt 318 -&gt<br />
'scientifically favorable';<br />
{fahrenheit, N} when N &gt= 68, N =&lt 113 -&gt<br />
'favorable in the US';<br />
_ -&gt<br />
'avoid beach'<br />
end.<br />
<br />
Aquí la respuesta a "es el momento adecuado para ir a la playa?", dadas 3 temperaturas diferentes: grados Celsius, Kelvin, Fahrenheit. La coincidencia de patrones y guardas son combinadas en orden para devolver una respuesta satisfactoria a todos los usos. Como apuntamos anteriormente, las expresiones "case ... of" son la misma cosa que varias cabeceras de funciones con guardas. De hecho podriamos reescribir nuestro código de la siguiente manera.<br />
<br />
beachf({celsius, N}) when N &gt= 20, N =&lt 45 -&gt<br />
'favorable';<br />
...<br />
beachf(_) -&gt<br />
'avoid beach'.<br />
<div>
<br /></div>
<div>
Esto genera la siguiente pregunta. Cuando deberiamos usar "if", "case ... of" o funciones para hacer expresiones condicionales.</div>
<div>
<br /></div>
<div>
<b>Que utilizar?</b></div>
<div>
<br /></div>
<div>
Que utilizar es una pregunta dificil. La diferencia entre llamadas a funciones y 'case ... of' son minimas: de hecho son representadas de la misma manera a bajo nivel. y usar una o la otra tiene el mismo costo en términos de rendimiento. Una diferencia entre ambas es cuando más de un argumento necesita ser evaluado "function(A,B) -&gt ... end." puede tener guardas y valores que coincidan con A y B pero una expresión case necesitaría ser formulada de la siguiente manera:</div>
<div>
<br /></div>
<div>
case {A,B} of</div>
<div>
Pattern Guards -> ...</div>
<div>
end.</div>
<div>
<br /></div>
<div>
Esta forma es raramente vista, y puede sorprender un poco al lector. En situaciones similares llamar a una función debería ser más apropiado. De igual manera la función insert/2 previamente escrita, es podría decirse la manera más limpia en lugar de tener una llamada a función para continua con la manejar la simple clausula true o false.</div>
<div>
<br /></div>
<div>
La otra pregunta es para que usar if, dado que cases y functions son los suficientemente flexibles para incluso abarcar if a través de guardas? Lo racional detrás del if es simple. Este fue agregado para que tener en el lenguaje una manera corta de tener guardas sin necesidad de escribir toda la coincidencia de patrones cuando no es necesaria.</div>
<div>
<br /></div>
<div>
[0] http://learnyousomeerlang.com/syntax-in-functions</div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-9842950885880342662015-02-21T17:40:00.000-03:002015-02-21T17:40:01.896-03:00Algoritmos y Programación - Python [0]<b>Problemas no computables [1] </b><br />
Son aquellos problemas que nunca podrán ser resueltos por una computadora por más poderosa que sea.<br />
<br />
<b>Problemas intratables [2]</b><br />
Son aquellos problemas que pueden ser resueltos pero que requieren de un enorme poder de computo y memoria.<br />
<br />
<b>Algoritmo</b><br />
es cualquier metodo para obtener un resultado. [3]<br />
<br />
<b>Construcción de Programas</b><br />
<br />
1. Analizar el problema<br />
Entender profundamente cual es el problema y dejarlo por escrito.<br />
<br />
2. Especificar la solución<br />
Describir qué debe hacer el programa, especificar datos de entrada, de salida y la relación entre ellos.<br />
<br />
3. Diseñar la solución<br />
Cómo vamos a resolver el problema, cuales son los algortimos y las estructuras de datos que usaremos.<br />
<br />
4. Implementar el diseño<br />
Traducir en un lenguaje de programación el diseño.<br />
<br />
5. Probar el programa.<br />
Diseñar un conjunto de pruebas para probar cada una de sus partes.<br />
<br />
6. Mantener el programa<br />
Realizar los cambios en respuesta a nuevas demandas.<br />
<br />
Todos estos pasos deben ser documentados.<br />
<br />
<b>[4] Guia para diseño</b><br />
<br />
<ul>
<li>¿Han visto este problema antes, aunque sea de manera ligeramente diferente? </li>
<li>¿Conocen un problema relacionado? ¿Conocen un programa que puede ser útil?</li>
<li>Fijense en la especificación. Traten de encontrar un problema que les resulte familiar y que tenga la misma especificación o una parecido.</li>
<li>Acá hay un problema relacionado con el que ustedes tienen y que ya fue resuelto. ¿Lo pueden usar? ¿Puede usar sus resultados? ¿Pueden usar sus métodos? ¿Pueden agregarle alguna parte auxiliar a ese programa del que ya disponen?</li>
<li>Si no pueden resolver el propuesto, traten de resolver uno relacionado. ¿Pueden imaginarse uno relacionado que sea más fácil de resolver? ¿Uno más general? ¿Uno más especifico? ¿Un problema analogo?</li>
<li>¿Pueden resolver una parte del problema? ¿Pueden sacar algo útil de los datos de entrada? ¿Pueden pensar que információn es útil para calcular las salidas? ¿De qué manera se pueden manipular las entradas y las salidas de modo tal que estén "más cerca" unas de las otras?</li>
<li>¿Usaron todos los datos de entrada? ¿Usaron las condiciones especiales sobre los datos de entrada que aparecen en el enunciado? ¿Han tenido en cuenta todos los requisitos que se enuncian en la especificación?</li>
</ul>
<b>Las funciones</b><br />
<br />
Una función es un conjunto de instrucciones que llevan a cabo la solución de una parte particular del problema. Las funciones llevan ninguno, uno o más argumentos que son la parte variable que se debe definir en cada ejecución de la función. Es recomentable documentar las funciones ya que con el crecimiento del programa crece su complejidad y tener las funciones documentadas ayudar a la mantenibilidad.<br />
<br />
Las variables y parametros que se declaran dentro de una función no existen fuera de ella. Por consiguiente en lenguajes como python de utiliza "return" para decirle a una función que el valor debe ser retornado al hilo principal para que el programa pueda utilzar esa salida para hacer otras tareas.<br />
<br />
[0] Algoritmos y Programación - Python<br />
[1][2][3] Algoritmos y Programación - Python Pagina 9<br />
[4] Algoritmos y Programación - Python Pagina 28<br />
[5] http://www.cs.kent.ac.uk/people/staff/sjt/Haskell_craft/HowToProgIt.html <br />
[6] Algoritmos y Programación - Python Pagina 30GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-28369712612597535262014-12-15T00:34:00.002-03:002014-12-15T00:42:50.325-03:00WebSocket Server Escalable SoftwarePareciera que los servicios de WebSocket en la nube están de moda. Muchos proyectos proveen una abstracción sobre los websockets con un modelo de pago por transacción que además parece ser bastante caro es masomenos entendible por que diseñar un servicio de WebSocket o de Publish/Subscribe parecería bastente dificil en principio pero no es más dificil que armar una API Rest sin framework hoy en día. Algunos datos del software que creo necesario para lograr hacer un WebSocket server escalable en Python obviamente ya que es el lenguaje que nos gusta en este Blog.<br />
<br />
<b>Tornado[0],</b> es un Framework para hacer aplicaciones Web principalmente pero también es muy conocido por tener una clase para manejo de WebSockets y hay benchmarks que lo comparan en velocidad de respuesta con nodejs un muy conocido lenguaje de programación basado en el motor v8 sobre el que corre javascript en los browsers. [1]<br />
<br />
<b>SockJS</b>[2], es principalmente una libreria de javascript que emula el funcionamiento de WebSockets intentando dar la mayor compatibilidad con los browsers a la vez que intenta mantener una interfaz muy similar al WebSocket puro. El único que inconveniente en principio es que para implementar sockjs y aprovechar todas sus caracteristicas se necesita una implementación del lado del servidor. <br />
<br />
<b>sockjs-tornado</b>[3], es una libreria que implementar sockjs sobre un servidor tornado, esto se hace cambiando la clase de la que se hereda el WebSocketHandler. <br />
<br />
<b>redis</b> [4], es un base de datos en memoria que utiliza como estructura principal key-value, donde las peticiones son hechas a traves de una clave y devuelven un valor, muy util para utilizar como cache. Pero en el caso de un WebSocket server vamos a usar una de sus caracteristicas como Publish/Subscribe [5].<br />
<br />
Antes de terminar con las tecnologias a usar voy contarles por que necesitamos un server con la modalidad de Publish/Subscribe. Una aplicación web masomenos bien diseñada puede escalar horizontalmente [6][7], gracias a que hay un tercero donde comparten la información, y esa es la base de datos comunmente relacional del tipo SQL. En cuanto al WebSocket cada conexión hecha contra un servidor puede (en su implementación normal) solamente comunicarse con otros websockets dentro del mismo servidor por eso la única manera para hablar entre diferentes servidores es agregando a un tercero que maneje algo parecido a canales de comunicación y a eso viene la funcionalidad de Publish/Subscribe, que nos ofrece tener canales donde dos servidores o más pueden publicar y subscribirse y al subscribirse recibiran todos los mensajes que vayan a ese canal. De esa manera podemos levantar n servers sabiendo que todos los websockets aunque estén distribuidos si se subscriben al canal adecuado van a recibir los mensajes que les corresponden.<br />
<br />
<b>tornado-redis</b>[8] es una implementación de redis para tornado, lo que permite generar un solo cliente por instancia de tornado y manejar las subscripciones desde ahí, además, tiene una clase de abstracción para manejar subscripciones basadas en sockjs-tornado[9]<br />
<br />
Y eso creo que es todo ya tenemos todo un hermoso Stack de tecnologias para empezar a desarrollar nuestra aplicación web basada en Sockets ahora es cuestión de juntar todo y ponerse a escribir código.<br />
<br />
[0] <a href="http://tornadoweb.org/">http://tornadoweb.org/</a><br />
[1] <a href="http://swizec.com/blog/benchmarking-node-tornado-and-django-for-concurrency/swizec/1616">http://swizec.com/blog/benchmarking-node-tornado-and-django-for-concurrency/swizec/1616</a><br />
[2] <a href="http://sockjs.org/">http://sockjs.org/</a><br />
[3] <a href="https://github.com/MrJoes/sockjs-tornado">https://github.com/MrJoes/sockjs-tornado</a><br />
[4] <a href="http://redis.io/">http://redis.io/</a><br />
[5] <a href="http://redis.io/topics/pubsub">http://redis.io/topics/pubsub</a><br />
[6] <a href="http://blog.deploshark.com.ar/2014/01/otros-atributos-de-calidad-capitulo-12.html">http://blog.deploshark.com.ar/2014/01/otros-atributos-de-calidad-capitulo-12.html</a><br />
[7] <a href="http://es.wikipedia.org/wiki/Escalabilidad#Escalabilidad_horizontal">http://es.wikipedia.org/wiki/Escalabilidad#Escalabilidad_horizontal</a><br />
[8] <a href="https://github.com/leporo/tornado-redis/">https://github.com/leporo/tornado-redis/</a><br />
[9] <a href="https://github.com/leporo/tornado-redis#pubsub">https://github.com/leporo/tornado-redis#pubsub</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-3572375073366108822014-09-14T20:19:00.003-03:002014-09-14T20:19:49.297-03:00Aprendiendo Erlang parte 6 Modulos III<b>Más acerca de mó</b><b>dulos</b><br />
<br />
Antes de movernos a profundizar nuestro conocimiento en relación a como escribir funciones y algunos fragmentos de código, pero antes tenemos un poco más de información que te será útil en el futuro.<br />
<br />
Una de las primeras son los metadatos de los módulos. Los atributos de los módulos son metadatos que describen el módulo en si mismo. Donde podemos encontrar estos metadatos cuando no tenemos acceso al código fuente? Bueno, el compilador nos ayuda con esto: cuando compilamos un módulo, este toma la mayoría de los atributos y los almacena en una función llamada <b>module_info/0 . </b>Así pueden ver los metadatos de un módulo.<br />
<br />
<pre>9> useless:module_info().
[{exports,[{add,2},
{hello,0},
{greet_and_add_two,1},
{module_info,0},
{module_info,1}]},
{imports,[]},
{attributes,[{vsn,[174839656007867314473085021121413256129]}]},
{compile,[{options,[]},
{version,"4.6.2"},
{time,{2009,9,9,22,15,50}},
{source,"/home/ferd/learn-you-some-erlang/useless.erl"}]}]
10> useless:module_info(attributes).
[{vsn,[174839656007867314473085021121413256129]}]</pre>
<pre></pre>
El snippet anterior además muestra la función <b>module_info/1 </b>que permite solicitar una pieza especifica de información.<br />
<div>
<br /></div>
<div>
<b>Sintaxis en funciones</b></div>
<div>
<br /></div>
<div>
Coincidencia de patrones</div>
<div>
<br /></div>
<div>
Ahora tenemos la habilidad de almacenar y compilar código, podemos empezar a escribir funciones más avanzadas. La primera función que vamos a escribir necesita saludar de manera diferente según el genero. En la mayoría de los lenguajes podrías escribir algo así.</div>
<div>
<br /></div>
<div>
function saludar(Genero, Nombre)</div>
<div>
if Genero == masculino then</div>
<div>
printf("Hola, Sr. %s!", Nombre)</div>
<div>
else if Genero == femenino then</div>
<div>
printf("Hola Sra. %s!", Nombre)</div>
<div>
else</div>
<div>
printf("Hola, %s!", Nombre)</div>
<div>
<br /></div>
<div>
Con coincidencia de patrones (pattern matching), erlang te ayuda a no escribir tanto código similar. La misma función en erlang se vería como esto.</div>
<div>
<br /></div>
<div>
saludar(masculino, Nombre) -></div>
<div>
io:format("Hola, Sr. ~s!", [Nombre]);</div>
<div>
saludar(femenino, Nombre) -></div>
<div>
io:format("Hola, Sra. ~s!", [Nombre]);</div>
<div>
saludar(_, Nombre) -></div>
<div>
io:format("Hola, ~s!", [Nombre]).</div>
<div>
<br /></div>
<div>
Hay que adminit que la función de impresión por pantalla es un poco más fea en erlang que entro lenguaje pero ese no es el punto. La diferencia principal aquí es que nosotros usamos la coincidencia de patrones para definir las dos partes de una función se debe utilizar y ligas los valores al mismo tiempo. Aquí no se necesita primero ligar los valores y entonces compararlos.<br />
En lugar de:<br />
<br />
function(Args) <br />
if X then<br />
Expression<br />
else if Y then<br />
Expression<br />
else<br />
Expression<br />
<br />
Nosotros escribimos:<br />
<br />
function(X) -><br />
Expression;<br />
function(Y) -><br />
Expression;<br />
function(_) -><br />
Expression.<br />
<br />
De esta manera se obtiene los mismo resultados pero con un estilo más declarativo. Cada una de estas declaraciones de funciones es llamada clausula de función. Las clausulas de función deben ser separadas con punto y coma ";"<br />
<br />
La coincidencia de patrones en las funciones puede ser más complejo y poderoso que eso. Tal vez recuerdas de capitulos anteriores donde usabamos coincidencia de patrones patrones para encontrar la cabeza y cola de una lista. Vamos a hacer esto. Creamos un modulo llamado funciones.<br />
<br />
-module(functions).<br />
-compile(export_all).<br />
<br />
La primera función que vamos a escribir es head/1, que actua exactamente como erlang:hd/1 que toma una lista como argumento y retorna su primer elemento. Los haremos con la ayuda del signo "|".<br />
<br />
head([H|_]) -> H.<br />
<br />
Si vos escribis functions:head([1,2,3,4]) en la terminal (una vez que el modulo sea compilado), puedes esperar que te retorne el valor 1. Consecuentemente para obtener el segundo elemento de la lista, puedes crear la siguiente función.<br />
<br />
second([_,X|_]) -> X.<br />
<br />
La lista será deconstruida por erlang en orden a hacer coincidir los patrones. Intentalo en la terminal.<br />
<br />
1> c(functions).<br />
{ok, functions} <br />
2> functions.head([1,2,3,4]).<br />
1<br />
3> functions.second([1,2,3,4]).<br />
2<br />
<br />
esto podría ser repetido en la lista tanto como quitas, pero es impráctico para cientos de valores. Esto se puede resolver escribiendo funciones recursivas, aunque veremos como más adelante. Por ahora concentremonos más en la coincidencia de patrones. El concepto de variables libres y llenas nosotros los discutimos anteriormente, esto es así también para las funciones, podemos entonces comparar y conocer si dos parametros pasados a una función son lo mismo o no. Para esto, crearemos una función llamada same/2 que toma dos argumentos y dice si son identicos.<br />
<br />
same(X,X) -><br />
true;<br />
save(_,_) -><br />
false.<br />
<br />
Y es así de simple. <br />
<br />
<b>Guardas, guardas.</b><br />
<br />
Las guardas son clausulas adicionales que pueden ir en la cabecera de una función para hacer la coincidencia de patrones más expresiva. Como mencionamos antes la coincidencia de patrones está de alguna manera limitada ya que no puede expresar cosas como rangos de valores o cierto tipo de datos. Unos conceptos que no podemos representar serían los siguientes. Es este jugador de 12 años demasiado petizo para jugar con los profesionales? Es esta distincia demasiado larga para caminar sobre tus manos? Eres demasiado viejo o demasiado joven para manejar un auto?. No puedes responder esto simplemente con coincidencia de patrones. Se puede representar la pregunta sobre el manejo de un auto de la siguiente manera.<br />
<br />
old_enough(0) -> false;<br />
old_enough(1) -> false;<br />
old_enough(2) -> false;<br />
... <br />
old_enough(14) -> false;<br />
old_enough(15) -> false;<br />
old_enough(_) -> true.<br />
<br />
Pero esto es increiblemente impráctico. Puedes hacerlo si lo quieres, pero trabajarás solo en tu código por siempre. Si quieres eventualmente hacer amigos, entonces debes usar el modulo de guardas así podremos escribir la pregunta sobre el manejo de la siguiente manera.<br />
<br />
old_enough(X) when X >= 16 -> true;<br />
old_enough(_) -> false.<br />
<br />
y listo. Como puedes ver es mucho más limpio y corto. Notarás que la regla básica de una guarda es que debe retornar true cuando es correcta, la guarda puede fallar si retorna false o si lanza una excepción. Supongamos ahora que no queremos tener en cuenta a las personas que son mayores de 104 años. Entonces deberiamos cuidarnos de eso, pero como?, simplemente agregando una segunda guarda.<br />
<br />
right_age(X) when X >= 16, X <= 104 -><br />
true;<br />
right_age(_) -><br />
false.<br />
<br />
La "," funciona como un "y tambien", y el punto y coma ";" funciona como un "o sino" <br />
<br />
<br />http://learnyousomeerlang.com/modules#mode-about-modules</div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-70679907814930112582014-09-05T20:43:00.001-03:002014-09-05T20:43:16.857-03:00WeUseShort - Un acortador de Urls con tu propio dominioCon la intención de probar AngularJS en algunas cuestiones y hacer algo sencillo en Flask y Redis para probar esas tecnologías fue que me dispuse a hacer el pequeño ejemplo de un Acortador de Urls que cualquier puede usar para acortar las urls que envia en sus redes sociales. Si bien twitter lo hace por default a veces es bonito tener tu propio subdominio acortado con tu propia redirección. Por eso está es una aplicación muy sencilla que cumple su objetivo y que está abierta a que la mejores y propongas cambios.<br />
<br />
<br />
Caracteristicas:<br />
Acorta urls usando tu propio dominio.<br />
Redis como db.<br />
Cuenta los hits por cada url.<br />
Login sencillo.<br />
Ultrarápido<br />
<br />
Mejoras pensadas para un futuro:<br />
<br />
Mapa de Geolocalización por IP origen. (GeoIP)<br />
Redirección por tipo de dispositivo (user-agent?)<br />
<br />
Si alguien quiere colaborar<br />
<br />
https://github.com/gonzafirewall/WeUseShort<br />
<br />
Están más que invitados.GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-78076212892388598522014-08-15T19:00:00.001-03:002014-08-15T19:00:08.665-03:00Poderosa Edición Nro8 de #TheOriginalHackerEsta edición [0] es poderosa, con el estilo simple y profundo que la caracteriza, Eugenia nos redobla la apuesta con distintos análisis de alto nivel en lo profesional y de bajo nivel en lo computacional. <br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://originalhacker.org/logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://originalhacker.org/logo.png" height="176" width="400" /></a></div>
<br />
<br />
<b>PHP y el manejo de datos en memoria</b><br />Los lenguajes de programación de alto nivel generalmente administran la memoria por nosotros y los más desinteresados crean y usan variables sin preocuparse demasiado pero si vos sos de aquellos a los que SI les importa ese tipo de manejos. Bueno este artiulo es para vos.<br /><br /><b>PHP: Hacking, debugging, o simplemente diversión</b><br />La diversión, como la belleza en la programación pueden parecer (para algunos) conceptos mal usados cuando se trata de un proceso que en gran proporción es racional, pero, la creatividad y la humanidad que cada uno le imprime a su manera de escribir código, nos hace retomar esos conceptos en su forma más pura. Divertirse debuggeando o hackeando eso es lo que Eugenia nos propone en este articulo.<br />«Belleza es la API de la librería requests de Kenneth Reitz para Python[1]»<br /><br /><b>Software Libre y la diferencia con el software privativo desde la óptica intrínsecamente profesional y no política</b><br />Huff, un articulo profundo, simplemente tremendo. <br /><br /><b>La orientación a objetos y sus enfoques como estilo y paradigma.</b><br />Amo este articulo (no es por que los ejemplos estén escritos en Python bueno un poco sí) por que nuevamente se puede ver como con palabras sencillas se puede llegar profundo en cosas que normalmente se explican en libros enormes. (que igualmente no habría que dejar de leer). <br /><br />En síntesis:<br /><br />Una edición tremenda donde encontrarás como dije al principio un alto nivel profesional y un bajo nivel computacional. <br /><br />Y nuevamente me gustaría decirle a Eugenia como le dije por Twitter [2].<br />Gracias por decidir ser Libre.<br />
<br />
[0] http://originalhacker.org/<br />
[1] http://docs.python-requests.org/en/latest/ <br />
[2] https://twitter.com/GonzaMartinez/status/500384932536262656GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-24921029456670004052014-08-09T14:41:00.001-03:002014-08-09T14:41:12.614-03:00Autenticación en Apache2 contra DB SQLHace un par de días estaba limpiando modulos que estaban instalados innecesariamente en un WebServer y obviamente para deshabilitarlos sin romper demasiado me fuí leyendo para que funcionaba cada directiva. Acá les dejo como configurar una que me pareció cuando menos interesante.<br />
<br />
<b>mod_authn_dbd</b> es una directiva para poder usar como backend de autenticación una base de datos de manera masomenos simple pero directamente desde el WebServer en este caso apache2.<br />
<br />
Acá les dejo un ejemplo sacado de la doc oficial y resolviendo algunas cosas que en esa misma doc no se aclaran sobre como hacerlo en debian-based OS.<br />
<br />
Instalamos los siguientes paquetes ya que es un servidor limpio recien instalado.<br />
<br />
# Instalamos Apache y MySQL hasta acá nada raro es lo minimo<br />
apt-get install apache2 mysql-server<br />
# Esta es la libreria que hacer la magia<br />
apt-get install libaprutil1-dbd-mysql <br />
<br />
<blockquote class="tr_bq">
No hace falta obviamente tener el servidor mysql en el mismo que el apache yo lo hago así para simplificar la configuración</blockquote>
<br />
# Se debe habilitar ese modulo<br />
<a href="http://httpd.apache.org/docs/2.2/mod/mod_authn_dbd.html">a2enmod authn_dbd</a><br />
<br />
/etc/init.d/apache2 restart<br />
<br />
luego en el conf correspondiente limitamos el Directory con la configuración como continua.<br />
<br />
<blockquote class="tr_bq">
DBDriver mysql <br />
DBDParams "host=localhost, dbname=midb,user=user_db,pass=pass_db,port=3306"<br />
<br />
DBDMin 4<br />
DBD Keep 8<br />
DBDMax 20<br />
DBDExptime 300<br />
<br />
<directory privado="" var="" www=""></directory><Directory /var/www/privado><br /> AuthType Basic<br /> AuthName "Mi Servidor"<br /> AuthBasicProvider dbd<br /> Require valid-user<br /> AuthDBDUserPWQuery \<br /> "SELECT password from auth_table where user = %s"<br /></Directory></blockquote>
<br />
A mi no me resulto tan obvio pero la password del usuario tiene que ser encriptada en la DB con la función ENCRYPT de mysql.<br />
<br />
<a href="http://httpd.apache.org/docs/current/mod/mod_authz_dbd.html">Otra directiva</a> interesante permite hacer login y logout pero esa los voy a dejar que se peleen ustedes con los problemas que pueda causa esa configuración.<br />
<br />
Espero que les haya parecido cuando menos raro esto de autenticar desde el WebServer contra la DB directamente creo que yo ya le tengo una utilidad.<br />
<br />
<a href="http://httpd.apache.org/docs/2.2/mod/mod_authn_dbd.html">http://httpd.apache.org/docs/2.2/mod/mod_authn_dbd.html</a><br />
<a href="http://httpd.apache.org/docs/current/mod/mod_authz_dbd.html">http://httpd.apache.org/docs/current/mod/mod_authz_dbd.html</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-74576324034665912242014-06-09T01:02:00.002-03:002014-06-09T01:03:47.950-03:00Como configurar un RAID0 en AWSLa problemática empieza por mejorar la performance de IO en el server de Base de datos no es un problema actualmente pero tampoco queremos que lo sea<br />
<br />
Primero que todo configuramos para nuestro renovado server una de las instancias con mejor performance de memoria según Amazon las instancias R3 [0]<br />
<br />
<blockquote class="tr_bq">
Las instancias R3 están optimizadas para aplicaciones con un uso intenso de la memoria y ofrecen el coste más bajo por GiB de RAM entre los tipos de instancias de Amazon EC2.</blockquote>
Estos servidores tienen un Almacenamiento de Instancia [1] respaldado en Disco SSD pero estos son temporales por consiguiente si se Para y luego se Inicia nuevamente todo lo que habia en ese disco simplemente desaparece. Por eso decidimos seguir respaldando la DB en un EBS [2] y para mejorar un poco más la performance decidimos poner dos EBSs en RAID0<br />
<br />
Entonces empecemos contando que es un EBS. Amazon Dice:<br />
<blockquote class="tr_bq">
Amazon Elastic Block Store (Amazon EBS) proporciona volúmenes de almacenamiento de nivel de bloque persistentes y diseñados para utilizarlos con las instancias de Amazon EC2 en la nube de AWS.</blockquote>
En resumen son digamos unos discos rigidos a pedido que van y vienen por la nube y que se pueden adjuntar a cualquier tipo de Instancia de EC2 y que son de almacenamiento permanente.<br />
<br />
Ahora vamos con un poco sobre algo que siempre me costó entender ¿que es un RAID? [3]. Básicamente es un conjunto de discos independientes que se usan en conjunto generalmente para dar mayor redudancia a las implementaciones de Almacenamiento. Releyendo para escribir este Post me acuerdo cual es el motivo de que nunca lo terminara de entender y el motivo es que tiene muchos niveles y algunos resultan realmente complejos. Nivel se le llama a cada tipo de configuración que existente. Obviamente nosotros vamos a explicar algunas de las más caracteristicas.<br />
<br />
<b>El RAID0</b> (Data Striping) es la útilización de un conjunto de discos fisicos como si fueran uno solo. En verdad lo que se hace es distribuir equitativamente los datos en uno y otro disco por lo que esta configuración no le agrega redundancia al almacenamiento pero si nos ayudará en la mejora del rendimiento de lectura y escritura. En cuanto al tamaño este es limitado por el más pequeño de los discos si se tiene 2 discos de 100 GB el tamaño se duplicaría entonces pasariamos a tener un disco de 200GB ya que cada uno aporta 100GB a la distribución, pero si se tiene un disco de 300GB y uno de 100GB la distribución se hace sobre el más pequeño y cada uno aporta 100GB por lo que se obtiene un disco de 200GB perdiendo 200GB del disco más grande.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Raid0.png/220px-Raid0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Raid0.png/220px-Raid0.png" /></a></div>
<br />
<b>El RAID1</b> (Mirroring) crea una copia exacta de cada dato que va a un disco en uno o más. Esto es bueno para entornos donde es más importante la velocidad de lectura que la capacidad ya que (en su implementación más básica) se usarían dos discos de 100 GB cada uno y el máximo de almacenamiento es tanto como el más pequeño de los discos. Además tener un disco copiado exactamente le agrega redundancia al conjunto lo que es muy útil en ambientes de alta disponibilidad ya que si un disco falla el otro puede tomar su lugar sin demasiado problema.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Raid1.png/220px-Raid1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Raid1.png/220px-Raid1.png" /></a></div>
<br />
<br />
Hay más? Si mucho más y es un tema largo y se puede volver bastante complejo. Leer en Wikipedia te va a dar una buena mirada [3].<br />
<br />
Ahora vamos a lo nuestro como configurar un RAID0 para una instancia EC2 sobre Volúmenes EBS primero adjuntamos dos volumenes EBS a nuestra Instancia esto se puede hacer durante el lanzamiento de la Instancia en la Sección de "Add Storage" o posteriormente desde el Panel de Volúmenes de EC2 creando un Volumen y luego adjuntandolo a la Instancia. En este caso vamos a usar dos volúmenes de 30 GB.<br />
<br />
Nosotros somos gente grosa así que usamos el tipo de servidores que sostiene al 95% de Internet servidores Linux entonces vamos a usar el comando "lsblk" que según man "lista los dispositivos de bloque"<br />
<br />
vamos a ver algo como esto<br />
<br />
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT<br />
sda 8:0 0 8G 0 disk<br />
└─sda1 8:7 0 8G 0 part /<br />
sdb 8:0 0 30G 0 disk<br />
sdc 8:0 0 30G 0 disk<br />
<br />
El disco sda de 8G es el que se monta como root por default en todas las intancias EC2 y el sdb y sdc son los que se van a usar para hacer el RAID0.<br />
<br />
<b><i>$ sudo mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=numero_de_volumenes dispositivo_1 dispositivo_2</i></b><br />
<br />
Ejemplo:<br />
<b><i>$ sudo mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 sdb sdc</i></b><br />
<div>
<br /></div>
<div>
Esto básicamente lo que hace es crear un nuevo dispositivo llamado md0 con los bloques sdb y sdc usando el nivel "stripe" que también podría ser "0" o "raid0"</div>
<div>
<blockquote class="tr_bq">
-l, --level=<br />
Set RAID level. When used with --create, options are: linear,<br />
raid0, 0, stripe, raid1, 1, mirror, raid4, 4, raid5, 5, raid6,<br />
6, raid10, 10, multipath, mp, faulty, container. Obviously some<br />
of these are synonymous.</blockquote>
</div>
<div>
Luego crearemos un sistema de archivos y un punto de montaje para montar el dispositivo.</div>
<div>
<br /></div>
<div>
<i><b>$ sudo mkfs.ext4 /dev/md0</b></i></div>
<div>
<i><b>$ sudo mkdir /mnt/md0</b></i></div>
<div>
<i><b>$ sudo mount -t ext4 /dev/md0 /mnt/md0</b></i></div>
<div>
<br /></div>
<div>
Una vez montado ya podremos usarlo pero tendremos algunos problemas (no aparecerá el punto de montaje) si paramos y prendemos la instancia para eso se debe agregar la siguiente linea al archivo /etc/fstab. </div>
<div>
<br /></div>
<div>
<i><b>/dev/md0 /mnt/md0 ext4 defaults 0 0</b></i></div>
<div>
<br /></div>
<div>
Como dice el man de fstab </div>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
The file fstab contains descriptive information about the various file systems. fstab is only read by programs, and not written; it is the duty of the system administrator to properly create and maintain this file.</blockquote>
</div>
<br />
Y listo ya tenemos nuestro raid0 configurado en nuestra instancia ec2 o en verdad en cualquier linux.<br />
<br />
Pueden probar como mejora el performance de IO con diferentes herramientas hdparm [4] o bonnie++ [5]<br />
<br />
Más data de como hacer esta configuración y sus ventajas y desventajas en el siguiente link [6]<br />
<br />
[0] http://aws.amazon.com/es/ec2/instance-types/<br />
[1] http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html<br />
[2] http://aws.amazon.com/es/ebs/<br />
[3] http://es.wikipedia.org/wiki/RAID<br />
[4] http://es.wikipedia.org/wiki/Hdparm<br />
[5] http://en.wikipedia.org/wiki/Bonnie++<br />
[6] http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/raid-config.htmlGonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-13085224808154922872014-04-27T20:45:00.003-03:002014-04-27T20:52:07.193-03:00#Flisol2014 sede Agenda Digital <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhS8DU3Gnt-eo9BCJhJsw_UPDBVkFbS8YynuyTxpKVQI1RqbnlHOs_wht_z5NDcTdbgbTwC01xpJyoGFkou5HcyMohCsOZp9e_Bo0pPXgcQ6R1tXBPRi5MFzUQd6WJ9IkHrN43F3ibxPpI/s1600/IMG_20140427_205018.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhS8DU3Gnt-eo9BCJhJsw_UPDBVkFbS8YynuyTxpKVQI1RqbnlHOs_wht_z5NDcTdbgbTwC01xpJyoGFkou5HcyMohCsOZp9e_Bo0pPXgcQ6R1tXBPRi5MFzUQd6WJ9IkHrN43F3ibxPpI/s1600/IMG_20140427_205018.jpg" height="226" width="320" /></a></div>
<b><br /></b>
<b><br /></b>
<b>Panel de apertura "El vínculo entre el Software Libre y el Estado"</b><br />
<div>
Constanza Necuzzi - Pablo Etcheverry - Santiago Ceria<b><br /></b><br />
<div>
Pablo Etcheverry hizo una exposición sobre los aprendizajes con respecto al Software Libre en el estado, algunos referentes a las dificultades en la coordinación de las necesidad de las areas especificas del estado que necesitan seguir gestionando sus recursos y la idea de ingresar cada vez con más software libre que por momentos son dispares, ya que el estado no puede dejar de funcionar por que se quieran cambiar sus sistemas a software libre hay cosas que llevan todo un proceso de migración.Constanza Necuzzi, hizo un analisis más profundo que el SoftLibre en sí, sino abarcando a "Las Comunidades de Práctica" [8] y como estas comunidades de práctica en general y la de software Libre en particular ayudan a generar una sociedad mejor. Santiago Ceria, nos contó sobre el programa Programar2020 [9] y como la programación y el conocimiento informático en general es importante para entender la complejidad del mundo moderno.</div>
<div>
<b><br /></b></div>
<b>Panel: ¿Qué es el Grupo de Trabajo Software Libre del Foro de la Agenda Digital? [0] - Laura Marotias - Verónica Xhardez</b><br />
Laura y Veronica contaron cual es su lugar dentro del Foro de la Agenda Digital y como de a poco van de manera transversal tocando las diferentes áreas que participan en aquel foro. Pero empecemos desde el principio la Agenda Digital Argentina "<i>es una herramienta creada mediante el Decreto presidencial 512/2009 que impulsa la conformación de un Gabinete Multisectorial orientado al aprovechamiento de las posibilidades que ofrece la Sociedad de la Información y el Conocimiento." </i>[1] y el Foro propiamente dicho, es un encuentro interinstitucional donde se debaten diferentes temáticas dentro de los que la agenda Digital tiene injerencia. Además, este lugar se convierte en un espacio "predecisional" donde diferentes organismos del estado, organizaciones civiles, etc. pueden participar de estas predecisiones, que luego, serán o no parte de una política pública según lo decidan quienes los funcionarios o las instituciones como el Congreso, etc. Los grupos que forman parte actualmente del foro son los siguientes:<br />
<div>
Interoperabilidad, Gestión Documental/Digitalización, Profesionalización del Gestor de Información, Software Público, Datos Públicos, GeoInformación, Software Libre, Gobierno Abierto, Seguridad, Contenidos Públicos. [2]<br />
<div>
<br />
En ese marco el Grupo de Software Libre [3] se encarga de concientizar a los diferentes interesados sobre la necesidad y/o conveniencia de utilizar Software Libre en el estado. Muy Pronto van a lanzar una Web donde presentarán casos éxitos de utilización de software Libre en el estado <a href="http://www.softwarelibre.gob.ar/">www.softwarelibre.gob.ar</a>. Donde entre otras cosas se va a mostrar el caso de Éxito de la ANAC [4] y Xtech [5] que viene a continuación.<br />
<br />
<b> Panel: "El vínculo entre el Estado y las empresas de Software Libre: el caso ANAC - Xtech" - Sandra D'Agostino - Daniel Coletti</b><br />
<br />
Sandra D'agostino nos relató la cantidad importante de Software Libre con el que trabaja la ANAC y como gracias a eso ahorran mucho en Licencias para invertir su "buen financiamiento" en lo que para ellos es más importante. Luego Daniel Coletti contó como por intermedio de una licitación pública que ganó Xtech la empresa de la que es dueño, empezaron un proceso de migración del correo electronico de la ANAC que antes funcionaba bajo software privativo, y que ahora, va a pasar a funcionar bajo Expresso Livre[6] que es la misma plataforma que funciona actualmente en el correo de Brasil, el cual implementó esta solución en forma acelerada desde que el Gobierno Brasilero se enteró del espionaje internacional que estaba sufriendo [7]. </div>
<div>
<br /></div>
<div>
<b>En síntesis</b></div>
<div>
<b><br /></b></div>
<div>
Las charlas a mi criterio fueron muy interesantes para saber como se mueve la comunidad de software libre dentro del estado, como se van ganando espacios de a poco y se va demostrando no solo lo importante que es a nivel económico sino lo importante que es a nivel soberanía tecnológica, independencia de las corporaciones y la apropiación de la dirección que se le quiere dar al software por parte del estado amoldandolo a sus necesidades reales.<br />
<div>
<br /></div>
<div>
[0] <a href="http://flisolcaba.usla.org.ar/app/talk/detail/78">http://flisolcaba.usla.org.ar/app/talk/detail/78</a></div>
<div>
[1] <a href="https://www.agendadigital.gob.ar/agenda-digital">https://www.agendadigital.gob.ar/agenda-digital</a></div>
</div>
</div>
<div>
[2] <a href="https://www.agendadigital.gob.ar/grupos-de-trabajo_p172">https://www.agendadigital.gob.ar/grupos-de-trabajo_p172</a></div>
<div>
[3] <a href="https://www.agendadigital.gob.ar/software-libre_p179">https://www.agendadigital.gob.ar/software-libre_p179</a></div>
<div>
[4] <a href="http://www.anac.gov.ar/">http://www.anac.gov.ar/</a></div>
<div>
[5] <a href="http://www.xtech.com.ar/">http://www.xtech.com.ar/</a></div>
<div>
[6] <a href="http://softwarelivre.org/expresso-livre">http://softwarelivre.org/expresso-livre</a></div>
<div>
[7] <a href="http://www.elpais.com.uy/mundo/brasil-reacciona-denuncias-espionaje-parte.html">http://www.elpais.com.uy/mundo/brasil-reacciona-denuncias-espionaje-parte.html</a></div>
</div>
<div>
[8] <a href="http://es.wikipedia.org/wiki/Comunidades_de_pr%C3%A1ctica">http://es.wikipedia.org/wiki/Comunidades_de_pr%C3%A1ctica</a></div>
<div>
[9] <a href="http://program.ar/">http://program.ar/</a></div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-18633235861349818002014-04-24T13:02:00.001-03:002014-04-24T13:06:28.197-03:00Pascal debe morir!Pascal [0] ha sido un lenguaje muy interesante y posiblemente lo siga siendo para aprender algoritmos pero tengo la sensación que para aprender a Programar o como parte de una materia como Programación I, hace rato que es demasiado pobre, sobre todo por que hoy en día no sirve para nada más que aprender. Entonces los alumnos o quienes están aprendiendo pierden tiempo (no mucho en verdad pero todos sabemos que el tiempo es "dinero") aprendiendo su sintaxis aprendiendo algunas características particulares que no sirve para nada más que aprender no a programar :S en mi punto de vista sino para aprender algoritmos que debería ser utilizado capaz dentro de esa misma materia. Si bien quien lee este post sabe que soy Fan de Python también saben que Python es categorizado por muchos como un buen lenguaje para aprender, además de ser un lenguaje de propósito general, por lo cual aquel pibe que sabe la sintaxis de Python aprende (además del pensamiento algorítmico) un lenguaje que le puede servir para programar Web, para Programar aplicaciones de Escritorio y para hacer pequeños Scripts para automatizar cosas.<br />
Sin ir más lejos el año pasado participé del PyDay Junin y allí en la UNNOBA[1] presentaron la muy buena iniciativa de cambiar su primer lenguaje de programación que era justamente Pascal por Python [2] [3] y hay, desde hace unos años, cada vez más lugares donde se enseña Python como lenguaje de programación de entrada [4]. Igualmente aunque no parezca mi idea no es decir que Python DEBE ser el lenguaje de programación en verdad creo que cualquier otro lenguaje de los masomenos modernos (Python, Ruby, etc) puede ser útil para entusiasmar a los que aprenden programación en sus primeros pasos.<br />
<br />
Esto se basa en algo que leí hace poco pero que siempre creí sin conocer esta frase.<br />
<br />
<div>
<blockquote class="tr_bq">
"Si quieres construir un barco, no empieces por buscar madera, cortar tablas o distribuir el trabajo. Evoca primero en los hombres y mujeres el anhelo del mar libre y ancho."<br />
Antoine de Saint-Exupéry</blockquote>
<br />
El proceso de conocer algo no siempre es hermoso, fluido y tangible generalmente es abstracto, a veces engorroso y pareciera poco útil por eso creo fervientemente que para hacer algunas cosas en programación o en cualquier trabajo en verdad. uno debe creer en lo que hace, debe amar lo que hace, por que sino no se entiende como alguien hace cosas tan complicadas. Por eso mi justificación es que Pascal no ayuda en ese proceso HOY de amar la programación, capaz si lo hacia hace años pero creo que el Rol de quienes enseñan hoy en día es actualizarse y no tenerle miedo al cambio y además ser autocríticos y analizar año a año el cambio de los paradigmas sino pasa que te quedás atrás inevitablemente y con eso atrasas a todos a los que les enseñás.<br />
[0] http://es.wikipedia.org/wiki/Pascal_(lenguaje_de_programaci%C3%B3n)<br />
[1] http://www.unnoba.edu.ar/<br />
[2] http://prezi.com/haoscmd_yuca/cambio-de-lenguajes-para-programacion-imperativa/<br />
[3] http://journal.info.unlp.edu.ar/journal/journal35/papers/JCST-Apr13-6.pdf<br />
[4] http://python.org.ar/Proyectos/UsoDePythonEnLaUniversidad</div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-20225823492949298482014-04-09T12:53:00.001-03:002014-04-09T12:53:41.217-03:00Aprendiendo Erlang parte 6 Modulos IIUna última función agregada al modulo, usando ambas funciones anteriores<br />
<br />
greet_and_add_two(X) -><br />
hello(),<br />
add(X,2).<br />
<br />
No olvides agregar <b>greet_and_add_two/1 </b>a la lista de funciones exportadas. En las llamadas a <b>hello/0 </b>y <b>add/2 </b>no necesitas escribir el nombre del modulo delante de ellos por que son declaradas en el módulo mismo.<br />
<br />
Si hubieras querido ser capaz de llamar a io:format/1 en la misma manera que add/2 o cualquier otra función definida en el módulo, deberías agregar el siguiente atributo de modulo al comienzo del archivo <b>-import(io, [format/1]). </b>Entonces podrías llamar a <b>format('Hola Mundo!~n').</b> directamente. De manera más general puede seguir esta receta.<br />
<br />
<b>-import(Module, [Funcion1/Aridad, ..., FuncionN/Aridad]).</b><br />
<b><br /></b>
Importar una función no es más que un atajo para los programadores cuando escriben su código. Los programadores Erlang a menudo desalientan el uso del atributo -import ya que algunas personas encuentran que reduce la legibilidad del código. En el caso de io:format/2 la función io_lib:format/2 también existe. En caso de que se use una de estas el programador tendría que ir al comienzo del archivo para saber de cual de las dos se trata. Consecuentemente, dejar el nombre de módulo es considerada una buena práctica. Usualmente, las únicas funciones que verás importadas vienen del módulo de listas: estas funciones son usadas con mucha frecuencia que las otros módulos.<br />
<br />
Tu módulo useless debería ahora verse algo así<br />
<br />
-module(useless).<br />
-export([add/2, hello/0, greet_and_add_two/1]).<br />
<br />
add(A,B) -><br />
A + B.<br />
<br />
%%<br />
%%<br />
hello() -><br />
io:format("Hola mundo!~n").<br />
<br />
greet_and_add_two(X) -><br />
hello(),<br />
add(X,2).<br />
<br />
Hemos terminado con el módulo 'useless'. Puedes guardar el archivo bajo el nombre userless.erl . El nombres del archivo deberá el nombre del módulo como fue definido en el atributo <b>-module</b>, seguido de '.erl' que es el tipo de extensión standard para Erlang.<br />
<br />
Anteriormente vimos como compilar el módulo y finalmente intentar todas sus funciones, veremos como definir y usar macros. Las macros de Erlang son realmente similares a las declaraciones '#define' de C, principalmente usado para definir funciones cortas y constantes. Ellas son expresiones simples representadas por texto que será reemplazado antes de que el código sea compilado por la VM. Tales macros son útiles principalmente para evitar valores mágicos flotando alrededor de tus módulos. Una macro es definida como un atribudo módulo de la forma <b>-define(MACRO, some_value). </b>y es usada como <b>?MACRO</b> dentro de cualquier función definida en el módulo. Una 'función' macro debería escribirse como <b>-define(sub(X,Y), X-Y).</b> y usada como <b>?sub(23,47) </b>luego reemplazado por <b>23-47 </b>por el compilador. Algunas personas usarán macros más complejas, pero la sintaxis básica se mantiene igual.<br />
<br />
<b>Compilando el código</b><br />
<b><br /></b>
El código Erlang es compilado a bytecode para ser usado por la máquina virtual. Puedes llamar al compilador desde distintos lugares <b>$ erlc flags file.erl </b>en la linea de comandos, <b>compile:file(FileName)</b> en la shell o en un módulo <b>c()</b> en la shell, etc.<br />
<br />
Es tiempo de compilar nuestro módulo useless. Abrir la Shell de Erlang y escribir lo siguiente.<br />
<br />
<b>1> cd("/path/to/where/you/saved/the-module").</b><br />
<b>"Path name to the directory you are in"</b><br />
<b>ok</b><br />
<br />
De manera predeterminada, la shell solo busca archivos en el mismo directorio que esté fue lanzado y en la libreria estandar: cd/1 es una función definida exclusivamente para la Shell de Erlang, diciendole que cambie el directorio uno nuevo por lo que es menos molesto navegar por nuestros archivos. Los usuarios de Windows deberían recordar de usar la barra invertida. Cuando esto se realice haz lo siguiente.<br />
<br />
<b>2> c(useless).</b><br />
<b>{ok, useless}</b><br />
<br />
Si obtienes otro mensaje, asegurate que el nombre del archivo es correcto, que estás en el directorio correcto, y que no tienes errores en tu módulo. Una vez que compiles el código exitosamente, te darás cuenta que un archivo <b>useless.beam</b> fue agregado en el mismo directorio que tu <b>useless.erl</b>. Este es el módulo compilado. Probemos nuestras funciones.<br />
<br />
<b>3> useless:add(7,2).</b><br />
<b>9</b><br />
<b>4> useless:hello().</b><br />
<b>Hello, World!</b><br />
<b>ok</b><br />
<b>5> useless:greet_and_add_two(-3).</b><br />
<b>Hello, World!</b><br />
<b>-1</b><br />
<b>6> useless:not_a_real_function().</b><br />
<b>** exception error: undefined function useless:not_a_real_function/0</b><br />
<br />
Las funciones funcionando como esperamos <b>add/2</b> agrega números, <b>hello/0 </b>muestra por pantalla "Hello World!", y<b> greet_and_add_two/1 </b>hace ambas cosas. Por supuesto, te preguntarás por que <b>hello/0 </b>retorna el atomo ok luego del texto saliente. Esto es por que las funciones Erlang y expresiones deben <b>siempre </b>returnar algo, incluso si ellas no son necesarias en otros lenguajes. Así como, <b>io:format/1</b> retorna 'ok' para denotar una condición normal, la ausencia de errores.<br />
<br />
La expresión 6 muestra un error siendo lanzado por que una función no existe. Si te olvidás de expotar una función, este es el tipo de mensaje de error que obtendrás cuando lo ejecutes.<br />
<br />
Hay un montón de banderas de compilación existentes para tenes más control sobre como es compilado el módulo. Puedes obtener una lista de todos ellos en la documentación de Erlang [0] . Los más comunes son.<br />
<br />
-debug_info<br />
Las herramientas de Erlang como debuggers, cobertura de código, y herramientas de analisis estático se usan para la información de depuración de un módulo con el fin de realizar su trabajo.<br />
<br />
-{outdir, Dir}<br />
Por default, el compilador de Erlang creará los archivos 'beam' en el directorio actual. Este te permitirá elegir donde poner el archivo compilado.<br />
<br />
-export_all<br />
Ignorará el atributo -export del módulo y en su lugar exportará todas las funciones definidas. Este es principalmente útil cuando estás probando o desarrollando código nuevo, pero no debería ser usado en producción.<br />
<br />
-{d, Macro} or {d,Macro,Value}<br />
Define una macro a ser usada en el módulo, donde Macro es un atomo. Este es usado más frecuentemente cuando se trata de pruebas unitarias, lo que garantiza que un módulo solo tendrá sus funciones de prueba creadas y exportadas cuando se quieren explicitamente. Por default, Value es 'true' si esta no es definida en el tercer lugar de la tupla.<br />
<br />
Para compilar nuestro módulo useless con algunas banderas, deberíamos hacer lo siguiente:<br />
<br />
<b>7> compile:file(useless, [debug_info, export_all]).</b><br />
<b>{ok, useless}</b><br />
<b>8> c(useless, [debug_info, export_all]).</b><br />
<b>{ok, useless}</b><br />
<br />
Puedes tambien ser astuto y definir opciones del compilador dentro de un módulo con un atributo de módulo:<br />
<br />
<b>-compile([debug_info, export_all]).</b><br />
<b><br /></b>
Entonces solo compilará y obtendrás los mismos resultados que si pasaras las banderas manualmente. Ahora estamos listos para escribir funciones, compilarlas, y ejecutarlas. Es el momento de ver hasta donde podemos llevarlo.<br />
<br />
Tarde y de a poco sigo traduciendo, como salga, pero aprendiendo algo cada día. [1]<br />
[0] http://erlang.org/doc/man/compile.html<br />
[1] http://learnyousomeerlang.com/modules<br />
<br />GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-3096007275490680552014-03-18T22:36:00.003-03:002014-03-18T22:36:37.954-03:00Patrones Estructurales - AdapterLos patrones estructurales se refieren a como las clases y objetos son compuestos para formar grandes estructuras. Los patrones de clase estructural usa herencia para componer interfaces o implementaciones. Como un ejemplo simple, considerar como la herencia múltiple mezcla dos o más clases dentro de uno. El resultado es una clase que combina las propiedades de su clase padre. Este patrón es particularmente útil para hacer que bibliotecas de clases desarrolladas independientemente trabajen juntas. Otro ejemplo es la forma de la clase del patrón Adapter. En general, un adaptador hace una interfaz (el adaptado) para ajustarse a otro, así provee una abstracción uniforme de diferentes interfaces. Una clase adaptador logra esto por la herencia privada desde un clase adaptada. El adaptador entonces expresa su interfaz en términos del adaptado.<br />
<br />
<div style="text-align: center;">
<i><b>Adapter</b></i></div>
<br />
<b>Intento,</b><br />
Convertir la interfaz de una clase a otra interfaz que el cliente espera. Adapter permite que las clases trabajen juntas que de otro manera no podrían por que sus interfaces son incompatibles.<br />
<br />
<b>Motivación</b><br />
A veces una clase de una caja de herramientas que es diseñada para su reutilización no es reutilizable solo por que sus interfaces no coinciden con la interfaz especifica del dominio que una aplicación requiere.<br />
Considera por ejemplo un editor de dibujo que permite a los usuarios dibujar y organizar los elementos gráficos (lineas, polígonos, texto, etc.) dentro de imágenes y diagramas. La clave del editor de dibujo es el objeto gráfico, que tiene una forma editable y puede dibujarse a si mismo. La interfaz para objetos gráficos es definido por una clase abstracta llamada Shape. El editor define una subclase de Shape por cada tipo de objeto gráfico: un clase LineShape para lineas, una clase PolygonShape para polígonos, y así sucesivamente.<br />
<br />
Clases para cada forma elemental de la geometría como LineShape y PolygonShape son bastante fáciles de implementar, porque su dibujo y capacidades de edición son limitados por la herencia. Pero una subclase TextShape que puede mostrar y editar texto es considerablemente más dificil de implementar, desde la edición de texto, incluso lo más básico consiste en la actualización constante de la pantalla y el manejo del buffer. Mientras tanto un producto listo para la interfaz de usuario es el kit de herramientas que deberia estár listo para proveer una sofisticada clase TextView para mostrar y editar texto. Idealmente, nos gustaría reusar TextView para implementar TextShape, pero el kit de herramientas no fue diseñado con la clase Shape en mente. Así que nosotros no podemos usar los objetos TextView y Shape de manera intercambiable.<br />
<br />
Como puede una clase existente y no relacionada como TextView trabajar en una aplicación que espera clases con una interfaz diferente e incompatible? Podríamos cambiar la clase TextView tal que sea ajuste a la interfaz de Shape, pero ese no es una opción a menos que nosotros tengamos acceso el código fuente del kit de herramientas. Incluso si lo tuvieramos, no tendría sentido hacer el cambio a TextView; el kit de herramientas no deberia tener que adoptar interfaces especificas del dominio solo para hacer que una aplicación funcione.<br />
<br />
En su lugar, definimos TextShape tal que esta <i>adapte </i>la interfaz de TextView a Shape's. Podemos hacer esto en una o dos maneras: (1) por herencia de la interfaz de Shape e implementación de TextView o (2) componiendo una instancia de TextView con una TextShape e implementando TextShape en terminos de la interfaz de TextView. We call TextShape an <b>adapter.</b><br />
<b><br /></b>
<b>Aplicabilidad</b><br />Usa el patron Adapter cuando:<br />
<br />
<ul>
<li>quiere usar una clase existente, y su interfaz no coincide con el que usted necesita.</li>
<li>quiere crear una clase reutilizable que coopera con clases no relacionadas o imprevistas, es decir, clases que no necesariamente tienen interfaces compatibles.</li>
<li>(solo adaptador de objetos) necesitas usar muchas subclases existentes, pero no es práctico adaptar su interfaz por subclaseo cada vez. Un objeto adaptador puede adaptar la intefaz de su clase padre.</li>
</ul>
<div>
<b>Participantes.</b></div>
<div>
Target, define la interfaz especifica del dominio que el cliente usa.</div>
<div>
Cliente, colabora con objetos ajustándose a la interfaz del Target.</div>
<div>
Adaptee, define una interfaz existente que necesita ser adaptada.</div>
<div>
Adapter, adaptar la interfaz del Adaptee a la interfaz de Target.</div>
<div>
<br /></div>
<div>
<b>Ejemplos de uso en Python [0] [1]</b></div>
<div>
<br /></div>
<div>
[0] <a href="http://ginstrom.com/scribbles/2009/03/27/the-adapter-pattern-in-python/">http://ginstrom.com/scribbles/2009/03/27/the-adapter-pattern-in-python/</a></div>
<div>
[1] <a href="http://python-3-patterns-idioms-test.readthedocs.org/en/latest/ChangeInterface.html">http://python-3-patterns-idioms-test.readthedocs.org/en/latest/ChangeInterface.html</a></div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-28330519593723148872014-03-18T18:40:00.003-03:002014-03-18T18:41:00.078-03:00Patrones Creacionales - SingletonIntento,<br />
Asegurar que una clase solo tiene una instancia y proveer un punto de acceso global.<br />
<br />
Motivacion<br />
<br />
Es importante para algunas clases tener exactamente una sola instancia. Aunque puede haber muchas impresoras en un sistema, debe haber solo una cola de impresión. Debe ser solo un sistema de archivo y un administrador de ventanas. Un filtro digital tendrá un convertidor A/D. Un sistema contable será dedicado a server una compania.<br />
Como podemos asegurar que una clase tiene solo una instancia y que la instancia es facilmente accesible? Una variable global hace a un objeto accessible, pero no te resguarda de instanciar multiples objetos.<br />
<br />
Una mejor solución es hacer a la clase responsable de si misma para mantener un registro de una sola instancia. La clase puede asegurar que ninguna otra instancia puede ser creada(interceptando los pedidos para crear nuevos objetos), y puede proveer una manera de acceder a la instancia. Este es el Patrón Singleton.<br />
<br />
Aplicabilidad<br />
<br />
Usa el patrón Singleton cuando.<br />
<br />
<ul>
<li>Debe haber exactamete una instancia de una clase, y esta debe estar accesible a los clientes de un punto de acceso conocido.</li>
<li>Cuando la única instancia debería ser extensible por subclaseo, y los clientes deberían ser capaces de usar un instancia extendidad sin modificar su código.</li>
</ul>
<div>
Participantes</div>
<div>
Singleton, define una operación de Instance que permite a los clientes acceder a la instancia unica. Instance es una operación de clase (que es, un metodo de clase en Smalltalk y una función miembro estático en C++).</div>
<div>
Puede ser responsable por crear la propia única instancia.</div>
<div>
<br /></div>
<div>
Ejemplos del Patrón Singleton [0] [1] </div>
<div>
<br /></div>
<div>
[0] <a href="http://stackoverflow.com/a/1810367">http://stackoverflow.com/a/1810367</a></div>
<div>
[1] <a href="http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/">http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/</a></div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-90842564474465106422014-03-17T01:24:00.001-03:002014-03-17T12:11:29.461-03:00Analizando Quiper - Compará precios descuidados<b style="font-style: italic;">Quiper[0], </b>es una aplicación móvil desarrollada en la empresa donde trabajo, que se llama Quicuo[1].<br />
<br />
Su nombre es principalmente una fusión de la palabra Quicuo y Super. <b><i>Es una aplicación que permite comparar los precios de todo tipo de productos en los supermercados más grandes del país y en principio funciona bastante bien para los que son de Capital y Gran Buenos Aires.</i></b><br />
<br />
<i><b>Aplicación Movil</b></i><br />
La aplicación móvil está desarollada en HTML, CSS y Javascript. Con una terrible ayuda de PhoneGap [2] para hacerla multi plataforma. Principalmente fue creada para Android[3] pero con muy pocos cambios puede ser y va a ser generada para IPhone muy pronto.<br />
<br />
<b><i>Backend - API</i></b><br />
La API de consulta está desarrollada sobre node.js[4], con expressjs[5] como Framework de desarrollo y sequelize[6] como ORM[7] para las consultas a la base de datos.<br />
Todo esto es servido a tráves de pm2[15] como supervisor de procesos en nodejs y con Nginx[16] como WebServer.<br />
<br />
<b>Backend - DB, Extracción y Analisis</b><br />
La extracción que es parte principal del desarrollo está escrita sobre Python[9], en principio se analizó un Scrappeador profesional pero para los primeros intentos nos pareció un poco complejo así que se optó por hacer un Scrapper propio bien amoldado para nuestro propósito. Por consiguiente, se utilizaron diferentes librerías que son bastante típicas en verdad para esto. BeautifulSoup[10] como parseador de las respuestas HTML para extracción de datos. Mechanize[11] como generador de requests dinamicas y crawler de webs, en principio fue generado todo con Mechanize y luego en algunos casos simples se usó requests[12] una librería con una API mucho más elegante. Además para guardar estos datos de forma más programática se uso SQLObject[13] como ORM en esta etapa.<br />
<br />
Finalmente el análisis y unión de datos fue escrito en PHP[14] y se usó su conector para MySQL limpio sin ORM.<br />
<br />
<b>Servidores</b><br />
Básicamente los servidores están en Amazon EC2[17] y por el momento son Dos uno como WebServer para los servicios que corren Nodejs. La Api que consume la app móvil y la Web que todavia no se lanzó.<br />
Y otro server que es el más grande y es el de la DB que tiene MySQL y corre periódicamente la extracción y análisis de datos.<br />
Los servidores fueron ambos desplegados con Ansible [18]<br />
<br />
Un crisol de tecnologías libres que unidas generan una aplicación que funciona y cumple su objetivo, principalmente participaron de este proyecto Dos Desarrolladores(principalmente uno para Phonegap css html y js y otro para el Analisis de datos con PHP), un ProjectLeader, el CEO de Quicuo y un SysAdmin/Desarrollador Python (este soy yo).<br />
<br />
[0] <a href="http://www.quiper.com.ar/">http://www.quiper.com.ar</a><br />
[1] <a href="http://www.quicuo.com.ar/">http://www.quicuo.com.ar</a><br />
[2] <a href="http://phonegap.com/">http://phonegap.com/</a><br />
[3] <a href="https://play.google.com/store/apps/details?id=com.quicuo.quiper">https://play.google.com/store/apps/details?id=com.quicuo.quiper</a><br />
[4] <a href="http://nodejs.org/">http://nodejs.org/</a><br />
[5] <a href="http://expressjs.com/">http://expressjs.com/</a><br />
[6] <a href="http://sequelizejs.com/">http://sequelizejs.com/</a><br />
[7] <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">http://en.wikipedia.org/wiki/Object-relational_mapping</a><br />
[8] <a href="http://www.mysql.com/">http://www.mysql.com/</a><br />
[9] <a href="https://www.python.org/">https://www.python.org/</a><br />
[10] <a href="http://www.crummy.com/software/BeautifulSoup/">http://www.crummy.com/software/BeautifulSoup/</a><br />
[11] <a href="http://wwwsearch.sourceforge.net/mechanize/">http://wwwsearch.sourceforge.net/mechanize/</a><br />
[12] <a href="http://docs.python-requests.org/en/latest/">http://docs.python-requests.org/en/latest/</a><br />
[13] <a href="http://sqlobject.org/">http://sqlobject.org/</a><br />
[14] <a href="http://php.net/">http://php.net/</a><br />
[15] <a href="https://github.com/Unitech/pm2">https://github.com/Unitech/pm2</a><br />
[16] <a href="http://nginx.org/">http://nginx.org/</a><br />
[17] <a href="http://aws.amazon.com/es/ec2/">http://aws.amazon.com/es/ec2/</a><br />
[18] <a href="http://www.ansible.com/home">http://www.ansible.com/home</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-50769721354912653602014-03-17T00:40:00.002-03:002014-03-17T00:42:32.551-03:00Patrones de Diseño - Factory Method y Prototype<div style="text-align: center;">
<b><i>Factory Method</i></b></div>
<b><i><br /></i></b>
<b><i>Proposito,</i></b><br />
<br />
Define una interfaz para crear un objeto, pero permite a las subclases decidir que clases instancia. Factory Method permite a una clase derivar la instanciación a las subclases.<br />
<br />
<i><b>Motivo</b></i><br />
<br />
Los Frameworks usan clases abstractas para definir y mantener relaciones entre objetos. Un framework es normalmente responsable por crear estos objetos.<br />
Considerar un framework para aplicaciones que pueda presentar multiples documentos a el usuario. Dos abstracciones claves en este framework son las clases Aplicacion y Documento. Ambas clases son abstractas, y los clientes tienen las subclases de ellas para realizar la implementación especifica de la aplicación. Para crear una aplicación de dibujo, por ejemplo, nosotros definimos las clases DrawingApplication y DrawingDocument. la clase Application es responsable para manejar Documents y los creará como sea requerido - cuando el usuario selección Abrir o nuevo desde un menu, por ejemplo.<br />
<br />
El patrón Factory Method ofrece una solución. Este encapsula el conocimiento de que subclase Document crear y mueve este conocimiento por fuera del Framework.<br />
<br />
<b><i>Aplicabilidad</i></b><br />
<br />
Usa el patrón Factory Method cuando,<br />
<br />
<ul>
<li>Una clase no puede anticipar la clase del objeto que debe crear.</li>
<li>Una clase quiere que sus subclases especifiquen el objeto a crear.</li>
<li>Las clases delegan la responsabilidad a una o muchas subclases auxiliares, y tu deseas localizar el conocimiento de que subclase auxiliar es la delegada.</li>
</ul>
<div>
<b><i>Participantes,</i></b></div>
<div>
<ul>
<li>Product, define la interfaz de objetos que el Factory Method crea.</li>
<li>ConcreteProduct, implementa la interfaz de Product.</li>
<li>Creator, declara el Factory Method, que retorna un objeto de tipo Product. El creador también puede definir una implementación predeterminada de el Factory method que retorne un objeto ConcreteProduct predeterminado. Puede llamar al Factory Method para crear un objeto Product.</li>
<li>ConcreteCreator, sobreescribe el Factory Method para return una instancia de un ConcreteProduct.</li>
</ul>
<div>
<br /></div>
<div>
<b><i>Ejemplos de Factory Method en Python.</i></b></div>
<div>
<b><i>Estos son dos ejemplos más que interesantes. [0][1]</i></b></div>
</div>
<div>
<br /></div>
<div style="text-align: center;">
<b><i>Prototype</i></b></div>
<div>
<br /></div>
<div>
<b><i>Intento,</i></b></div>
<div>
Especificar los tipos de objetos a crear usando una instancia como prototipo. y crear nuevos objeto copiando este.</div>
<div>
<br /></div>
<div>
<i><b>Motivación,</b></i></div>
<div>
<br /></div>
<div>
Podrías construir un editor para partituras personalizando un framework general para editores gráficos, y agregando nuevos objetos que representen notas, silencios, y pentagramas. El Framework editor podría tener una paleta de herramientas para agregar estos objetos de música a la partitura. La paleta debería también incluir herramientas para seleccionar, mover y otro tipo de manipulación de objetos musicales. </div>
<div>
<br /></div>
<div>
El framework provee un clase Graphics abstracta para los componentes gráficos, como son las notas y pentagramas. Provee una clase Tools para definir herramientas como esas en la paleta. El Framework también predefine un subclase Graphic-Tool para herramientas que crean instancias de objetos gráficos y agrega estos al documento.</div>
<div>
<br /></div>
<div>
Pero GraphicTool presenta un problema al diseñador del framework. Las clases para notas y pentagramas son especificas de nuestra aplicación, pero la clase GraphicTool pertence al framwork. GraphicTool no sabe como crear instancias de nuestras clases de musica para agregarlas a la partitura. Nosotros podríamos definir subclases de GraphicTool para cada tipo de objeto de música que instancia. Nosotros sabemos que la composición de objetos es una alternativa flexible al subclaseo. La pregunta es, como puede el framework usarlo para parametrizar instancias de GraphicTool por la clase de Graphic que se supone crear?.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
La solución está en hacer que GraphicTool cree un nuevo Graphic copiando o "clonando" una instancia de una subclase de Graphic. Nosotros llamamos a esta instancia un prototipo. GraphicTool es parametrizado por el prototipo que debería clonar y agregar a el documento. Si toda Subclase de Graphic soporta una operación Clone, entonces la GraphicTool puede clonar cualquier tipo de Graphic.</div>
<div>
<br /></div>
<div>
<b><i>Aplicabilidad,</i></b></div>
<div>
<br /></div>
<div>
Usa el patrón Prototype cuando un sistema deberia ser independiente de como sus productos son creados, compestos y representados; and</div>
<div>
<br /></div>
<div>
<ul>
<li>Cuando las clases a instancia son especificadas en tiempo de ejecución, por ejemplo, por carga dinámica, o</li>
<li>para evitar la construcción de una jerarquia de clases de Factories que sean paralelas a la jerarquia de clases de productos, o</li>
<li>cuando las instancias de una clase puedan tener una de solo unas pocas combinaciones diferentes de estado. Esta deberia ser más conveniente para instalar un número correspondiente de prototupos y clonarlos en lugar de instanciar la clase manualmente, cada vez con el estado apropiado.</li>
</ul>
<div>
<i><b>Participantes</b></i></div>
</div>
<div>
<ul>
<li>Prototype, declara una interfaz para clonarse a si mismo.</li>
<li>ConcretePrototype, implementa una operación para clonarse a si mismo.</li>
<li>Cliente, crea un nuevo objeto pidiendole a un prototipo que se clone a si mismo.</li>
</ul>
<div>
<b><i>Ejemplos del Patron Prototype en Python que tiene hasta formas PreConstruidas para este fin.</i></b></div>
</div>
<div>
<b><i>[2] [3]</i></b></div>
<div>
<br /></div>
<div>
[0] <a href="http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Factory.html">http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Factory.html</a></div>
<div>
[1] <a href="http://www.informit.com/articles/article.aspx?p=2131418&seqNum=3">http://www.informit.com/articles/article.aspx?p=2131418&seqNum=3</a></div>
<div>
[2] <a href="http://www.informit.com/articles/article.aspx?p=2131418&seqNum=4">http://www.informit.com/articles/article.aspx?p=2131418&seqNum=4</a></div>
<div>
[3] <a href="http://code.activestate.com/recipes/86651-prototype-pattern/">http://code.activestate.com/recipes/86651-prototype-pattern/</a></div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-39279392316959595442014-03-11T00:53:00.001-03:002014-03-11T00:53:07.313-03:00Por que todavia no hay un PaaS en Argentina?Es necesario que haya un PaaS en Argentina? Hay mercado? que tan buenos son los proveedores que hoy ofrecen algo parecido al IaaS o simplemente VPSs?<br />
<br />
Este post va a ser simplemente una opinión y está por consiguiente cargado por mi vagaje, de creencias y/o de ideologia.<br />
<br />
Amazon y RackSpace son enormes y son los que hoy se llevan todos los aplausos cuando se habla de IaaS [0] Son empresas que han innovado un montón. Amazon pasó de ser un enorme E-Commerce de libros, a una enorme empresa basada en lo último sobre redes, servidores y servicios de IT. RackSpace tiene otra historia pero hoy son dos de las más grandes y tienen varias ventajas con empresas nacionales razones obvias son que todo el hardware, redes, conexión a la red de internet y todo lo que es "VITAL" se comercializa en la misma moneda de su país de origen (eso obviamente no le quita todos los méritos de innovación o de masividad que han generado) pero si les dá una ventaja enorme por sobre cualquier otra empresa local que quiera hacer algo parecido. Hay desarrolladores y buenos ingenieros en argentina? Sin lugar a dudas dense una vuelta por los videos de PyConAr del año pasado[1] y verán un "¿montón de gente?" que hace cosas y que ama lo que hace. Nos faltan ingenieros lo sé, pero a ellos también les falta sino entren a sus Webs y verán que todas estás empresas tienen varios puestos abiertos alrededor del mundo de manera constante. Pero bueno yo creo que su principal ventaja es tener dos cosas una el monopolio de la moneda que ellos mismos imprimen y dos una cultura del esfuerzo y de la creencia firme de que se puede ser de los grandes [2]. Incluso esa idea es tan fuerte que atrae más a los inmigrantes que a los estadounidenses mismos. (Como aquello que cuando lo tenés muy cerca hace tanto ruido que te ensordece pero que desde la lejania te suena bien)<br />
<br />
Sin IaaS no hay PaaS? Y básicamente no, por que PaaS es una capa de servicios más por encima de IaaS, conozco o veo buscando por internet muchas empresas de las nuestras que ofrecen todavia Hostings PHP/ASP+ MySQL y esas cosas que son viejisimas. El rango se reduce cuando buscás alguna que ofrezca VPS (ni hablar de los costos o rendimiento) y el rango es casi nulo cuando se busca directamente infraestructura. Algunas empresas de las grandes (Telecom/IPLAN) seguramente ofrecen algo más parecido al IaaS a empresas grandes pero no hay nada para la otra gran parte del universo del mercado que son las pujantes pero grandes inversoras locales PyMes. Una PyMe o una StartUp técnologica hoy viendo costos no duda en pagar los dolares con su tarjeta más impuestos antes de poner su innovación dorada en los servidoruchos de muchos de los Hostings Locales. Sin ir más lejos "ElServer.com" todavía no puede estabilizar su servicio de correos que siempre anduvo muy mal y estamos hablando de correo no de OpenStack.<br />
<br />
Puede haber mercado en la Argentina para esto? No lo sé. Acaso Amazon hizo un analisis de mercado o vió que podía hacerlo y lo hizo? Acaso la gente de Facebook antes de viralizarse se sentó y diagramó un gran plan comercial para ver si se podía o era fáctible ellos hicieron algo mejor algo mucho mejor. Hicieron Algo y ellos mismos construyeron a su alrededor la demanda.<br />
<br />
Para finalizar por que no hay PaaS? No hay por que no hay IaaS y no hay IaaS por que todos los servidores, switches, caños de conexión a internet vienen envasados en "dolares". Software para hacerlo no nos falta por que hay miles de muestras opensorce esperando a ser forkeadas OpenStack, OpenNebula, CloudStack, Docker, lxc, Debian, Ubuntu, Fedora, CentOs, Dokku, y cientos de personas o empresas que han compartido un pedazo de su conocimiento.<br />
<br />
En fin, yo quiero un PaaS que pueda pagar en pesos. Una locura tal vez? Pero una firme creencia de que llegará.<br />
<br />
[0] <a href="http://en.wikipedia.org/wiki/Infrastructure_as_a_service#Infrastructure_as_a_service_.28IaaS.29">http://en.wikipedia.org/wiki/Infrastructure_as_a_service#Infrastructure_as_a_service_.28IaaS.29</a><br />
[1] <a href="http://www.youtube.com/results?search_query=PyConAr%202013&sm=3">http://www.youtube.com/results?search_query=PyConAr%202013&sm=3</a><br />
[2] <a href="http://es.wikipedia.org/wiki/Sue%C3%B1o_americano">http://es.wikipedia.org/wiki/Sue%C3%B1o_americano</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-81029036986082101092014-03-09T22:40:00.002-03:002014-03-09T22:40:22.790-03:00Patrones de Diseño - Builder<b><i><u>Builder</u></i></b><br />
<br />
<b>Objetivo</b>, Separa la construcción de un objeto complejo de su representación de modo que el mismo proceso de construcción puede crear diferentes representaciones.<br />
<br />
<b>Motivo</b>:<br />
<br />
Un lector para el formato de intercambio de documentos RTF (Rich Text Format) debería ser capaz de convertir RTF a muchos formato de texto. El lector puede convertir documentos RTF en texto plano ASCII o en un Widget de texto que pueden ser editados interactivamente. El problema, sin embargo, es que el número de conversiones posible es abierto. Por lo tanto, debe ser fácil de añadir una nueva conversión sin modificar el lector.<br />
<br />
<b>Aplicabilidad</b><br />
<br />
Usar el patrón Builder cuando:<br />
<br />
<ul>
<li>El algoritmo para crear un objeto complejo deber ser independiente de las partes que conforman el objeto y como están ensambladas.</li>
<li>El proceso de construcción debe permitir diferentes representaciones para el objeto que es construido.</li>
</ul>
<div>
<b>Participantes</b></div>
<div>
<br /></div>
<div>
<i>Builder,</i></div>
<div>
- especifica una interfaz abstracta para crear partes de un objeto Product.</div>
<div>
<i>ConcreteBuilder</i></div>
<div>
- construye y ensambla partes del productopara implementar la interfaz Builder.</div>
<div>
- define y mantiene un seguimiento de la representación que crea.</div>
<div>
- provee una interfaz para obtener el producto</div>
<div>
<i>Director</i></div>
<div>
- construye un objeto usando la interfaz del Builder.</div>
<div>
<i>Product</i></div>
<div>
- representa el objeto complejo en construcción. El ConcreteBuilder construye la representación interna del producto y define el procesos por el cual este es ensamblado.</div>
<div>
- incluye clases que definen las partes constituyentes, inclyendo interfaces para ensamblar las partes en el resultado final.</div>
<div>
<br /></div>
<div>
<b>Ejemplos de Código [0] [1]</b></div>
<div>
<br /></div>
<div>
<b>La diferencia entre el Builder y el Abstract Factory</b></div>
<div>
La principal diferencia es que el Builder se enfoca en construir un objeto complejo paso a paso. El Abstract Factory hace incapié en la familia de objetos producto (ya sea sencilla o compleja). El Builder retorna el producto como un paso final, pero en cuanto al Abstract Factory el producto es retornado inmediatamente.</div>
<div>
<br /></div>
<br />
[0] http://es.wikipedia.org/wiki/Builder_(patr%C3%B3n_de_dise%C3%B1o)<br />
[1] http://tratandodeentenderlo.blogspot.com.ar/2010/02/patrones-de-diseno-builder.htmlGonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-71781712069311414932014-03-08T00:43:00.001-03:002014-03-08T00:43:23.476-03:00Patrones de Diseño Creacionales - Abstract Factory<b>Los patrones de diseño creacionales</b> son aquellos que abstraen el proceso de instanciación. Ellos ayudan a hacer un sistema independiente de como sus objetos son creados, compuestos, y representados. Una patrón creacional de clase usa herencia para variar la clase que es instanciada, mientras un patron creacional de objeto delegará la instanciación a otro objeto.<br />
<br />
Los patrones creacionales se vuelven importantes en sistemas que pasan a depender más de la composición de objetos que de la herencia de clases. Como eso sucede, el enfasis cambia de modificar dificilmente un conjunto fijo de comportamientos hacia definir un conjunto pequeño de comportamientos fundamentales que pueden ser compuestos dentro de cualquier numero de los más complejos. Creando así objetos con un comportamiento particular que requiere más que simplemente instanciar una clase.<br />
<br />
<b>Abstract Factory</b><br />
<br />
Intenta:<br />
proveer una interfaz para la creación de familias objetos relacionados o dependientes sin especificar sus clases concretas.<br />
<br />
Aplicación:<br />
<br />
<ul>
<li>Un sistema debería ser independiente de como sus productos son creados, compuestos, y representados.</li>
<li>Un sistema debería ser configurado con una de múltiples familias de productos.</li>
<li>Una familia de objetos producto relacionados es diseñada para ser usados juntos y necestás hacer cumplir esta restricción.</li>
<li>Buscás proveer una biblioteca de clases de productos, y buscas revelar solo sus interfaces, no su implementación.</li>
</ul>
<div>
Participantes:</div>
<div>
<ul>
<li>Abstract Factory - declara una interfaz para operaciones que crean objetos producto abstractos.</li>
<li>ConcreteFactory - implementa las operaciones para crear objetos producto concretos.</li>
<li>AbstractProduct - declara una interfaz para un tipo de objeto producto.</li>
<li>ConcreteProduct - define un producto objeto para ser creado por el correspondiente Concrete Factory. - implementa la interfaz del AbstractProduct.</li>
<li>Client - usa solo las interfaces declaradas por las clases AbstractFactory y AbstractProduct<br /></li>
</ul>
Ejemplos de Abstract Factory en Python</div>
<div>
[0][1][2]</div>
<div>
<br /></div>
<div>
[0] http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Factory.html#abstract-factories</div>
<div>
[1] http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/</div>
<div>
[2] http://jpython.blogspot.com.ar/2012/09/python-design-pattern-abstract-factory.html</div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br />GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com1tag:blogger.com,1999:blog-5700899517559664773.post-31920623133920916852014-03-03T23:11:00.002-03:002014-04-08T11:54:41.655-03:00Aprendiendo Erlang parte 6 Modulos ILos módulos son un grupo de funciones reagrupadas en un solo archivo, bajo un nombre. Adicionalmente todas las funciones en erlang deben ser definidas en módulos. Ya has usado modulas tal vez sin darte cuenta. Las BIFs (Built-In Functions) mencionadas en el capitulo anterior <b>hd </b>o <b>tl</b>, en realidad pertenecen al módulo erlang, así como toda la aritmética. lógica u operadores booleanos. Los BIFs del módulo erlang difieren de otros módulos en que son automaticamente importados cuando usas Erlang. Cada una de las otras funciones definidas en un modulo que uses debe ser llamada con la forma <b>Modulo:Funcion(Argumentos)</b>.<br />
<br />
Lo podés ver por vos mismo:<br />
<br />
1> erlang:element(2, {a,b,c}).<br />
b<br />
2> element(2,{a,b,c}).<br />
b<br />
3> lists:seq(1,4).<br />
[1,2,3,4]<br />
4> seq(1,4).<br />
** exception error: undefined shell command seq/2<br />
<div>
<br /></div>
<div>
Aquí la función <b>seq</b> del modulo <b>lists</b> no fue automáticamente importada mientras que <b>element </b>si lo fue. El error 'undefined shell command' viene desde la shell buscando por un comando shell como <b>f() </b>y no es capaz de encontrarlo. Hay algunas funciones del modulo erlang que no se importan automáticamente, pero tampoco son muy usadas.</div>
<div>
<br /></div>
<div>
Lógicamente, deberías ponet funciones similares dentro de un mismo modulo. Las operaciones comunes sobre listas son mantenidas dentro del modulo <b>lists</b>, mientras que las funciones de entrada y salida (como escribir en una terminal o en un archivo) son agrupadas en el modulo <b>io</b>. Uno de los únicos módulos que no respeta ese patrón es el antes mencionado modulo <b>erlang </b>que tiene funciones de matemática, conversiones, trabajar con multiprocesamiento, o jugar con la configuración de la máquina virtual, etc. Ellos no tienen ningún punto en común solo que son funciones previamente construidas (BIFs). Tu deberías evitar crear módulos como <b>erlang</b> y en su lugar enfocarse en separaciones lógicas limpias.<br />
<br />
<b>Declaraciones de Módulos</b><br />
<br />
Cuando escribimos módulos, tu puedes declarar dos tipos de cosas: funciones y atributos. Los atributos son metadatos que describen el módulo en si mismo como es su nombre, las funciones que deberían ser visibles a el mundo exterior, el autor del código y así sucesivamente. Este tipo de metadatos es útil porque le dá indicaciones al compilador sobre como debe hacer su trabajo y también por que este permite a la gente obtener información útil sobre el código compilado sin tener que consultar las fuentes.<br />
<br />
Hay una gran variedad de atributos de módulos actualmente usados en el código de Erlang a través del mundo, de hecho, podes incluso declarar tus propios atributos para lo que quieras. Hay algunos atributos predefinidos que aparecerán más frecuentemente que otros en tu código. Todos los atributos de módulo siguen la forma de <b>-Nombre(Atributo).</b>. Solo uno de ellos es necesario para que tu módulo sea compilable.<br />
<br />
<blockquote class="tr_bq">
-module(Nombre).<br />
Este es siempre el primer atributo (y declaración) de un archivo y por una buena razón: este es el nombre del módulo actual, donde el nombre es un atomo. Este es el nombre que usarás para llamar a funciones de otros módulos. Las llamadas son hechas con la forma <b>M:F(A) </b>donde <b>M </b>es el nombre del módulo, <b>F </b>la función, y<b> A</b> los argumentos.</blockquote>
Es hora de escribir código! Nuestro primer módulo será muy simple y poco útil. Abrí tu editor de texto y escribe lo siguiente, y guárdalo baje el nombre <b>userless.erl</b><br />
<b><br /></b>
-module(useless).<br />
<br />
Esta linea de texto es un módulo válido. Realmente! Por supuesto que esto es muy poco útil. Primero vamos a decidir que funciones vamos a exportar de nuestro módulo 'useless'. Para hacer esto, usaremos otro atributo.<br />
<br />
<blockquote class="tr_bq">
<b>-export([Funcion1/Aridad, Funcion2/Aridad, ..., FuncionN/Aridad]).</b>Este es usado para definir que funciones de un módulo puede ser llamadas desde el mundo exterior. Este toma una lista de funciones con su respectiva aridad. La aridad de una función es un entero que representa cuantos argumentos pueden ser pasados a la función. Esta es una información critica, por que diferentes funciones definidas dentro de un módulo pueden compartir el mismo nombre si y solo sí ellas tienen aridad diferente. Las funciones <b>add(X,Y)</b> y <b>add(X,Y,Z)</b>, por lo tanto deberían ser consideradas diferentes y escritas en la forma <b>add/2</b> y <b>add/3 </b>respectivamente.</blockquote>
Nuestro modulo useless exportará una función útil llamada 'add' que tomará dos argumentos. El siguiente atributo <b>-export</b> puede ser agregado después de la declaración del módulo.<br />
<br />
-export([add/2]).<br />
<br />
y ahora escribir la función<br />
<br />
add(A,B) -><br />
A + B.<br />
<br />
La sintaxis de una función sigue la forma <b>Nombre(Argumentos) -> Cuerpo.</b> donde el <b>Nombre </b>tiene que ser un átomo y el <b>Cuerpo</b> puede ser uno o más Expresiones Erlang separada por comas.La función finaliza con un punto. Nota que erlang no utiliza la palabra clave 'return' . 'Return' es inutil. En su lugar, la última expresión lógica de una función a ejecutar tendrá su valor retornado al llamador automaticamente sin tener que mencionarlo.<br />
<br />
Agrega la siguiente función (por que sí, todo tutorial necesita su ejemplo "Hola Mundo" Incluso en su cuarto cápitulo!) sin olvidar agregar el atributo <b>-export</b><br />
<b><br /></b>
%% Mostrar Saludo.<br />
%% io:format/1 es una función estándar para salida de texto.<br />
hello() -><br />
io:format("Hola Mundo!~n").<br />
<b><br /></b>Lo que se observa en esta función es que los comentarios son de una sola línea y comienzan con un signo % (se utiliza %% simplemente como una cuestión de estilo). La función <b> hello/0 </b>demuestra como llamar funciones de otros módulos dentro de tu módulo. En este caso<b> io:format/1</b> es la función estándar para escribir texto en pantalla como es escrito en el comentario.<br />
<br />
[0] http://es.wikipedia.org/wiki/Aridad</div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-47051762734258784962014-03-03T01:13:00.005-03:002014-03-03T01:17:12.530-03:00Rockeandola con Python Parte 3<br />
Esta seguidilla de Posts sobre algunas cuestiones mas o menos avanzadas de Python tuvieron muchas visitas y eso me gusta no por que me sienta importante ni nada de eso sino por que alimenta mi idea de que compartir mi aprendizaje es útil para mí y para quienes leen cada tanto mi blog.<br />
<br />
Hoy terminaré de contarles las cosas que se hacen con With, Partials, una particularidad sobre la relación entre los Zips y Python y algunas rarezas que se encuentran instaladas en nuestra libreria.<br />
<br />
<b>With</b><br />
<br />
Este es un elemento copado bien utilizado se ve muy estetico para la lectura del código. Básicamente esta declaración ejecuta sobre el objeto que se le pasa los métodos mágicos __enter__ y __exit__<br />
El ejemplo básico de este método es el de cerrar automáticamente el archivo cuando se sale de su alcance (scope).<br />
<br />
with open('archivo.txt') as f:<br />
print(f.read())<br />
<br />
Para la libreria de ejecución de comandos remotos llamada Fabric[2] es muy usada y yo diría tan bien usada que hace como dije al principio una mejor lectura del código un ejemplo es el de ejecutar comandos bajo un mismo directorio.<br />
<br />
with cd('/path/to/app'):<br />
run('.mkdir una_carpeta')<br />
run('.wget http://unawebcopada.com.ar/el_archivo.tar.gz')<br />
<br />
<b>Partial</b><br />
<b><br /></b>
Parece ser común (todavia no me pasó) escribir el mismo método varias veces cambiando únicamente un parámetro.<br />
Con partial se puede escribir un método como una plantilla y usarlo con diferentes argumentos fijos para generar un metodo que tenga una funcionalidad especifica algunos ejemplos que encontré por internet que me gustaron son los siguientes.<br />
<br />
In [1]: from functools import partial<br />
In [2]: base_dos = partial(int, base=2)<br />
In [3]: base_dos.__doc__ = "Convierte texto de base 2 a un entero"<br />
In [4]: base_dos('10010')<br />
Out[4]: 18<br />
<div>
<br /></div>
<div>
Este [3] primer ejemplo es de crear una función especifica usando como template la función int que transforma un string en enteros para transformarla en una función que pasa strings en base 2 a entero.</div>
<div>
<br /></div>
<div>
<div>
In [1]: from functools import partial</div>
<div>
In [2]: def plantilla_log(nivel, mensaje):</div>
<div>
...: print("{}: {}".format(nivel, mensaje))</div>
<div>
...: </div>
<div>
In [3]: log_info = partial(plantilla_log, "info")</div>
<div>
In [4]: log_cuidado = partial(plantilla_log, "cuidado")</div>
<div>
In [5]: log_error = partial(plantilla_log, "error")</div>
<div>
In [6]: log_info('Este es un log informativo')</div>
<div>
info: Este es un log informativo</div>
</div>
<div>
<br /></div>
<div>
En este [4] se trata de una función que es un template sobre como hacer un log via pantalla y luego se generan las funciones especificas donde se fija el primer parámetro que es el nivel.</div>
<div>
<br /></div>
<div>
<b>El amor entre Zip y Python </b></div>
<div>
<b><br /></b></div>
<div>
Usted se preguntará si en la vida de la ejecución de código en python es todo .py? Esta es una pregunta muy razonable. pero veremos una respuesta un poco extraña</div>
<div>
<br /></div>
<div>
<div>
admin@quicuo-kaizen:/tmp$ cat __main__.py </div>
<div>
print "Estoy dentro de un ZIP"</div>
<div>
admin@quicuo-kaizen:/tmp$ zip ejemplo __main__.py </div>
<div>
updating: __main__.py (stored 0%)</div>
<div>
admin@quicuo-kaizen:/tmp$ python ejemplo.zip </div>
<div>
Estoy dentro de un ZIP</div>
</div>
<div>
<br /></div>
Y finalmente un poco de Diversión para cerrar estas <b>3 Partes de Rockeandola con Python</b><br />
<br />
Parece que alguien alguna vez estaba hecho un poeta escribió una poesia sobre python y sus bases estéticas o de ideales. Esto pareció gustar tanto que fue incluida en el código fuente y al hacer lo siguiente se puede leer.<br />
<br />
In [1]: import this<br />
The Zen of Python, by Tim Peters<br />
<br />
Beautiful is better than ugly.<br />
Explicit is better than implicit.<br />
Simple is better than complex.<br />
Complex is better than complicated.<br />
Flat is better than nested.<br />
Sparse is better than dense.<br />
Readability counts.<br />
Special cases aren't special enough to break the rules.<br />
Although practicality beats purity.<br />
Errors should never pass silently.<br />
Unless explicitly silenced.<br />
In the face of ambiguity, refuse the temptation to guess.<br />
There should be one-- and preferably only one --obvious way to do it.<br />
Although that way may not be obvious at first unless you're Dutch.<br />
Now is better than never.<br />
Although never is often better than *right* now.<br />
If the implementation is hard to explain, it's a bad idea.<br />
If the implementation is easy to explain, it may be a good idea.<br />
Namespaces are one honking great idea -- let's do more of those!<br />
<div>
<br /></div>
Otra cosa muy interesante es, que es lo que pasa, cuando escribís en la consola interactiva de python "import antigravity". Yo diría que eso, es lo que siente uno cuando escribe en Python, que puede hacer un import y empezar a programar la Matrix misma.<br />
<br />
[0] http://magmax.org/2013/09/30/python-avanzado.html<br />
[1] http://effbot.org/zone/python-with-statement.htm<br />
[2] http://docs.fabfile.org/en/1.6/api/core/context_managers.html<br />
[3] http://docs.python.org/3/library/functools.html#functools.partial<br />
[4] http://tech.pro/tutorial/1520/partial-function-application-in-pythonGonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-32511984822230404082014-03-01T17:38:00.003-03:002014-03-01T17:38:57.445-03:00Patrones de Diseño - GoF - Introducción<br />
<b>"Programa una interfaz, no una implementación"</b><br />
<br />
No declares variables para ser instancias especiales de una clase concreta. En su lugar, genera solo una interfaz definida por una clase abstracta.<br />
<br />
<b>Herencia Vs Composición</b><br />
<br />
<b>La herencia</b> indica que una clase hereda muchas o todas sus características de una (o más) clase padre.<br />
<br />
Cuando en Python hacemos<br />
<br />
class Padre(object):<br />
def saltar(self):<br />
print 'Estoy saltando'<br />
<br />
class Hijo(Padre):<br />
pass<br />
<br />
Estamos diciendo que la clase Hijo hereda de Padre y le escribimos un "pass" para decir que no vamos a definir nada nuevo en esa clase. Entonces lo que sucederá es que el hijo va a heredar todo el comportamiento de su padre en este caso la clase hijo tiene de manera implícita el método "saltar" que hereda de su "Padre"<br />
<br />
Hay otros detalles sobre el uso de herencias múltiples en Python que van a poder ver con más detalle en los links de referencia al final del Post [0]<br />
<br />
<b>La composición</b> es definida en tiempo de ejecución a través de un objeto que adquiere referencias a otro objeto.Es un objeto que usa la interfaz de otro objeto lo que genera que se tenga que tener especial cuidado en el diseño. Y el objeto referenciado puede ser cambiado siempre que mantenga las mismas interfaces.<br />
<br />
Un ejemplo de composición podría ser el siguiente:<br />
<br />
Class HabilidadSalto(objetc):<br />
def ejecutar(self):<br />
print 'Estoy saltando'<br />
<br />
Class Persona(object):<br />
def __init__(self):<br />
self.habilidadSaltar = HabilidadSalto()<br />
<br />
def saltar(self):<br />
self.habilidadSaltar.ejecutar()<br />
<br />
No estoy seguro de que sea un ejemplo muy adecuado pero es aproximadamente a lo que se refiere básicamente un objeto tiene dentro suyo una referencia a otro objeto y usa la interfaz de este último para llamar a acciones concretas.<br />
<br />
<b>"Favorece la composición de objetos por sobre la herencia de clases"</b><br />
<b><br /></b>
<b>Delegación</b><br />
<b><br /></b>
La delegación es una manera de hacer composición tan potente para su reutilización como la herencia.<br />
Dos objetos son los involucrados donde uno recibe el pedido y delega la operación a su delegado. Un ejemplo podría ser el siguiente que yo escribí en Python basándome en la explicación del libro [1] Design Patterns de GoF.<br />
<br />
class Rectangulo(object):<br />
def __init__(self, ancho, alto):<br />
self.ancho = ancho<br />
self.alto = alto<br />
<br />
def Area(self):<br />
return self.ancho * self.alto<br />
<br />
class Ventana(object)<br />
def __init__(self, ancho, alto):<br />
self.rectangulo = Rectangulo(ancho, alto)<br />
<br />
def Area(self):<br />
self.rectangulo.Area()<br />
<br />
Esto tiene ventajas como que la ventana podría cambiar su comportamiento en tiempo de ejecución tan solo reemplazando la referencia a la clase Rectángulo por una referencia a otra clase Circular. Esto suponiendo que Circular y Rectángulo son del mismo tipo.<br />
<br />
Las siguientes son causas comunes para el rediseño y como los patrones de diseño ayudan en ellas.<br />
<br />
1. La creación de un objeto especificando una clase explicitamente. Especificar una nombre de clase cuando creas un objeto te compromete con una implementación particular, en vez de una particular interfaz.<br />
Patrones de Diseño: Abstract Factory, Factory Method, Prototype.<br />
<br />
2. Dependencia de operaciones especificas. Cuando especificas una operación particular, te comprometes a una manera de satisfacer un pedido. Para evitar solicitudes codificadas específicamente, deberías hacer más fácil cambiar la manera en que un pedido es satisfecho ambos en tiempo de compilación y en tiempo de ejecución.<br />
Patrones de Diseño: Chain of Responsibility, Command.<br />
<br />
3. Dependencia de la plataforma de Software y Hardware. Las Interfaces externas del sistema operativo y de la interfaces de programación de la aplicación (APIs) son diferentes en diferentes plataformas de hardware y software. Es importante por lo tanto que el diseño de tu sistema limite las dependencias de la plataforma.<br />
Patrones de Diseño: Abstract Factory, Bridge<br />
<br />
<b>4. Dependencia de representaciones de objetos o implementaciones. </b>Los clientes que conocen como un objeto es representado, almacenado, asignado o implementado. puede ser que necesiten ser cambiados cuando el objeto cambie. Esconder esta infroma de los clientes mantiene los cambios en cascada.<br />
Patrones de Diseño,: Abstract Factory, Bridge, Memento, Proxy.<br />
<br />
5. Dependencias Algorítmicas. Los algoritmos son a menudo extendidos, optimizados, y reemplazados durante el desarrollo y reuso. Los objetos que dependan de un algoritmo tendrán que cambiar cuando el algoritmo cambie.<br />
Patrones de diseño: Builder, Iterator, Strategy, Template, Method, Visitor.<br />
<br />
6. Estrecho acoplamiento. Las clases que están estrechamente acopladas son dificiles de reusar en aislación, ya que dependen una de otra. El estrecho acoplamiento lleva a sistema moniliticos, donde no puedes cambiar o eliminar una clase sin entender o cambiar muchas otras clases.<br />
El Acoplamiento débil incrementa la probabilidad de que una clase puede ser reusada por si misma y que un sistema pueda ser aprendido, portado, modificado, y extendido más fácilmente.<br />
Patrones de Diseño: Abstract Factory, Bridge, Chain of responsibility, Command, Facade, Mediator, Observer.<br />
<br />
7. Extender funcionalidad subclasificando. La personalización de un objeto por subclaseo a menudo no es fácil. Cada nueva clase tiene un implementación fijada desde el vamos (inicialización, finalización, etc). Definir una subclase requiere un profundo entendimiento de la clase padre.<br />
La composición en general y la delegación en paticular proveen alternativas flexibles a la herencia por combinación de comportamientos. Nuevas funcionalidades pueden ser agregadas a nuevas subclases por la composición de objetos en nuevas maneras antes que definir nuevas subclases de clases existentes.<br />
Patrons de Diseño: Bridge, Chain of Reponsibility, Composite, Decorator, Observer, Strategy<br />
<br />
8 Inhabilidad de alterar clases convenientemente. A veces tiene que modificar una clase que no puede ser modificada convenientemente. Quizás necesitas el código fuente y no lo tienes (como sería el caso de una librería comercial). O tal vez cualquier cambio requerirá la modificación de muchas de las subclases existentes. Los patrones de diseño ofrecen varias maneras de modificar clases en estas circunstancias.<br />
Patrones de Diseño: Adapter, Decorator, Visitor.<br />
<br />
En subsiguientes Posts estaré resumiendo o explicando según mi entendimiento otras partes de este libro que comencé a leer y que me interesa bastante.<br />
<br />
[0] http://learnpythonthehardway.org/book/ex44.html<br />
[1] http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-30390086179076663462014-02-23T01:26:00.001-03:002014-03-01T22:51:11.477-03:00Rockeandola con Python Parte 2Siguiendo los pasos de magmax [0]<br />
<br />
<b>Diccionarios que se comportan como objetos</b><br />
<br />
En este ejemplo vamos a crear una clase que hereda todas las funcionalidades de un diccionario solo vamos a modificar las funciones de obtener el atributo y de asignarle un atributo para interfacearlos con los del diccionario.<br />
<br />
Esta es la definición de la clase:<br />
<br />
class DictObject(dict):<br />
def __getattr__(self, key):<br />
return self[key]<br />
<br />
def __setattr__(self, key, value):<br />
self[key] = value<br />
<br />
Esta es la implementación de la misma.<br />
<br />
>>> d = DictObject()<br />
>>> d['uno'] = 'one'<br />
>>> d.uno<br />
'one'<br />
>>> d['uno']<br />
'one'<br />
<br />
Hacer esto nos genera un inconveniente por que las clases para los atributos tienen ciertas restricciones como que no se pueden comenzar con números, contener espacios ni otros signos de puntuación por consiguiente va a haber valores que no vamos a poder usar.<br />
<br />
<b>Closures == Clausura <> Torneo Clausura</b><br />
<br />
Siguiendo una recomendación que se dá en los comentarios del Post de JuanjoConti[1] voy a tratar de contarles antes de empezar con los decoradores que es un Closure.<br />
<br />
<blockquote class="tr_bq">
En <a href="http://es.wikipedia.org/wiki/Inform%C3%A1tica">Informática</a>, una clausura es una función que es evaluada en un entorno conteniendo una o más <a href="http://es.wikipedia.org/wiki/Variable_(programaci%C3%B3n)">variables</a> dependientes de otro entorno. Cuando es llamada, la función puede acceder a estas variables. El uso explícito de clausuras se asocia con <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_funcional">programación funcional</a> y con lenguajes como el <a href="http://es.wikipedia.org/wiki/ML">ML</a> y el <a href="http://es.wikipedia.org/wiki/Lisp">Lisp</a>. Construcciones como los objetos en otros lenguajes pueden ser también modelados con clausuras. [2]</blockquote>
Un ejemplo de clausura es puede observar en la implementación de los decoradores a continuación.<br />
<br />
<b>Decoradores</b><br />
<br />
Un decorador es una función 'a' que recibe como argumento otra función 'b' y devuelve una función 'c' que es la función 'b' decorada con 'a'.<br />
<br />
Imaginemos que necesitamos loggear el acceso y salida de una función por pantalla.<br />
<br />
>>> def avisar(f):<br />
... def inner(*args, **kwargs): ## Esta es una clausura<br />
... print 'Se ejecuta la funcion %s' % f.__name__<br />
... f(*args, **kwargs)<br />
... print 'Se termino de ejecutar %s' % f.__name__<br />
... return inner<br />
...<br />
>>> def SumaLoca(a,b):<br />
... print a + b<br />
...<br />
>>> SumaLoca(10,5)<br />
15<br />
>>> avisarSumaLoca = avisar(SumaLoca)<br />
>>> avisarSumaLoca(10,6)<br />
Se ejecuta la funcion SumaLoca<br />
16<br />
Se termino de ejecutar SumaLoca<br />
<br />
Ahora esta función decorada nos avisará sobre su ejecución o finalización.<br />
<br />
Desde Python 2.4 en adelante se ha añadido Azucar a la cosa esto lo hace un lenguaje más dulce (Cuak!) ( a esto se le llama Azucar Sintáctica) y nos permite hacer lo mismo pero de la siguiente forma.<br />
<br />
>>> @avisar<br />
... def SumaLoca(a,b):<br />
... print a + b<br />
...<br />
>>> SumaLoca(10,6)<br />
Se ejecuta la funcion SumaLoca<br />
16<br />
Se termino de ejecutar SumaLoca<br />
<br />
Esta es una manera mucho más visual para hacerlo.<br />
<br />
Una explicación mucho mejor al respecto van a encontrar en la edición Nro 4 de TheOriginalHackers [3] que está pronta a salir [4].<br />
<br />
<b>@staticmethod @classmethod</b><br />
<br />
Leyendo un poco para arrancar esta seríe de Posts! es que entré al Blog de magmax y encontré la solución a algo que siempre me pregunté. Por ejemplo para que quiero el parametro self en una método de una clase cuando ese método no toca nada de la clase. Bueno a explicarlo.<br />
<br />
@staticmethod es un decorador que se utiliza para crear metodos que no requieren acceso a la clase principal.<br />
@classmethod es decorador que reemplaza el paso de la variable self (que es una instancia de la clase) que es la predeterminada en cada metodo de una clase por la clase misma (o sea sin implementar).<br />
<br />
Un ejemplo excelente de un buen uso acá [5]<br />
<br />
<b>Generadores </b><br />
<b><br /></b>
Son funciones que devuelven resultados poco a poco y para esto lo hacen retornando un valor y retomando la ejecución desde ese punto en adelante generalmente dentro de alguna instrucción de bucle o repetición.<br />
<br />
Ejemplo Kamikaze mío tiene que ver en crear un metodo que recorra urls y devuelva el titulo de la web de a poco.<br />
<br />
from BeautifulSoup import BeautifulSoup as bs<br />
import urllib<br />
<br />
urls = ['http://www.google.com.ar', 'http://facebook.com', 'http://infobae.com.ar']<br />
<br />
def recorrer_urls(urls):<br />
for url in urls:<br />
html = urllib.urlopen(url).read()<br />
soup = bs(html)<br />
yield soup.title<br />
<div>
<br /></div>
In [2]: recorrer_urls(urls)<br />
Out[2]: <generator 0x8c6d144="" at="" object="" recorrer_urls=""></generator><br />
<br />
In [3]: gen_urls = recorrer_urls(urls)<br />
<br />
In [4]: gen_urls.next()<br />
Out[4]: <title>Google</title><br />
<br />
In [5]: gen_urls.next()<br />
Out[5]: <title id="pageTitle">¡Bienvenido a Facebook en Español!</title><br />
<br />
In [6]: gen_urls.next()<br />
Out[6]: <title>"El Chapo" Guzmán - Tragedia de Once - WhatsApp - Telegram - Paritarias - Crisis política en Venezuela - Fotos - Infobae</title><br />
<div>
<br /></div>
Esto es interesante cuando necesitemos recorrer una serie de datos pero no necesitamos que todos sean devueltos al mismo tiempo sino que se van generando dinamicamente uno a uno. [6]<br />
<br />
[0] <a href="http://magmax.org/2013/09/30/python-avanzado.html">http://magmax.org/2013/09/30/python-avanzado.html</a><br />
[1] <a href="http://www.juanjoconti.com.ar/2008/07/11/decoradores-en-python-i/">http://www.juanjoconti.com.ar/2008/07/11/decoradores-en-python-i/</a><br />
[2] <a href="http://es.wikipedia.org/wiki/Clausura_(inform%C3%A1tica)">http://es.wikipedia.org/wiki/Clausura_(inform%C3%A1tica)</a><br />
[3] <a href="http://www.originalhacker.org/">http://www.originalhacker.org/</a><br />
[4] <a href="http://blog.deploshark.com.ar/2014/02/the-original-hacker-nro4.html">http://blog.deploshark.com.ar/2014/02/the-original-hacker-nro4.html</a><br />
[5] <a href="http://stackoverflow.com/a/12179752">http://stackoverflow.com/a/12179752</a><br />
[6] <a href="http://www.alvarohurtado.es/generadores-en-python/">http://www.alvarohurtado.es/generadores-en-python/</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-2291312187845156522014-02-22T22:44:00.002-03:002014-02-22T22:44:53.137-03:00The Original Hacker Nro4Llegará prontamente una nueva edición de <b><i>OriginalHacker</i></b>[0], que continua con la misma dedicación en la explicación y con una exactitud teórica y práctica que asombra linea a linea.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCYp5ddhLKwFeCWIjnKk9Kova5rjhowoIsxAnZ-9juJ6my4Lsa5-MVXGL4nu2Ol6nQ6_oHyOcQuGfo-AqXUo8pjN1PGPs5sA7a2ERBxq7jnR9kQFJHD6jDmoe4iA0Zgr016pdCxdoMsJ7/s1600/tapa4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCYp5ddhLKwFeCWIjnKk9Kova5rjhowoIsxAnZ-9juJ6my4Lsa5-MVXGL4nu2Ol6nQ6_oHyOcQuGfo-AqXUo8pjN1PGPs5sA7a2ERBxq7jnR9kQFJHD6jDmoe4iA0Zgr016pdCxdoMsJ7/s1600/tapa4.png" height="400" width="282" /></a></div>
<br />
Es tán copado y entretenido para quienes nos gusta hacer mover nuestro cerebro que cuando terminás de leerlo te quedás con ganas de más.<br />
<br />
<h3>
<i><b>En esta entrega que sale a la Luz el próximo 25 de Febrero nos encontraremos con lo siguiente.</b></i></h3>
<br />
[Bash Scripting Avanzado] Bash un lenguaje que viene instalado por defecto en todos nuestros Linuxes del que Eugenia nos sigue mostrando su magía.<br />
<br />
[Seguridad Informática] Se presenta y explica EuropioCode [1] una implementación de Seguridad respetando el modelo SAC, que también será brevemente explicado en el proceso.<br />
<br />
[Ingeniería Inversa] Debo aceptar que esta es la sección que más estoy disfrutando en la primera nos involucramos en el proceso de desarrollo y sus pasos para aplicar "Ingenieria Inversa" como corresponde en nuestras aventuras de desarrollo.<br />
<br />
[Ingenieria Inversa] El segundo amor de Eugenia (Python) y la mejor explicación que encontré (o que me encontró a mí) sobre Decoradores y Wrappers que dejará por el piso mi intención de explicar en mi publicación "Rockeandola Con Python Parte 2" (que saldrá en unos minutos o mañana no lo sé aún)<br />
<br />
[EuropioEngine Lab] Como es aplicada la Capa de Seguridad desarollada para EuropioEngine. [2]<br />
<br />
[0] <a href="http://originalhacker.org/">originalhacker.org</a><br />
[1] <a href="https://launchpad.net/europiocode">https://launchpad.net/europiocode</a><br />
[2] <a href="http://www.europio.org/">http://www.europio.org/</a>GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-76273996290418600862014-02-19T00:51:00.001-03:002014-02-19T00:56:38.739-03:00Rockeandola con Python Parte 1Tomando como base un Post [0] muy interesante del que dejo referencia más abajo intentaré ahondar en mi propia explicación sobre lo que aprendí al respecto, ya que estoy en un momento en el que intento mejorar y profesionalizar mi forma de escribir código Python.<br />
<br />
Métodos Mágicos [1]<br />
<br />
<blockquote class="tr_bq">
<span style="background-color: #fafafa; color: #111111; font-family: Georgia, serif; font-size: 17px; line-height: 23px;">What are magic methods? They're everything in object-oriented Python. They're special methods that you can define to add "magic" to your classes.</span></blockquote>
Estos métodos normalmente están encerrados entre "__" (doble guion bajo o underscore para los que saben inglés). Un ejemplo es __add__ que se llama cuando se hace entre dos objetos la operación de suma. En el Shell Interactivo de Python le pedimos un poco de ayuda sobre que hace el Entero 4 y nos dice lo siguiente
<br />
<br />
>>> help(4)<br />
Help on int object:<br />
<br />
class int(object)<br />
| int(x[, base]) -> integer<br />
<div>
(Resumido)</div>
<div>
<div>
| __add__(...)</div>
<div>
| x.__add__(y) <==> x+y</div>
</div>
<div>
<br /></div>
Entonces podríamos hacer cosas Interesantes o locas como por ejemplo<br />
<br />
class Hombre(object):<br />
def __init__(self, nombre):<br />
self.nombre = nombre<br />
<br />
def __add__(self, Persona):<br />
if isinstance(Persona, Mujer):<br />
return Hijo()<br />
<br />
class Mujer(object):<br />
def __init__(self, nombre):<br />
self.nombre = nombre<br />
<br />
def __add__(self, Persona):<br />
if isinstance(Persona, Hombre):<br />
return Hijo()<br />
<br />
class Hijo(object):<br />
def __init__(self):<br />
self.nombre = raw_input('Despues de nueve meses has tenido un hijo\nPonle un nombre: ')<br />
<br />
>>> from suma_clases import *<br />
>>> juan = Hombre('Juan')<br />
>>> martina = Mujer('Martina')<br />
>>> hijo = juan + martina<br />
Despues de nueve meses has tenido un hijo<br />
Ponle un nombre: Sergio<br />
>>> hijo.nombre<br />
'Sergio'<br />
<div>
<br /></div>
Este es un ejemplo burdo pero imagínense las posibilidades? Hacer suma de objetos que cambien dinamicamente su comportamiento o contengan comportamientos nuevos según si se lo suma con tal o cual otro. Además de la legibilidad que le agrega hacer una suma como una suma y no con una funcion llamada sumar() o add(). Lo mismo se puede hacer con muchas otras cosas como por ejemplo para comparar si dos objetos son iguales. [2]<br />
<br />
Se muestra el ejemplo de agregarle el eq a la clase mujer:<br />
class Mujer():<br />
(Resumido)<br />
def __eq__(self, Persona):<br />
if isinstance(Persona, Hombre):<br />
print 'Todos somos iguales'<br />
return True<br />
else:<br />
return False<br />
<div>
<br /></div>
>>> from suma_clases import *<br />
>>> juan = Hombre('Juan')<br />
>>> martina = Mujer('Martina')<br />
>>> juan == martina<br />
Todos somos iguales<br />
True<br />
<div>
<br /></div>
Por lo que aprender a usar BIEN estos métodos mágicos seguramente te ayude a hacer hermosas APIs y código no solo más legible sino más bonito.<br />
<br />
Otro cosa que me tocó hacer para un proyecto del trabajo es sobrecargar el __setattr__ de SQLObject para que haga un trigger o update en una tabla cuando se cambiaba cierta columna que es representada como una propiedad de esa clase.<br />
<br />
Esto lo hice con el ejemplo que transcribo acá [3].<br />
<br />
<pre style="background-color: white; border-bottom-color: rgb(170, 204, 153); border-bottom-width: 1px; border-style: solid none; border-top-color: rgb(170, 204, 153); border-top-width: 1px; color: #252a24; line-height: 15.600000381469727px; overflow-x: auto; overflow-y: hidden; padding: 5px;"><span class="k" style="color: #007020; font-weight: bold;">class</span> <span class="nc" style="color: #0e84b5; font-weight: bold;">Comment</span><span class="p">(</span><span class="n">SQLObject</span><span class="p">):</span>
<span class="n">User</span> <span class="o" style="color: #666666;">=</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s" style="color: #4070a0;">'TG_User'</span><span class="p">)</span>
<span class="n">Created</span> <span class="o" style="color: #666666;">=</span> <span class="n">DateTimeCol</span><span class="p">(</span><span class="n">notNone</span><span class="o" style="color: #666666;">=</span><span class="bp" style="color: #007020;">True</span><span class="p">,</span> <span class="n">default</span><span class="o" style="color: #666666;">=</span><span class="n">datetime</span><span class="o" style="color: #666666;">.</span><span class="n">now</span><span class="p">())</span>
<span class="n">Modified</span> <span class="o" style="color: #666666;">=</span> <span class="n">DateTimeCol</span><span class="p">(</span><span class="n">notNone</span><span class="o" style="color: #666666;">=</span><span class="bp" style="color: #007020;">True</span><span class="p">,</span> <span class="n">default</span><span class="o" style="color: #666666;">=</span><span class="n">datetime</span><span class="o" style="color: #666666;">.</span><span class="n">now</span><span class="p">())</span>
<span class="n">Subject</span> <span class="o" style="color: #666666;">=</span> <span class="n">StringCol</span><span class="p">(</span><span class="n">length</span><span class="o" style="color: #666666;">=</span><span class="mi" style="color: #208050;">200</span><span class="p">)</span>
<span class="n">Body</span> <span class="o" style="color: #666666;">=</span> <span class="n">StringCol</span><span class="p">()</span>
<span class="k" style="color: #007020; font-weight: bold;">def</span> <span class="nf" style="color: #06287e;">__setattr__</span><span class="p">(</span> <span class="bp" style="color: #007020;">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="p">):</span>
<span class="nb" style="color: #007020;">super</span><span class="p">(</span> <span class="n">Comment</span><span class="p">,</span> <span class="bp" style="color: #007020;">self</span> <span class="p">)</span><span class="o" style="color: #666666;">.</span><span class="n">__setattr__</span><span class="p">(</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="p">)</span>
<span class="k" style="color: #007020; font-weight: bold;">if</span> <span class="n">name</span> <span class="ow" style="color: #007020; font-weight: bold;">in</span> <span class="bp" style="color: #007020;">self</span><span class="o" style="color: #666666;">.</span><span class="n">sqlmeta</span><span class="o" style="color: #666666;">.</span><span class="n">columns</span><span class="o" style="color: #666666;">.</span><span class="n">keys</span><span class="p">():</span>
<span class="nb" style="color: #007020;">super</span><span class="p">(</span> <span class="n">Comment</span><span class="p">,</span> <span class="bp" style="color: #007020;">self</span> <span class="p">)</span><span class="o" style="color: #666666;">.</span><span class="n">__setattr__</span><span class="p">(</span> <span class="s" style="color: #4070a0;">'Modified'</span><span class="p">,</span> <span class="n">datetime</span><span class="o" style="color: #666666;">.</span><span class="n">now</span><span class="p">()</span> <span class="p">)</span></pre>
<br />
En mi caso además de modificar la fecha de actualización en la tabla debía agregar unos datos en una tabla que sirve como historial.<br />
<br />
Atributos bajo demanda<br />
<br />
En python todo funciona como fuera un diccionario por eso se pueden listar todos los atributos llamando al atributo de solo lectura llamada __dict__<br />
<br />
>>> juan = Hombre('Juan')<br />
>>> juan.__dict__<br />
{'nombre': 'Juan'}<br />
Usando ese atributo __dict__ podemos por ejemplo agregarle a esa instancia un atributo que no viene en la Clase de la que fue instanciada. Como por ejemplo<br />
<div>
>>> juan.__dict__['nombre_falso'] = 'Pedro'</div>
<div>
<div>
>>> juan.__dict__</div>
<div>
{'nombre': 'Juan', 'nombre_falso': 'Pedro'}</div>
</div>
<div>
<div>
>>> juan.nombre_falso</div>
<div>
'Pedro'</div>
</div>
<div>
<br /></div>
<div>
Algo mucho más interesante para hacer es utilizarlo para hacer que una clase tenga como atributos cualquier cosa que se le pase como parámetros nombrados.</div>
<div>
<br /></div>
<div>
<div>
class Example(object): </div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>def __init__(self, **kwargs): </div>
<div>
<span class="Apple-tab-span" style="white-space: pre;"> </span>self.__dict__.update(kwargs)</div>
</div>
<div>
<br /></div>
<div>
Que se usaría de esta manera.</div>
<div>
<br /></div>
<div>
<div>
>>> ej = Example(nombre='Gonzalo', perro='Chicho', facebook=True)</div>
<div>
>>> ej.nombre</div>
<div>
'Gonzalo'</div>
<div>
>>> ej.perro</div>
<div>
'Chicho'</div>
<div>
>>> ej.facebook</div>
<div>
True</div>
</div>
<div>
<br /></div>
<div>
El post de magmax es más largo y yo lo voy a partir en pedacitos para ver si además de decirlo con mis palabras lo puedo extender con experiencias propias. Asi que los veo en las siguientes partes.</div>
<br />
[0] http://magmax.org/2013/09/30/python-avanzado.html<br />
[1] http://www.rafekettler.com/magicmethods.html<br />
[2] http://www.rafekettler.com/magicmethods.html#comparisons<br />
[3] http://turbogears.org/1.0/docs/SQLObject/AutoUpdateField.html<br />
<br />GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0tag:blogger.com,1999:blog-5700899517559664773.post-53262943414855997882014-02-08T15:44:00.001-03:002014-02-08T15:44:56.848-03:00Patrones y Tácticas ArquitecturalesUn patrón arquitectural<br />
<br />
<br />
<ul>
<li>Es un paquete de decisiones de diseño que es encontrado repetidamente en la práctica.</li>
<li>tiene propiedades conocidas que permiten reusarlo, y</li>
<li>describe una clase de arquitecturas</li>
</ul>
<div>
Por que los patrones son (por definición) encontrados repetidamente en la práctica, uno no los inventa; uno los descubre.</div>
<div>
Las tácticas son más simples que los patrones. Las tácticas tipicamente usan solo una simple estructura o mecanismo computacional, y están destinados a significar una simple fuerza arquitectónica. Por esta razón se les da un control más preciso a un arquitecto cuando hace decisiones de diseño de patrones, que tipicamente combina múltiples decisiones de diseño en un paquete. Las tácticas son los "bloques de construcción" de diseño a partir del cual los patrones arquitecturales son creados. Las tácticas son átomos y los patrones son moléculas. </div>
<div>
<br /></div>
<div>
Un patrón arquitectural establece una relación entre ellos:</div>
<div>
<ul>
<li>Un contexto. Una recurrente, situación común en el mundo que da a plantear un problema.</li>
<li>Un problema. El problema, apropiadamente generalizado, que surge en el contexto dado.</li>
<li>Una solución. Una resolución arquitectural exitosa a el problema.</li>
</ul>
<div>
Sistemas complejos exhiben múltiples patrones de una sola vez.</div>
</div>
<div>
<br /></div>
<div>
Los patrones pueden ser categorizados por el tipo de elementos dominante que muestran. patrones de módulos, muestran módulos. patrones de conectores-componentes muestran componentes y conectores. y los patrones de asignación muestran una combinación de elementos de software (módulos, componentes, conectores ) y elementos que no son de software. Los patrones más publicados son los patrones C&C, pero hay patrones de módulos y de asignación también. </div>
<div>
<br /></div>
<div>
Un patrón es descrito como una solución a una clase de problemas en un contexto general. Cuando un patrón es elegido y aplicado, el contexto de esta aplicación se vuelve muy especifico. Un patrón documentado por lo tanto es poco especifico con respecto a la aplicación de una situación especifica. Podemos hacer un patrón más especifico a nuestro problema añadiéndole tácticas. Aplicando tácticas sucesivas es como pasar a través de un espacio de juego, y es un poco como el ajedrez: las consecuencias de el siguiente movimiento son importantes y observas varios movimientos por adelantado es útil.</div>
GonzaMartinezhttp://www.blogger.com/profile/17785873687297260815noreply@blogger.com0