Protocol Buffer

Escrit per Aaloy a 08 de July , 2008 a les 10 p.m.

Protocol Buffer és una llibreria d'intercanvi de dades que Google ha alliberat i que segons promet és de 20 a 100 vegades més ràpida que l'XML (i ja no parlem de SOAP) per a l'intercanvi de dades entre aplicacions.

Lo de la velocitat s'haurà de comprovar, però el que sí pareix clar és que és prou senzilla per ser abastable, la documentació és bona, i ja va dirigida als tres principals llenguatges de programació (C++, Java i Python).

Com que en faig servir dos habitualment, doncs es cosa de fer-hi una ullada i algunes proves d'stress a veure si realment és tant ràpida com diuen.

La cosa no sé si s'imposarà com a format d'intercanvi entre llocs d'Internet, però el que sí tenc clar és que si és més ràpid pot ser ideal com a format per a tecnologies SOA dins de la mateixa empresa. Una reducció d'un factor 10 ja seria prou bona, amb l'avantatge de que es podrien crear (com ara, per cert) serveis en un llenguatge i consumir-los en un altre, però sense tenir que pagar el preu que suposa en termes de rendiment fer-ho en format WSDL.

Es prest, per donar-ne una opinió amb més fonament, però pel que he vist de la documentació i els exemples, crec que aquest format i jo ens durem bé :)

2 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Java


Sigues dinàmic

Escrit per Aaloy a 29 de June , 2008 a les 3:53 p.m.

L'altra dia vaig fer un petit prototip per veure amb quines dificultats em trovaba a l'hora de connectar amb Python contra l'LDAP de l'empresa (un Notes) i contra l'Active Directory. Aquesta funcionalitat ja la tenia desenvolupada en Java, però com que l'aplicació que estava plantejant es faria amb Python, vaig començar a mirar els tempes més problemàtics: l'autentificació i com imprimir els pdfs.

La connexió amb l'LDAP i la funcionalitat que volia, per tal d'obtenir tota la informació del l'usuari que es connectava no va ser gens problemàtica, en total 76 línies de codi davant les 350 llargues de Java, o el que és el mateix en Python vaig haver d'escriure un 80% menys de línies per a tenir la mateixa funcionalitat. D'això no poden concloure que sempre els programes en Python seran un 80% més curts, però és una evidència més del que parlam quan deim que s'escriu molt menys codi i que és més ràpid fer-ho.

El perquè en aquest cas concret, dóna peu a aquest apunt, presentarem la manera de tractar amb Python dues situacions bastant comuns quan ens hem de connectar a altres sistemes o fer servir llibreries de tercers: la transformació de diccionaris en objectes i el com tractar el cas en que tenim múltiples paràmetres opcionals.

Diccionaris a objectes

La situació és la següent: tenim un diccionari que volem passar com a paràmetre i fer servir les seves claus com si fossis propietats de la classe, de tal manera que si una clau no existeix ens dóni el valor per defecte.

Aquesta situació me la vaig trobar connectant a l'LDAP. La llibreria de Python en interroga l'LDAP torna un diccionari i volia que aquest diccionari formàs part de la classe Usuari que havia de contenir tota la informació de l'usuari que s'estava connectant a l'aplicació.

Suposem doncs que el diccionari que ens retornen és:

dades = {'nom': 'Antoni Aloy',
         'telefon': '555 55 55 55',
         'localitat': 'Binissalem',
         'email': 'aaloy@example.com',
         'blog': 'http://trespams.com'
    }

El que volem és posar tota aquesta informació dins una objecte de tipus Usuari de tal manera que sigui fàcilment manipulable i entendible. És a dir, que puguem fer usuari.telefon,

       class Usuari:
           "Exemple de com transformar les claus d'un diccionari en propietats"
           def init(self,ldap_prop = dict()):
               self.__propietats = ldap_prop

    def __getattr__(self, name):
        "Obtenim l'el valor de la propietat del diccionari"
        try:
            return self.__propietats[name]
        except:
            return "No assignada"

    def __str__(self):
        "Representació textual de l'usuari"
        return "%s - %s" % (self.nom, self.email)

    def propietats(self):
        "Retorna la llista de propietats"
        return self.__propietats.keys()

Ho podríem fer servir amb el codi següent:

    if __name__ == "__main__":
        u = Usuari( ldap_prop = dades)
        print "Nom %s" % u.nom
        print "Telefon %s " % u.telefon
        print "Provincia %s " % u.provincia
       print u

El nostre cas era prou senzill, si volem quelcom més complexe podem anar a a una recepte de Michael Foord, on podem veure com s'extén l'objecte diccionari per a fer el mateix que hem fet en el nostre exemple i a més permetre la utilització de paràmetres normals.

Parametrització

Tenim una classe amb una gran quantitat de paràmetres que es poden modificar. Per defecte tots aquests paràmetres tenen un valor per defecte. Volem que l'usuari pugui actualitzar els valors i obtenir-los. A més hi pot haver paràmetres que són sols de lectura.

Aquesta situació me la vaig trobar instanciant classes de Reportlab. A l'hora d'utilitzar la llibreria ens trobam en aquesta situació: tenim una gran quantitat d'atributs que podem assignar, però la major part del temps els valors per defecte ja ens estan bé. Vegem com ha resolt la situació la gent de Reportlab:

    class BaseDocTemplate:
        """...."""
        _initArgs = {   'pagesize':defaultPageSize,
                        'pageTemplates':[],
                        'showBoundary':0,
                        'leftMargin':inch,
                        'rightMargin':inch,
                        'topMargin':inch,
                        'bottomMargin':inch,
                        'allowSplitting':1,
                        'title':None,
                        'author':None,
                        'subject':None,
                        'keywords':[],
                        'invariant':None,
                        'pageCompression':None,
                        '_pageBreakQuick':1,
                        'rotation':0,
                        '_debug':0}
        _invalidInitArgs = ()
    
        def __init__(self, filename, **kw):
            """create a document template bound to a filename (see class 
                documentation for keyword arguments)"""
            self.filename = filename
    
            for k in self._initArgs.keys():
                if not kw.has_key(k):
                    v = self._initArgs[k]
                else:
                    if k in self._invalidInitArgs:
                        raise ValueError, "Invalid argument %s" % k
                    v = kw[k]
                setattr(self,k,v)
    
            p = self.pageTemplates
            self.pageTemplates = []
            self.addPageTemplates(p)
            ...

A l'hora de crear la classe BaseDocTemplate els atributs es defineixen dins un diccionari _initArgs, a la inicialització de la classe l'únic paràmetre obligatori és filename, però perfectament podem fer

myTemplate = BaseDocTemplate(filename="test.pdf", showBoundary=1, author="aaloy")

A l'init el que fa es repassar-se tots els atributs que hem definit al diccionari, si els paràmetres que s'han passat no coincideixen amb la clau del diccionari es crea un nou atribut a l'objecte amb el valor que té al diccionari (el valor per defecte). En canvi si hi és, verifica primer que no sigui un paràmetre de sols lectura, comprovant-ho a _invalidInitArgs i en cas que no ho sigui crea l'atribut amb el valor que li passam com a paràmetre en lloc del valor per defecte que té definit al diccionari.

D'aquesta manera ens permet utilitzar i assignar valor molt fàcilment i sols inicialitzar allò que necessitam.

La quantitat de codi que ens estalvien aquests deus receptes és proporcional al nombre d'atributs que tengui la nostra classe si la fessin en un llenguatge de programació no dinàmic.

4 comentaris, 0 trackbacks (URL) , Tags: Python


La meva experiència amb Django

Escrit per Aaloy a 22 de June , 2008 a les 12:03 p.m.

En Maties Bonet ens va escriure un e-mail a mi i a Guillem demanant-nos per la nostra experiència en l'ús de Django.

Amic Maties, bona cosa has demanat! Pepara't perquè aquest apunt pot ser llarg :)

La meva relació seriosa amb Django ja té més de dos anys, és difícil estimar la data, però si en tingués que donar una seria la del 3 d'agost del 2006, data del primer commit del major projecte que hem fet amb Django fins ara,amb actualment més de 12.000 línies de codi

Aquest projecte inicialment estava desenvolupat en PHP, però necessitàvem més funcionalitat i essent les nostres filies més tendents cap al Python que cap a altra cosa, començarem a investigar els bastiments que començavent a surgir. Cercàvem quelcom que permetés una bona escalabilitat, facilitat de desenvolpament i una separació molt clara entre codi i capa de presentació. A més una de les restriccions inicials era que el servidor que tenia que dur tot això no havia de ser massa potent, un host virtual baratet hauria de ser suficient per començar.

