miércoles, marzo 28, 2007

VLC se pasa a Qt

Leo a través de una noticia sobre el reproductor multimedia VLC en OSNews, VLC: Beyond the Basics, que VLC va a dejar de usar wxWidgets para pasarse a Qt. Las razones que se aducen para el cambio son sobre todo de localización: problemas con lenguajes escritos de derecha a izquierda y problemas con unicode, aunque otra razón es para probar algo nuevo :) La elección ha sido Qt. Como comenta el desarrollador de VLC tema da para muchísimos flames, pero ¿Que librería de interfaces gráficos de usuario multiplataforma usas? ¿Por qué?

VLC se pasa a Qt en barrapunto

martes, marzo 20, 2007

Copiar, pegar y código de producción

Hay veces que se juntan varias notas que lees por diversos sitios y te llevan al mismo lugar, al lugar en donde has llegado antes por tus propios medios...

En esta ocasión la moraleja es es Cuidado con el código que cortas/pegas de por ahí. Ya sé, es de lógica, de sentido común pero hay veces que la cosa es bastante sutil. Hay muchos motivos por los que analizarlo, pero entre otros:

  • Puede ser código peligroso: Me acabo de encontrar con un ejemplo de código de "ayuda" en un grupo de noticias a través de Reflections on Trusting Example Code en donde se hace la pregunta ¿habrá muchos problemas de seguridad en código posteado por internet?
  • Puede ser código simplificado: En exampleCode != productionCode se habla de código copiado directamente del ejemplo de los libros y la diferencia con un código eficiente y mantenible.
  • Puede hacer asunciones peligrosas: Hace poco buscando ejemplos de uso de criptografía en .NET, para codificar y decodificar con AES concretamente, casi todos los ejemplos usaban PasswordDeriveBytes que tanto en la MSDN como en la documentación de mono: PasswordDeriveBytes dicen que es obsoleta y que produce problemas de interoperabilidad (no usa un algoritmo estándar) Para el framework 2.0 por cierto existe Rfc2898DeriveBytes.GetBytes que no tiene ese problema, porque, este si, usa un algoritmo estándar, PBKDF2 con HMACSHA1. Lo que asumía el código de ejemplo es que no nos importaba la interoperabilidad ni los estándares, cosa que en este caso por supuesto no es cierta ;)
En fín, que el mantra que me voy a repetir hoy es Trata el código de los demás como si fuese tuyo: debe pasar por la misma evaluación de tecnologías, los mismos test, por el mismo control de calidad, como mínimo...



Copiar, pegar y código de producción en Barrapunto

martes, marzo 13, 2007

POO, el código como diseño, y más cosas



POO, el código como diseño, y más cosas en Barrapunto

domingo, febrero 11, 2007

Más sobre C++0x, memoria transaccional y paralelismo

Demasiadas cosas para hacer una entrada por cada una, así que resumiendo:

A disfrutar con tanta lectura :)

"Más sobre C++0x, memoria transaccional y paralelismo" en Barrapunto

jueves, febrero 08, 2007

¿Estructuras de datos sin bloqueos?

En una entrada en su blog, Lock-Free Datastructures, Ulrich Drepper duda de la aplicación actual de estructuras de datos compartidas y sin bloqueos sin implementar un gestor de memoria personalizado. No obstante viene a decir que esto cambiará en un futuro próximo...

Por otro lado otros, menos pragmáticos, aconsejan una vía hacia la iluminación que incluye el paso por esos senderos, advirtiendo, eso si que hay que cambiar de un modo de pensar centrado en el lenguaje a uno centrado en la arquitectura (me pregunto yo si merece la pena perder la preciada portabilidad) Hay a algunos que si les merece la pena: Tom Leonard de Valve

Y por supuesto para quien (como a mi) le apetezca saber más hay por ahí alguna referencia, "Some notes on lock-free and wait-free algorithms" de Ross Bencina y la entrada de la wikipedia inglesa Lock-free and wait-free algorithms


