sábado, 4 de septiembre de 2010

iOS Bigger than Linux and Android Combined [STATS]

 According to the latest numbers from Net Applications, iOS is the third most popular platform on the Internet, surpassing Linux and Android combined.

[Original]

domingo, 20 de junio de 2010

Mitos en el juego de la ruleta

Ayer estuve intentando hacer entrar en razón a un amigo sobre un falso mito acerca del juego de la ruleta. Según él, apostando siempre al mismo color al final siempre te acaba tocando. Esto es cierto en parte, y falso en otra parte (esta parte bastante más grande...).
El juego de ruleta, como cualquier otro juego de azar, es un juego dominado por probabilidades de éxito. Se puede decir por ejemplo, que antes de lanzar a girar la ruleta, existen las mismas posibilidades de conseguir el color rojo o el negro, lo cual es cierto. Sin embargo, muchos jugadores tienden a confundir algunas situaciones de juego, la mas común es creer que si en una jugada ya salió el color rojo, lo mas probable es que en la próxima aparezca el contrario, y decida apostar al color negro.
La realidad es que la ruleta no tiene memoria, y lo que sucede en una jugada no tiene porque afectar las jugadas suguientes, o sea, que cualquier jugada que se realice al apostar a la ruleta, es totalmente independiente de todas las jugadas previas que se hallan efectuado. Entonces si apostamos al 16 rojo y no obtenemos éxito, y decidimos volver a apostar al 16 rojo, tendremos las mismas probabilidades de éxito que en la jugada anterior.
Asi también, si logramos ganar a la ruleta con el 16 rojo, existen tantas posiblidad de volverlo a conseguir en la próxima vuelta como si cambiaramos y apostaramos al 10 negro. A pesar de esto, la gran mayoría piensa que existen mínimas probablilidades de volver a conseguir el 16 rojo, y preferirán apostar en cualquier otro número que para ellos les ofrezca mas posibilidades de ganar a la ruleta.
Ahora viene el truco con el que nos vamos a hacer ricos todos (nótese la ironía). El truco consiste en apostar una cantidad inicial a un color, y ésta será la cantidad que al final habremos ganado. Si se pierde, se apuesta el doble al mismo color. Y así sucesivamente hasta que salga nuestro color. Si hacemos cuentas, la cantidad inicial será la que una vez salga nuestro color habremos granado, independientemente del número de apuestas que hayamos hecho. Aunque apostemos varias veces al mismo color, cada apuesta tiene la misma probabilidad de acierto (independientemente de que anteriormente haya salido un millón de veces el mismo color). Pero es cierto que al final acabaremos ganando. ¿Por qué? ¿Donde está el truco que hace que nadie sea millonario gracias a esto?
A la primera pregunta, es sencillo contestar. Suponamos esta secuencia de colores en diez tiradas de la ruleta:
RRRNNRRNRN (R = rojo [60%], N = negro [40%]). En este caso, si apostamos siempre al mismo color y hemos decidido apostar al rojo siempre, ganaremos 6 veces de 10. La probabilidad de que salga rojo o negro es del 50%, lo que quiere decir que si hacemos esta prueba infinitas veces, al final el número de veces que salga un color o que salga el otro, será el mismo. Si hubiéramos decidido apostar al negro, simplemente habríamos ganado 4 veces, pero habríamos ganado (siempre y cuando hayamos seguido el sistema anteriormente descrito de doblar la apuesta en caso de perderla). ¿Y todo esto por qué? Por apostar siempre al mismo color. Si no lo hacemos así, y decidimos realizar la secuencia de apuestas NNNRRNNRNR, nunca habríamos ganado...
La segunda pregunta también tiene fácil contestación. El sistema era, si perdíamos, doblar la apuesta. Supongamos que apostamos inicialmente 5€. El el caso anterior, si hubíeramos decidido apostar siempre al negro, el número de veces que habríamos perdido seguidas sería de 3 veces (al principio). Por lo que tendríamos que disponer de 5€ + 5€x2 + 5€x4 + 5€x8 = 75€. Como vemos, en la apuesta de 40€ habríamos ganado y nos lo habrían doblado, con lo que ganamos 80€ de los que habíamos perdido 75€, por lo que ganamos la apuesta inicial de 5€. ¿Qué ocurriría si en lugar de haber salido 3 veces seguidar el rojo, sale 13? Es poco probable, pero posible que ocurra...y en este caso, para ganar 5 míseros euros habríamos necesitado 81.915€. Interesante, ¿verdad?

sábado, 27 de febrero de 2010