Amb Juan avaluarem un grapat d'opcions. Anàvem mirant frameworks i en discutíem els avantatges i inconvenients. Férem una ullada a Pylons, a TurboGears i alguns altres, fent algun prototip i discutint-ne els resultats.

TurboGears estava força bé, i Pylons representava gairebé l'estat de l'art en quant a integració de componentes, però Django tenia una avantatja per a nosaltres fonamental: la seva integració entre els distints components (integració que a més no compromet a res), una documentació fantàstica i el ser un bastiment que s'havia fet servir en projectes grans, en projectes que estaven funcionant. Es podria dir que no era sols una idea sinó que el funcionament del framework era una realitat.

Així doncs ens decidirem per Django. Mesos després Guido Van Rossum com el framework que li agradava més. Un any i mig després veuríem Django com un bastiment suportat per Google. Això vol dir que tenim bon ull per les tecnologies? Segurament, però vist en perspectiva l'elecció de qualsevol dels altres dos bastiments també ens hauria anat força bé.

Django, però té aquell quelcom que et fa sentir content i satisfet amb la programació que fas. És entenidor i abastable i quan t'enfrontes a un problema de la vida real trobes que hi ha una solució en Django, per una raó molt senzilla: el bastiment es va crear per resoldre problemes de la vida real, com una resposta a la necessitat que tenien els seus creadors de tenir un bastiment que els proporcionàs una gran rapidesa en el desenvolupament i al mateix temps una gran escalabilitat.

Una vegada vàrem veure la potència del bastiment, junt amb la potència de Python i ho compararem amb el que teníem i feiem en Java, el pas següent va ser lògic: utilitzar el que sabíem en la feina diària per a l'empresa per la qual treballàvem, una multinacional del turisme. Sense deixar Java del tot, ara podíem incorporar una nova eina que ens permetria poder desenvolupar webs a la velocitat que li agradava al negoci.

Posar Django i Python a una empresa molt tradicional no és senzill, "aquest tipus de la web sempre fent coses rares!" Però l'evidència s'imposa i amb un poc de ma ampla del nostre director d'informàtica anterior començarem a fer els nostres primers projectes amb Django per a l'empresa. És una tasca que avui en dia encara costa. Quant més consultors externs té l'empresa més difícil és aquesta tasca. Aquests suposats experts no tenen idea de què és Django i de les seves possibilitats, i tampoc els convé, ja que després de la consultoria hi sol haver un desenvolupament i com que el desenvolupament és més ràpid i ells cobren per hores, doncs que no convé gaire. Però això és una altra història i també serà un altra apunt.

Actualment doncs, feim/faig servir Django i Python en quatre grans tipus de projectes:

  • projectes on no s'ataca a la base de dades "legacy" de l'empresa, sinó que s'han desenvolupat des de zero.
  • projectes on hi ha una gran part de continguts i a més lògica de negoci senzilla.
  • projectes que consumeixen web services en SOAP que estan a la seva vegada desenvolupats en Java.
  • el nostres projectes particulars, com aquest blog.

Els resultats són molt bons, un exemple: fa dues setmanes ens telefonaren del dimecres per a un projecte crític, s'havia de crear una web completa per a un client que havia d'estar llesta el divendres al matí de la mateixa setmana. El dimecres horabaixa en tendríem més detalls.

L'horabaixa ens defineixen un poc millor el projecte: bàsicament contingut que se'ns aniria passant en format word i que segurament aniria sofrint modificacions damunt la marxa.

Tot just penjar el telèfon ens posarem en marxa. La gent de sistemes creà el repositori subversion pel projecte (no importa la pressa que tenguis, sempre, sempre un control de versions) i inicià la configuració del nou domini.

Una hora després ja teníem el domini intern funcionant i la primera versió del codi dins el subversions. Havíem reaprofitat la funcionalitat que teníem per a la gestió de continguts i ara sols era cosa de crear el disseny, passar-ho a plantilles i posar el contingut. El que ens feia més por era no tenir els DNS replicats per l'hora d'entrega.

El dijous al matí el disseny ja estava llest i es comença a maquetar i pujar continguts. Es crearen algunes plantilles per a fer que les opcions de menú canviessin dinàmicament i s'anava pujant tot al servidor de producció mitjançant un update del subversions. El temps de pujada d'una nova versió era aproximadament de 30 segons, versió que ja pujava testejada gràcies a que amb Django pots anar provant l'aplicació amb el seu servidor integrat (i amb recàrrega automàtica).

Ens sobraren un parell d'hores del temps limit. Total del projecte 35 hores-home. Entregable: aplicació amb subdomini propi, tipus portal de continguts, multi-idioma, amb menús desplegables, i la maquetació a partir de documents word de l'equivalent a una trentena de planes web amb una mescla de text, fotografies i descàrrega d'arxius. Rendiment de l'aplicació: generació d'una plana web en 1,2 segons sense caché.

Si ho haguéssim tingut que fer en Java encara estaríem muntant el CMS o pujant els continguts. Amb les plantilles de Django i la possibilitat d'herència que tenen, poguérem crear el nostre lloc web amb molt poc temps i passar els continguts a HTML de manera molt més ràpida que l'equivalent a crear el disseny en un CMS clàssic de PHP o Java (ja no en parlem de fer el mateix amb Java i sense CMS).

El millor de tot és que encara que no sabíem que se'ns demanaria estàvem raonablement segurs de que si no era res molt complexe es podria fer, ja que el bastiment no ens fermava (com sovint fan els CMS més habituals) sinó tot el contrari.

La meva experiència amb Django? Fantàstica i demostrable. Fins al punt que quan veig el que puc fer en aquest entorn em fa molta peresa tornar cap a Java, els temps d'espera tot i que desenvolupam en local resulten molests, les posades en producció s'eternitzen. I això que gràcies al nostres administradors de sistemes ho tenim tot que va com una seda a l'entorn J2EE i les posades en producció són ràpides, però quan ho compares amb un pocs segons tot resulta lent.

Consider Django com un avantatge competitiu: ens permet fer desenvolpaments molt ràpidament i a més sabem que escalaran bé. Com que no estam lligats a cap bastiment de javascript concret podem incorporar el que necessitem segons el projecte: jQuery, extjs, res... i la separació que es fa en capes de l'aplicació també es pot fer a l'hora de desenvolupar i permet treballar en paral·lel a la gent de sistemes, disseny i programació.

I així doncs, quan voleu que posem Django a la vostra empresa?

4 comentaris, 0 trackbacks (URL) , Tags: Python Django


A la pregunta de Servo ....

Escrit per Aaloy a 15 de June , 2008 a les 7:20 p.m.

Al comentari del darrer apunt de Servo es demanava el perquè el Set hauria de ser més ràpid si el primer algorisme és d'ordre N.

El codi dels sets es molt semblant al dels diccionaris, però està una mica més optimitzat, a l'igual que els diccionaris està implementat com una taula hash, però a diferència d'aquests els conjunts sols guarden el parell clau/hash en lloc de la tripleta clau/valor/valor del diccionari.

Com que els sets guarden els parells clau/hash, totes les operacions binàries, com la intersecció s'executen sense cap cridada al mètode _ _hash__ dels elements individuals. Això és molt més ràpid que el codi equivalent que fa servir diccionaris.

També resulta que quan feim un bucle damunt un set Python (CPython) directament recorre la taula hash en lloc de fer ús d'un iterador (que seria un poc més lent).

La pregunta ha servit per fer un poc de recerca, de fet la meva resposta és la traducció d'una resposta molt completa l'he trobada a Python in Science .

Però no ens conformem amb això, fem un "show me the code" a la plana citada anteriorment hi ha un exemple que ens anirà bé per començar. Es tracta de trobar la intersecció de dos conjunts, però ho podem adaptar per fer les cerques al diccionari:


import random
import time
REPETICIONS = 1000

## Generam els valors
seta = set([random.randint(0,100000) for n in xrange(10000)])
setb = set([random.randint(0,100000) for n in xrange(10000)])

print "Cerques a conjunts"

t0 = time.clock()
    for i in xrange(REPETICIONS):
    total = seta.intersection(setb)
print "Intersections - Time: %s seconds"%(time.clock()-t0)

t0 = time.clock()
for i in xrange(REPETICIONS):
    total2 = []
    for element in seta:
        if element in setb:
            total2.append(element)
