[ x ]

Faig servir les cookies de Google Analytics per al control de visites i estadístiques..
És una pardalada, però la llei diu que us he d'avisar, ja veus. Així que si visitau aquest blog donau-vos per informats o sortiu ara mateix i netejau les cookies del vostre navegador. Si continuau llegint, suposaré que ja us està bé. Si vols saber com llevar les cookies del teu navegador: aquí ho pots trobar

Mantenibilitat en llenguatges tipats i no tipats

Quan surt aquesta discusió sovint, al manco al meu àmbit, la discusió es redueix a comparar Java i Python. Recentment en Paco ha obert la capsa dels trons al twitter amb una afirmació "Para escribir código mantenible, mejor un L.P. fuertemente tipado. Si es compilado, mejor".

Damunt el tipat o no em remetré al post de Ned Batchelder i a un comentari d'aquest post, amb al qual hi estic d'acord en un 90%, que traduït lliurement i sense limitar-ho a java diria:

  1. Python maximitza la productivitat dels bons programadors

  2. Els llenguatges tipats (Java a l'original) minimitzen el mal que els programadors mediocres poden fer al sistema.

Tant de bo la segona afirmació fos certa. La gent pot ser molt creativa i cap tipat del món no pot evitar que es faci un borrat complet contra la base de dades, que s'equivoqui amb l'algorisme del càlcul de l'IVA, les possibilitats són infinites. La referència obligada de que el tipat fort no és cap garantia de mantenibilitat la tenim al post How to Write Unmaintainable Code o passar-se per The daily WTF. El primer cas és fins i tot més sagnant, ja que la gran majoria d'exemples i tècniques es refereixen a llenguatges fortament tipats com el C, C++ i Java. Usos creatius del define, noms de variables que no tenen res a veure amb el que fa la variable, noms lleugerament semblants que fan coses totalment distintes,...

No vull fer sang damunt el tipat fort, la majoria de les coses que expliquen al How to Write es poden extrapolar a qualsevol llenguatge de programació. Però la realitat és el tipat fort no és cap garantia de mantenibilitat.

La mantenibiliat ens la donen les convencions del codi, la documentació, la inspecció periòdica o sistemàtica del nostre codi (o del codi d'altres), el llegir el code complete i aplicar els consells i pràctiques també ajuda força. Tenir test unitaris, programes que ens gestionin l'adherència als estàndarts i la complexitat del codi (n'hi ha per Java, Python, C++, ...), gestió acurada del errors, tests de regressió, etc. a l'hora de la mantenibilitat poden fer molt més que el simple tipat.

Potser perquè molts de programes que he fet al llarg del temps s'han mantingut en producció durant anys sóc un tant fanàtic de la mantenibilitat, preferesc codi matenible a codi guais que al cap d'un mes ningú, ni el seu creador, sabrà perquè ho va fer d'aquella manera. I aquest tipus de mantenibilidad no la dóna el tipat fort o el compilador, la mantenibilitat ens la dóna la gent i les regles que ens imposem a l'hora de crear el codi.

Com la seguretat la mantenibilitat no és quelcom que es pugui posar una vegada el programa està llest. La mantenibilitat ha de formar part del procés de desenvolupament. Sovint he refet o he fet refer codi perquè era mal de seguir, per massa acoblament, perquè la quantitat de ifs feia difícil saber per on anava el codi, i això m'ha passat tant en Java, Pascal o FORTRAN com en Python.

Llavors, pensant en que els programes es fan per a ser mantenibles tant en llenguatges tipats com en els no tipats, la pregunta que ens faríem doncs és perquè triar un llenguatge o un altra i aquí ja entraríem en un altre tipus de discusió.

Si pensam sols en termes de mantenibilitat i suposant que programam com toca potser estarem d'acord que hauríem de triar un llenguatge que fos bo de llegir, de seguir, expressiu i d'alt nivell. El millor codi és aquell que no s'ha d'escriure. Per mi pocs llenguatges compleixen això tant bé com Python, és un llenguatge molt clar de llegir, amb una corba d'aprenentatge molt suau i amb una dèria cap a la llegibilitat i la mantenibilitat que està incorporada al llenguatge dins la pròpia sintaxi (la identació) i a l'intèrpret mateix (provau import this) o llegiu The Zend of Python i les convencions de codi són públiques i definides des del 2001, la qual cosa no vol dir que no s'hagin canviat al llarg del temps.

En conclusió: el codi mantenible no ho dóna un compilador sinó el programador i la gestió que se dugui del projecte. No podem confiar en que el tipat fort ens farà la feina i ens alliberarà de la feina de crear tests unitaris, de comprovar que el codi està d'acord als estàndards o de que fa el que ha de fer.

Java, C, C++ són grans llenguatges no perquè tenguin tipat fort, sinó pel que els programadors hem fet amb ells. De la mateixa manera Python, PHP, Perl, Ruby són grans llenguatges no per la seva absència de tipat, sinó per codi que ens permeten escriure.

Comentaris
  1. Paco Ros Paco Ros on 01/11/2009 15:08 #

    En general estic d'acord amb el que dius :-)

    És un tema molt complex i el primer que hauríem de fer és plantejar-nos què és un software mantenible i quines característiques desijables hauria de tenir.

    Si en podem trobar alguna mètrica, millor.

    D'altra banda, el post parla de que el tipat fort no garanteix la mantenibilitat. N'estic d'acord, però no demostra que un programa sense tipat sigui més mantenible o que el tipat fort presenti defectes que facin un llenguatge dinàmic o no tipat preferible.

    Només aportes com argument que python, per mor de que el sintàctic està basat en el nombre de tabs abans de cada línia és més legible i, per tant, més mantenible. No et diré que no ajudi, però les begin ... end, les claus... etc bén posats i amb una indentació correcta o un formatador del codi (Has provat Shift + Alt + f a NetBeans?) aquest avantatge no és tal.

    Els llenguatges amb tipat fort i els llenguatges compilats (o al menys aquells que permeten passar-li un analitzador sintàtic i semàntic abans de l'execució) són més immunes als efectes laterals dels canvis, mentre que els intepretats i no fortament tipats, requereixen de forçar-ne una execució per comprovar que funcionen.

    Si el programador és igual de bo programant en C++ o en Ruby (per donar dos exemples) cometrà el mateix número d'errades amb els dos, però amb el primer necessitarà d'uns segons per adonar-se'n i amb el segon necessitarà simular una execució completa.

    Cercaré un poc de bibliografia per ilustrar tot això i raonar millor aquesta opinió, però, ja que ho has escrit i comentçat el debat, mereixies una resposta :-)

    SAlut!

  2. aaloy aaloy on 01/11/2009 15:44 #

    >Només aportes com argument que python, per mor de que el sintàctic està basat en el >nombre de tabs abans de cada línia és més legible i, per tant, més mantenible. No >et diré que no ajudi, però les begin ... end, les claus... etc bén posats i amb una >indentació correcta o un formatador del codi (Has provat Shift + Alt + f a >NetBeans?) aquest avantatge no és tal.

    No exactament, vull dir que hi ha llenguatges més orientats que altres cap a la mantenibilitat. En altres llenguatges t'has d'ajudar dun formatador, a Python la legibilitat és tan important que va dins el llenguatge.

    >Els llenguatges amb tipat fort i els llenguatges compilats (o al menys aquells >que >permeten passar-li un analitzador sintàtic i semàntic abans de l'execució) >són més >immunes als efectes laterals dels canvis, mentre que els intepretats i >no fortament tipats, requereixen de forçar-ne una execució per comprovar que >funcionen.

    Puc passa analitzador al Python, el pycheck o el pylint per exemle, de fet tenc el pylint integrat al vim per exemple. El tema és que ho pots fer com i quan vols. Respecte als efectes laterals dels canvis, dependrà molt de quins sigui els canvis. Si canvies els tipus paràmetres d'una funció mentre siguin comparables (duck typing) a Python o Ruby no hi haurà efectes laterals, a un llenguatge tipat sí.

    >Si el programador és igual de bo programant en C++ o en Ruby (per donar dos >exemples) cometrà el mateix número d'errades amb els dos, però amb el primer >necessitarà d'uns segons per adonar-se'n i amb el segon necessitarà simular una >execució completa.

    L'argumentació és correcta. Pel mateix motiu si el programador escriu menys línies de codi cometrà menys errors (està acceptat que el nombre d'errors que comet un programador per cada 1000 línies de codi és constant). Llavors la gràcia està en escriure el menys possible.

    El cicle de modificació, testeig i depuració és més curt en els llenguatges interpretats que en els compilats (que aquí podem traduïr per tipats). Està clar que es pot fer servir la compilació en línea però és el mateix que donen actualment els editor com Netbeans i Eclipse per Python, PHP o Ruby, no te compilen, però t'avisen de variables sense utilitzar i passen el pyLint en el cas de Python. Gairebé no hi ha diferència. I al cap i a la fi hauràs de testejar o passar els tests unitaris.

    Tenc bibliografia damunt mètriques de mantenibilitat, però el que sí s'ha d'aclarir és el concepte en sí: parlam de capacitat de fer un mantenimient correctiu, evolutiu o parlam del ratio d'errors? De tot en conjunt?

  3. ricardo galli ricardo galli on 01/11/2009 21:53 #

    > Els llenguatges amb tipat fort i els llenguatges compilats (o al menys aquells que permeten passar-li un analitzador sintàtic i semàntic abans de l'execució)

    Paco, estás radicalmente equivacodo:

    1. El nivel de análisis semántico en cuanto a la "correctitud" de un C o C++ es el mismo que puede tener cualquier lenguaje interpretado modernos (como Perl, Java, Python...).

    2. El análisis semántico se refiere sólo a la verificación que cumple con la gramática del lenguaje, no tiene nada que ver con los resultados de la ejecución.

    3. Si te refieres a que en un compilado puedes saber si tienes todo el código necesario (librerías), tampoco es cierto desde el momento que se usan librerías compartidas (o los usos de llamadas como dlopen() para incluir código externo). Lo único que aseguras es que las tienes en el momento de compilar... pero no cuando ejecutas. Lo mismo puedes forzar en cualquier lenguaje "interpretado".

    4. Desde el punto de vista de "computabilidad" da exactamente lo mismo que sea compilado o no. Al fin y al cabo uno u otro lenguaje funcionan sobre "computadores universales" y ambos están sujetos a las mismos problemas teóricos y prácticos

    5. Salvo excepciones, el Java es tan "interpretado" como Python, C# o Perl.

    6. Cualquier lenguaje es factible de ser "compilado", por lo que están todos en igualdad de condiciones.

  4. servo servo on 02/11/2009 18:51 #

    > 2. El análisis semántico se refiere sólo a la verificación que cumple con la gramática del lenguaje, no tiene nada que ver con los resultados de la ejecución.

    El que sembla que troba a faltar el Paco és el type-checking dels llenguatges de tipat estàtic. Però, com ja ha respost adequadament en Toni es pot dir que el fet d'emprar tests unitaris resol en bona part la falta de tipat dinàmic, a l'hora que aconsegueixes disminuir el nombre de línies per "l'expressivitat" del llenguatge.

    http://en.wikipedia.org/wiki/Type_checking#Type_checking

Els pingbacks estan tancats.