Cómo se almacenan datos de sesión a través de cookies en rails

Hace algún tiempo estuve leyendo sobre la seguridad de los datos almacenados en sesion en rails. En la actualidad, existen dos modos de almacenamiendo: en cookies o en base de datos. Pues bien, los datos de sesión almacenados en cookies, son totalmente visibles por cualquier usuario un tanto hábil. Sin embargo, esto no quiere decir que almacenar datos en cookies no sea seguro. Veamos el proceso de almacenamiento usado por rails, de forma que al final del texto el lector sea capaz de sacar sus propias conclusiones acerca de ello. Por supuesto, expondré las mias.

Generación del sid (session ID)
Si no existe sesión, una nueva es creada y es cuando rails invoca el método generate_sid:
# actionpack/lib/action_controller/session/cookie_store.rb
def generate_sid
ActiveSupport::SecureRandom.hex(16)
end
Como puede verse, generate_sid devuelve una cadena hexadecimal y aleatoria de longitud 16. Esta función no es invocada de nuevo mientras dure la sesión actual.

Message Verifier
Para generar el valor de la cookie, Rails crea una instancia de ActiveSupport::MessageVerifier. MessageVerifier hace dos cosas: por un lado genera el mensaje a almacenar en la cookie; por otro, añade una cadena "message digest" al final de lo anterior. Así, el mensaje final está formado por por las dos partes anteriores, separadas por -- . El método que genera este contenido es:
def generate(value)
data = ActiveSupport::Base64.encode64s(Marshal.dump(value))
"#{data}--#{generate_digest(data)}"
end

Como puede verse, value es el valor que queremos almacenar en la cookie. En general, Rails almacena un hash con una serie de datos. Marshal nos permite pasar un objeto Ruby a cadena para por ejemplo, almacenarlo en una cookie, y posteriormente con esa cadena poder volver obtener el objeto Ruby original, en nuestro caso un hash. Por último esta cadena es codificada en base 64.

Generate Digest y conclusiones
Generate digest nos genera una cadena, a partir de la cadena que teníamos inicialmente (la que queremos almacenar en la cookie). También hace uso de una clave secreta que podemos encontrar en initializers/session_store.rb .
Por tanto, si nos vamos al contenido de la cookie y le hacemos un simple decode64, podemos ver (aunque con dificultad) el contenido de la session_id, o incluso otros datos almacenados (como user_id, éste muy frecuente). Está bien, ¿y podemos hacer algo con este user_id? Pues la verdad es que no, nada, excepto tener conocimiento de él. Pero...si el sistema de autenticación usa este user_id, ¿podemos cambiar el valor de la cookie y pasar a estar en el sistema como otro usuario? La respuesta es NO. ¿Por qué? Pues simple, porque si cambia el contenido de la primera parte de la cadena almacenada en la cookie, también deberá cambiar la segunda (la generada por generate digest) y a no ser que tengamos acceso a la clave almacenada en initializers/session_store.rb este proceso no nos será posible. Rails básicamente lo que hace es, al leer la sesión, comprobar que esta segunda parte es correcta. Si no lo es, sabrá que algo va mal... Por tanto es seguro, en tanto que un usuario malicioso no nos podrá cambiar su contenido. Sin embargo, no ofrece ninguna seguridad para leer su contenido, por lo que nunca se deberá usar para almacenar datos sensibles, tales como contraseñas, números de cuentas bancarias, etc.

domingo, 6 de diciembre de 2009

CruiseControl

CruiseControl es una herramienta de integración continua escrita en, y para, ruby. Su finalidad básica es la de alertar a los miembros de un proyecto software cuando un cambio en el repositorio de control del código fuente (como svn) rompe dicho proyecto. En el caso de RoR, lo que hará periódicamente será la ejecución de los test de la aplicación, informando del resultado.

Es muy fácil de usar. Basta con descargarlo (es un mini-proyecto RoR), añadirle nuestro proyecto (indicando el repositorio del código fuente), y arrancarlo. Por defecto arranca en el puerto 3333, y si accedemos nos encontraremos algo como esto. Además, podemos integrar rcov en cruisecontrol y obtener información del code coverage de nuestro proyecto.

Usando rcov desde cuisecontrol

