segunda-feira, julho 06, 2009

Nokia vai mudar para Qt no Maemo

Como já era esperado a Nokia anunciou durante o GCDS que o Maemo 6 (Harmattan) vai trocar o GTK pelo Qt. Embora o Gnome Mobile continue sendo a base do sistema, a interface com usuário passa a utilizar Qt. Essa mudança era esperada devido a compra da Trolltech pela Nokia.

Mesmo sendo uma decisão esperada, ao meu ver a Nokia parece complicar ainda mais o já ruim processo de aceitação do Maemo e seus Internet Table NXXX pelo mercado. O atual Maemo 5 que ainda não foi lançado, foi basicamente reconstruído utilizando GTK/Clutter mudando totalmente a interface em relação ao seu antecessor o Maemo 4 que era basicamente GTK. Agora na próxima versão mais mudanças na interface com adoção do Qt.

O GTK ainda vai estar disponível no Maemo mantido pela comunidade, garantindo que aplicativos legados continuem funcionando mesmo que com visual diferente do sistema. Trocar de GTK para Qt não é uma simples mudança de ui toollkit mas também de linguagem já que Qt se baseia em C++ e GTK em C, ou seja, uma grande mudança para todos os desenvolvedores.

Na minha opnião, a Nokia mostra mais uma vez que as decisões em relação ao Maemo são tomados mais por diretores sem conhecimento e menos pelos técnicos ou ao menos demonstra que existe pouca sinergia entre esses dois grupos, já que não ter GSM no N810 e mudar completamente sua interface a cada versão não anima desenvolvedores para produzir aplicativos para essa plataforma e não traz novos usuários.

Tudo bem, Qt é uma excelente biblioteca, mas na minha opinião essa mudança já deveria ter sido feita no Maemo 5, evitando que novos aplicativos para o Maemo 5 tenham que portardos em seguida para o Maemo 6 quando estiver utilizando Qt.

Maemo é uma excelente plataforma e meu sonho de consumo é o futuro N900 assim que for lançado, mas espero que a Nokia tenho um pouco mais de cuidado com suas decisões em relação ao Maemo, afinal Android e Moblin estão criando excelentes plataformas.

terça-feira, junho 30, 2009

Sounding the Stars with Genetic Algorithms

Eu tenho muito interesse em computação aplicada na resolução de problemas reias, essa palestra que aconteceu no Google Sounding the Stars with Genetic Algorithms é um excelente exemplo.

O autor mostra um processo computacional automatizado utilizando Genetic Algorithm na busca de vida extraterrestre inteligente, comparando a freqüência emitida pelos astros com modelos conhecidos.

Mais vídeos como este em Google Research Tech Talks at Google.

quinta-feira, outubro 30, 2008

Decorators com argumentos

Nos últimos tempos estive escrevendo uma API que utiliza decorators para registrar eventos em uma aplicação PyGTK/Glade. Nessa API basicamente eu tenho eventos registrados no glade e associados a um handler na aplicação (glade.sinal_connect('event', handler)) e eventos conectados diretamente na aplicação associados a um handler e um widget (widget.connect('event', handler)).

Então precisei de um decorator que em alguns momentos não receberia nenhum parâmetro, associando a função decorada a um sinal registrado no glade com o mesmo nome da função.

# Associa a função 'destroy' ao evento 'destroy' já registrado no glade

@handler
def destroy(self, *args):
print args

# Mesmo funcionamento

@handler()
def destroy(self, *args):
print args


Ou ainda, este mesmo decorator poderia receber argumentos detalhando qual o nome do evento e widget para quais a função decorada deve ser associada.

# Associa a função 'x' ao evento 'destroy' já registrado no glade

@handler('destroy')
def x(self, *args):
print args

# Associa a função y ao evento 'on_bt_ok_clicked' no widget bt_ok

@handler('on_bt_ok_clicked', bt_ok)
def y(self, *args):
print args


Quando nenhum argumento é informado (@decorator()) utilizo uma função aninhada para ser retornada como decorator e assim efetivamente decorar a função. O mesmo funcionamento se aplica quando os argumentos não são funções ou métodos (@decorator('x'), @decorator('x', a=1)), utilizando o módulo inspect . Esse comportamento só muda quando o decorator não recebe parâmetros, ou seja, quando este não é invocado, retornando a função ou método recebido sem nenhuma modificação.

def decorator(*args, **kargs):
import inspect
# @decorator() or @decorator('x') or @decorator('x', d='a')
if not args or not inspect.isroutine(args[0]):
def deco(func):
def wrapper(*f_args, **f_kargs):
return func(*f_args, **f_kargs)
return wrapper
return deco
elif inspect.isroutine(args[0]): # @decorator
return args[0]