print "Fent el bucle Time: %s seconds"%(time.clock()-t0)

## I ara el nostre cas

print "Cerques amb diccionaris"

## Generam els valors
dicta = {}
dictb = {}
for i in xrange(10000):
    dicta[random.randint(0,100000)]=i
    dictb[random.randint(0,100000)]=i

t0 = time.clock()
for x in xrange(REPETICIONS):
    total2 = []
    for valor in dicta.keys():
         if dictb.get(valor):
            total2.append((valor, dicta[valor]))

print "Bucle - Time: %s seconds"%(time.clock()-t0)

t0 = time.clock()
for x in xrange(REPETICIONS):
    total2 = [ (repe,dicta[repe]) for repe in   set(dicta).intersection(set(dictb))]

print "Set intersection - Time: %s seconds"%(time.clock()-t0)

I aquí el resultat


Cerques a conjunts
Intersections - Time: 0.94 seconds
Fent el bucle Time: 6.11 seconds
Cerques amb diccionaris
Bucle - Time: 11.63 seconds
Set intersection - Time: 6.97 seconds

En el primer cas estam davant un algorisme d'ordre N² davant un algorisme NlogN sin o record malament de la intersecció de conjunts.

El nostre cas és una mica menys clar en el que fa a l'ordre de l'algorisme, però amb el codi es pot veure com el resultat final s'obté és un 60% més ràpid.

Tot i això fixem-nos amb que per a obtenir el resultat en segons he tingut que fer 1.000 iteracions i que hem fet servir un conjunt de 10.000 elements, sols per a que quedi clar de que potser ambdós algorismes són prou ràpids per a la nostra tasca diària. Sols hem de tenir clar que quan cerquem maneres d'optimitzar el nostre codi, mirar si feim aquests tipus d'algorismes moltes vegades

0 comentaris, 0 trackbacks (URL) , Tags: Python


Trobar elements repetits

Escrit per Aaloy a 15 de June , 2008 a les 12:37 p.m.

Tenim el següent problema: "tenim dos diccionaris amb dades i volem trobar els elements d'una diccionari que estan també dins l'altra"

Suposem, per exemple que tenim:

x = {'a':1,'b':2,'r':3}
y = {'a':1,'r':3, 'c':14}

La opció més directe pareix ser la de recorre els elements de la primera llista i veure si hi són a la segona, una cosa com

for valor in x.keys():
    if y[valor]:
        print valor, y[valor]
a 1
r 3

o bé una altra opció més curta:

for repe in set(x).intersection(set(y)):
     print repe, x[repe]

o si m'apurau

[ (repe,x[repe]) for repe in set(x).intersection(set(y))]
[('a', 1), ('r', 3)]

Ara quan algú us demani que és això de que Python ve amb les piles incloses ja teniu un exemple més per a mostrar.

4 comentaris, 0 trackbacks (URL) , Tags: Python


Millores al blog

Escrit per Aaloy a 08 de June , 2008 a les 11:30 a.m.

De tant en tant faig feina al blog, no per escriure-hi sinó per afegir-hi noves funcionalitats. Encara hi ha moltes coses que m'agradaria posar-hi i millorar, però a poc a poc esper anar arribant-hi.

A la darrera actualització he fet algunes millores que recomanaven al Google Webmaster Tools com la d'afegir descripcions úniques per apunt. Django a les seves plantilles té el filtre truncatewords_html que m'ha anat fantàstic per això.

Una de les millores que volia fer també era la d'amagar un poc tota la llista de mesos que hi ha. Aquest blog té apunts des del 2004 i la llista començava a ser molt llarga. Ara veureu que sols apareixen els anys (sempre que tingueu el javascript activat clar) i que en pitjar damunt ells es despleguen els mesos. Fer això ha estat entretingut perquè ha implicat jugar amb dos tags més de Django, el for per obtenir si estava a la primera posició del bucle o a la darrera, per tal de poder tancar els divs, i el tag ifchanged que ens permet saber si una variable (en el meu cas l'any) ha canviat o no respecte al seu valor anterior.

Amb aquestes eines ha estat possible muntar l'estructura necessària per a utilitzar un el Animated Collapsible DIV, una petita utilitat per jquery que permet ocultar i mostrar divs a voluntat, agrupant-los per categories si convé.

Ara la plana principal al meu entendre queda un poc més neta i amb prou espai a la columna lateral esquerra per anar afegint més coses.

0 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Django


Capa de negoci a Django

Escrit per Aaloy a 28 de May , 2008 a les 11:55 p.m.

Del post anterior em quedava el tema de tractar el tema de la capa de negoci en els llenguatges dinàmics. Com en el cas anterior faré servir Django com a exemple i deix al lector la feina d'extrapolar cap el seu llenguatge dinàmic+bastiment preferit.

En Domingo diu que els llenguatges dinàmics mostren molta de la seva potència a la capa de presentació, que és allà on en treuen més profit. Això és veritat però es queda curt. És a dir, quan un usuari demana un canvi, el més habitual és que aquest s'acabi reflexant en la capa de presentació,però això no vol dir que no se canvii la capa de negoci. El fet però és que anar des de la capa de persistència, passant per negoci i mostrar el resultat al navegador, té un cicle de temps més curt en el llenguatge dinàmic, interpretat, que en el compilat, ja que sol ser molt més curt fer els canvis (gearing factor i totes aquestes herbes) i necessitea un temps més curt de desplegament, però no ens enganem, és tot el procés que és curt, si no afecta a capa de presentació el que passarà és que el desenvolupament serà encara més ràpid.

Sovint amb les aplicacions del tipus crea el teu blog en 10 minuts en Django, Rail o qualsevol altra, es dóna una idea equivocada del que se pot fer, donant la imatge de que aquestes aplicacions van molt bé per fer webs que depenen d'un conjunt de taules senzilles i que tenen una lògica de negoci poc complexa.

Bé, supòs que podríem demanar-li a Ricardo, que és un exemple que tenim ben aprop,de com s'ho fa per calcular el karma de Meneame o per saber si una notícia ha de sortir en portada o quan ha de deixar de ser-hi. Tot això es lògica de negoci, està feta en un llenguatge interpretat, el PHP.

En el cas de Django no oblidem que el que tenim per davall és Python i que l'ORM que ens proporciona Django ho podem fer servir o no, substituir-ho per un altre, fer les cridades directament a BD o senzillament, utilitzar-ho com a part del nostre model de negoci i posar-i les regles que ens convenguin.

Segons la nostra aplicació podem anar afegint custom managers que ens permetran definir regles damunt les dades que volem obtenir, mètodes de classe per definir les funcionalitats que vagin damunt tots els elements de la taula, i missatges que ens ajudin a manipular la informació i les seves relacions.

Això ho podem fer directament des de la classe de l'ORM, el model, o bé, recordem que tenim Python a la nostra disposició, crear un nou paquet, crear una classes o un conjunt de classes i utilitzar el model per aplicar les regles de negoci que vulguem quan aquestes s'hagin de convertir en registres de la base de dades o la seva informació hagi de venir de la base de dades. Per cert, i abans que algún ho demani, sí hi ha transaccions!

Això vol dir que podem fer servir els llenguatges dinàmics per a modelar la nostra capa de negoci, doncs sí, ho podem fer. Això vol dir que la nostra aplicació ha d'estar escrita en un llenguatge dinàmic sempre? No, depèn de l'aplicació. Potser per una aplicació concreta amb un requeriments concrets tenir un contenidor EJB amb transaccions distribuïdes serà el que necessitam, el que vull dir és que no podem descartar fer l'aplicació en un llenguatge dinàmic sols perquè ens hem quedat amb la idea de que sols va bé perquè el seu ORM te crea molt fàcilment les taules i els CRUDs.

De fet la part d'administració de Django va molt bé com a eina administrativa, però no és una eina d'usuari final. Com a desenvolupador te va molt bé perquè pots fer cerques ràpidament, començar a omplir les dades del manteniments mestres i anar directament a les butzes de les dades, però no hem de confondre això ni amb l'aplicació final i amb que és tot el que se pot fer amb els llenguatges dinàmics.