¿Estructuras de datos sin bloqueos? en Barrapunto

lunes, enero 29, 2007

Exceso de información, filtros bayesianos y DIY

Desde que leí esta entrada de manje, "Selección de noticias mediante filtro bayesiano" en la que presentaba su proyecto, lo pensé... ¿por que nadie ha hecho un lector al que lo entrenes y te filtre según lo has entrenado? Bueno, manje lo tiene hecho y se pude probar (es TU PERIODICO)

No estoy seguro de que un filtrado automático sea la solución al exceso de fuentes de información, además de tenerlo que entrenar, con la inversión en esfuerzo que eso supone. Pero a este respecto manje y los usuarios de TU PERIODICO nos pueden comentar más. Yo a nivel personal si que digo que me ha resultado más entretenido programar un miniscrí que entrenar el filtro y que sigo usando bloglines a pesar de haber alternativas seguramente mejores...

En fin, como me interesó la idea, al menos un rato :), pues me puse a hacerlo yo mismo... porqué no, ¿verdad? Total que me hice un script en Ruby, porque me apetecía, porque yo lo valgo y para ser buzzword compliant :) (No sé, a otros les ha servido de algo :)). Como no tengo ningún tiempo de seguir su desarrollo (y tampoco se para que...) lo pongo por aquí por si le sirve a alguien, aunque sea solo de mal ejemplo. Aviso que está hecho con la velocidad y el descuido de la pasión, con lo que no es de calidad de producción ni en la forma ni en la organización.

Permite leer feed por feed en modo interactivo o todo seguido y se va guardando las fechas de última lectura de las fuentes, con lo que en teoría debería mostrar solo los ítems nuevos. En la práctica, sospecho que a mitad por el parser de feeds que he usado, Ruby feedparser, a mitad por que los que los forman no tienen mucho cuidado (pero no lo he analizado en serio) hay fuentes que salen entradas ya leídas. El escrí permite ir llenando su "base de datos" de fuentes o importarlas de bloglines. Permite, claro, entrenarlo (con Classifier, que se instala a través de rubygems) y permite que la salida sea en modo texto, para esos frikis como yo a los que nos encanta la consolica, y claro, para todos aquellos que quieran procesar la salida...

Después de estos preámbulos, ahí va:


require 'rubygems'
require 'stemmer'
require 'classifier'
require 'yaml'

class SimpleFeed
attr_reader :url, :date
attr_writer :date
def initialize(url, date)
@url = url
@date = date
end
end

def serialize( c, name )
File.open( name, 'w' ) do |out|
YAML.dump( c, out )
end
end

require 'net/http'
require 'uri'

def fetch(uri_str, date, limit = 10)
#TODO: I should choose better exception.
raise ArgumentError, 'HTTP redirect too deep' if limit == 0

header={'If-Modified-Since' => date.to_s}
uri=URI.parse(uri_str)
http = Net::HTTP.new(uri.host, uri.port)
response=http.get(uri.path,header)
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
else
puts "error getting " + uri_str + response
STDIN.gets()
response.error!
end
end

#const
Filter_file = "filter.yaml"
Feeds_file = "feeds.yaml"


#default options
add_feed = false
train = false
html_content = false
no_interactive = false
bloglines_import = false
bloglines_file = ''


ARGV.each_with_index do |arg,index|
case arg
when '--add_feed'
add_feed = true
when '--train'
train = true
when '--html_content'
html_content = true
when '--no_interactive'
no_interactive = true
when '--bloglines_import'
bloglines_import = true
bloglines_file = ARGV[index+1]
puts bloglines_file
end

end

#load filter
begin
filter =YAML::load_file( Filter_file )
rescue SystemCallError
filter= Classifier::Bayes.new 'Interesting', 'Uninteresting'
end


#load feeds
feeds = Array.new
if(bloglines_import == false)
begin
feeds = YAML::load_file(Feeds_file)
rescue SystemCallError
end
else
require 'rexml/document'
include REXML
file = File.new(bloglines_file)
doc = Document.new(file)
doc.root.each_element('body/outline/outline'){
|outline| feeds.push(SimpleFeed.new(outline.attributes['xmlUrl'],Time.at(0)))
}
end

