Debería funcionar http://fermat.nireblog.com Divulgación y, sobretodo, divagación sobre computación, mayormente práctico. Sat, 30 Aug 2008 17:08:46 +0100 Debería funcionar http://fermat.nireblog.com/blogs/fermat/gravatar.gif http://fermat.nireblog.com http://nireblog.com Programando en pequeñito (II): la memoria de trabajo del cerebro http://fermat.nireblog.com/post/2008/02/08/programando-en-pequenito-ii-la-memoria-de-trabajo-del-cerebro http://fermat.nireblog.com/post/2008/02/08/programando-en-pequenito-ii-la-memoria-de-trabajo-del-cerebro A través de la comunidad formada alrededor de la revista Scientific American, he llegado a un artículo escrito por Andrew W. McCollough y Edward K. Vogel, de la Universidad de Oregon, reflexionando sobre la memoria de trabajo, e incluso calificándola de filtro antispam del cerebro.

Así, y recordando mi primer artículo sobre programación bajo recursos limitados, imagina que nuestra memoria de trabajo fuera de 1MB. Imagina ahora que ese espacio correspondiese al que tenemos para nuestra bandeja de entrada (inbox, pudiendo tener carpetas con más tamaño, que corresponderían a otras áreas de nuestro cerebro), y que los mensajes nuevos sólo pudiesen llegar a dicha bandeja de entrada. Parece conveniente tener un buen sistema que no nos muestre (filtre) la basura en dicha bandeja de entrada porque estaría ocupando espacio, a priori innecesario (quien sabe, hay gente que se lee los mensajes de viagra...), que no podría ser ocupado por mensajes que sí nos interesasen más.

Tal como comentan estos investigadores del Laboratorio de Memoria de Trabajo Visual y Atención de Oregon, existen dos explicaciones para esta limitación en la capacidad. Por un lado, esta memoria podría ser comparada con un espacio de almacenamiento (o disco duro), que variaría de tamaño en cada persona. Por el otro, la capacidad dependería de la eficiencia con la que se use el mismo (o muy parecido) espacio. Por tanto, una mayor capacidad vendría dada por ser mejor en cuanto al descarte de información irrelevante. Es decir, un mejor filtro antispam.

Según sus investigaciones, parece que esta segunda explicación cobra fuerza. Su sorpresa está en que dichas investigaciones darían a entender que las personas con menor capacidad (es decir, peor filtro antispam) tendrían más información residiendo en la memoria de trabajo, pero irrelevante, la mayor parte. Es decir, cuarenta mensajes de basura y dos legítimos.

En dicho artículo continúan con la pregunta clave que tratan de responder: ¿Dónde reside dicho filtro antispam? (Parece que unos investigadores del Instituto del Cerebro de Estocolmo lo han respondido). Pero bueno, en el campo de las investigaciones psicológicas, yo lo dejo aquí (aunque bien podéis seguir los enlaces :)

En cambio, en el plano de las tecnologías de la información, estos estudios también me parecen muy interesantes (y aplicables)... y voy a seguir por aquí.

No sólo podemos deducir que la precisión, en el procesamiento de información, es más importante que su almacenamiento indiscriminado, ni que el mantenimiento de las bandejas de entrada de los usuarios de correo electrónico exija un filtrado óptimo del spam para que éstos puedan fijar su atención, si no que habría que preocuparse, también, por la gestión del conocimiento que nos ayuda a realizar nuestras tareas. Historiales, Marcadores, Mis Favoritos, etc. son buenas ayudas para nuestros propósitos en el campo de los navegadores Web. Los Wikis llevan más de una década sirviendo para esta causa, y sitios Web, como Amazon, nos recuerdan nuestros paseos anteriores por su tienda virtual, mostrándonos lo que piensan que más nos puede interesar, y ahorrándonos (posiblemente) tiempo de paseo, intentando que caminemos por una librería (o tienda, en general) personalizada.

Los motores de búsqueda también suelen incorporar cookies (o recuerdos) relacionadas con nuestro ordenador, ayudando a reencontrar información anteriormente buscada, o intentando mejorar los resultados devueltos, de acuerdo con nuestras anteriores intenciones.

En definitiva, todos estos sistemas suelen buscar el filtrado de información irrelevante (para nosotros), intentando construir una memoria de trabajo de alta capacidad que nos fije la atención y nos ayude en nuestras tareas o propósitos. Al fin y al cabo, nuestra limitada memoria de trabajo, que nos ayuda a sobrevivir cada día, requiere de una programación en pequeñito... :-)

