viernes, 15 de abril de 2016

To REST or not to REST

Harto de encontrarme por todos lados en los últimos tiempos las palabras REST o RESTful cuando se habla de aplicaciones web, servicios web y temas relacionados, y no saber qué significan, me he decidido dedicar un rato (un par de horas) a aprender qué quiere decir esto.

Aquí va mi resumen personal para leer en cinco minutos, al que volveré dentro de un tiempo cuando se me haya olvidado, y espero que me sirva de refresco. Quien quiera más detalles, abajo encontrará algunos enlaces. Básicamente, lo que resumo aquí se basa en un 70-80% en el primer enlace, que es el que más útil me ha parecido de los que he encontrado hasta ahora.

Fig. 1. REST es un conjunto de ideas de las que destacan 4 tomates principios. 
Imagen de Softeis - Trabajo propio, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=143779
 

1. Qué es REST

Un conjunto de principios de arquitectura para el desarrollo de aplicaciones y servicios web.
Surge en oposición a SOAP y WSDL, que son más complicados.
Grandes proveedores 2.0 usan APIs RESTful (Google, Facebook...)

El énfasis se pone en los recursos (¿objetos?) y su transferencia por HTTP.

2. Principios básicos

2.1. Uso explícito de métodos HTTP
Se deben utilizar como se definieron en la especificación original de HTTP 1.1 (RFC 2616). Esto significa:

- GET para consultas
- POST para altas
- PUT para actualizaciones
- DELETE para ...¿lo adivinas?

Usar un GET para insertar o actualizar un registro en una BD es posible pero no es acorde con los principios RESTful.

2.2. Protocolo cliente/servidor sin estado
Cada petición HTTP debe contener toda la información necesaria.

Esto debe facilitar la escalabilidad, no se debe hacer que un servidor recupere el contexto si, por ejemplo, tiene que redirigir la petición a otro servidor para balanceo de carga.

Se transfiere el problema de mantener el estado al cliente.

Aunque a la hora de la práctica, aplicaciones que se definen como RESTful suelen usar cookies y otras formas de mantener el estado. ??

2.3. Exponer URIs como directorios y ficheros
Las URIs son así más intuitivas. Por ejemplo: http://www.dominio.com/informes/2016/04 nos podría devolver los informes de abril de 2016. Es una especie de sintaxis universal.