I encara hi ha un punt que no hem tractat, el tema de la integració dels llenguatges dinàmics amb els llenguatges compilats (jpython, jruby, groovy, etc). Segons la nostra aplicació i els nostres usuaris, tenir un llenguatge interpretat, fins i tot creat per al domini de la nostra aplicació pot ser una opció molt interessant. Permeteu-me una batalleta: fa un grapat d'anys vaig desenvolupar el programa de gestió d'excursions de l'empresa on feia feina (Delphi + IBObjects + Firebird), una aplicació client servidor clàssica amb un grapat de procediments amagatzemats quan feia falta. La cosa és que hi havia excursions que tenien ofertes que el proveïdor donava i que s'havien de cotitzar, ofertes del tipus: "si es reserva una excursió per dos adults i un nin, el nin tendrà un 25% de descompte damunt la tarifa" o "el tercer adult es gratis i els nins no paguen" etc. Això ho podria haver desenvolupat amb un bon conjunt de camps de la base de dades i tenir previstes les condicions, però la solució hagués estat visualment atractiva però mala de programar i molt propensa a errors. Per contra vaig optar per a modelar-ho con si fos una fórmula de una fulla de càlcul, a la que els meus usuaris estaven acostumant on es podia jugar amb el preu per data, amb sumes, restes, if i tant per cents i parèntesi, un mini intèrpret pensat per a tractar amb fórmules matemàtiques. Les condicions així posades eren flexibles i amb unes possibilitats pràcticament il·limitades respecte al que haurien estat si ho hagués fet amb una "interfície amigable". En aquest cas, integrar un intèrpret a l'aplicació va ser la millor solució.

Com no me cansaré de repetir, no es tracta de dinàmics/interpretats respecte d'estàtics/compilats. Es tracta de perdre la por i els perjudicis i poder triar en cada cas aquella tecnologia que millor s'adapti al problema a resoldre de manera que aquest es pugui resoldre amb el menor cost actual i futur per al nostre client, en alguns casos aquest llenguatge serà C, C++, C#, Java o el que sigui, però en altres, en molts altres un llenguatge dinàmic serà la millor opció per als nostres clients.

5 comentaris, 0 trackbacks (URL) , Tags: Python Django Gestió de projectes


D'errors i línies de codi

Escrit per Aaloy a 26 de May , 2008 a les 9:30 p.m.

En Domingo al seu blog fa una referència al meu apunt damunt llenguatges dinàmics i un bon grapat de bones reflexions.

Això de no creure's el que dic és una postura molt sana, sobretot perquè en la redacció d'un apunt me puc deixar detall i dades que són interessants. Una postura crítica ajuda a reflexionar i a completar les frases que d'altra banda s'haurien deixat com a dogmes de fe. Jo sóc del mateix tarannà, hi ha coses que me crec i coses que a poc que vegi indicis de contradiccions, doncs cerc més informació o deman explicacions. Això, he de dir també, m'ha causat força problemes en el món empresarial, on sovint el "no pensis" és una qualitat que ajuda a progressar.

Bé, però no me'n vull anar per les bardisses, o sí, ja que hi sóm, aprofitaré per dir perquè no faig servir el Twitter: no hi ha espai abastament :)

Afirmació: El nombre de línies de codi que escriu un programador al dia és una constant. Això és un efecte estadístic. Fa temps es parlava de que un programador escriu cinc línies de codi sense errors al dia. Està clar que és una dada estadística i fins i tot controvertida, ja que que és molt complexa definir què és i que no és una línia de codi i de que les línies de codi no s'han de fer servir per mesurar el rendiment. Tot i això podem trobar referències capítol 5 de Software estimation de McConnell on a la Taula 5.1 torbam la relació entre les línies d'un projecte i les línies de codi per programador i any. Això no vol dir que tots els programadors escriguin les mateixes línies de codi (de fet la productivitat entre programador pot arribar a un factor 10 -Peopleware-, però sí que en mitja i per a una organització i projecte, el nombre de línies de codi que s'escriu en promig és constant. A Sofware Mesurement and Estimation diu "Studies have shown that a proficient programmer can programm aproximately the same number of debugged lines of code per day regarless of the language". D'aquí que gent com QSM o David Consulting Group facin comparatives entre llenguatges per a comparar l'expressivitat de cada llenguatge. Per exemple C té un gearing factor de 128 i Java de 53. Això vol dir que una funció que en C necessita 128 línies de codi en Java en necessitarà en promig 53. Si un programador experimentat escriu, essent optimistes 10 línies de codi depurat al dia, llavors necessitarà 13 dies en C i 6 en Java (nombres redons).

D'aquí llavors que els llenguatges dinàmics, al necessitar menys línies de codi per fer el mateix poden completar els projectes en un temps més curt. Com que el temps significa doblers, implica que els projectes surten més barats.

Afirmació: el número de errores directamente proporcional al número de líneas que se escriben Aquí també entram en temes estadístics. De fet es parla de nombre d'errors d'un programa per mils de línies de codi. De la mateixa manera que en el cas de les línies de codi que escriu un programador, hi ha moltes diferències, però Casper Jones a "Program Quality and programmer Poductiviy (1997)" va recopilar algunes dades, que també cita en McConnell. També Reifer en va fer estudis, per exemple per la part Web estudià 65 projectes, i trobà que el ratio és de 6 errors per KESLOC (KESLOC Kilo (Thousand) Equivalent Source Lines of Code). Aquest nombre depèn força del tipus del projecte i de l'organització, però és estadísticament significatiu. Per tant, si donam com a bo el que els llenguatges dinàmics necessiten menys línies de codi per expressar el mateix que els llenguatges compilats tradicionals (Java, C, C+, ...) tendrem que el nombre d'errors en valor absolut també serà menor.

He trobat també una comparativa entre el nombre d'erros per Java i C++ a un paper de Geoffrey Phipps anomenat Comparing Observed Bug and Productiviy Rates for Java and C++, me l'he d'acabar de llegir, però conclou que amb un 95% de confiança C++ té 9,7 vegades més defectes per KLOC que Java i que a més els defectes en Java són més fàcils de corregir. D'aquí a fer una extrapolació cap a la banda dels llenguatges dinàmics hi ha sols un pas, sols falta que algú s'animi a fer l'estudi.

En Domingo també demana l'opinió damunt els llenguatges dinàmics per la capa de negoci, però això crec que dóna per un apunt per ell sol, així que ho deixaré per la propera vegada, però promet, amenaç, amb tractar-ho.

0 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Django Gestió de projectes


Llenguatges dinàmics

Escrit per Aaloy a 25 de May , 2008 a les 11:18 a.m.

Link to Llenguatges dinàmics

Al blog de Ricardo he esta llegint l'apunt anomenat "Lenguajes dinámicos, programadores y FUD" així com els seus comentaris. Tot i que hi he deixat allà un comentari amb la meva opinió, crec que com a programador en llenguatges dinàmics i tradicionals he de dir la meva.

El primer de tot que voldria fer és evitar el FUD damunt els llenguatges dinàmics, per una raó molt senzilla: la realitat és molt cruel i estam cansats de veure i de llegir damunt projectes web realitzats en Python, Ruby o PHP que estan triomfant i que no desapareixen o exploten per mor de no tenir un llenguatge compilat al darrera. Per tant, la primera cosa que hem de tenir clara és que la teoria pot estar molt bé, però la realitat ens està dient dia a dia que és possible escriure i mantenir programes en llenguatges dinàmics. A un li poden agradar més o menys aquests tipus de llenguatges, però el que no es pot fer és negar la realitat.

També m'agradaria focalitzar l'àmbit de discussió: estam parlant de programes web. Per programes d'escriptori no tenc dades abastament, potser perquè els llenguatges dinàmics brillen en el desenvolupament web més que en la part d'escriptori, llevat de que considerem el Visual Basic com a llenguatge dinàmic, clar.

La cosa està en que amb les màquines actuals els llenguatges dinàmics son ja prou ràpids com per ser competitius amb els llenguates compilats. Això no vol dir que siguin més ràpids, sinó que són prou ràpids per fer la feina i que la diferència de velocitat que hi hagi no sigui rellevant. Que PHP ens serveixi una plana en 1 segon i en Java la serveixi en 0,98 segons, doncs no és rellevant ja que per l'usuari de l'aplicació no significarà cap diferència en l'espera.

Això vol dir que ens hem de passar ja a programar en un llenguatge dinàmic i deixar els compilats? No. Vol dir que és necessari que a més d'un llenguatge tradicional convé que tinguem al caixò de les eines un llenguatge dinàmic. D'aquesta manera quan ens demanin una aplicació podrem sospesar els pros i els contres i fer-la en el llenguatge que s'adapti millor al projecte. Fins i tot si el nostre projecte es farà en un llenguatge tradicional, tenir un llenguatge dinàmic se pot integrar al projecte en forma de rutines de generació de codi, scripts de testeig, etc.

Dit això, i considerant l'àmbit de les aplicacions web, anem a veure avantatges i inconvenients d'elegir un llenguatge dinàmic per al nostre projecte, com que el que més conec és el Python, em permetreu la llibertat de donar els exemples i les referències en aquest llenguatge, in en Java en el cas de llenguatge compilat, en el ben entès que segur que hi ha el mateix tipus de solucions en Ruby, PHP o el vostre llenguatge dinàmic preferit i en C, C++ o .Net, etc.

Cicle de desenvolupament Agafem una aplicació web típica Java desplegada a un servidor Tomcat i la mateixa aplicació feta en Python. El cicle al primer cas és: escriure codi, compilar, corregir els errors de sintaxi, desplegar-ho al servidor, provar i iniciar novament tot el cicle, bé per escriure nou codi o bé per corregir els errors. A l'aplicació Python+Django tendríem: escriure codi, provar i tornar a escriure el nou codi. L'augment de productivitat la tenim no per el fet de no tenir que corregir errors, sinó pel fet de no tenir temps d'espera en el desplegament i per haver d'escriure menys línies de codi.

Errors de sintaxi. Aquí algun haurà pensat, "s'ha deixat els errors de sintaxi", efectivament, ho he fet perquè vull dedicar-lis el seu propi apartat. El compilador caça els errors de sintaxi i ens n'informa, però això vol dir que hem d'executar el compilador, és veritat que això els IDEs com Eclipse ho fan automàticament, però tot i això s'ha de fer. Realment podem fer el mateix amb eines com Pylint o Pychecker i a més el primer a més és capaç de treure tot un conjunt d'estadístiques damunt la qualitat del codi, talment com ho fan eines Java com PMD. El pylint per exemple és el que fa servir PyDev per a indicar els errors de sintaxi i donar avisos damunt el codi. Està clar que aquests errors potser no seran tan acurats como els dels compiladors, però són prou bons com per fer la feina, amb l'avantatge, però que ho podem llançar quan nosaltres vulguem i que no s'ha de passar necessàriament pel compilador per a executar el programa.

Per una altra banda, que el compilador o pylint ens caci els errors de sintaxi ens pot donar una falsa sensació de seguretat, el errors de sintaxis poden fer petar l'aplicació, és veritat, però els errors més greus solen ser els errors en la lògica de negoci de l'aplicació. Quan aquests se detecten el que s'ha de fer és corregir-los el més aviat possible, i en aplicacions web entram en

La fase de desplegament El temps que necessitam per posar una aplicació en producció seria anecdòtic si les aplicacions no tinguessin errors. Necessitar 30 minuts o 10 minuts per una aplicació que es posi en producció i que estigui mesos o anys sense modificar-se no és significatiu. Però, si l'aplicació sofrirà canvis o els errors que es detectin s'han de resoldre el més aviat possible, una diferència de 30 minuts en el desplegament pot marcar la diferència. En el cas d'un error en la lògica de l'aplicació que afecti a un .jar, significa en el millor dels casos compilar l'aplicació o el jar corresponent, substitur-ho i reiniciar el servidor d'aplicacions o l'aplicació, cosa que pot dur entre uns 30 segons y un bon grapat de minuts, depèn del que hi hagi desplegat. El el cas d'un llenguatge dinàmic sovint basta actualitzar els arixus afectats (svn update per exemple) i fer un reload del servidor Apache que tenguem. Cosa d'un parell de segons tot plegat. Està clar que podem minimitzar el primer cas amb servidors redundants i configuracions d'alta disponibilitat, però a un cost major de complexitat.

L'orientació a la tasca Les aplicacions web tracten fonamentalment amb text i produeixen text. Agafam dades de formularis, les tractam, obtenim dades de les bases de dades i les manipulam per a presentar-les a l'usuari en una sortida HTML, etc. Tractar cadenes és part fonamental de les aplicacions, i això és una cosa que els llenguatges compilats fan en general força malament des del punt de vista del nombre de línies de codi que s'han de picar. Els llenguatges dinàmics són força bons tractant informació textual. Posaré un exemple que ens pot servir per il·lustrar aquest fet: les plantilles. En Java tenim tres llenguatges de plantilles principalment: JSP-EL (ja ho sé està agafat pels pels però acceptau-me'l), Freemaker i el venerable Velocity i en general són força infumables. Comparem-ho amb el que hi ha per Python i veurem la diferència (Django, Web String, Cheetath, Mako, Jinja, ...). No crec que sigui anecdòtic, la diferència és que és força senzill manipular text en Python i per tant és força senzill crear-te el teu propi llenguatge de plantilles.