Comments

]]>
Fri, 08 Feb 2008 00:50:20 +0100
Programando en pequeñito (I) http://fermat.nireblog.com/post/2008/01/16/programando-en-pequenito-i http://fermat.nireblog.com/post/2008/01/16/programando-en-pequenito-i Muchos de nosotros (por no decir todos, que suena un poco prepotente) hemos aprendido a programar como buenamente hemos podido, pero delante de ordenadores hechos y derechos, sin dar mayor importancia (o ninguna) a circunstancias como el uso comedido de dispositivos (memoria, procesador, disco...).

Claro que tampoco tiene mucho sentido pensar en ello cuando no existe tal limitación. El problema viene cuando nuestro programa no va a utilizarse en un ordenador de sobremesa clónico, o en un portátil con 2 procesadores y más espacio en RAM que los primeros Pentiums en disco, sino cuando se utilizará un teléfono móvil para ello, o una libreta electrónica, o una webcam avanzada (y demás dispositivos limitados).

Por lo general, es necesario dar una vuelta de tuerca al diseño del software que se desarrollará para estos sistemas que, normalmente, no pueden utilizar más de 1MB de espacio, ya sea en disco o en memoria, enfocando, así, el diseño en la mayor limitación que padecemos. Además, como no somos los primeros que nos enfrentamos a estos diseños, tenemos la suerte de poder echar mano de soluciones funcionales y bien probadas para los problemas más comunes que surgen en este tipo de software. Estas soluciones probadas son lo que se conocen como patrones de diseño.

Algunas técnicas definidas en esos patrones son:

  1. Uso de estructuras de datos pequeñas/simples (para que no ocupen mucho)
  2. Diferentes enfoques en cuanto a la asignación de memoria
  3. Uso de compresión: el caso más sangrante es el de las demos de 4ks de las parties (tipo Euskal Party), que ese es el máximo que ocupan en disco (aunque luego se expande esa información en memoria hasta que deja a todo el público boquiabierto)
  4. Uso de almacenes secundarios de la información (como tarjetas sim)
  5. Cambios en los estados de los programas para permitir un máximo de ellos ejecutándose al mismo tiempo

En el primer caso, se pueden utilizar métodos de enmascaramiento de los datos para que ocupen menos. Un ejemplo podría ser la forma de almacenar una dirección IP. Lo primero que nos viene a la cabeza (o no xD) es el uso de una cadena de caracteres para almacenar cada número (y cada punto) tal como son leídos por el ser humano (ej. 127.0.0.1). La segunda posibilidad es almacenarlo como un conjunto de bytes, que es, además, cómo trabajan los sistemas operativos con estos datos. Si la forma en que dicho dato se almacenase nos diese igual, podríamos demostrar que es mejor la segunda opción por lo siguiente:

  • Un carácter ocupa 1 byte de memoria, lo que unido a 9 caracteres que forman la IP de localhost, nos dan 9 bytes utilizados (en IPv6 se complica un poco más)
  • Un entero largo, que es dónde se almacena la dirección IP en forma numérica, ocupa 8 bytes de memoria (el doble que un entero normal). De esta forma, estaríamos usando 1 byte menos que en la primera forma, pudiendo ahorrar hasta 7 bytes (pensad en una estructura repetida muchas veces y multiplicad el ahorro).

Otra recomendación, extendida a todo tipo de programas, aunque muy aconsejada en este tipo de sistemas, es el uso de clases contenedoras de datos (conocidas como DTO (Data Transfer Object)). Igualmente, se aconsejan diseños que fomenten el uso compartido de información, con el fin de evitar duplicados (aunque podría traer problemas mayores ante concurrencia en el acceso a dichos datos... para lo que utilizaríamos otro patrón de diseño conocido que evitaría inconsistencias).

Pasando al siguiente punto, la asignación dinámica de memoria (malloc) es uno de los grandes progresos en la codificación de programas porque permite variar su tamaño en tiempo de ejecución, pudiendo ampliar o reducir su contenido, y así dar flexibilidad a dichos programas. Pero esta flexibilidad tiene un precio, pagado (como casi siempre) en variaciones del rendimiento de nuestros programas.