Exemplos de uso:

@decorator
def d(x, y, d=1):
print x, y, d
#d = decorator(d)

@decorator()
def e(x, y, d=1):
print x, y, d
#e = decorator()(e)

@decorator('x')
def f(x, y, d=1):
print x, y, d
#f = decorator('x')(f)

@decorator('x', d=5)
def g(x, y, d=1):
print x, y, d
#f = decorator('x', d=5)(g)


Abaixo o mesmo decorator utilizando classe, assim o comportamento do decorator pode ser facilmente expandido para funcionar com métodos seguindo esse texto Decorators and Descriptors, fazendo o decorator ser ainda mais flexível podendo ser utilizado com funções ou métodos ao mesmo tempo:

class decorator(object):
def __init__(self, *args, **kargs):
import inspect
# @decorator() or @decorator('x') or @decorator('x', d='a')
if not args or not inspect.isroutine(args[0]):
def deco(func):
def wrapper(*f_args, **f_kargs):
return func(*f_args, **f_kargs)
return wrapper
self.func = deco
elif inspect.isroutine(args[0]): # @decorator
self.func = args[0]

def __call__(self, *args, **kargs):
return self.func(*args, **kargs)

def __get__(self, obj, type=None):
if obj is None:
return self
new_func = self.func.__get__(obj, type)
return self.__class__(new_func)


Exemplos de uso:

class A:
@decorator
def b(self, x, y):
print x, y

a = A()
a.b(1, 2)

@decorator
def b(x, y):
print x, y

b(2, 3)

sexta-feira, setembro 26, 2008

Python e MVC - Parte 2

Continuando o post anterior Python e MVC - Parte 1.

Durante o desenvolvimento de uma aplicação aqui na empresa estive decidido a utilizar um framework MVC para Python que além de me prover as ferramentas necessárias para resolver os meus dilemas de design como manutenção facilitada, separação da aplicação em partes lógicas e criação de uma estrutura de componentes este também deveria ser genérico o suficiente para permitir a troca da view na minha aplicação de maneira simples e fácil.

O problema é que hoje existem basicamente três frameworks MVC para Python: Kiwi, pygtkmvc e PureMVC. O Kiwi é um framework muito bom e desenvolvido para uma aplicação real o Stoq, o pygtkmvc apesar de ter idéias interessantes parece ser um projeto abandonado e o PureMVC por sua vez é um projeto iniciado em ActionScript que mais tarde foi portado para diversas linguagens entre elas Python.

O Kiwi e o pygtkmvc são altamente acoplados com a view no caso PyGtk, o que vai totalmente contra o princípio de fraco acoplamento entre as partes como diz o MVC, e isso IMHO é muito importante e também é um requisito da minha aplicação. Sendo assim, sobra apenas nosso amigo PureMVC.

Eu também poderia construir meu próprio framework MVC, de acordo com minhas necessidades e me baseando nestes últimos três exemplos, reunindo assim o melhor de cada um. Sem dúvida, essa seria a melhor alternativa, mas como sempre o tempo era curto e essa não era uma possibilidade. Sem falar no esforço enorme de análise e um conhecimento muito profundo de design patterns necessário para se criar algo genérico o suficiente.

O PureMVC possui alguns problemas, IMHO. O primeiro problema é seu estilo ou filosofia e sua nomenclatura que são extremamente diferentes do que estamos acostumados em Python. A implementação então nem se fala, obviamente foi feita por um programador Java ou algo do tipo, embora funcione.

Algumas coisas não seguem uma linha de simplicidade e facilidade no uso, tornando coisas simples um pouco complexas demais. Como exemplo, o código abaixo foi retirado do demo do projeto que utiliza wxPython:


class ProductListMediator(Mediator, IMediator):
NAME = "ProductListMediator"
product_proxy = None
def __init__(self, view_component):
self.view_component = view_component
super(ProductListMediator, self).__init__(self.NAME, view_component)


O código acima pode ser simplicado com uma meta class como essa:


class MetaMediator(type):
def __init__(cls, name, bases, namespace):
cls.NAME = name


class BaseMediator(Mediator, IMediator):
__metaclass__ = MetaMediator
def __init__(self, view_component=None, constant_list=[]):
self.constant_list = constant_list
super(BaseMediator, self).__init__(self.NAME, view_component)



Obtendo o mesmo resultado que o código original sem perder em flexibilidade:


class ProductListMediator(BaseMediator):
product_proxy = None


O PureMVC reune uma gama de padrões em uma solução bem interessante. Todas as partes do MVC são agrupadas e invocadas por um padrão facade, este facade invoca o controller através do padrão command utilizando um esquema de execução por variáveis globais, com essa solução o controller não fica acoplado ao facade, já que se o nome do método for alterado, basta alterar em um local, no alias definido na variável global.


