Joaquin Tita: About Design

We live surrounded by tons of products that are no longer ordinary or inactives. Most of them are interactive and because we are so used to them, we are not conscious in what manner they contribute to our daily live. Those devices I'm talking about are mobile phones, personal computers, coffee machines, printers, videogames, just to list a few of them.
The important question here is: How many are easy to use and enjoyable without making a huge effort?
Of course, this is pretty easy to answer and the list will be quite small!
Sometimes we end up hammering our heads against the wall because we are not able to complete the desired task with this product.
Why this happens?
The answer is because some products were not designed with the user in mind.
The aim of interaction design is to solve these kind of issues bringing usability to the design process. That is, developing products that are easy, effective, and enjoyable to use from the user perspective.

Good Design vs Poor Design 
A good way to start thinking when a product has a good or bad interactive design is explore some examples that reflect the concept we are looking for.
Hitting the radio
Why I cannot use the radio while carrying my beverages?

Coffee Machine
In this coffee machine after inserting the coins in the slot you have to select your coffee bean. So, you press the rectangular labels to select your coffee but...they are not buttons! Probably you might think this because of Coke Can Machines work that way but...these ones not. Mmm...this is really working? Lets press the + or - sign that supposedly controls the amount of sugar...Wait WHAT? they are not buttons! After 10 minutes standing at the machine you can distinguish BLACK rounded buttons with BLACK background. Clearly a bad design!

Keyboard Layout
The guy who came up with this amazing design should be in prison right now. In fact, a friend used to have this keyboard. I never was able to use it. Every time I wrote something, suddenly the computer shut down unexpectedly...My friend always said to me "you probably has pressed the shut down key".  Nice...thanks for the two hours I have sent to the trash. Terrible design!

Thinking in What, Why and How
Suppose you have to design a new software product what would you do?
Start coding in a frenzy way until you are done with? Studying the characteristics of a well known similar software? Asking your end users about their experience, their problems, studying their tools and based on this start thinking about the what, why and how to design it? Probably the best approach would be the latter one. One of the main advantages is that you will definitely save money, time and effort.   

Conceptual Models
A good way to better understanding the problem domain is to develop conceptual models. By conceptual models we mean a description of the proposed system in terms of ideas and concepts about what it should do and look like also being understandable by the users. 
Developing conceptual models helps to envision the future product based on the user's needs and other requirements identified. As the product is being developed it is highly advisable to do iterative testing to ensure that it is designed to be understandable in the way that was planned. A key aspect in the design process is to identify what tasks the user will be doing when using the product. As with any aspect of interaction design, the process of filtering or cleaning the conceptual models should be done iteratively, using different methods such as sketching ideas, storyboards, brainstorming sessions (or visual brainstorming), describing scenarios (like "stories")  and prototyping aspects of how the system works.

Norman's Framework (1988)
One of the most important activities while developing a conceptual model is to determine if the users will understand the system in the manner intended. Norman presented a framework to make the relationship between the design of a conceptual model and the user's understanding be clearer.
Norman Framework
In this framework we can distinguish three different components:
  • the Design Model represents how the system should work, 
  • the System Image represents how the system actually works
  • the User's Model represents how he thinks the system works.
The point is that even though everybody should have the same idea or (metal model) of the system, real world doesn't work that way. Users, in most of the cases, are not able to complete their tasks effectively and error-free because their mental model is quite different from the Design Model and the System Image.
Jacob Nielsen wrote a blogpost explains a little bit what Mental Models are. In it, he says that mental models are "based on belief, not facts: that is, it's a model of what users know (or think they know) about a system such as your website". This definition brings to the light the discrepancies that Norman's Framework want to iron out. Also, "Metal Models" by Indi Young states that "metal models give you a deep understanding of people’s motivations and thought-processes, along with the emotional and philosophical landscape in which they are operating". Moreover, the author highlight the importance that these kind of models have. She summary this idea in the "three C's":


  • Confidence - guide the decision of the solution, 
  • Clarity - make good user and business decisions,
  • Continuity - ensure longevity of vision and opportunity.
Furthermore, Don Norman affirmed previously the idea that "the designer has an obligation to provide an appropriate conceptual model for the way that the device works. It doesn't have to be completely accurate, but it has to be sufficiently accurate that it will help in both the learning of the operation and also dealing with novel situations".