Productivitat El nombre de línies de codi que escriu un programador al dia és una constant. Això vol dir que si volem tenir més productivitat s'ha d'anar cap a llenguatges que ens permetin escriure més funcionalitat en menys codi. Donat el boom que viuen actualment els llenguatges dinàmics encara no hi ha molta literatura al respecte in encara no hi ha ni Ruby, ni PHP ni Python al QSM, però sí que hi ha forces comparatives, una de les més interessants és la d'Stephen Ferg que senyala que programar en Python és de 5 a 10 vegades més productiu que fer-ho en Java.

Diversió i motivació Els llenguatges dinàmics són sexy. Permeten al programador un alt grau de realimentació. Pot provar les seves idees molt ràpidament i això el motiva molt més que tenir que esperar a que el compilador acabi per poder fer les proves.

Pel demés, els llenguatges dinàmics també necessiten unit tests (sols que es poden escriure més ràpidament i amb menys línies), una gestió acurada dels projectes, planificació del que volem fer i refactorització del codi.

La conclusió de tot això és que deixem de banda FUDs que no duen a res i a l'hora d'avaluar un projecte considerem també si és apte per a ser fet en un llenguatge dinàmic, si ho és endavant, el nostre cul no perilla per dita elecció, ja que tant Python, com Ruby com PHP seran prou capaços de fer la feina.

3 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Django


vim ide per python

Escrit per Aaloy a 17 de May , 2008 a les 9:22 a.m.

Aquesta setmana i gràcies a l'entrada del blog de sontek he retornat al vi com a editor principal per a la programació en Python.

Periòdicament estic canviant entre vim, kate o Eclipse amb PyDev, segons la màquina en que faig feina i el que estic fent, però pas gran part del temps fent feina amb la consola i trobar la configuració que permet tenir el millor de els entorns gràfics a vim m'ha sorprès gratament.

Amb la configuració i el conjunt de plugins que ha seleccionat sontek tenim un editor que permet tabs, autocompletat, plantilles, integració amb subversion i tota la potència d'edició de vim. El tema del depurador integrat està un poc més verd, però tampoc l'he trobat massa a faltar.

A un dels comentaris hi havia la recomanació per a la instal·lació a més de NERDTree un navegador de fitxers integrat al vim que facilita molt la vida, i també ho vaig posar. També he adaptat les plantilles que venen per Django per a que agafi la sintaxi del trunk i he afegit algun retoc més com que posi la codificació als fitxers i coses així, les plantilles són tan bones de modificar que me pareix que puc acabar amb un bon repositori de codi :)

Tot i que no poseu la configuració crec que és interessant fer-hi una ullada a com ha organitzat Sontek (John M. Anderson) el seu fitxer de configuració per veure un exemple del que es pot fer amb vim i de com es pot incloure codi Python dins l'arxiu de configuració. Una de les maneres d'aprendre a programar és llegir codi d'altres (bon codi si és possible) i en l'arxiu de configuració de vim podem dir el mateix: llegint configuracions d'altra gent podem arribar a personalitzar l'editor fins a límits insospitats.

4 comentaris, 0 trackbacks (URL) , Tags: Python Django


Primeres modificacions al blog nou

Escrit per Aaloy a 15 de April , 2008 a les 9:11 p.m.

Link to Primeres modificacions al blog nou

Avui he fet les primeres modificacions al Blog. Ja us deia que això de posar en producció les coses et força a trobar i corregir els errors més ràpid.

M'he trobat que els RSS no funcionaven. La idea era mantenir la compatibilitat amb els RSS de Wordpress, de tal manera que els vells subscriptors no notassin el canvi, però me vaig deixar una s i no anaven. El canvi ha esta molt senzill, però ha sigut cosa d'esperar a arribar a casa per fer les modificacions.

