Una Java más Pythonico. ¿si o no?

Con uds. Python!

Python es un lenguaje de programación que entre sus características más distitivas está el uso de la identación para definir bloques.

Esto fue inicialmente muy polémico y ahora es considerado como una de las características más importantes del lenguaje, por que nos ayuda ( casi forza ) a tener un estilo consistente.

Para quién aún no haya visto Python este es un ejemplo sencillo:

class Persona:
  def saluda(self, aquien = '' ):
    if aquien == '':
      print 'Hola extraño'
    else:
      print 'Hola %s' % aquien
  def edad( self ):
    return self.edad

class Main:
  def main():
    Persona().saluda()

Como se ve, el contenido de la clase, el método, el if y el else están delimitados por la identación. Cuando termina la identación termina el cuerpo. Por ejemplo, la calse main, está identada al mismo nivel que la clase Persona y eso lo hace que este fuera.

Como decía, es polémico, pero con el tiempo esto se ha considerado incluso bello en el lenguaje.

Como punto de contraste en Java haríamos lo siguiente:

class Persona {
  int edad;

  void saluda( String a ) {
    if( a == "" ) {
      out.println("Hola extraño");
    } else {
      out.println("Hola %s", a );
    }
  }

  int edad() {
    return this.edad;
  }
}
class Main {
   void main() {
       new Persona().saluda("");
   }
}

Esto es a lo que nuestro ojo está acostumbrado. Y a mi me parece suficientemente bueno.

Que pasaría si...

Pues bien, ayer, ví este post http://bit.ly/hmvTe9 donde alguien escribía que en un proyecto una persona alinea todos los ";" y los "{}" a la derecha, para que el código se viera más pythonico.

En un inicio me pareció super extraño ( y de hecho si llego a ver a algo así en algún proyecto, de menos le doy un par de zapes al que lo escriba ) Sin embargo hay algo importante aquí. Que tanto necesitamos realmente ese llaverío. O que tan limpio y fácil de leer sería el código sin ellos?

class Persona
  int edad

  void saluda( String a )  
    if( a == "" )  
      out.println("Hola extraño")
    else  
      out.println("Hola %s", a )

  int edad()  
    return this.edad

class Main  
   void main()  
       new Persona().saluda("")

Luce bien. Sin embargo en un ejemplo tan chiquito como este, no se podría apreciar y decidir, si hay un beneficio o no. En python me queda claro que sirve ( Python esta a punto de convertirse en un lenguage de programación mainstream ) ; pero como mis ojos no están acostumbrados a ver Python, no puedo apreciarlo. Se necesita un código más largo y que se ejecute en una aplicación real para ver si existe o no el beneficio.

Así pues tomé la primera clase de jAlarms que encontré ( perdón Enrique ) y este es el resultado ( ADVERTENCIA : La imagen a continuación puede causar malestar o incomodidad para algunas personas )

http://javamexico.pastebin.com/As80a82Q

Obvio, no compila, pero esté sería el mismo código con la infame técnica de alinear todo a la derecha ( NO HACER ESTO EN CASA )

http://javamexico.pastebin.com/Uu4967vY

Pregunta

¿Que creen que pasaría si se pudiera escribir código así? ¿Aclararía en algo lo que leemos? ¿Lo haría más dificil?

Es evidente que las llaves, los puntos y coma y paréntesis son una ayuda para el compilador y nosotros los humanos nos hemos acostumbrado a ellos, pero, ¿en realidad son necesarios?