Para que CruiseControl nos facilite información sobre el Code Coverage, necesitamos:
  1. Gema rcov ('sudo gem install rcov'). Comprobamos ejecutando 'rcov' en el terminal.
  2. Plugin rails_rcov ( './script/plugin install http://svn.codahale.com/rails_rcov' --> Doc: http://agilewebdevelopment.com/plugins/rails_rcov)
  3. Añadir en lib/tasks/ el fichero cruise.rake con el siguiente contenido:

# Set the artifacts dir for development
ENV['CC_BUILD_ARTIFACTS'] ||= File.expand_path("#{RAILS_ROOT}/metrics")
ENV['RAILS_ENV'] = 'test'

# This hack is needed because db:test:purge implementation for MySQL drops the test database, invalidating
# the existing connection. A solution is to reconnect again.
def reconnect
require 'active_record' unless defined? ActiveRecord
configurations = ActiveRecord::Base.configurations
if configurations and configurations.has_key?("test") and configurations["test"]["adapter"] == 'mysql'
ActiveRecord::Base.establish_connection(:test)
end
end

desc 'Continuous build target'
task :cruise do
# Add local user gem path, in case rcov was installed with non-root access
#ENV['PATH'] = "#{ENV['PATH']}:#{File.join(Gem.user_dir, 'bin')}"

puts
puts "[CruiseControl] Build environment:"
puts "[CruiseControl] #{`cat /etc/issue`}"
puts "[CruiseControl] #{`uname -a`}"
puts "[CruiseControl] #{`ruby -v`}"
`gem env`.each_line {|line| print "[CruiseControl] #{line}"}
puts "[CruiseControl] Local gems:"
`gem list`.each_line {|line| print "[CruiseControl] #{line}"}
puts

out = ENV['CC_BUILD_ARTIFACTS']
mkdir_p out unless File.directory? out if out

if File.exists?(Dir.pwd + "/config/database.yml")
if Dir[Dir.pwd + "/db/migrate/*.rb"].empty?
raise "No migration scripts found in db/migrate/ but database.yml exists, " +
"CruiseControl won't be able to build the latest test database. Build aborted."
end

# perform standard Rails database cleanup/preparation tasks if they are defined in project
# this is necessary because there is no up-to-date development database on a continuous integration box
if Rake.application.lookup('db:test:purge')
Rake::Task['db:test:purge'].invoke
end
if Rake.application.lookup('db:migrate')
reconnect
Rake::Task['db:migrate'].invoke
end
end

if RUBY_VERSION == '1.8.7'
puts '!!!!!! Skipping rcov on Ruby 1.8.7'
Rake::Task["test:units"].invoke
Rake::Task["test:functionals"].invoke
else
ENV['SHOW_ONLY'] = 'models,lib,helpers'
Rake::Task["test:units:rcov"].invoke
mv 'coverage/units', "#{out}/unit test coverage" if out

ENV['SHOW_ONLY'] = 'controllers'
Rake::Task["test:functionals:rcov"].invoke
mv 'coverage/functionals', "#{out}/functional test coverage" if out
end
end

Para probar que funciona correctamente y que cruise-control no va a fallar, podemos probar a ejecutar:
rake cruise

sábado, 14 de noviembre de 2009

Google libera Closure, la librería JavaScript detrás de Gmail y Gmaps

Me hago eco de la siguiente noticia, leída en javahispano.org:

Google ha liberado una librería y un conjunto de herramientas para trabajar con JavaScript: Closure. Closure es empleada por aplicaciones como Gmail y Gmaps. Está formado por un optimizador que permite comprimir el código JavaScript, y a la vez realiza un análisis sintáctico del código para encontrar errores comunes.

Por otro lado está una librería con utilidades para manipular el DOM, comunicarse con el servidor, crear animaciones, soporte para edición de texto... La librería es completamente "multi navegador", su diseño es modular y (obviamente, dada las aplicaciones en las que ha sido empleada) está muy bien testada.

Por último, tenemos un sistema de plantillas tanto para Java como para JavaScript cuyo propósito es simplificar la tarea de generar dinámicamente HTML. Las plantillas están implementadas tanto en Java como en JavaScript, lo que permite emplearlas tanto el servidor como en el cliente.

lunes, 28 de septiembre de 2009

Testing con "redirect_to :back"

Si necesitas testear un controlador rails que contiene un "redirect_to :back" obtendrás un error al lanzar el test. Si vamos a la implementación, podemos encontrar:

  • :back - Back to the page that issued the request. Useful for forms that are triggered from multiple places. Short-hand for redirect_to(request.env["HTTP_REFERER"])
Si estamos testeando no tendremos un request, por lo que fallará la redirección y por lo tanto el test.

SOLUCIÓN:

def test_should_get_new
   @request.env['HTTP_REFERER'] = 'http://whatever'
   get :new, :link_id => 1
   assert_redirected_to 'http://whatever'
end