En este aspecto, quizás lo más importante sea la predicción del uso de memoria. Es decir, tener en mente un rango de uso de memoria del que nunca va a salir nuestros programas. Para ello, hay diferentes aproximaciones, entre las que se podría destacar el evitar llamar a malloc cada vez que se necesite. Las razones son variadas. Por un lado, podría darse el caso de que no tuviésemos suficiente memoria para completar todo el programa. Para resolverlo, se podría asignar toda la memoria que se pretende utilizar al principio del programa (en base a una matriz de objetos o structs), y así no se ejecutará ningún proceso hasta que se esté seguro de tener espacio para ello. Por otro lado, la asignación dinámica no tiene un tiempo definido para realizar dicha asignación (depende del núcleo del sistema operativo y del recolector de basura), algo inconcebible en sistemas de tiempo real. En estos casos, quizás se debería realizar una preasignación que será utilizada de manera transparente durante el programa (haces como que asignas, pero internamente reutiliza un espacio ya asignado). El inconveniente es que se asigna toda la memoria que será utilizada, posiblemente en tiempos diferentes, en todo el programa. Por último, están 2 formas de asignación similares a las anteriores: pool de asignaciones (con nodos en forma de árbol) y asignación estática (no variable, y a la que no afecta el recolector de basura).

Durante la asignación dinámica tiene especial relevancia una sección del espacio asignado en memoria para la ejecución del programa llamada heap, lugar donde se almacena la información asignada. La forma en que construimos el proceso de asignación de memoria de nuestro programa es muy importante ya que los pequeños espacios asignados pueden fragmentar espacios mayores que se asignen posteriormente (lo que provocaría problemas de rendimiento). La idea para resolver esto sería asignar primeramente los espacios mayores, pero tarde o temprano estos espacios se librarán y volverá a surgir dicho problema. Si ésta parece una circunstancia inevitable (asignar y desasignar continuamente), quizás habría que pensar en crear grupos, o varios heaps (a nivel de usuario), con el fin de destruir dichos grupos (eliminando varios espacios del mismo grupo de una sola vez), o incluso optimizar los espacios en memoria.

El tercer punto que comentaba era el de la compresión. Aunque es difícil de implementar, creo que se gana mucho con ello. Dicha compresión puede ir enfocada a los datos (como la codificación de Huffman) o a tablas (en casos de codificaciones de caracteres extrañas, como el cirílico o el chino).

Otra forma de reducir el uso de memoria es mediante el procesamiento secuencial de la información, que se puede conseguir mediante pipes (tuberías). También suele ser interesante cargar las bibliotecas, con funciones externas a nuestro programa, de forma dinámica (es decir, en el momento que vayamos a usarlas), con el fin de reducir el tiempo que permanecen accesibles (y ocupando) en memoria.

Y por último, y para no aburrir más, recordar que estamos jugando con fuego cuando tenemos pocos recursos, donde puede ocurrir que nuestro programa sea interrumpido inesperadamente por el sistema operativo (si es que no estamos programando el sistema operativo xDD) con el fin de salvarse a sí mismo. En estos casos, deberíamos reducir los daños colaterales que se producirían (inconsistencias, etc.), e incluso pensar en una política de recuperación ante problemas (de qué prescindir en el rearranque, ...). Si estamos programando el gestor de memoria del sistema operativo, sería necesario dar a cada proceso en ejecución una prioridad, una importancia, con el fin de clasificarlos y así sacrificar el menos importante/necesario.

Comments

]]>
Wed, 16 Jan 2008 00:12:54 +0100
Los lenguajes de scripting, ¿son una moda? http://fermat.nireblog.com/post/2007/12/30/los-lenguajes-de-scripting-son-una-moda http://fermat.nireblog.com/post/2007/12/30/los-lenguajes-de-scripting-son-una-moda Desde hace más de un siglo, existen unos lenguajes creados artificialmente con el fin de ayudar a sus creadores en aquellos problemas repetitivos que les han ido surgiendo en sus vidas, y para conseguir resolverlos de forma más rápida.

De esta manera, se empezaron diseñando máquinas que conseguían tejer más deprisa que a mano, otras que entendían el dibujo, a base de perforaciones, de una tarjeta, con el fin de generar distintas presiones en un conjunto de válvulas neumáticas y hacer que funcionara un piano por sí solo... y así se llegó a la fase en la que a un buen hombre, llamado Von Neuman, se le ocurrió que no debería ser necesario modificar los conectores de las máquinas que realizaban las operaciones cada vez que éstas cambiaban a otro conjunto de operaciones a realizar, si no que eso debía ser transparente en base a un programa (a base de instrucciones) que se le pasara. Curiosamente, dicho diseño de las máquinas (o hardware) no ha variado demasiado.