De pas he aprofitat per arreglar quatre etiquetes que no estaven ben posades i posar una validació als comentaris de manera que "peti" en posar un comentari buid. La part de comentaris és potser el que menys m'agrada, ja que encara fa servir les llibreries de oldforms de Django i jo ja estic molt acostumat a les noves. El canvi de oldforms a newforms serà de les primeres coses que vull fer. El que em frena un poc és la part de control de l'spam, però miraré si puc fer servir algun component per a connectar amb l'Akismet i fer-ne el backoffice per a controlar-ho.

De les coses que més m'agraden del nou programa és la possibilitat de fer servir el Markdown per a escriure els posts. Al Wordpress segurament se deu poder fer alguna cosa per l'estil, però no m'hi he volgut barallar mai. Vaig posar també javascript per a colorejar codi Python, així que ara veureu que els articles que tenguin codi quedaran un poc millor presentats.

0 comentaris, 0 trackbacks (URL) , Tags: Python Django


Powered by Django

Escrit per Aaloy a 14 de April , 2008 a les 9:24 p.m.

Link to Powered by Django

Un dels propòsits del 2008 pareix que ja s'ha complert. Gràcies a Bernat avui hem canviat el blog vei en wordpress que quedarà a blog.trespams.com, més que res per si alguna cosa anàs malament mentre es fa el canvi.

El nou blog està en fase beta, però seguint els principis del la programació àgil, he preferit posar-ho en producció i anar polint els detalls que queden. Com podeu veure pel titol el blog és Django powered. Corre damunt un servidor dedicat que tenim per APSL dins un entorn chroot que en Bernat ha montat.

El codi font del blog està disponible al repositori de google code, com a una branca amb suport unicode del blogmaker, així que tothom és benvingut a col·laborar-hi i a posar-hi tickets pels errors que segurament hi trobareu.

Al codi font també hi ha l'importador de Wordpress cap al blog, de manera que veureu que els articles de l'antic lloc, comentaris i trackback estan inclosos en el nou. La importació no ha estat massa complexa i s'ha fet a partir de l'exportación en format RSS que fa el Wordpress. Tot i això hi ha petites millores a fer, com les de tractar millor els paràgrafs. Alguns articles encara no han passat per la modificació i les lletres es veuen molt atapides, fruit de la combinació de l'importado i de la fulla d'estils que he fet servir per a contruir el lloc, el multiflex.

Encara queden cosetes a polir, veig que m'he deixat el peu del "powered by django" per exemple, la part d'agraïments, etc. etc. que aniré posant durant els propers dies i setmanes. El d'avui és una beta, gairebé alfa, però com us dic, crec que l'important és perdre la por i posar-ho en producció i anar-ho millorant dia a dia.

6 comentaris, 0 trackbacks (URL) , Tags: Python Django


Ja tenim el compte d’Appengine

Escrit per Aaloy a 11 de April , 2008 a les 11:37 p.m.

Doncs això, fa poques hores he rebut el missatge que diu que ja puc fer coses amb l'Appengine de Google, en morenosan en va dir ahir que havia rebut també el seu, així que pareix que estan obrint el grifó bastant de pressa.

Ara es cosa d'anar pensant què es pot fer. De totes maneres no es tant l'aplicació en sí, com poder provar l'entorn i començar a veure les seves possibilitats, com s'hi fa feina, quines diferències hi ha entre poder fer l'ORM de Google i el de Django, veure les limitacions que ens imposa...

Temps al temps!

1 comentari, 0 trackbacks (URL) , Tags: Python Django


Bons temps per Python

Escrit per Aaloy a 09 de April , 2008 a les 12:03 a.m.

La blogosfera en va plena Google ha llançat el seu appengine , un servei que permet hostejar aplicacions de fins a 500 Mb d'espai i 5 milions de visites mensuals que Google ha llançat i que té com a llenguatge vehicular el Python.

Per a accedir-hi un s'ha d'apuntar a la llista d'espera, ja que pareix que els comptes en fase beta s'han esgotat, i tot i les limitacions del sistema en el que fa referència als accessos als sistemes de fitxers, limitacions de la part de base de dades, que no es puguin llançar subprocessos i coses per l'estil, obre la possibilitat a tot un ventall d'aplicacions web.

On la notícia ha impactat més és a la comunitat Python: un llançament espectacular de Google, amb Guido pel mig, am Python com a protagonista i amb Django com a estrella convidada, ja que Django, encara que la versió "estable", ve de sèrie en el sistema.

Si encara no ho heu fet és un bon moment per aprendre Python i Django (ueps, tal volta seria un bon moment per publicitar-ne cursos :-P ) ja que un dels emperòs més grans que hi havia és que no se disposava d'un servidor a preus assequibles on poder fer anar les aplicacions. Ara amb el llançament de Google, les possibilitats de fer desenvolupaments amb Python i Django es multipliquen, limitats a les possibilitats de l'entorn que proporciona Google, sí, però permetran en breu començar a fer aplicacions web i hostetjar-les a un preu inmillorable.

Amb això esper a més que els hostingaires de sempre es posin les piles i donin a preus raonables allotjament per Django, proporcionant a més el servei que ara Google no ofereix: el de tenir una base de dades relacional pròpia al darrera.

I és que un dels grans problemes de l'oferta de Google és que no ets ben bé l'amo de la teva base de dades i algunes coses que permet fer l'ORM de Django molt fàcilment a l'ORM substitutiu de Google no es poden fer.

És clar que no totes les aplicacions necessiten d'una base de dades relacional al darrera, així que l'appengine de Google és per una part un bon banc de proves per veure com va això de la programació web amb Python i Django i per una altra una manera ràpida i econòmica de posar en producció projectes web que d'altra manera tendrien un cost prohibitiu pel programador mig.

2 comentaris, 3 trackbacks (URL) , Tags: Informàtica Python Django


Propietats a Python

Escrit per Aaloy a 21 de March , 2008 a les 1:41 p.m.

En Corey Goldberg al seu blog a un recull interessant d'enllaços de lectura obligada per aquella gent que està fent la transició de Java o C# cap a Python.

Un dels més interessant és l'article de Phillip J. Eby anomenat Python is not Java on recull les diferències fonamentals que hi ha entre programar en Java o programar en Python. Una de les afirmacions més xocants és potser aquesta: Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans. Do not write getters and setters, és a dir "Els getter i setters són el dimoni. El Dimoni, dic. Els objects de Python no són Java beans. No escriguis getters i setters."

La frase pot semblar molt bèstia, i de fet ho és, ja que és una afirmació que s'ha de matitzar molt, com de fet ho fa en Ryan Tomayko al l'apunt Getters/Setters/Fuxors on s'explica molt bé quan fer servir aquest tipus de construccions, però en definitiva el que ens hem de quedar és amb la idea de que normalment Python no necessita mètodes accessors i que l'ús normal d'aquest és el de marcar un atribut com de sols lectura.

Com sempre hi ha "la manera de Python" de fer les coses, i sol ser la manera més senzilla de fer-les.

1 comentari, 0 trackbacks (URL) , Tags: Informàtica Python


Integració de Hudson i Trac

Escrit per Aaloy a 15 de March , 2008 a les 11:52 a.m.

A un altre post ja vaig parlar de Hudson, un sistema d'integració contínua, relativament nou però que permet fer el que un necessita d'aquestes característiques de manera fàcil i amb una interfície molt cuidada.

Hudson es pot integrar amb Trac, de manera que al Timeline del projecte trac poguem veure com han anat les integracions sense tenir que anar al Hudson. D'aquesta manera la gent que fa el seguiment del projecte pot veure a més dels commits al subversions, modificacions al wiki i tickets, com han anat les integracions i quan s'han fet.

La integració dels dos aplicatius és força senzilla:

  • Instal·lam el python-feedparser si no ho tenim ja al nostre servidor.
  • Anam a http://trac-hacks.org/wiki/HudsonTracPlugin i descarregam el plugin.
  • Descomprimim el plugin i amb permisos d'administrador executam python setup.py install això ens crearà el paquet egg i configurarà el plugin a nivell global dins el trac.
  • Editam l'arxiu trac.ini del nostre projecte trac que volguem enllaçar amb Hudson i modificam la llista de components, en el meu cas la cosa queda com
[components]
iniadmin.iniadmin.iniadminplugin = enabled
webadmin.* = enabled
HudsonTrac.* = enabled
  • Cream també una entra a anomenada hudson allà on posarem tant la url del rss del nombre projecte hudson que volguem controlar com el de la vista del projecte, de tal manera que s'hi crei un enllaç dins Trac