class AppFacade(Facade):
ON_ACT_STARTUP = 'on_act_startup'

@staticmethod
def getInstance():
return AppFacade()

def initializeController(self):
super(AppFacade, self).initializeController()
super(AppFacade, self).registerCommand(AppFacade.ON_ACT_STARTUP,\
controller.StartupCommand)


O controller por sua vez utiliza o padrão observer para se comunicar com a view garantido fraca acoplamento com o uso de notificações.


class DeleteCommand(SimpleCommand, ICommand):
def execute(self, note):
product = note.getBody()
product_proxy = self.facade.retrieveProxy(model.ProductProxy.NAME)
product_proxy.delete(product)
self.facade.sendNotification(main.AppFacade.ON_PRODUCT_DELETE)


A view então utilizando o padrão mediator para se comunicar com a visão concreta Gtk, Html, etc mantem mais uma vez acoplamento fraco, se for preciso mudar de Gtk para Html ou Qt, muito pouco do código precisará ser modificado, sanando a minha necessidade inicial.


class DialogMediator(Mediator, IMediator):
NAME = "DialogMediator"
def __init__(self, view_component):
self.view_component = view_component

def listNoticationInterests(self):
return [main.AppFacade.ON_SHOW_DIALOG,]


E por fim o model utiliza o padrão proxy para garantir abstração por interface, assim proporcionando independência da tecnologia utilizada no model, ORM, XML, serialização, etc.


class ProductProxy(Proxy):
NAME = "ProductProxy"
def __init__(self):
super(ProductProxy, self).__init__(self.NAME, [])

def get_all(self):
return value_object.ProductVO.query.all()


O esquema utilizado pelo PureMVC é um tanto complexo a primeira vista, mas se for utilizado com bom senso e sempre com simplicidade em mente o retorno pode ser muito positivo. Além da fraco acoplamento a manutenção fica muito fácil, já que cada entidade da aplicação fica bem separada evitando propagação de erros pela aplicação. Vale lembrar que o PureMVC funciona como um esqueleto para sua aplicação não obrigando o uso explicito de todos os componentes.

Como o PureMVC é feito para um conjunto de linguagens ao qual o Python não se encaixa, uma camada acima do PureMVC se faz necessária afim de simplificar a utilização deste e excluindo as partes desnecessárias, como os exemplos mostrados acima.

Uma dica é simplificar o esquema de notificações do mediator para que as notificações executem os métodos da classe implementa o mediator que tiverem o mesmo nome das notificações, excluindo assim a necessidade do registro e criação das notificações na classe. Como exemplo abaixo, retirado da mesma demo:


def listNotificationInterests(self):
return [
main.AppFacade.ON_PRODUCT_CHANGE,
main.AppFacade.ON_PRODUCT_DELETE,
]

def handleNotification(self, note):
if note.getName() in [main.AppFacade.ON_PRODUCT_CHANGE, main.AppFacade.ON_PRODUCT_DELETE]:
self.view_component.clear()
self.view_component.fill(self.product_proxy.get_all())


Neste parte de código o programador precisa especificar quais as notificações a classe recebe e escrever um método com um monte de condicionais para tratar cada notificação. É muito mas fácil escrever uma metaclass para transformar isso em um esquema de sinal que invoca o sinal que tiver um método na classe com o mesmo nome do sinal.

Fica na minha lista de coisas a fazer uma versão deste framework para Python, com um código e uma filosofia adaptada ao estilo Python de ser.

Por fim um link interessante sobre o PureMVC.

quinta-feira, setembro 18, 2008

Papo de programador

Eu: The class of a class is ...

Programador X: Humm.... another class?

Eu: Não.

Depois de muitas respostas "interessantes"..

Programador Z: Pesquisei no google, é uma metaclass, mas o que é uma metaclass?

Programador Y: Simplificando é uma classe que serve para construir outra classe.

Programador W: Eu uso VI para construir uma classe, então o VI é uma metaclass.

Python e MVC - Parte 1

É fato que durante o desenvolvimento de uma aplicação mais complexa alguns problemas ou dilemas
podem fazer nosso cérebro fritar. Para que o programador alcance uma boa solução é recomendável
que ele se concentre no contexto do problema e da solução. Python alcança esse objetivo de maneira magnífica, com um alto nível de abstração, simplicidade e coesão a linguagem permite que o programador se desvincule da linguagem e fique livre para se focar na solução.