En cambio, los programas (o software) sí que han cambiado mucho. O mejor dicho, los lenguajes en los que se escriben, hasta el punto de existir, hoy en día, miles de ellos, creados por empresas (por iniciativa propia), universidades (igualmente) o por expertos comunicados a través de Internet (aunque patrocinados, algunos de ellos, por empresas y/o universidades).

Al principio, dichos lenguajes eran muy cercanos al funcionamiento de las máquinas (mover dato del primer registro al segundo), probablemente por inercia de lo que pocos años antes se realizaba (mover el conector de la primera ranura a la segunda). A continuación, se crearon lenguajes que juntaban algunas de estas instrucciones en una sola (sumar y almacenar), hasta llegar a los llamados lenguajes de alto nivel, entre los que se hayan (y basan) los lenguajes de scripting.

Salvando varios años de esta historia (una pena), nos plantamos en algunos de los lenguajes más usados actualmente, y porqué.

C, por ejemplo, es el lenguaje de programación con el que se han escrito la mayoría de lenguajes de scripting existentes (por lo menos, en sus versiones originales, y más usadas), por no mencionar programas más importantes, como el corazón de millones de ordenadores (el núcleo de varios sistemas operativos). Éste es un lenguaje bastante complicado (porque puede requerir saber interioridades de las máquinas), pero extremadamente potente en manos de un experto.

De aquí, se puede extraer la primera crítica hacia dichos lenguajes de scripting: en cuanto a rendimiento, estos lenguajes son lentos, ya que al estar escritos en C, nunca podrían correr más rápido que aquellos escritos en C. Sin embargo, no se debería olvidar que C fue inventado para poder escribir UNIX de forma que fuera multiplataforma, con el fin de evitar la necesidad de reescribir todo el código para cada tipo de máquina. Es decir, C se pensó para la programación de sistemas, y puede que la balanza quede desequilibrada si ponemos sus ventajas e inconvenientes para el desarrollo de aplicaciones, u otro tipo de código.

Por otro lado, está Java, lenguaje nacido en los ochenta con el fin de facilitar el desarrollo de programas enfocados a la televisión interactiva, que por aquellos años Sun Microsystems pensaba que sería el futuro inmediato. ¡mooonc!. Pronto cambió su objetivo a la naciente Web, y hasta hoy (gracias al apoyo inicial de Netscape). Los programas en este lenguaje, tras ser compilados, generan un código que es ejecutado por máquinas virtuales, de forma que no es necesario recompilarlos para ser ejecutados en múltiples plataformas diferentes.

Y por último, está Bash, intérprete de comandos de los sistemas GNU basado en SH que, apoyado en pequeños programas como sed, tr, ... y por otros lenguajes como awk, se utiliza en programas de administración de dichos sistemas. El problema es que este lenguaje limita su uso a los sabores GNU de UNIX, y obliga a utilizar múltiples procesos para una misma tarea, algo que puede resultar lento en situaciones más complicadas. Además, awk no permitía mantener abierto más de un fichero.

Volviendo al primer párrafo de esta divagación, y cuando parecía que las herramientas a nuestro alcance eran suficientes para generar programas enfocados a operaciones de sistemas, de aplicaciones o administrativas, varios inconformistas crearon Perl, Python, Ruby, PHP... y el más nuevo: Groovy.

Estos lenguajes de scripting son difíciles de catalogar porque, todos ellos, pueden ser compilados o interpretados, descolocando a aquellos que, como yo, pensaban que esa era la característica diferenciadora, y que les mantenían a distintos niveles.

Las ideas principales que pululan por ahí sobre los lenguajes de scripting son:

  • Conseguir que sea (más) fácil programar
  • Crear un código legible
  • Reducir las líneas de código necesarios para una misma tarea
  • Tipado dinámico (no hace falta declarar las variables)
  • Recolectores de basura (encargados de gestionar la memoria del programa y otros asuntos del que algún día espero escribir)
  • En algunos casos, son diseñados para un dominio específico (como la Web)
  • Crear un conjunto numeroso de bibliotecas (o módulos) bien probados y fiables que permitan no reinventar la rueda
  • Independientes de la máquina en la que se ejecuten (multiplataforma)