The Process of Design

Pabini Gabriel-Petit, a professional with more than 20 years of experience in User Experience and Design, in an article at uxmatter.com wrote that in the goal for achieving optimal design solutions, designers need an effective process that provides a framework to work with to deliver high quality work.
This should be a user-centered design (UCD) process, but also being a flexible process.  She came up with UC3D Lifecycle that comprises three phases: Discovery, Design, and Development Support.
UC3D Lifecycle - from uxmatters.com
The UC3D can be summarised in the following steps:
Discovery Phase:
  • Learning about your users 
Try to gain all the understanding possible of your users. Use your intuition to put yourself in your user's place. Once you truly understand your users, this understanding provides a basis for modelling your users. 
  • Modelling your users (like using model personas)
Once you are armed with all the information your group can develop profiles (or "personas" which are fictional user archetypes that are representative of your end users). Based on your information, you can develop a set of clearly differentiated user profiles whose goals and needs you intend your product to serve.
  • Analysing your user's tasks
This step comprise the identification of the tasks (task domain) that the user follow while using the future system and will be the basis for designing its workflows. Task analysis is an activity that can help you to understand much in depth the tasks.
  • Eliciting and Defining Clear Product Requirements
During this step requirements are clearly identified and prioritised. The working team will design and define what capabilities, features, and qualities your product must have. 

Design Phase:
  • Developing Conceptual Models
Conceptual modelling is an activity that helps your working group see your product's concepts, workflows, features, and language from your users's viewpoint and envision, define, and design products that are simpler, more consistent, and easier for users to understand.
  • Solving Key Design Problems Through Ideation
During ideation everyone on your working group has an opportunity to communicate requirements and constraints and contribute design ideas. Ideation involves rapidly generating many different possible workflows and user interface design solutions and capturing them by sketching designs on easel pads or whiteboards or in notebooks. As an example this can be seen in the video How Google fixed its design process and started making beautiful apps and also being part of the next step.
  • Doing Detailed Design
Once your working group has agreed on some basic design approaches during previous step, you will continue working on them during this step, continually refining your interaction design solutions by optimising workflows and interaction models, and creating design artifacts that communicate them effectively (like flowcharts and wireframes). All the feedback from the working group is taking into account to make more refinements on the design solutions. After all team is satisfied all stakeholders will approve design artifacts for implementation.

Development Support:
  • Providing Development Support
Your iterative process of design refinement should continue throughout product development as developers discover they need additional design details. All doubts that may arise should be answered by the working team to the people in charge of the development, and clarify design artifacts as necessary.
Also at this stage, if the testing reveals usability problems or usability issues you will need to do recheck your design solutions and artifacts. However, most of the usability issues you discover at this step are not addressed until the next product release. The Development Support Phase ends with the delivery of the (supposedly) high quality product that meets user's needs and is easy to learn and use.


Conclusion
Finally, if we can separate the less possible the Design Model and the User's Model making good conceptual models we will come up with understandable, enjoyable and easy to use products. In addition to have good conceptual models, expertise in the domain can help substantially. But, the implementation of an efficient design process such as UC3D will play a central role in the deliver of a high quality product.

Gonzalo Martinez: Rockeandola con Python Parte 3


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.

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.

With

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__
El ejemplo básico de este método es el de cerrar automáticamente el archivo cuando se sale de su alcance (scope).

with open('archivo.txt') as f:
    print(f.read())

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.

with cd('/path/to/app'):
    run('.mkdir una_carpeta')
    run('.wget http://unawebcopada.com.ar/el_archivo.tar.gz')

Partial

Parece ser común (todavia no me pasó) escribir el mismo método varias veces cambiando únicamente un parámetro.
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.

In [1]: from functools import partial
In [2]: base_dos = partial(int, base=2)
In [3]: base_dos.__doc__ = "Convierte texto de base 2 a un entero"
In [4]: base_dos('10010')
Out[4]: 18

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.

In [1]: from functools import partial
In [2]: def plantilla_log(nivel, mensaje):
   ...:         print("{}: {}".format(nivel, mensaje))
   ...:     
In [3]: log_info = partial(plantilla_log, "info")
In [4]: log_cuidado = partial(plantilla_log, "cuidado")
In [5]: log_error = partial(plantilla_log, "error")
In [6]: log_info('Este es un log informativo')
info: Este es un log informativo

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.