[hudson] display_subprojects = false feed_url = http://servidorhudson/hudson/view/Java/rssAll main_page = http://servidorhudson/hudson/view/Java/
  • Canvia el servidorhudson pel vostre servidor. Aquí el que he fet és enllaçar directament contra la vista de projectes anomenada Java que he creat. Podria enllaçar a un projecte concret o a una vista relacionada amb el projecte que es gestiona amb el Trac.

Si s'han seguit aquestes passes i una vegada refrescada la plana del Trac, ens apareixerà una nova secció anomenada Hudson a la part de navegació del Trac que enllaça a la url que hem posat a main_page i al timeline apareixerà una opció que ens permetrà visualitzar les integracions, en forma de control check.

Pels que feu servir Trac de manera habitual, és interessant instal·lar-se també el plugin IniAdminPlugin, que ens crea un menú de configuració per web del trac.ini del nostre projecte.

És interessant a tot això adonar-se de que gràcies als formats oberts, en aquest cas al RSS que publica Hudson i que pot consumir Trac, dues aplicacions fetes en tecnologies totalment diferents es poden integrar.

Al Hudson passa una cosa semblant, està pensat per tractar amb format oberts, típicament sortides XML en format UnitTest, la qual cosa permet afegir-hi projectetes de Python, Java o SoapUI.

2 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Java


Winpdb

Escrit per Aaloy a 27 de January , 2008 a les 11:15 a.m.

Winpdb és un depurador en mode consola i gràfic per aplicacions Python.. Fa un parell de setmanes que han alliberat una nova versió. En la seva part gràfica, el programa presenta una interfície clara i permet la depuració remota de les aplicacions.

Es pot utilitzar per depurar scripts de Python molt fàcilment sols executant el programa passant-hi com a paràmetre l'script a depurar, tal com se fa amb el depurador estàndard de Python.

La vertadera potència, però està en la facilitat en que es poden depurar aplicacions remotes o aplicacions com les que es poden fer en Django per exemple. En a quest cas afegint aquesa línia al que vulguem depurar

import rpdb2 
rpdb2.start_embedded_debugger_interactive_password('clau de seguretat')

ens permetrà connectar-hi el depurador.

Winpdb fa temps que roda, però és la primera vegada que puc fer anar la depuració remota sense problemes. Una eina més a afegir a la capça de programació.

0 comentaris, 0 trackbacks (URL) , Tags: Python


Ordre a la llista!

Escrit per Aaloy a 23 de September , 2007 a les 7:18 p.m.

Una de les accions més repetitives que sovint feim quan passam cap a la capa de presentació és la d'ordenar els elements que volem que es presentin. Potser algú dirà que els elements ja poden venir ordenats de la consulta a la base de dades, però què passa si en lloc d'atacar a una base de dades directament obtenim el que s'ha de mostrar d'un servei web? o ja hem fet un tractament de les dades i ara les volem ordenar per un altra camp. Poder fer ordenacions de manera senzilla i ràpida ens soluciona molts maldecaps. Anem a veure com Python ens permet fer ordenacions de llistes de pràcticament qualsevol cosa. Python fa servir el mètode sort per a ordenar una llista. L'exemple més senzill seria l'ordenació d'una llista d'enters $ llista = [2,4,5,6,7,6,7] $ llista.sort() $ llista [2, 4, 5, 6, 6, 7, 7] Sí, és tan senzill com pareix, i fins i tot podem fer $ llista.reverse() $ llista [7, 7, 6, 6, 5, 4, 2] Però clar, una llista a Python pot contenir qualsevol cosa, no sols sencers, anem a veure què passa si passam una llista de parells (tuples) $ llista = [(1,5),(1,2),(2,2),(3,5),(4,8),(1,9)] $ llista.sort() $ llista [(1, 2), (1, 5), (1, 9), (2, 2), (3, 5), (4, 8)] Suposem però que jo el que vull és que s'ordeni pel segon element de la tupla, aquí si un prové d'altres llenguatges de programació ja se pot esperar tenir que escriure un bon munt de codi, però no en Python, l'ordenació es fa per una clau i podem definir quina és aquesta clau passant-li al mètode sort una funció construida de manera que prengui un sol element i ens retorni la clau a comparar. Per fer el que volem farem servir el mòdul operator, i dins aquest la funció itemgetter, aquesta funció ens retorna una altra funció que aplicada damunt una llista o tupla ens donarà l'element especificat que haguem definit, així per exemple $ segon=itemgetter(1) $ segon(llista) (2, 2) $ llista [(1, 2), (2, 2), (1, 5), (3, 5), (4, 8), (1, 9)] $ segon(llista) (2, 2) $ segon((1,5)) 5 Farem servir aquesta funció per a obtenir la clau per la qual volem ordenar la nostra llista, així $ llista.sort(key=segon) $ llista [(1, 2), (2, 2), (1, 5), (3, 5), (4, 8), (1, 9)] Pensem en les implicacions que té això quan volem omplir un select d'html, encara que la llista ens hagi arribada ordenada per codi, podem fàcilment canviar l'ordenació al texte sols amb aquesta instrucció. Un altra paràmetre que ens serà de molta utilitat a l'hora de fer ordenacions és el cmp, aquest ens permet passar una funció que donats dos arguments haurà de retornar un nombre positiu per indicar que el primer és major que el segon, zero per indicar que els elements són igual o negatiu per indicar que el segon és major que el primer. Per exemple, suposem que el que volem fer és ordenar la nostra llista segons el que sumen els seus components. $ t=llista[:] #Farem primer una còpia de la llista original $ def ordena(x,y): p1 = x[0]+x[1] p2 = y[0]+y[1] return p1-p2 $ t.sort(cmp=ordena) $ t [(1, 2), (2, 2), (1, 5), (3, 5), (1, 9), (4, 8)] $ llista [(1, 2), (2, 2), (1, 5), (3, 5), (4, 8), (1, 9)] O també poden fer un codi més florit i escriure $ t = llista[:] $ t [(1, 2), (2, 2), (1, 5), (3, 5), (4, 8), (1, 9)] $ t.sort(lambda x,y: x[0]+x[1]-y[0]-y[1]) $ t [(1, 2), (2, 2), (1, 5), (3, 5), (1, 9), (4, 8)] Si algú ha tingut la paciència d'arribar fins aquí, un momentet, que ara ve el més interessant. Què passa quan en lloc de llistes de nombres tenim llistes d'objectes? Doncs res, podem fer servir el paràmetre cmp o el paràmetre key segons ens vagi millor per fer l'ordenació. Anem a veure tres maneres de fer el mateix. Primer definirem la nostra llista d'objectes class Persona: def __init__(self, nom, edat): self.nom = nom self.edat = edat def __cmp__(self, altri): return cmp(self.edat,altri.edat) Aquí el que he defint és una funció cmp dins la classe, que és la que faríem servir per defecte a l'hora d'ordenar una llista d'objectes d'aquest tipus, així: $ agenda = [Persona('Benjamí', 31), Persona('Pau', 22), Persona('Juan',34), Persona('Ricardo',38), Persona('Guillem',28), Persona('Bernat',58)] $ agenda.sort() $ for amic in agenda: $    print "%25s \t %i" % (amic.nom, amic.edat)
                      Pau        22
                  Guillem        28
                  Benjamí        31
                     Juan        34
                  Ricardo        38
                   Bernat        58
Ara suposem però que volem ordenar la llista per nom. Una opció seria refer el mètode cmp, però tenim altres opcions. La primera és encriure una nova funció de comparació: $ def compara_nom(amic1, amic2): $    return cmp(amic1.nom,amic2.nom) $ agenda.sort(compara_nom) $ for amic in agenda: $    print "%25s \t %i" % (amic.nom, amic.edat)
                  Benjamí        31
                   Bernat        58
                  Guillem        28
                     Juan        34
                      Pau        22
                  Ricardo        38
O bé, si ens agrada més l'opció lambda $ agenda.sort(lambda amic1, amic2: cmp(amic1.nom,amic2.nom)) Però encara tenim una altra maner, deixant que Python faci la feina per nosaltres, hem d'indicar la clau d'ordenació i fer que les eines de comparació del llenguatge facin la seva via. El problema però està en com dir-li quina clau fer servir, això s'aconsegueix amb attrgetter de la llibreria operator. $ agenda.sort(key=attrgetter('nom')) $ for amic in agenda: $    print "%25s \t %i" % (amic.nom, amic.edat) Fixau-vos el senzill que seria poder fer una ordenació per qualsevol camp de la classe. Referències:

1 comentari, 0 trackbacks (URL) , Tags: Python


Creant objectes a la manera de Python.