Tampoco podemos olvidar la motivación de sus inventores. Por ejemplo, Perl nació de la mano de un administrador de sistemas y redes que por aquel entonces (1987) trabajaba en un centro de investigación (JPL-NASA) en el que necesitaba realizar informes de los registros (logs) generados por otros programas. Por lo menos, esto es lo que inicialmente trascendió al populacho :-D. En ese caso, probablemente podría haberse utilizado SH, CSH, Bash, o el intérprete de comandos que usaran los sistemas que administraba. Pero el problema, a grandes rasgos, era la XOR obligada cuando quería utilizar funcionalidades de C y de *SH (o usaba uno, o usaba el otro). Además, es posible que entre dichas máquinas hubiesen algunas con Windows, el cual, por aquella época (y por ésta O:-D), no disponía de un intérprete de comandos adecuado, y le obligaría a reescribir sus programas para otros lenguajes (Basic o el que fuere), poco preparados para su objetivo.

Otro caso muy interesante es el de Python, lenguaje liberado al público 5 años después que Perl. La primera versión fue desarrollada en unas navidades aburridas, según comentaba su creador, y se basaba en otro lenguaje llamado ABC, en el que por aquel entonces trabajaba. Su motivación principal era acercar el mundo de la creación de programas a personas que no fueran programadoras. De hecho, en ocasiones puede parecer una poesía matemática, por su mezcla de conjunciones (if, while), nombres (variables), verbos (is, is not), identación, álgebra de boole, etc.

Ambos creadores, probablemente, aprendieron del infierno de otros lenguajes de scripting como APL, muy concisos pero complicados de ser leídos, y en general de todos los lenguajes de programación creados anteriormente. Un ejemplo simplón es el de separar distintos ámbitos (o entornos) en base a palabras (begin, end), llaves, o identación, según la legibilidad que se piensa se conseguirá. Pascal es un ejemplo de verborrea en comparación con C y sucedáneos.

Tradicionalmente, se ha pensado que estos lenguajes de scripting eran un reemplazo de los intérpretes de comandos, o de otras herramientas de preparación de programas para ser configurados e instalados. Así, hay desarrolladores que prefieren usar Ruby en lugar de ANT (menor limitación en el uso de condicionales, ...), o programas administrativos que han sido reescritos en Perl o Python (como el administrador de paquetes de Red Hat, o el informador de bugs de Debian), pero sobretodo Python. Estos usos pueden confundir a los recién llegados a estos lenguajes que, viniendo de la filosofía anterior de usar cada lenguaje para un dominio específico, no consiguen entender que cada uno de ellos pueda ser utilizado para (casi) cualquier intención.

Por ejemplo, Perl se utiliza fundamentalmente como simulación avanzada de los anteriores programas en Bash, pero también tiene un amplio uso en algoritmia, bioinformática, catalogación, ... y Python es muy utilizado como enlace entre programas tradicionalmente utilizados a golpe de ratón (o lapiz óptico), como Gimp, 3d Studio, etc., y programas propios, añadiendo ese plus de potencia a nuestros programas.

Aunque en la década de los 90 existía la misma emoción por el uso de Java que la que hay ahora con estos lenguajes de scripting (¡¡son el futuro!!), siempre quedan algunas dudas al buscar equivalencias con lo que ya se tiene, para intentar una migración casi transparente (y ganando la productividad que tanto se vende con estos lenguajes). Tras esta emoción previa surgen preguntas sobre cómo gestionar proyectos con un gran número de desarrolladores en estos lenguajes (o si siquiera existe ese gran número de desarrolladores que sean expertos en estos lenguajes), si existen los mismos patrones de diseño que con los actuales lenguajes, si se consigue integrar el código tan bien o mejor que con lo actual... y la verdad es que no he conseguido leer apenas sobre estos asuntos (de lo que deduzco que es el momento de innovar y lanzarse a la piscina... y ver qué pasa).

En cuanto a los patrones de diseño, es algo que, en mi opinión, va a haber que replanteárselo, porque para conseguir soluciones funcionales y muy contrastadas a lo largo de los años, como el patrón Singleton, es necesario hacer trucos sucios para replicarlo en estos lenguajes.