El amor entre Zip y Python 

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

admin@quicuo-kaizen:/tmp$ cat __main__.py 
print "Estoy dentro de un ZIP"
admin@quicuo-kaizen:/tmp$ zip ejemplo __main__.py 
updating: __main__.py (stored 0%)
admin@quicuo-kaizen:/tmp$ python ejemplo.zip 
Estoy dentro de un ZIP

Y finalmente un poco de Diversión para cerrar estas 3 Partes de Rockeandola con Python

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.

In [1]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

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.

[0] http://magmax.org/2013/09/30/python-avanzado.html
[1] http://effbot.org/zone/python-with-statement.htm
[2] http://docs.fabfile.org/en/1.6/api/core/context_managers.html
[3] http://docs.python.org/3/library/functools.html#functools.partial
[4] http://tech.pro/tutorial/1520/partial-function-application-in-python

Gonzalo Martinez: Patrones de Diseño - GoF - Introducción


"Programa una interfaz, no una implementación"

No declares variables para ser instancias especiales de una clase concreta. En su lugar, genera solo una interfaz definida por una clase abstracta.

Herencia Vs Composición

La herencia indica que una clase hereda muchas o todas sus características de una (o más) clase padre.

Cuando en Python hacemos

class Padre(object):
    def saltar(self):
        print 'Estoy saltando'

class Hijo(Padre):
    pass

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"

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]

La composición 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.

Un ejemplo de composición podría ser el siguiente:

Class HabilidadSalto(objetc):
    def ejecutar(self):
        print 'Estoy saltando'

Class Persona(object):
    def __init__(self):
        self.habilidadSaltar = HabilidadSalto()

    def saltar(self):
        self.habilidadSaltar.ejecutar()

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.

"Favorece la composición de objetos por sobre la herencia de clases"

Delegación

La delegación es una manera de hacer composición tan potente para su reutilización como la herencia.
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.

class Rectangulo(object):
    def __init__(self, ancho, alto):
        self.ancho = ancho
        self.alto = alto

    def Area(self):
        return self.ancho * self.alto

class Ventana(object)
    def __init__(self, ancho, alto):
        self.rectangulo = Rectangulo(ancho, alto)

    def Area(self):
        self.rectangulo.Area()

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.

Las siguientes son causas comunes para el rediseño y como los patrones de diseño ayudan en ellas.

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.
Patrones de Diseño: Abstract Factory, Factory Method, Prototype.

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.
Patrones de Diseño: Chain of Responsibility, Command.

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.
Patrones de Diseño: Abstract Factory, Bridge

4. Dependencia de representaciones de objetos o implementaciones. 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.
Patrones de Diseño,: Abstract Factory, Bridge, Memento, Proxy.

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.
Patrones de diseño: Builder, Iterator, Strategy, Template, Method, Visitor.

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.
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.
Patrones de Diseño: Abstract Factory, Bridge, Chain of responsibility, Command, Facade, Mediator, Observer.

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.
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.
Patrons de Diseño: Bridge, Chain of Reponsibility, Composite, Decorator, Observer, Strategy

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.
Patrones de Diseño: Adapter, Decorator, Visitor.

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.

[0] http://learnpythonthehardway.org/book/ex44.html
[1] http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612

Joaquin Tita: Review of Metaphor, myth and mimicry: the bases of software engineering

In the paper "Metaphor, myth, and mimicry: the bases of software engineering", Antony Bryant  analyses the problematic around the term "software engineering", exposing and discussing multiple point of views from different recognised authors over the last years concerning what brings with (as unwanted baggage) the use of the status "engineering" in software.

Bryant opens his paper saying that in the 80s the term wasn't problematic at all and used to be a "good thing" but with the pass of time, the concept was transformed into more activities than just ordinary programming. The idea that software had to be "engineered" gave an image of rigour, care and assurance. However, soon began to be often misunderstood. In the late 90s, there was a consensus over the term within the academic and research community. Later discussions threads on the electronic list from the Conference of Professors and Heads of Computing produced and accepted what involves research, the study of computing, informatics, software engineering and other related terminology. Anyhow, the ones that were senior academic understood it but not the ones that were outside that domain such as practitioners, wider engineering communities, potential students and so on. In this point, is where Bryant sets the dilemma that software developers wants to imitate engineers and demand the status of an engineering discipline but commercial demands and consumer desires do not support this. Likewise, he suggests that maybe the term by itself adds extra complexity or confusion. This is where he wants to focus much more in depth in the rest of his work.  