Supongo que es dificil contestar esto desde nuestra optica de programadores de Java ( sobre todo cuando los otros lenguajes en los que aveces programamos tienen la misma naturaleza, Groovy, C, Objective-C, JavaScript, C# ) y puede ser algo natural.

Suponiendo que el compilador no tuviera problemas con esto ¿lo usariamos?, ¿lo usarias tu?

Comenten.


Actualización

Por cierto, estos comentarios aplican también para otros elementos como los parentesis. Ahora recuerdo que en Ruby (casi) todos los parentesis son opcionales, lo cual por ejemplo Scala lo toma al pie de la letra y supongo que Groovy también:

Por ejemplo haciendo los paréntisis opcionales quedaría:

class Persona
  int edad
 
  void saluda( String a )  
    if a == ""  
      out.println  "Hola extraño"
      someOtherMethod args      
    else  
      out.println "Hola %s", a
      someOtherMethos null

  int edad
    return this.edad

class Main  
   void main()  
       new Persona.saluda ""

Como ultimo ejemplo está este lenguaje CoffeeScript que ya hace algo similar para JavaScript.

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Mareo

Cuando te refieres a sentir malestar por ver el código así pensé que sería por repulsión estética o algo así, pero lo que sentí fue honestamente un poco como de vértigo. Como que voy leyendo un método y de repente caigo a un precipicio, porque no hay una llave que detenga el final del método...

Lo del punto y coma no le veo tanta bronca, hoy en día cuando escribo algo en Groovy (que no es diario, sigo usándolo para scripts y programas que hay que sacar rápido pero no lo he integrado en aplicaciones existentes), ya es muy raro que se me vaya un ; al final de una sentencia. Pero con las llaves por lo que me di cuenta ahorita, creo que sí tendría más bronca para acostumbrarme...

Originalmente el ; y las llaves sí eran como ayuda para el compilador, por cuestiones de desempeño también, para que no te quedaras mucho tiempo esperando a que tu código compilara. Pero hoy en día la compilación es algo que se realiza muy rápido, sobre todo si usas un IDE como Eclipse o IDEA donde la compilación se vuelve algo transparente para el programador. En Groovy fue relativamente fácil quitar el ; (o dejarlo como opcional realmente) porque el parser se complica un poquito más para determinar cuándo termina una sentencia (no siempre es con cambio de linea) pero no es gran cosa y el performance de la compilación (y por lo tanto de la interpretación, cuando corremos directamente un script en Groovy) no se vio afectado de manera notable.

Pero pues hay cosas en los lenguajes de programación que finalmente están pensadas para mejorar la legibilidad del código, aunque el compilador las ignore. Por qué tenemos dos tipos de sintaxis para comentarios? Pues porque si quieres escribir un comentario de una línea, algo rápido, es más rápido poner // y escribir el comentario, o si quieres comentar una sola linea de código sólo tienes que ir al principio y poner //; si no tuvieras esa opción tendrías que ir al principio de la línea y poner /* y luego ir al final de la línea y poner */ (o hacerlo en orden inverso, no importa, pero son 2 acciones en vez de 1).

De igual manera pienso que las llaves hoy son mejores para delinear bloques de código, que usar pura indentación. Es demasiado idealista pensar que tener buena indentación te forza a escribir mejor código; no faltará quien se aviente un método larguísimo y que sea difícil de leer porque hay puros cambios de indentación y es más difícil identificar bloques a simple vista, o incluso con ayuda de un IDE (tendría que haber colores o algo así para identificar los bloques), en cambio con llaves en muchos IDE's le das doble click a una llave y te muestra la contraparte o te selecciona todo el bloque.

En fin, no se trata solamente de lo que el compilador necesite o no. Si fuera lo único que importa, todos programaríamos en Perl únicamente, que es un lenguaje write-only y el intérprete hace un mínimo esfuerzo porque ya casi casi escribiste el bytecode directamente.

Python


¿Que creen que pasaría si se pudiera escribir código así? ¿Aclararía en algo lo que leemos? ¿Lo haría más dificil?

Es dificil responder la pregunta.
Según yo, creo que depende como el programador quiera escribir el código no tanto que se vea bonito si no funcional.

Ejemplo en Python sacado desde Google
def Factorial(n):
if n==0:
return 1
else
return n * Factorial(n-1)

Ejemplo en Java
static long Factorial(long n){
if (n==0)
return 1;
else
return n * Factorial(n-1);
}

Pues a mi me parece algo

Pues a mi me parece algo magnífico Python. Aunque son unas por otras. Por ejemplo en Python tienes en cada 2 o 3 líneas (si lo usas orientado a objetos) tienes que poner self:

class Persona(object):
----def __init__(self, nombre=None):
--------self["nombre"] = nombre

----def getNombre(self):
--------return self["nombre"]

----def setNombre(self, nombre=None):
--------self["nombre"] = nombre

En cambio en Java es opcional poner el << this >>:

class Persona{
----private String nombre;

----public Persona(_nombre){
-------setNombre(_nombre);
----}

----public void setNombre(String _nombre){ nombre=_nombre; }

----public String getNombre(){ return nombre; }
}

Otra cosa en contra de Python son los modificadores de acceso, es algo muy poco estándar:

class Persona(object):
----#Este es un método público
----def saluda(self):
--------print("Te saludamos %s", self["nombre"])

----#Este es un método privado
----def __saluda(self):
--------print("Te saludamos privadamente %s", self["nombre"])

Considero más intuitivo a Java ya que antepone si es publico o privado o protegido, seguido de qué tipo de dato regresa, continuando con el nombre del método y por último con los parámetros. Si a esto agregamos quen en python el método __init__ (constructor) es quién define las propiedades del objeto, algo que no me parece bueno (algo que en Java al canto dices "ah eso es un atributo, eso es un método, eso es una variable de clase, etc.").

En lo personal, me gusta mucho la sintaxis de Python (incluso más que la de Java), pero tiene sus puntos tanto buenos cómo malos, ya es cuestión de gustos o filosofías también.

@ezamudio Quizá por eso mismo

@ezamudio Quizá por eso mismo Ruby solo usa "end" para mostrar el fin del "bloque" en cuestión ( sería horrible que también tuviera begin ):




clas A begin
....
   def metodo  begin 
   end 
end 

yiack!!

Sin embargo yo creo que sí ayuda tener menos "tinta" en la pantalla. Si bien es verdad que no te hace mejor programador por sí solo, tampoco te ayuda a que seas peor , en el caso de Perl, el tener el scope en el nombre de la variable definitivamente fomenta que el código sea menos legible. Con Ruby pasa algo similar ( heredado directamente de Perl ) cuando tienes que estar escribiendo @ cada vez que quieres usar una variable de instancia, salvo que Ruby "automitiga" este problema con la meta-programación y que los paréntesis sean optativos; así tu variable @name, puede ser accedida libremente con los métodos def name() y def name=(newName) generados por attr_accessor :name

Y claro, en cualquier método de más de 200 lineas de código, con hasta 5 o 10 if's anidados y un montón de variables temporales regadas por doquier, es imposible de leer, con o sin llaves, y en cualquier lenguaje de programación.

Por cierto sobre la ayuda del IDE, un buen IDE le puedes dar el mismo doble click

En fin, supongo que sería cosa de tener que participar algunos meses en un proyecto así, y lo que escribo es puritita especulación.

@carraro Fue un mal ejemplo el mío. Cuando se trata de una sola línea es idéntico en Java y Python, pero en Python se pueden poner más de una linea:

if  condition: 
       do_a()
       do_b()
       do_c()
else:
   do_nothing()

Por cierto, no escribir llaves en Java cuando se trata de una sola línea, puede llegar incluso a ser peligroso. Yo creo que debería estar prohibido.

Alguna vez me pasé 4 hrs. buscando un bug que al final tuvo que ver precisamente con que alguién, no le puso llaves:

if(  debeEliminarAlgo() )  
     elimina( algo ) 

Luego llego otra persona y puso un log y pues catástrofe:

if(  debeEliminarAlgo() )  
     log.info("Sip, vamos a borrar algo");
     elimina( algo ) 

Resultado, siempre se borraba ese algo, aún cuando no tuviera que. Ya sé, suena estúpido, pero esto sí pasa.

@whishmaster77 Yeap, tener que ser tan explicito siempre, esta feo después de un rato. El self como parametro, está tán arraigado que ni siquiera en la nueva versión Python3000 Guido se lo puso quitar, dijo "No es tán facil como creen".

Otra cosa que parece genial al principio, pero se vuelve un tanto fea conforme lo usas, es la falta de tipos. Como dice Enrique, cuando usas duck typing, terminas haciéndola de ornitorrincologo.

Imagen de ezamudio

sí pasa

Usar llaves incluso para bloques de una línea es una buena práctica en cualquier lenguaje que use llaves (C, Java, C#, etc). Lo que me parece estúpido es que en python piensen que se arregla ese problema porque no existen las llaves y entonces no hubieras tenido ese problema en python. Pero no ven que si alguien pone algo mal indentado ya es otro bloque o termina ahí el bloque, etc.

Al final es una cosa por otra. Delinear bloques con llaves tiene ventajas y desventajas, al igual que delinear bloques con indentación.

Si, un poco peligroso

no escribir llaves en Java cuando se trata de una sola línea, puede llegar incluso a ser peligroso. Yo creo que debería estar prohibido.

Tienes razón @OscarRyz. Y peor cuando no hay documentación del programa y no sabes que hace " cada cosa".

Código como este

public class Formulas{

private double Velocidad;
private double Distancia;
...
...

public ponerVelocidad(double vel)
  this.velocidad=vel;
...
...
public verVelocidad()
 return velocidad;

...

}//fin clase Formulas

class Calculos{

public static void main(String[] args)

Scanner=new Scanner(System.in);

Formulas f=new Formulas();
...
...

}//fin clase Calculos

Aunque es fácil de encontrar los errores. Y no es tan "extremo" como en otros donde le faltan lo mas cosas

Re: @ezamudio Quizá por eso mismo

mmm...pues lo de los modificadores de acceso fue justo lo que mencioné (de hecho lo reexplicaste -fíjate en el ejemplo, tengo un método privado y uno público-).

Imagen de CharlieCorner

Creo que también es una

Creo que también es una cuestión de qué tan puristas se quiera ser. Hay gente que se la pasa trolleando a la generación que creció con C, Java y compañía por que cree que las llaves son obsoletas etc. Pero también existe el bando contrario.

A final de cuentas creo que es imperativo, se use una sintaxis "Pythonesca" o de C, que todo programador, nuevo o veterano tenga buenas prácticas de código. Como el ejemplo que se pone de usar llaves en Java tengan o no más de una sentencia en el bloque if o de cualquier otro tipo. En ambientes universitarios, los maestros deberían inculcar buenas prácticas de código desde la primera clase y exigir que, aunque el código del alumno funcione, tenga buenas costumbres, sino demeritaría la nota.

Afortunadamente, cuando yo tuve POO en la universidad, nuestro maestro era buenísimo, pero además, nos enseñaba las convenciones y sí, nos bajaba calificación porque un método empezara con mayúscula, o el nombre de una clase con minúscula o no usáramos correctamente CamelCase. Más adelante, cuando me tocaba ver código tanto propio como ajeno, era muchísimo más fácil entendernos. El problema es que no todos los maestros, instructores, líderes de proyecto tienen la inquietud de infundir en la gente a su cargo estas prácticas, y entonces se vuelve un círculo vicioso.

Sobre la pregunta original, porque ya me fui muy off topic, creo que me acostumbraría si cambiaran la sintaxis. Aunque, por cuestiones más bien puristas, personalmente preferiría las llaves; pero es eso, puro capricho mío.

Reconozco que en Python, cuando he llegado a jugar con él, ha sido una maravilla no tener que usar llaves, pero siento que es pura novedad por ahora, finalmente, en proyectos grandes es mejor tener un IDE a la mano y, por ejemplo, NetBeans y Eclipse autoformatean con indentación tu código con un solo click, haciendo de todo el embrollo algo más trivial. El problema viene cuando se usa un editor de texto simple, pero esa, es otra historia...

Imagen de luxspes

Un python mas javonico

Bueno, y que tal un phython mas javonico? ;-):


class Persona{
  
  def saluda(this, aquien = '' ){
    if aquien == ''{
      print 'Hola extraño'
    }
    else{
      print 'Hola %s' % aquien 
    }
  } 
  
  def edad( this ){
    return this.edad
  } 
}

class Main{
  def main(){
    Persona().saluda()
 }
}

Quedo destruida la elegancia de python al javonizarlo (ponerle llaves, cambiar self por this)? o mas bien da mas o menos lo mismo? o haria falta ponerle mas caracteristicas "javeras"? (en que momento dejaria de ser "phytonico" para convertirse en "javonico"?)

Re: Un python más javonico

mmm...no se me da apariencia a perl. En mi opinión se ve feo XD y le has quitado toda la elegancia a Python.

Y para los que critican a Ruby o a otros lenguajes que no usan llaves pues ya es cuestión de cada quien. Por ejemplo a mi me encanta lo declarativo que puede Ruby, la simplesa de Python y lo específico de Java. Cada cual tiene su función (francamente no me veo haciendo programación funcional en otro lenguaje que no sea Python) y pues para eso existen. Siempre existiremos los fans de uno u otro; sin embargo hay que ser objetivos y ver las ventajas y desventajas que trae cada uno.

En lo personal, ¿cuál sería el chiste de usar Java (o cualquier otro lenguaje) si tuvieran el mismo estilo de sintaxis, las mismas características, las mismas ventajas, etc.?. Simplemente zapatero a sus zapatos, teclear Java cómo Java, Python cómo Python y así te ahorras muchos problemas.

Imagen de beto.bateria

Acerca de Python

Despues de trabajar mucho tiempo en java, en estos momentos estoy programando en python. Generamente cuando programo en java me alineo a las especificaciones, eso me ayudo mucho para considerar las tabulaciones en python. Lo que si me esta dando lata es que en algunos metodos no especifican el tipo de variable en el return. Tambien ayuda mucho las varibles tipo dinamico, ya que te puedes saltar el polimorfismo completamente. Otra cosa que me gusto es que soporta la herencia multiple :). Tengo todavia muchas dudas y he visto otras ventajas, pero creo que es una buena competencia de muchos lenguajes que son mas famosos.

@beto.bateria Yeap, es muy

@beto.bateria Yeap, es muy bueno. Este año fue elegido nuevamente como Lenguaje del año repitiendo el éxito obtenido en el 2007.

Este post fue más como curiosidad, que como propuesta.