No entanto, alguns problemas não fazem parte do contexto do problema e da solução, estes geralmente são ocasionados por nós mesmos, seja por falta de conhecimento da linguagem em questão, de organização, planejamento ou ainda pelo uso de uma solução pouco elegante ou inadequada.

Um sistema que se inicia de maneira desorganizada e sem planejamento com o passar do tempo e com evolução natural do mesmo, tende a enfrentar dificuldades assustadoras em relação a manutenção.

Qual a solução? Simples, vamos nos organizar, planejando e definindo muito bem como nosso sistema deve ser feito, vamos utilizar um bom processo de analise e pronto! Esse já é um grande passo, mas além desses pontos precisamos nos perguntar, será que os problema que estou tentando resolver já não possuem uma solução?

Sim, alguns problemas já possuem soluções "amplamente" divulgadas e aceitas, essas soluções são chamadas de Design patterns (Padrões de projeto) ou Architectural patterns (Padrões de arquitetura de software).

O MVC (model, view, controller) é um padrão de arquitetura que serve para separar conceitos lógicos da sua aplicação. O grande problema é que o próprio MVC, como todo padrão, por si só, não resolve todos os problemas e algumas vezes pode acabar criando outros problemas. O uso ideal de MVC com alguns cuidados e uma série de padrões de projeto pode nos garantir uma aplicação muito bem escrita e de fácil manutenção.

Inicialmente utilizar MVC e outros padrões fielmente pode ser um tanto chato e cansativo, mas como o tempo esse esforço pode render bons frutos. Aliar esses padrões com a simplicidade e elegância do Python não é um equilíbrio tão fácil de se alcançar, mas que pode ser muito gratificante.

Quando utilizo algum padrão em Python sempre procuro ter em mente que este padrão pode não se aplicar em Python, ou seja, tento não aceitar esses padrões como únicas e infalíveis soluções.

No próximo post vou falar sobre os frameworks MVC para Python (Kiwi, PureMVC, etc), quais as opções e detalhes de implementação.

quinta-feira, setembro 04, 2008

Django 1.0

Depois de uma espera de três anos finalmente foi lançada a versão 1.0 do excelente framework web Django. O lançamento dessa versão representa muito para esse framework que se tornou o mais popular framework web escrito em Python.

A versão 1.0 traz consigo um número muito grande de vantagens para os desenvolvedores, mas a principal é a estabilidade. Com toda certeza essa versão deve definitivamente posicionar esse excelente trabalho da comunidade como uma das melhores escolhas para desenvolvimento web.

Confira todas as novidades!
Experimente essa excelente ferramenta!

Parabéns a toda comunidade.

quinta-feira, agosto 14, 2008

Implementações da Sequência de Fibonacci em Python

O número de Fibonacci [1] ou sequência de Fibonacci é um exemplo clássico utilizado na computação para demonstração de recursividade.

No entanto, existem diversas implementações e geralmente com uma performance melhor que a versão recursiva:

Versão recursiva:

def fibonacci(n):
if n < 2:
return n
else:
return fibonacci(n-1)+fibonacci(n-2)

for x in range(10):
fibonacci(x)


Versão iterativa:

def fibonacci(n):
a,b = 0,1
for i in range(n):
a,b = b,a+b
return a

for x in range(10):
fibonacci(x)


Versão iterativa com "generators" [3]:

def fibonacci():
a, b = 0, 1
while True:
yield a
a,b = b,a+b

f = fibonacci3()
for x in range(10):
f.next()


Versão com "cálculo da proporção áurea (phi)" [4]

from math import log
phi = (1 + 5**0.5) / 2

def fibonacci(n):
return int(round((phi**n - (1-phi)**n) / 5**0.5))

for x in range(10):
fibonacci(x)



Versão recursiva/funcional:

fibonacci = lambda n,a=1,b=1:[b,0][n>0] or fibonacci(n-1,b,a+b)

for x in range(10):
fibonacci(x)


Utilizando o módulo "timeit" [5] repetindo 3 vezes e executando 1000 vezes cada função temos a lista de performance:

Versão recursiva: 0.635288953781
Versão iterativa: 0.0393660068512
Versão iterativa com "generators": 0.0163049697876
Versão com "cálculo da proporção áurea (phi)": 0.0362870693207
Versão recursiva/funcional: 0.100222110748

De longe o pior resultado é a versão recursiva como esperado, e o melhor resultado é da versão iterativa com "generators".

[1] - http://en.wikipedia.org/wiki/Fibonacci_number
[2] - http://pt.wikipedia.org/wiki/Recursividade
[3] - http://www.python.org/dev/peps/pep-0255/
[4] - http://en.wikipedia.org/wiki/Golden_ratio
[5] - http://docs.python.org/lib/module-timeit.html