Looking much in depth the second section, the author tries to expose the distinct opinions of different authors about what software engineering is and fundamental key points to take into account. His goal is to reflect the ambiguity or unclearness of some ideas that still predominates over time caused by an emerging discipline that still needs to establish itself. Also, he strongly points out that terminology highly influence knowledge and the practice. [o] I think the terminology will always be an obstacle when it comes to the definition of software engineering. Consequently, the practice and domain will always be affected. 

Moving on to the third section, Brooks's classic paper "No Silver Bullet" comes into consideration to depict the dilemma of software engineering. Moreover, in his work he expressed his worry about the use of construction metaphors in software engineering (also referring at this as the replacement of a metaphor by another) that derive in a powerful impact on people's practices and cognition. From this, maybe the term "software engineering" itself its constraining rather helping in software development. At the end, the author of this paper poses the idea of rejecting metaphors altogether or at least admit the side effects of them. In my opinion, trying to eliminate all the existent metaphors can have serious drawbacks. People are used to them, they feel comfortable with them and literature from many years ago use it. Additionally, there will be cases where people will refuse in changing their way of thinking. Thus, the only suitable choice is admitting the drawbacks and live with them. Maybe, as an extreme idea, we could create new metaphors but again we will come again to the starting point of the discussion. 

In order to analyse and dismantle the engineering metaphor for software development, the author presents two examples. The first one, IT, illustrates how terminology generates a barrier for understanding what the term means. For instance, causing people erroneously apply for a job in IT or not applying to it. Frankly, I still have doubts about the definition of the term and I have always seen as clear example of how a word can blur a job or area.
The second one, requirements, is much more critical to software development practices. There is a general idea that requirements phase is seen as the most important and most difficult phase. Furthermore, the term "requirements engineering", is associated to activities that lead to the creation of the products of these phase. The terminology surrounding requirements for computer-based systems is replete with references to the engineering metaphor. Similarly, the idea that a good requirement specification should be clear, concise, concrete, and so on. Moreover, the assumption is that the requirement process must be systematic with some elements of formality and management. Bryant states that although the engineering metaphor provides a useful basis it's partially correct, arguing that it might obscure key features of the process.

I partially agree with Bryant in saying that metaphors hide or blur key aspects, but the reality also indicates that they also form a basic human mechanism to transform or interpret complex ideas or concepts in a more humane way. Personally, I don't think that metaphors obscure essential aspects if they are handled correctly.  

Also, to depict how communication can have a big impact in the interpretation of the ideas, the author explains the conduit metaphor. The underlying concept of the conduit metaphor is that the information is transferred from one point or person to another. Good communication flows without blockages and good reception involves extraction and unwrapping it. 

From my point of view, failure in the communication within all the parts involved is due a series of factors. As Davis stated paraphrasing Demarco, anyone involved in requirements should have strong human skills, communication skills, feeling skills and listening skills. Moreover, communication will fail without applying the proper effort. That is why I think that should be encouraged from the very first time.

Finally, the paper ends suggesting that the engineering metaphor moved us forward in the activity of developing a discipline for software development. I could not agree more with his statement. Personally, I believe that even though we are not seeing clearly where are we going or from where are we coming eventually we will find the appropriate foundation. Logically more discussions and new points of view will arise making us reformulate theory and concepts.

Gonzalo Martinez: Rockeandola con Python Parte 2

Siguiendo los pasos de magmax [0]

Diccionarios que se comportan como objetos

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.

Esta es la definición de la clase:

class DictObject(dict):
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

Esta es la implementación de la misma.

>>> d = DictObject()
>>> d['uno'] = 'one'
>>> d.uno
'one'
>>> d['uno']
'one'

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.

Closures == Clausura <> Torneo Clausura

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.

En Informática, una clausura es una función que es evaluada en un entorno conteniendo una o más variables dependientes de otro entorno. Cuando es llamada, la función puede acceder a estas variables. El uso explícito de clausuras se asocia con programación funcional y con lenguajes como el ML y el Lisp. Construcciones como los objetos en otros lenguajes pueden ser también modelados con clausuras. [2]
Un ejemplo de clausura es puede observar en la implementación de los decoradores a continuación.