También se oculta la tecnología (no se ven extensiones de archivos, como ocurre en casos como  http://www.dominio.com/informes/recuperar_informes.php donde se ve que se utiliza PHP). Así se puede cambiar la tecnología subyacente sin cambiar la URI.

Parece que este es el principio más REST de los cuatro.

4. Los recursos se devuelven en XML, HTML o JSON
Por ejemplo, un registro de una BD. Estos recursos pueden contener enlaces (URIs) a otros recursos.

3. Ideas importantes
Al exponer los recursos mediante una API RESTful, se facilita la integración de aplicaciones de diferente naturaleza y tecnologías. Se puede proporcionar una base de servicios REST que pueden utilizar otras aplicaciones más complejas para construir sobre ellos.

No todas las implementaciones públicas que se definen como REST son RESTful. Parece que el principio predominante que sí se suele respetar es el de la URI uniforme (principio 3), como podemos ver, por ejemplo, aquí.

También he detectado un poco de bombo en torno al término REST, pero esto es inevitable en esta profesión, donde los nuevos términos se utilizan a menudo como el equivalente tecnológico de cojonudo.

4. Más info
  • RESTful Web services: The basics
http://www.ibm.com/developerworks/webservices/library/ws-restful/index.html?ca=dgr-jw22RESTfulBasics&S_Tact=105AGX59&S_CMP=GRsitejw22

  • Versión en español del artículo anterior
http://www.dosideas.com/noticias/java/314-introduccion-a-los-servicios-web-restful.html

  • Artículo en la Wikipedia en español (mejor leerlo después de leer el primer enlace)
https://es.wikipedia.org/wiki/Representational_State_Transfer

  • Servicios que son "accidentalmente" RESTful
http://www.markbaker.ca/blog/2005/04/14/#2005-04-amazon-next

He leído también detalles en otras páginas, pero son cosas más puntuales, y nada que no podáis superar con una simple búsqueda.

jueves, 14 de abril de 2016

Espacio en disco en formato legible para las personas (linux)

Aunque hay muchas herramientas gráficas para ver el espacio disponible en disco, uno siempre acaba volviendo de forma recurrente al útil comando df, que se puede usar tecleando sin más

$ df

y produce una salida tal que así

Fig 1. Salida del comando df


Por pequeño que sea un disco, siempre salen números muy grandes, ya que da el tamaño en bloques de 1K. Resulta un poco difícil de decir, a bote pronto, cuántos gigas libres te quedan.

Pero claro, normalmente nos gusta más leer el tamaño en megas y gigas. Para esto, viene muy bien la opción -h (legible por Humanos) del comando df.

$ df -h


Fig 2. Salida del comando df con la opción -h (humanos)



Y ahora sí que se puede leer bien.

 Como curiosidad, he marcado la tercerra línea para comparar cómo se ve esa misma información con el explorador Nautilus de Ubuntu, mostrando las propiedades del equipo.

Fig. 3. Ver el espacio en disco con Nautilus

Y se ve algo así

Fig. 4. Salida de Nautilus (tarda un buen rato)

Una curiosidad es que Nautilus y el comando df no muestran exactamente el mismo espacio usado (10,6 GB en un caso y 10G en el otro). Curioso.

Por cierto, me estoy quedando sin espacio en la partición /boot. Habrá que hacer algo.




miércoles, 9 de marzo de 2016

Servidores web más populares en el IBEX 35

Hace poco vimos cómo analizar las cabeceras en las comunicaciones HTTP con cURL [aquí].

Entre otras cosas, vimos el valor de la propiedad "Server", que nos informaba del servidor web y algunas tecnologías que podían estar disponibles en el servidor (PHP, ASP...).

Pues bien, hace unos días me surgió la pregunta de qué servidores web son los más populares entre las "empresas grandes". Veamos cómo podemos usar cURL y los filtros de Linux (lo mismo se puede hacer en Windows) para hacer una pequeña estadística de esto.

Primero, como "empresas grandes" he considerado las que forman parte del IBEX 35.

Si queremos ver lo que nos devuelven un par de ellas, podemos escribir algo así:

curl -I --url www.abertis.com --url www.endesa.com

Y obtendríamos esta respuesta


Fig. 1. Cabeceras de dos sitios web

Podemos filtrar sólo aquellas cabeceras que tengan la cadena "Server:"

curl -I --url www.abertis.com --url www.endesa.com |grep "Server:"


Fig. 2. Filtrando para quedarnos exclusivamente con la cabecera "Server:"

Como se puede ver, al usar cURL en pipelines nos va mostrando una estadística con los porcentajes de descargas, un medidor de progreso (cURL lo llama "Progress Meter"). De momento lo ignoraremos.

En el ejemplo anterior he puesto únicamente dos URLs, pero como me interesan las 35 URLs de las empresas del IBEX 35, lo que haré será poner estas URLs en un fichero y usar la opción -K de cURL para decirle que tome de allí las URLs.


Fig. 3. Fichero con las URLs de las empresas del IBEX 35.

Ya podemos invocar a cURL con ese fichero:

curl -I -K urls_ibex35.txt |grep "Server:"


Fig. 4. Vamos viendo los servidores, pero el medidor de progreso nos ensucia la salida

Con la opción -s (silent) podemos hacer que desaparezca el medidor de progreso.

curl -I -K urls_ibex35.txt -s |grep "Server:"


Fig. 5. La cabecera "Server" sin el medidor de progreso

Vale, ya estamos cerca del final. Podemos ver unas cuantas cosas interesantes. En primer lugar, no todos los servidores devuelven la cabecera "Server". De hecho, hay tan sólo 26 resultados, lo cual quiere decir que más de la cuarta parte de los administradores web de estas empresas (9 servidores) han decidido ocultar la información acerca del servidor web que utilizan. Además, uno de ellos devuelve una cadena en blanco, lo cual es lo mismo que ocultarlo. Total, 10 de 35 no lo indican, casi un 29%. Lo cual quiere decir que el otro 71% ven con buenos ojos publicar esta información, aunque con diferentes niveles de detalle. Y todo esto, asumiendo que no hayan falseado esta cadena para devolver un valor erróneo, cosa que también cae dentro de lo posible (aunque lo considero poco probable, la verdad).

Por último, en vez de contar a mano, hagamos un poco de "pipelining".

curl -I -K urls_ibex35.txt -s |grep "Server:" |sort |uniq -c |sort -nr


Fig. 6. Agrupando por Servidor web

Como vemos, el ganador es...(redoble de tambores...)... ¡APACHE!

Apache está disponible en 12 de los 26 sitios web que publican la información, o sea, un 46%. Una gran diferencia con respecto a la segunda posición, ocupada por diferentes versiones del servidor de Microsoft, IIS, con 4 sitios (un 15%) y en tercera posición hay un (sorprendente para mí, pues no lo conocía) servidor llamado AkamaiGHost, que tienen 3 de las 26 empresas (casi un 12%).

Bueno, me parecen unos resultados interesantes de conocer. Además, no puede uno evitar pensar enseguida en extender esta estadística a otras empresas, universidades, organismos oficiales, gobiernos... Pero eso lo dejaremos para otra ocasión.



¿Y tu organización, qué servidor web utiliza? ¿Publica su nombre, versión, tecnologías asociadas...?

lunes, 22 de febrero de 2016

Convertir a mayúsculas o minúsculas con el comando dd

El comando dd permite, entre otras cosas, hacer copias de un fichero aplicando conversiones en el proceso. Dos conversiones sencillas que pueden llevarse a cabo con ficheros de texto son pasar todo a mayúsculas o a minúsculas.

Para ello,hay que teclear algo así

dd if=a.txt of=b.txt conv=ucase

Donde if significa "input file" y of significa "output file".

Si cambiamos "ucase" por "lcase" transformaremos todo el texto en minúsculas.


Atentos a los caracteres con tildes.

lunes, 8 de febrero de 2016

Configurar la cabecera Server en el servidor web Apache 2 (Ubuntu y Windows)

En la anterior entrada hablé sobre las cabeceras que envían los servidores web y, en particular, sobre la cabecera "Server". Pero, ¿dónde se configura esta cabecera en nuestro servidor web, en particular en el caso de Apache?


Esto se determina en la directiva ServerToken en el fichero de configuración (apache2.conf en Ubuntu, httpd.conf en Windows), o bien en algún fichero incluido de manera transitiva en él. 

Esta directiva puede tomar los valores Prod, Major, Minor, Minimal, OS, Full, enviando cada vez más información detallada en ese orden. Si no se especifica, se asume el valor Full. Como se explica en la documentación oficial de Apache (http://httpd.apache.org/docs/2.0/es/mod/core.html#servertokens):



Fig. 1. Valores posibles para la directiva ServerTokens

Vale. Entonces ¿dónde está el fichero de configuración?

EN UBUNTU

Ubicación del fichero de configuración:  /etc/apache2/apache2.conf

Fig. 2. Cuando no está establecida la directiva, se devuelve la información "Full"

Puede verse que la directiva existe, a modo de ejemplo (pero sin ser efectiva), en un fichero de configuración disponible en el subdirectorio conf-available, pero para que esta entrada fuera efectiva tendríamos que incluir una referencia a él en el fichero principal /etc/apache2/apache2.conf, lo que ahora mismo no está ocurriendo. 

Como podemos observar, el servidor ahora mismo está devolviendo la cadena Apache/2.4.12 (Ubuntu)

En nuestro caso, nos limitaremos a incluir una línea con la directiva establecida al valor Prod (esto significa Producción, entorno desde el que se debería enviar la mínima información como medida de precaución).
Modificamos el fichero, reiniciamos el servidor (esto es necesario) y preguntamos ahora por las cabeceras

Fig. 3. Tras la modificación, la cabecera ha cambiado el valor enviado

Como se ve, ahora se está devolviendo el valor Apache a secas.


EN WINDOWS

Lo único que cambia en Windows es el fichero de configuración, que en este caso es apache\conf\httpd.conf o, como ocurre en mi caso, puedo cambiarlo en el fichero extra\httpd-default.conf, que es incluido en el primero mediante una directiva

# Various default settings
Include "conf/extra/httpd-default.conf"


Pues nada, ya sabemos cómo configurar la cabecera Server. Cuidado con lo que enviáis a vuestros clientes.

viernes, 15 de enero de 2016

Cabeceras en comunicaciones HTTP con cURL

Aparte del contenido HTML que se transfiere durante una consulta a un sitio web, también se transmite otra información en forma de cabeceras, que no son más que pares del tipo "valor: resultado". Estas cabeceras normalmente no se muestran al usuario que está visitando el sitio web, pero el navegador sí que las recibe, pudiendo ignorar algunas y utilizar otras, según le interese. Es interesante echar un vistazo a esta información que, en principio, no se ve.

Echando un vistazo a lo que no se ve
Imagen: Lector con lupa, Lesser Ury. Fuente: wikipedia.

Con curl podemos ver las cabeceras que nos está enviando un servidor web usando la opción -I. Por ejemplo, para ver las cabeceras que envía el servidor de la RAE:

Fig. 1. Cabeceras del servidor web de la RAE

Como se puede ver en la Fig. 1, una de las cabeceras se llama Server. En el caso de la RAE, el valor es Apache, lo cual nos puede llevar a pensar que la RAE utiliza como servidor web Apache.

Digo "nos puede llevar a pensar" porque esto no es necesariamente así. Al fin y al cabo, el administrador del servidor web puede configurarlo para que devuelva en esa cabecera cualquier cadena de texto que quiera.

Algunos administradores, por motivos de seguridad, prefieren no informar a los visitantes del servidor web que utilizan, por ponérselo un paso más difícil a los hackers (esta técnica de ocultación tampoco contribuye demasiado, la verdad, pero algo es algo). Otros dejan tan sólo el nombre del servidor web y eliminan los números de versión (informar del nombre y versión del servidor web suele ser la opción configurada por omisión). Así, al menos, intentan dificultar que un hacker pueda explotar alguna vulnerabilidad conocida que sea específica de esa versión del servidor web o del motor de PHP, de ASP...

En este caso, podemos comprobar que el administrador del servidor web de la RAE ha eliminado la versión de la cadena que describe el servidor Apache (suponiendo que sea ese el servidor real, lo cual asumiremos por el momento).

Otras veces, en las cabeceras podemos encontrar si el servidor está utilizando PHP, ASP u otras tecnologías, incluyendo el número de versión:

Fig. 2. Cabeceras del servidor web de Endesa indicando que utiliza IIS en 
su versión 7.0 y ASP.NET (sin indicar número de versión)

Pero recordad, dado que lo que se devuelve es una cadena de texto libremente modificable, también puede darse el caso, siendo un poco más retorcido, de que se esté informando de un número de versión erróneo, a fin de despistar al visitante. Así que no conviene, como decía Microsoft en un anuncio, asumir que "por llamarse Mercedes, eso signifique que sea un coche".




martes, 15 de diciembre de 2015

Manejo del portapapeles desde la línea de comandos

El portapapeles está muy bien para copiar y pegar texto con el ratón, pero a veces nos puede interesar manipularlo de forma no interactiva, desde la línea de comandos o desde nuestros scripts.

Dos comandos especialmente populares en el mundo Mac permiten esto: pbcopy y pbpaste. Las iniciales "pb" significan "pasteboard", que es como llaman al portapapeles en los Mac, mientras que en Linux y Windows suele usarse más el término "clipboard", aunque en el fondo esto es cuestión de caprichos.

Aunque pbcopy y pbpaste sean los más famosos, los otros sistemas operativos también tienen comandos que podemos utilizar para lograr lo mismo. En Windows, tenemos el comando clip.exe (aunque me parece que sólo funciona para copiar, pero el pegado ha de ser interactivo). 



En Linux tenemos bastantes más opciones, mi elección ha sido el comando xsel. No viene en la distribución estándar, pero se instala fácilmente con 

$ sudo apt-get install xsel 

Si investigais un poco encontraréis otras herramientas (xclip...), con multitud de opciones.

De todas formas, tan populares se han hecho los nombres originales del mundo Mac que yo he optado por seguir el consejo que dan en muchas páginas web: hacer un alias para esos comandos. Para ello, en el fichero de configuración $HOME/.basrc no hay más que añadir estas dos líneas:

alias pbcopy='xsel --clipboard --input'
alias pbpaste='xsel --clipboard --output'

Aquí podéis ver un ejemplo para copiar un calendario al portapeles desde la línea de comandos y pegarlo luego tanto en la línea de comandos como en un editor de texto:


Para sacarle partido a fondo, ya se sabe:

$ man xsel | less
 
Ale, a copiar y pegar y copiar y pegar y copiar y pegar.

miércoles, 2 de diciembre de 2015

Visto y no visto: una parte ocultable en una página web

Los usuarios, esas ricuras

Me encantan los usuarios contradictorios. Al fin y al cabo, esas contradicciones no dejan de reflejar la naturaleza humana, así que no hay por qué asustarse. Hay que saber escucharlos, y darles lo que realmente quieren o necesitan, que muchas veces no coincide exactamente con LO QUE TE PIDEN.

En esta ocasión, por un lado me piden que les incluya un texto fijo en una página web, unas instrucciones que deben ser utilizadas y tenidas en cuenta por todos los que utilizan la página. A veces la aplicación web les devuelve determinados resultados y los usuarios tienen que consultar en la documentación en papel, unas normas complejas que en los últimos meses están cambiando bastante (dependen de unas leyes un tanto "inestables"). Tener la información a la vista en la página, mientras usan el programa, les evitaría tener que abandonar la página para sumergirse en los papeles.

Pero, por otro lado, tener delante el texto, todo el tiempo, les molesta. Funcionalmente, no aporta utilidad al programa. No se necesita consultar siempre, sólo si el programa devuelve determinados datos, para dar explicaciones, para realizar procesos manuales... Así que, mientras unos me piden que el texto esté a la vista, otros me pregunta si no se puede quitar, ya que les "ensucia" la página.

O sea, resumiendo, quieren que las instrucciones se vean, pero al mismo tiempo, no se vean. Qué ricos.

Fig. 1. Que se vea, pero que no se vea. 
Foto: Jorge A. Loffler, Flickr, licencia CC BY-SA 2.0

Texto ocultable

Para resolver esto se pueden dar muchas soluciones, y seguro que los especialistas en interacción persona-ordenador lo han estudiado hasta la saciedad. El tema de dónde ubicar un elemento en la interfaz de usuario no es algo para tomarse a la ligera, sobre todo en aplicaciones que tengan cierta repercusión, con un alto número de usuarios. 

Una opción sencilla sería poner las instrucciones en una página aparte, y en la página principal poner un enlace, que se abra en una nueva ventana o pestaña. Sin embargo, en esta ocasión, yo me voy a limitar a una solución también muy simple y bastante efectiva, a juzgar por el feedback que me han dado los usuarios.

La técnica consiste en comenzar con el texto oculto en la página, y un botón que permita visualizarlo o volver a ocultarlo a placer. También se podía haber hecho justo al contrario: empezar con el texto visible, y que el usuario pueda ocultarlo. La elección de cualquiera de las dos alternativas depende de la naturaleza y necesidad del texto. En mi caso, es un texto que sólo hay que consultar de forma ocasional, con lo que interesa que la mayor parte del tiempo esté oculto. Por eso al cargar la página el texto no se muestra. Si fuera un mensaje de lectura obligatoria, para que nadie pueda decir que no lo ha visto, por ejemplo, pues comenzaría con el texto visible y el botón permitiría ocultarlo (y visualizarlo de nuevo, claro). En fin, estos detalles parecen tonterías pero muchas veces son tonterías importantes, así que si uno se encuentra situaciones similares, es buena idea dedicarle una pensada de unos minutos o, mejor aún, preguntarle a los usuarios, que son quienes al fin y al cabo van a valorar la utilidad del software.

Pasando ya a lo meramente técnico, nos basaremos en tres cosas:
  • identificadores de elementos
  • código HTML de un elemento (propiedad innerHTML)
  • botón con una función Javascript asociada

Identificadores de elementos

Prácticamente cualquier elemento de una página puede tener un identificador (un id) que podemos utilizar para hacer referencia a él desde código Javascript. Esto incluye también a los párrafos, así que en vez de escribir

<p>Párrafo de texto</p>

Escribiremos

<p id="mensaje">Párrafo de texto</p>

Para poder manipularlo desde el código Javascript, accederíamos a ese elemento con la llamada

document.getElementById("mensaje");

Queremos comenzar con el texto oculto, lo que equivale a decir que el texto inicial del párrafo esté vacío. Debajo de ese párrafo pondremos un botón y debajo del botón, el resto de la página:


1 <p id="mensaje"></p>  
2 <button id="bInfo1" onclick="botonPulsado()">Mostrar mensaje</button> 
3 <p>Aquí va el resto de la página</p>

Como puede verse, el botón responderá al clic invocando a la función botonPulsado, que mostraremos más adelante.

Código HTML

Por otro lado, algunos elementos DOM tienen la propiedad innerHTML, que es un valor textual que representa el código HTML asociado a ese elemento. En el caso de un párrafo, es el texto HTML que se mostrará dentro. Esta propiedad puede ser tanto de lectura como de escritura, así que podemos recuperar el valor del párrafo o podemos asignarlo. Por ejemplo:

texto = "hola, caracola";
document.getElementById("mensaje").innerHTML = texto;

La función Javascript

Por último, necesitaremos una función que cambie el contenido del párrafo en cada pulsación del botón, mostrando u ocultando el texto, alternativamente. Esto se hará comprobando si el párrafo en ese momento está vacío o no:

    if (document.getElementById("mensaje").innerHTML == "") {
        document.getElementById("mensaje").innerHTML = texto;
        document.getElementById("bInfo1").innerHTML = "Ocultar mensaje";
    } else {
        document.getElementById("mensaje").innerHTML = "";
        document.getElementById("bInfo1").innerHTML = "Mostrar mensaje";
    }

Con esto, ya tenemos las tres piezas de nuestro pequeño puzzle. Así quedaría la página completa:



01 <HTML>  
02 <HEAD> 
03 <script> 
04 function botonPulsado() { 
05 texto = 'Esto es un bloque de texto <br>\  
06 que debería poder mostrarse u ocultarse <br>\  
07 según lo desee el usuario. Por ejemplo, unas<br>\  
08 instrucciones de cómo actuar en determinados casos,<br>\  
09 o unos teléfonos de contacto de emergencia...<br>\  
10 En general, cualquier información útil que tenga que<br>\  
11 estar rápidamente accesible<br>'  
12 if (document.getElementById("mensaje").innerHTML == "") { 
13 document.getElementById("mensaje").innerHTML = texto;  
14 document.getElementById("bInfo1").innerHTML = "Ocultar mensaje";  15 } else { 
16 document.getElementById("mensaje").innerHTML = ""; 
17 document.getElementById("bInfo1").innerHTML = "Mostrar mensaje"; 18 }  
19 }  
20 </script> 
21  
22 </HEAD> 
23 <BODY> 
24 
25 <H1>Página importantísima, con un mensaje secreto</H1>  
26  
27 <P ID="mensaje"></P>  
28 <BUTTON ID="bInfo1" ONCLICK="botonPulsado()">Mostrar mensaje</BUTTON>  
29 <P>Aquí va el resto de la página</P>  
30  
31 </BODY>  
32 </HTML>

Listado 1. La página al completo

Y si la probamos veremos el resultado de las imágenes:


Y una vez pulsado el botón


Unos comentarios finales

Como vemos, la técnica de mostrar y ocultar un elemento es muy sencilla, pero también muy versátil. Se puede utilizar, entre otras cosas, para
  • textos de instrucciones, notas legales o mensajes de ayuda para el usuario
  • bloques de iconos
  • una sección de enlaces corporativos
  • ...y cualquier otra cosa que se os ocurra y para la que tenga sentido verse y ocultarse
Como curiosidad, os comento que un par de usuarios me han felicitado efusivamente por el resultado. Para ellos, resulta muy práctico olvidarse de mirar los papeles cuando están en la página y tienen que consultar la normativa. La técnica empleada en la página, desde un punto de vista técnico, es una trivialidad, pero oyendo sus alabanzas parece que uno les hubiera hecho la aplicación del siglo, ya que han quedado muy satisfechos.

Esto viene a recordarnos que no todo es calidad técnica o calidad objetiva, sino que también es muy importante la calidad percibida por el usuario. De hecho, podemos rompernos la cabeza ideando virguerías técnicas y haciendo que nuestro programa sea una maravilla tecnológica, pero si los usuarios no lo perciben así, entonces quizás no tiene tanta calidad. O sin quizás.

Quien de verdad puede valorar algo es quien lo usa. Esto no es una verdad absoluta (recordemos el caso de los coches de Volkswagen: los usuarios podían estar satisfechos con la conducción, comodidad... pero su calidad tecnológica no llegaba a las exigencias legales en materia de emisiones), pero es importante tener en cuenta qué cosas podemos dar que aporten mayor valor a los usuarios de nuestras aplicaciones.

Esas cosas que aportan valor no siempre han de suponer un esfuerzo técnico muy alto, así que es bueno estar atentos para detectarlas y poder darlas. Así, con poco esfuerzo podemos aumentar el nivel de satisfacción de nuestros usuarios. Que los usuarios estén contentos es bueno para ellos y mejor aún para nosotros.

Bueno, aquí corto ya el rollo. A seguir programando.Y que los usuarios de vuestros programas os lo agradezcan, al menos ahora que se acerca la Navidad.


martes, 3 de noviembre de 2015

Solución quick-and-dirty para contar funciones

Pregunta 1: ¿Cuántas funciones escribiste para tu último proyecto en PHP? No cuentes las de librerías de terceros

grep -r "function " --include="*.php"  .|grep -v "./libs" |wc -l
1291




Pregunta 2: ¿Puedes sacar un listado de ellas, ordenado por los nombres de los ficheros en los que se encuentran?

grep -r "function " --include="*.php"  .|grep -v "./libs" |sort >funciones.txt





 Las dos líneas de código se explican casi por sí solas, en todo caso puede requerir una brevísima consulta a la ayuda de grep (grep --help), así que no me molestaré en explicar lo que ya está escrito allí. Una vez entendidas las opciones, se entiende muy fácilmente.


VAMOS A PONERLE PEGAS

1. En la primera solución se realizan dos llamadas al comando grep, cuando se podría hacer en una. Además, el primer grep obtiene líneas que luego desechará el segundo grep ==> Ineficiente.

2. Además de lo que se pretende, también muestra aquellas líneas que tengan la palabra 'function' seguida de un espacio, aunque estas estén entre comentarios ==> Aunque en mi caso es poco probable que se dé esa situación, sin embargo es algo potencialmente inexacto (si hay algún comentario en inglés conteniendo esa palabra)

Resumiendo: Ineficiente, potencialmente inexacto...

Y seguramente tiene muchas más pegas.



Y SIN EMBARGO... TE QUIERO

Pero tiene una ventaja brutal: es definitivamente rápido de hacer. Muy rápido. Y rápido, también, de ejecutar (en nuestro caso, dado el lote de ficheros con los que tengo que trabajar). Así que, ¿por qué hacerlo más complicado cuando una solución quick-and-dirty puede valer?

Y es que, a veces, lo perfecto es enemigo de lo bueno. O como dijo R. Gabriel, lo peor es lo mejor. Pero de esto ya hablaremos en otra ocasión.

martes, 27 de octubre de 2015

Por dónde se mueve la serpiente

Desde hace poco, estoy flirteando un poco con Python, y entre otras pruebas que estoy haciendo, tengo un programa que quiero que me funcione tanto en Linux como en Windows.

¿Cómo hacer que el programa sepa si está en una u otra plataforma? (Por ejemplo, para tratar con las rutas de ficheros, o para buscar determinados directorios de sistema que tienen nombres predefinidos...)

En realidad, para esas dos cosas que he dicho, debería usar variables del sistema o constantes predefinidas (separador de directorios, directorio del usuario... que tengo pendiente de investigar), pero es posible que aún y así todavía quiera seguir sabiendo cómo conocer en qué sistema operativo se está ejecutando el programa.

Simplemente hay que importar el módulo (librería) platform, e invocar el método system, que devolverá la cadena 'Windows' o 'Linux'.

Pues ya está. Aquí el listado:

 1 import platform
 2 print("Mostrar información sobre el ordenador")
 3 
 4 # Windows o Linux?
 5 if platform.system() == "Windows":
 6    print("En Windows")
 7    raiz = 'c:\\'
 8 elif platform.system() == "Linux":
 9    print("En Linux")
10    raiz = '/'
11    
12 print('------------------------------------------------------------------------')
13 print(platform.uname())
14 print('------------------------------------------------------------------------')
15 print('Arquitectura:')
16 print(platform.architecture())
17 print('Implementación: ' + platform.python_implementation())
18 print('------------------------------------------------------------------------')

Listado 1: Diferenciar entre Windows y Linux con platform.system()

Como podéis ver, hay otros métodos interesantes: uname, architecture y python_implementation, que nos pueden dar información que puede que necesitemos en algún caso. Aunque si queremos maximizar la portabilidad de nuestros programas, deberíamos usar esto lo menos posible, para no atarnos en demasía a una plataforma específica. Que sí, que luego siempre se acaba migrando, aunque uno no quiera. Y las dependencias de la plataforma son un lastre.

La llamada a uname devuelve un array con bastante información (contiene, entre otras, el tipo de sistema, como lo devuelve system).

La salida en Ubuntu la podéis ver aquí:



Y aquí en Windows 7:


Por último, avisar de que este código está hecho para Python 3, así que no olvidéis poner en la primera línea del archivo la ruta del ejecutable de python3. También os dejo aquí cómo indicar que el encoding del archivo es UTF-8, cosa que os será útil si trabajáis con eñes, tildes y otras 'cosas raras'. Simplemente hay que poner en las dos primeras líneas esto:

#!/usr/bin/python3
# -*- encoding: utf-8 -*-



Related Posts Plugin for WordPress, Blogger...