Escrit per Aaloy a 09 de September , 2007 a les 10:33 p.m.

He estat mirant coses damunt patrons de disseny aplicables al model d'interfície gruixuda d'usuari, aplicables a la programació amb wxPython, arribant a tres patrons:
  • El patró MVC (Model view controller) de sobres conegut per la gent que es dedica al desenvolupament web fonamentalment.
  • El patró MVP (Model view presenter) , que intenta fer que la part d'interacció sigui més testejable y que Flower ha considerat que s'havia de xapar en dos.
  • El patró Presentació Model, que independitza la capa de presentació de la vista, en un intent de separar el que és la part de comportament i estat de la vista en un model que és part de la presentació però que no es específic d'una implementació d'interfície concreta.
Llegint el codi he arribat una manera de construir objectes a partir de llistes que no havia fet servir fins ara. Això s'explica millor amb un exemple: class Agenda: ... def __init__(self, nom, llinatge, telefon, amic=True): ... self.nom = nom ... self.llinatge = llinatge ... self.telefon = telefon ... self.amic = amic ... La manera habitual de crear un objecte de tipus Agenda seria per exemple amic = Agenda('toni','aloy','971xxxxxxx') Suposem ara que tenim la informació dins una llista o una tupla, bastant habitual si per exemple hem importat les dades d'un arxiu de text o des de una base de dades, aleshores podem tenir la informació com un_amic =('Pau','Rul·lan','971xxxxxxx') La creació de l'objecte és molt ràpida d'escriure amic2 = Agenda(*un_amic) amic2.nom 'Pau' És a dir, s'han substituït els paràmetres de construcció de l'objecte pels valors de la llista. Aquesta substitució és posicional, és a dir, el primer valor correspon al primer paràmetre, el segon al segon, etc. La sintaxi és conseqüent amb la manera d'anomenar llistes de paràmetres en la construcció de funcions, per exemple: def prova (x, *y): ... print x ... for item in y: ... print item ... prova(2,3,4,5,6,7) 2 3 4 5 6 7 prova (2,7,10) 2 7 10 Però clar, si això funciona d'aquesta manera i estam parlant de Python i haurà una manera obvia de fer el mateix si en lloc d'una llista tenim un diccionari, és a dir, ara tenim: un_amic ={'nom':'Benjamí','llinatge':'Villoslada','telefon':'971xxxxxxx'} Les claus del diccionari coincideixen amb els noms dels paràmetres, i hauríem de poder fer amic3 = Agenda(**un_amic) Això és Python, i per tant amic3.nom 'Benjam\xc3\xad'

3 comentaris, 0 trackbacks (URL) , Tags: Python


Depurar una aplicació Django

Escrit per Aaloy a 23 de January , 2007 a les 1:27 a.m.

De tant en tant faig algun apunt per tenir una referència posterior, a manera de documentació per tal de no oblidar-me de com se fa una cosa, d'una referència o procediment. Avui és un d'aquests apunts.

Com he comentat en altres apunts darrerament estic fent molta cosa amb Python i Django com a bastiment MVT web. En un món ideal el meu G5 funcionaria de conya amb l'Eclipse i tendria un depurador de Python integrat a l'IDE, però com que no tot pot ser tan meravellós com la combinació de Python i Django, doncs vaig tenir que cercar alternatives. Una prou bona és el Kdevelop, així que al G5 per programar utilitz les següents eines:

  • Kdevelop com a Editor principal. Ben bé es podria fer amb Kate, però m'agrada la funcionalitat extra que aporta.
  • Vim, no pot faltar mai!
  • svn per interactuar amb el repositori subversion. També feia server kdesvn però al final m'és més còmode la línea de comandaments.
  • kdiff3. Que la comparació visual està molt bé, tú!
  • Firefox amb les extensions de webdeveloper tools i firebug
  • Eclipse. Quan la gestió dels canvis se me complica i puc mantenir-ho estable el temps suficient per fer els canvis.

El problema d'això és si no es fa servir l'Eclipse no disposam de depurador integrat a l'IDE. [1]. Això per mi és un problema, menor, sí, perquè Python és prou net i elegant i la informació de depuració de Django prou extensa com per anyorar-ho poc, però què voleu, m'agrada al manco tenir l'opció de poder seguir la traça d'un programa sense tenir que tirar de logs i prints. [2].

Doncs mirant un poc pels fòrums de Django i un poc per Google, he arribat a la següent recepta:

  1. Executam el servidor de Django amb l'opció de noreload: python manage.py --noreload runserver
  2. Al fitxer el codi del qual volem depurar feim from settings import DEBUG if DEBUG: import pdb
  3. L'important aquí és l'import, l'altre codi sols és per assegurar-nos que si ens deixam el codi de depuració en producció "petarà".

  4. Per acabar al lloc on voguem posar el punt de ruptura escriurem: pdb.set_trace()

Això fa que en arribar a al punt hom hem establer la traça, la consola del servidor de Django ens mostri el símbol de depuració.

-> user = request.user
(Pdb)

A partir d'aquí ja hem entrat en mode de depuració i basta llegir-se un poc la documentació del depurador integrat de Python per anar tirant. Recordem que no estam sols davant d'un simple depurador, sinó que tenim tota la potència de Python al depurador mateix. Un tutorial força senzill per començar és Debugging in Python.

Una vegada acabeu de depurar hem de recordar llevar o comentar el pbd.set_trace(). Possiblement hi haurà maneres més potents de fer això, com la depuració remota, però aquesta és prou senzilla de fer anar. [1] Eric en duu un de depurador integrat, però darrerament no hi ha manera de posar-hi accents a l'editor i no es cosa sols del G5, així que l'he descartat de moment com a IDE.

[2] He vist gent no fer servir el depurador integrat de l'Eclipse programant en Java, però me'n reservaré l'opinió.

2 comentaris, 0 trackbacks (URL) , Tags: Informàtica Python Django


wxPython in Action

Escrit per Aaloy a 23 de May , 2006 a les 12:59 a.m.

Per la llista de Python, concretament a pun apunt del Dr. Dobb's Python-URL! m'he assabentat de l'existència del llibre wxPython in Action i de la possibilitat de fullejar un dels seus capítols a la web pythontrheads.

Això són bones notícies, ja que vol dir que a partir d'ara tindrem més documentació d'aquesta excel·lent llibreria gràfica. Pels qui no la coneguin wxPython és un embolcall (binding) per Python de les llibreries wxWidgets, abans conegudes com wxWindows. Aquestes llibreries són portables, potents i no gaire pesades. L'emperò és que la seva gestió d'events no és tan neta com el mètode signal/slot de les Qt.

Com a avantatge tenim els nombrosos exemples que hi ha per fer gairebé de tot el que se'ns acudi en termes d'interfície gràfica i dissenyadors d'interfícies d'usuari com les wxGlade, o un IDE com el Boa Constructor .

Les wxPython són una opció a tenir en compte si ens plantejam fer una interfície d'usuari que sigui lleugera i portable, i m'atreviré a afegir dues característiques més: mantenible gràcies a la claretat i senzillesa de Python i divertida de programar.

1 comentari, 0 trackbacks (URL) , Tags: Informàtica Python


Un Hibernate per Python.

Escrit per Aaloy a 23 de May , 2005 a les 11:16 p.m.

Fa estona que tenc ganes de fer una aplicació de gestió amb Python, així com a prova de concepte i per passar-m'ho bé programant.

Una de les coses que més m'aturen és el tema de la persistència. Ja sabeu, al final les aplicacions de gestió han de volcar les seves dades a una base de dades i això fa que es tengui que escriure i mantenir força codi SQL.

Darrerament he estat llegint molt damunt Java i hi estic començant a fer feina professionalment. Quan estàvem montant l'arquitectura que faríem servir per les aplicacions també va sorgir el problema de la persistència. Llavors una de les opcions que més m'agradaren per la seva potència i simplicitat va ser l'Hibernate.. Aquest bastiment de persistència m'agrada molt i fa que una de les tasques més propenses a errors i més tocacollons com és el d'escriure i mantenir codi SQL estigui molt més controlada.

Per Python estava cercant quelcom semblant i no l'acabava de trobar. Avui se m'ha acudit cercar servidors web per Python i he anat a topar amb SunkWeb. Pel que he estat llegint fins ara pot ser la resposta, cap dels bastiments de persistència que havia vist per Python tenen la bona pinta que té aquest. Si és tan potent com pareix aviat podré tenir alguna cosa feta.

0 comentaris, 0 trackbacks (URL) , Tags: Python