Decoradores

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'.

Imaginemos que necesitamos loggear el acceso y salida de una función por pantalla.

>>> def avisar(f):
...     def inner(*args, **kwargs):  ## Esta es una clausura
...             print 'Se ejecuta la funcion %s' % f.__name__
...             f(*args, **kwargs)
...             print 'Se termino de ejecutar %s' % f.__name__
...     return inner
...
>>> def SumaLoca(a,b):
...     print a + b
...
>>> SumaLoca(10,5)
15
>>> avisarSumaLoca = avisar(SumaLoca)
>>> avisarSumaLoca(10,6)
Se ejecuta la funcion SumaLoca
16
Se termino de ejecutar SumaLoca

Ahora esta función decorada nos avisará sobre su ejecución o finalización.

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.

>>> @avisar
... def SumaLoca(a,b):
...     print a + b
...
>>> SumaLoca(10,6)
Se ejecuta la funcion SumaLoca
16
Se termino de ejecutar SumaLoca

Esta es una manera mucho más visual para hacerlo.

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].

@staticmethod @classmethod

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.

@staticmethod es un decorador que se utiliza para crear metodos que no requieren acceso a la clase principal.
@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).

Un ejemplo excelente de un buen uso acá [5]

Generadores 

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.

Ejemplo Kamikaze mío tiene que ver en crear un metodo que recorra urls y devuelva el titulo de la web de a poco.

from BeautifulSoup import BeautifulSoup as bs
import urllib

urls = ['http://www.google.com.ar', 'http://facebook.com', 'http://infobae.com.ar']

def recorrer_urls(urls):
    for url in urls:
        html = urllib.urlopen(url).read()
        soup = bs(html)
        yield soup.title

In [2]: recorrer_urls(urls)
Out[2]: 

In [3]: gen_urls = recorrer_urls(urls)

In [4]: gen_urls.next()
Out[4]: <title>Google</title>

In [5]: gen_urls.next()
Out[5]: <title id="pageTitle">¡Bienvenido a Facebook en Español!</title>

In [6]: gen_urls.next()
Out[6]: <title>"El Chapo" Guzmán - Tragedia de Once - WhatsApp - Telegram - Paritarias - Crisis política en Venezuela - Fotos - Infobae</title>

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]

[0] http://magmax.org/2013/09/30/python-avanzado.html
[1] http://www.juanjoconti.com.ar/2008/07/11/decoradores-en-python-i/
[2] http://es.wikipedia.org/wiki/Clausura_(inform%C3%A1tica)
[3] http://www.originalhacker.org/
[4] http://blog.deploshark.com.ar/2014/02/the-original-hacker-nro4.html
[5] http://stackoverflow.com/a/12179752
[6] http://www.alvarohurtado.es/generadores-en-python/

Gonzalo Martinez: The Original Hacker Nro4

