Lo bueno si simple dos veces bueno

This is a pervasive and growing concern in software: as libraries, interfaces, and tools become more complicated, they become less understood and less controllable. When everything works, rich programming environments can be very productive, but when they fail, there is little recourse. Indeed, we may not even realize that something is wrong if the problems involve performance or subtle logic errors. (…)
The importance of choosing simple algorithms and data structures, the simplest that will do the job in reasonable time for the expected problem size(…)
we find it best to start detailed design with data structures, guided by knowledge of what algorithms might be used; with the data structures settled, the code goes together easily (…)
As much as possible, start with something simple and evolve it as experience dictates.

(Kernighan & Pike, 1999)

Cositas interesantes de Ruby

Una pequeña chuleta de Ruby, con cosas previsibles y otras más interesantes….

a = if a<0
  a * -1
else
  a

a = a<0 ? a * -1 : a

a= a * -1 unless a>=0
variable = '' if variable.nil?
variable = '' unless variable
variable ||= ''

# Patrones
case palabra
  when /[a-z].*/ then "minusculas"
  when /[A-Z].*/ then "mayusculas"
  else "otro"
end
# Patron "insensible al caso"
print "Coinciden!" if /ABC/i =~ "1abc2"
nombre_variable
@atributo
 NombreClase

# hash table
colores = { "rojo" => 0, "verde" => 1, "azul" => 2}
colores["verde"]

# Cadenas
print "123456" [0..2]
# "123"
print "Azul #{colores["azul"]}"
print %q{"Muchas '"comillas' '" escapadas"" :-)}
# q => escape total, Q => interpreta bloques #{}
print %Q{"Estamos en #{Time.now.year}"}

while vs. until

array.each {|element| print element}
colores.each {|clave,valor| ... }
colores.map { |c| c[0].upcase }
# ["ROJO", "VERDE", "AZUL"]

 # numero de parametros variable, parametros por defecto
def funcion (param1, param2=0, *otros)
  otros.each { |p| ... }
end

# bloques
def traza(mensaje)
    $stderr.puts("#{Time.now} - comienzo #{mensaje}")
    $stderr.puts(yield)
    $stderr.puts("#{Time.now} - fin #{mensaje}")
end
def traza(mensaje, &bloque)
    $stderr.puts("#{Time.now} - comienzo #{mensaje}")
    $stderr.puts(bloque.call)
    $stderr.puts("#{Time.now} - fin #{mensaje}")
end
traza('suma') { 2 + 2 }

at_exit do { puts "Fin" }

set_trace_func proc { |evento, fichero, linea, id, vinculo , clase|
 puts "#{evento} en #{fichero}:#{linea} #{id} #{clase}"
}
print "Test"

File.open("fichero") do |f|
  f.puts("123")
end

# Otra forma sencilla de rastrear un script es usar el "Tracer" de la biblioteca estándar:
ruby -rtracer script.rb

class A < B
  def m1
  end
  def m2
  end
  private
  # a partir de private, los metodos son privados
  def m3
  end
end

Buenas prácticas:

  • Usar dos espacios en vez de tabuladores
  • ClasesCamello, serpientes_para_el_resto, INCLUIDAS_CONSTANTES

	

Depurar codigo Java JNI en Linux

Depurar una mezcla de código Java y C++ no es trivial, sobre todo porque aún no hay disponibles entornos (o plugins) estables que soporten esta posibilidad. Con lo cual hay que recurrir a la siguiente receta, que permite interactuar a la vez con los depuradores nativos de cada lenguaje (sean para consola como gdb, o gráficos como NetBeans)

Primero iniciar el programa en modo de depuración remota:

java -Xdebug -Xnoagent -Djava.compiler=none -Xrunjdwp:transport=dt_socket,server=y,suspend=y -Djava.library.path=$LD_LIBRARY_PATH -cp . -jar PROG.jar
Listening for transport dt_socket at address: 37112

Es importante definir java.library.path para que contenga el directorio donde se encuentra la biblioteca .so con el código nativo (en este caso, se le asigna el valor de la variable de entorno LD_LIBRARY_PATH).

Iniciar el depurador de Java y conectarse al puerto indicado por el comando anterior (en el ejemplo, 37112)

jdb -attach 37112

También se puede utilizar un depurador gráfico, por ejemplo el que viene con Eclipse. Para ello basta crear un perfil de depuración de tipo “Remote Java Application”. En Connection Properties usar localhost y como puerto el que nos devolvio el anterior comando java (siguiendo con el ejemplo, 37112)

Establecer el punto de parada en el código Java

stop at CLASE:NUM_LINEA
run

Una vez alcanzado el punto de parada en el código Java, iniciar el depurador de código nativo y vincularlo con el proceso java mediante su PID

gdb
attach PID
break JNI_FUNCTION

continue (retoma la ejecución del programa java)

Importante: para que el depurador C++ encuentre la función JNI, el programa Java debe tener ya cargada la biblioteca C++ (archivo .so). Si paramos la ejecución del programa Java demasiado pronto, cuando entremos en el gdb la biblioteca aún no se habrá cargado y por lo tanto al intentar el “break” se quejará de que no encuentra la función.

Estos tres comandos gdb también pueden ejecutarse dentro de ddd, lo cual nos permite depurar el código C++ con la comodidad de un entorno gráfico

Por último, de vuelta en jdb ejecutar run de nuevo (continua la ejecución en el depurador y se detiene en el breakpoint del código nativo definido en gdb)