if(add_feed == true)
print ('Insert a feed, please: ')
f=SimpleFeed.new(STDIN.gets().chop!,Time.at(0))
feeds.push(f)
end


require 'feedparser'
require 'feedparser/html2text-parser'

#iterate the feeds
feeds.each{ |sf|
puts 'Loading '+sf.url + ' ...'
begin
res=fetch(sf.url,sf.date)
s= res.body
rescue
puts "Error getting "+ sf.url
end

begin
#puts res['Date']
mod_date = res['Last-Modified']
puts mod_date
#URI::parse(sf.url), header
rescue
puts res
puts "Error: Web server doesn't implement date: "+ sf.url
end

begin
f = FeedParser::Feed::new(s)
if( f != nil and f.title!=nil )
puts(f.title)
else
puts("Title not available")
end
rescue
puts "Error parsing feed, Not valid: " + sf.url + "\n" +s
end
#Feeds are usually in temporal reverse order
if(f!=nil and f.items!=nil)
f.items.reverse_each {
|i|
#title, date, content
begin
if((i.date ==nil or sf.date==nil or i.date>sf.date) )
if(html_content == false and i.content != nil)

p = FeedParser::HTML2TextParser::new(true)
p.feed(i.content)
p.close
i.content = p.savedata
end
#TODO: -> content NULL
entry = ''
if i.title
entry+=i.title + " "# + i.date.to_s
end
if(i.content != nil)
entry+=i.content
end
puts(entry)
#puts ("Most recent date: " +sf.url+ " "+ i.date.to_s)
if(i.date!=nil)
sf.date=i.date
else
if (mod_date !=nil)
#If mod_date exists
sf.date=mod_date
end
end

if(train)
print(' (Interesting[Y/n]?)')
ans=STDIN.gets().chop!
print(ans)
if ans=='n'
filter.train_uninteresting(entry)
else
filter.train_interesting(entry)
end
else

puts(filter.classify(entry))# returns '[Un]interesting'
if(no_interactive==false)
STDIN.gets()
end
end
end
rescue
puts "Unknown Error"
end

}
end
}
serialize(filter, Filter_file)
serialize(feeds, Feeds_file)



La misma entrada en BP

lunes, diciembre 18, 2006

Memoria transaccional y concurrencia

En ACM Queue han publicado un articulo que ilustra bastante bien por donde irán los tiros (seguramente) en esto de la programación concurrente. Se trata de Unlocking Concurrency: Multicore programming with transactional memory y describe un poco que es la memoria transaccional y como se programaría en un lenguaje de los de uso cotidiano.

Básicamente se trata de especificar en el lenguaje que secuencias de operaciones forman una transacción de memoria, en la cual, como su nombre indica, o bien se realiza la operación completamente o bien es como si no se hubiese operado con ella, evitando la sincronización manual por parte del programador. Como se encargan de subrayar en el artículo tampoco es la panacea, pero ayuda(ría) mucho a la gestión de la concurrencia.

Sólo falta ahora que se implemente en lenguajes de uso común y deje de ser sólo objeto de investigación académica...


La misma entrada en BP

jueves, diciembre 14, 2006

Una herramienta, no una religión

Entrada interesante en Adding Simplicity - An Engineering Mantra, It's a Tool, Not a Religion!. Traduciendo muy libremente:

Recientemente he estado asistiendo al debate de REST contra SOA. La última semana me vi envuelto en discusiones de C++ contra Java. Esta noche pasada me tropecé con algunos debates sobre Django contra Rails. Me parece que los ingenieros de software somos únicos en el mundo técnico: más que disfrutar con una caja de herramientas variada, discutimos contra su contenido, esperando descartar todas excepto el conjunto más pequeño posible.

[...]