En cuanto a la integración, es una cuestión complicada de responder. En principio, opino que puede llegar a ser incluso más fácil de conseguir (tras un buen diseño, claro). El problema creo que está entre el teclado y la silla: crear buenas pruebas unitarias. Es decir, producir muchos más conjuntos de pruebas puesto que la libertad de valores manejados por las variables es infinitamente mayor. Con esto me refiero a la diferencia que supone el tipado estático (propio de C, Java, ...) y el dinámico (Perl, Python, Ruby...). En el primero, es necesario declarar las variables, y el compilador da fé de su buen uso a lo largo de todo el programa (asignaciones, pasos de parámetros, etc.). Por contra, el tipado dinámico permite no declarar variables hasta su primer uso, que podrá ir cambiado de tipo a lo largo del programa.

Por ejemplo, se puede tener un array de enteros y cadenas de caracteres mezclados, y cada uno heredará los métodos propios de su condición (substr, etc.). Éste uso es correcto en estos lenguajes de scripting, y por tanto está en manos de los programadores preparar una buena batería de pruebas para eliminar (reducir) funcionamientos no esperados.

Otra molestia muy relacionada con lo anterior es la escasa existencia de buenos IDEs (entornos de desarrollo) para estos lenguajes. Sí son capaces de conseguir integrar depuradores, coloreadores de sintáxis, ... pero complicado encontrar refactorizadores de código, autocompletadores de métodos de un objeto, etc. en gran parte debido a ese carácter dinámico.

En definitiva, los lenguajes de scripting son muy potentes (incluso aquellos específicos de un dominio, que lo serán para ese dominio), pero en ese gran crecimiento que están teniendo actualmente, se encuentran unas barreras quizás demasiado altas para pasar, en el mundo de la empresa, de ser utilizados en la generación de prototipos a cuestiones mayores, pero que han impulsado una nueva generación de lenguajes artificiales, que esta nueva generación sí que no creo que quede en una moda. De hecho, lenguajes como C# ya están incorporando tipado dinámico...

Desde bien pronto, el creador de Ruby ya dejó claro que su filosofía era crear un lenguaje fácil de usar, no enfocado en el rendimiento del mismo, básicamente porque no le parecía lo más importante dado que otras cuestiones en el ámbito de su uso (la Web) producirían cuellos de botella (como las comunicaciones de red), y siempre quedaría utilizar otros lenguajes en caso de priorizar dicho rendimiento.

Para mí, lo más importante es que todos estos lenguajes de scripting (famosos) son software libre, algo que ha impulsado la comunidad de usuarios y desarrolladores de módulos alrededor de ellos, y que sin ello no creo que hubiesen llegado al nivel en el que hoy están.

Recomiendo encarecidamente pasarse por sus sitios webs oficiales, donde se podrá encontrar abundante información sobre ellos, a todos los niveles.

Comments

]]>
Sun, 30 Dec 2007 19:09:59 +0100
Año nuevo, nuevo propósito. http://fermat.nireblog.com/post/2007/12/28/ano-nuevo-nuevo-proposito http://fermat.nireblog.com/post/2007/12/28/ano-nuevo-nuevo-proposito ¡Sorpresa! ¡Primer post! --que dirían en Slashdot-- del nuevo propósito para los próximos meses (espero): un blog sobre divulgación y, sobretodo, divagación entorno a la computación, desde un punto de vista mayormente práctico.

¿Otro más? Pozi, pero la motivación (inicial) es bastante egoísta y, por tanto, no espero ser leído (lo cual no hará mucha gracia a los proveedores de este servicio de blog xD). Básicamente, me parece una buena opción personal escribir sobre lo que creo que sé, en lo referente a estos temas, y así darme cuenta de lo que no (o incluso que alguien me llame la atención en cuanto a que no escriba de lo que no sé, en el peor de los casos, o me corrija, en el mejor. xD). Obviamente, pienso que voy a conseguir (a nivel humano) más que no llevando este propósito a cabo porque si no, vaya negocio... :-D

Así, intentaré escribir sobre asuntos técnicos del día a día de millones de personas, que en su mayoría pasan desapercibidos, haciendo hincapié en lo que viene a llamarse (en el mundo de la empresa) seguridad informática (y telemática). Ross Anderson, profesor de la Universidad de Cambridge, lo llamaba programar el ordenador de Satán. Yo añadiría... y hacer las pruebas unitarias en el ordenador de Murphy :-)

Si se os ocurre algún tema que os gustaría que tratase, escribidme personalmente (ya veremos si me encuentro capaz para ello).

Comments

]]>
Fri, 28 Dec 2007 04:17:16 +0100