Llegará prontamente una nueva edición de OriginalHacker[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.


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.

En esta entrega que sale a la Luz el próximo 25 de Febrero nos encontraremos con lo siguiente.


[Bash Scripting Avanzado] Bash un lenguaje que viene instalado por defecto en todos nuestros Linuxes del que Eugenia nos sigue mostrando su magía.

[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.

[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.

[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)

[EuropioEngine Lab] Como es aplicada la Capa de Seguridad desarollada para EuropioEngine. [2]

[0] originalhacker.org
[1] https://launchpad.net/europiocode
[2] http://www.europio.org/

Gonzalo Martinez: Rockeandola con Python Parte 1

Tomando 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.

Métodos Mágicos [1]

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.
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

>>> help(4)
Help on int object:

class int(object)
 |  int(x[, base]) -> integer
(Resumido)
|  __add__(...)
|      x.__add__(y) <==> x+y

Entonces podríamos hacer cosas Interesantes o locas como por ejemplo

class Hombre(object):
    def __init__(self, nombre):
        self.nombre = nombre

    def __add__(self, Persona):
        if isinstance(Persona, Mujer):
            return Hijo()

class Mujer(object):
    def __init__(self, nombre):
        self.nombre = nombre

    def __add__(self, Persona):
        if isinstance(Persona, Hombre):
            return Hijo()

class Hijo(object):
    def __init__(self):
        self.nombre = raw_input('Despues de nueve meses has tenido un hijo\nPonle un nombre: ')

>>> from suma_clases import *
>>> juan = Hombre('Juan')
>>> martina = Mujer('Martina')
>>> hijo = juan + martina
Despues de nueve meses has tenido un hijo
Ponle un nombre: Sergio
>>> hijo.nombre
'Sergio'

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]

Se muestra el ejemplo de agregarle el eq a la clase mujer:
class Mujer():
(Resumido)
    def __eq__(self, Persona):
        if isinstance(Persona, Hombre):
            print 'Todos somos iguales'
            return True
        else:
            return False

>>> from suma_clases import *
>>> juan = Hombre('Juan')
>>> martina = Mujer('Martina')
>>> juan == martina
Todos somos iguales
True

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.

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.

Esto lo hice con el ejemplo que transcribo acá [3].

class Comment(SQLObject):
User = ForeignKey('TG_User')
Created = DateTimeCol(notNone=True, default=datetime.now())
Modified = DateTimeCol(notNone=True, default=datetime.now())
Subject = StringCol(length=200)
Body = StringCol()

def __setattr__( self, name, value ):
super( Comment, self ).__setattr__( name, value )
if name in self.sqlmeta.columns.keys():
super( Comment, self ).__setattr__( 'Modified', datetime.now() )

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.

Atributos bajo demanda

En python todo funciona como fuera un diccionario por eso se pueden listar todos los atributos llamando al atributo de solo lectura llamada __dict__

>>> juan = Hombre('Juan')
>>> juan.__dict__
{'nombre': 'Juan'}
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
>>> juan.__dict__['nombre_falso'] = 'Pedro'
>>> juan.__dict__
{'nombre': 'Juan', 'nombre_falso': 'Pedro'}
>>> juan.nombre_falso
'Pedro'

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.

class Example(object): 
def __init__(self, **kwargs): 
self.__dict__.update(kwargs)

Que se usaría de esta manera.

>>> ej = Example(nombre='Gonzalo', perro='Chicho', facebook=True)
>>> ej.nombre
'Gonzalo'
>>> ej.perro
'Chicho'
>>> ej.facebook
True

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.

[0] http://magmax.org/2013/09/30/python-avanzado.html
[1] http://www.rafekettler.com/magicmethods.html
[2] http://www.rafekettler.com/magicmethods.html#comparisons
[3] http://turbogears.org/1.0/docs/SQLObject/AutoUpdateField.html

Hernán Grecco: A new PyVISA release is around the corner and we need your help

PyVISA is a Python wrapper for the VISA library that enables controlling control all kinds of measurement equipment through GPIB, RS232, USB and Ethernet. It has served the instrumentation community very well since 2005 (that's Python 2.3!) and still does.

However, Python and the different supported platforms have changed a lot in the recent years. We think that PyVISA can use an update. Within the Lantz Project we did a small proof of principle of such update in visalib. Now we are taking what worked well and use it into PyVISA 1.5 (without changing the API!). In other words, PyVISA 1.5 brings several important changes in the underlying architecture without forcing you to change the programs.

The new architecture is summarized here and the comparison with the previous one is here. Briefly you get Python 3 support, Mac OS X support, a better way to find libraries in your platform, an isolated ctypes wrapper. But the most important change is that the VISA library is not opened on import anymore. You can still use the instrument and get_instruments_list helpers (although we encourage not to do it!), but under the hood they will only instantiate a VisaLibrary object when you need them. We think that this will lead to more explicit and clear code, easier to deploy and to upgrade. There other small goodies around. Take a look at the docs.

We really need your help before uploading this to PyPI as an stable release. PyVISA is all about interacting with your operating system (finding and locating the C library) and you instruments. With the variety of platforms around, it is very difficult to test. We are asking all users to install PyVISA from the github repository and test it on your programs. You can do it safely on a virtual environment:

$ virtualenv --system-site-packages pyvisa15
$ cd pyvisa15
$ source bin/activate
$ pip install -U https://github.com/hgrecco/pyvisa/zipball/master

or just use the last line (you can always revert back to the pyvisa version that you were using before)

Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly. We even have

Read the docs: http://pyvisa.readthedocs.org/
or fork the code: https:/https://github.com/hgrecco/pyvisa/