¿Porque debemos trabajar tanto en reducir nuestro conjunto de herramientas hasta la herramienta definitiva? Hay una tendencia a buscar el lenguaje Navaja suiza apoyado por un framework que será la solución óptima para todos los problemas del mundo. La simple realidad es que ese lenguaje o framework no existe. ¿Por qué? Bueno, la solución de problemas informáticos es siempre acerca de adoptar compromisos que optimicen la solución en determinadas condiciones. Si tu problema cumple esas condiciones, perfecto. Si no, estarás usando una herramienta subóptima.

[...]

Es importante tener opciones para resolver los problemas de cada día. Entender las herramientas y su aplicabilidad a un problema dado debería ser nuestro trabajo

En resumen, en lugar de criticar herramientas, aprende su ámbito de aplicación...

La misma entrada en BP

domingo, diciembre 03, 2006

sky2 y sk98lin en Ubuntu

Nota: Esta entrada es obsoleta, porque desde la versión 2.6.17 el driver sky2 funciona correctamente y sk98lin ha dejado de mantenerse. O sea, que hay volver a configurar sky2 y hay que eliminar del fichero /etc/modprobe.d/blacklist la línea blacklist sky2 (si existe)

Referencias:
sk98lin en la wiki de gentoo en la que se explica un poco la historia
Una explicación de la situación el la lista del kernel


Entrada original:

Tenía problemas con el driver de la tarjeta de red, una Marvell Yukon, desde la actualización a Dapper y no lo sabía, porque no la usaba últimamente. Si se hace un uso intensivo de la red (léase P2P ;) ) sky2, que es el driver que ubuntu coge por defecto, se quedaba atascado. El caso es que he buscado (quizás no mucho) y no he encontrado, como suele ser usual, la receta sencilla. Lo que me ha servido a mi es:

  1. Instalar las cabeceras del kernel (en mi caso y salvo casos excepcionales linux-headers-generic)
  2. sudo apt-get install build-essential (si no lo tenemos)
  3. Bajar el driver de http://www.marvell.com/drivers/driverSearchResults.do y descomprimirlo
  4. Sustiuir #!/bin/sh por #!/bin/bash en el fichero install.sh
  5. En el directorio descomprimido: sudo ./install.sh y damos a 1. Installation
  6. sudo modprobe sk98lin
  7. añadir la línea blacklist sky2 al final del fichero /etc/modprobe.d/blacklist (edítalo como root o con sudo)
Espero que le sea útil a alguien...
(Basada en dos recetas, para mi, incompletas: http://www.ubuntu-es.org/index.php?q=node/30706 y http://ubuntuforums.org/showthread.php?t=176096 )

La misma entrada en BP

jueves, noviembre 30, 2006

Programadores e interfaces de usuario

Hay algunos brillantes, pero en general casi todos los programadores que conozco son(mos) muy malos diseñando interfaces de usuario. Esto tiene varios motivos, creo:

  • El programador tiende a ver la funcionalidad, no el uso.

  • El programador no tiene la formación adecuada (ni el interés(?)) acerca de usabilidad ni diseño. Quizás tampoco la formación adecuada en programación de GUI's

  • El programador, casi por definición es vago. Gastará el mínimo tiempo en el diseño del interfaz


También hay algunos aspectos que dificultan que un interfaz sea armonioso y usable: los continuos cambios de especificaciones, la indefinición de funcionalidad y de diseño:
- Eso... uhmmm... déjalo también configurable
- Ya, ¿pero dónde?
- Ya le encontrarás un hueco...
- Con tantas opciones ¿no será un poco difícil de usar?
- ...
De todos modos lo que a mi me parece adecuado es que el programador programe un interfaz de usuario diseñado por un diseñador conjuntamente con el cliente, o al menos validado por éste. Si no hay más remedio que diseñarlo por lo menos intentar no hacer el diálogo. En ese mismo enlace hay consejos sencillos sobre lo que no hay que hacer. El ejemplo del GUI de wget es espeluznante... :)

La misma entrada en BP