5 tips for working from home

July 30th, 2010 4 comments

Home office

I have been working in my pyjamas since more than two years ago. I mean by this that I have been working remotely from home. Now you may be thinking, I could never do that, and yeah, you are right, this kind of job is not made for everyone. It’s got its advantages, but it’s got its disadvantages as well like everything else in the world. If you don’t organize yourself thoroughly, you will never be able to put up with it for a long time. I must to admit that I sometimes miss working in an office with my colleagues, but in the other hand I’m absolutely aware of the great advantages that my current job offers me. I think the right thing to do is try to find a good balance among work and free time. Here you have some tips to help you find that balance.

1. Don’t work and spend your free time in the same place

This is one of the hardest facts for anyone working remotely to stand. It’s very frustrating (and unhealthy?) to sleep, work, eat, have a shower, watch TV, … in only one room. I know sometimes you have no choice since I also had to do all my life within four walls whilst I was living in San Francisco. Having a bed at a few meters from you when you are working on something boring is very tempting. Believe me, your productivity could fall off by far. So as long you can avoid doing this. Try to set up an independent workspace free of distractions.

2. Make people who are living with you realize that you are working

In case you are not living on your own, some people will find hard to realize that you are really working, not spending all day at home. They will tend to talk to you or ask you to do things whilst you are working. Let them know when you knock off.

3. Make a good use of the free time that a telecommute job offers you

One of the best advantages of working from home is the large amount of time that you can save in a day. I have realized that I can have up to 2 hours of free time more than when I was working in an office (trains, traffic stucks, lunch times, …). I normally spend that time on housework (laundry, house cleaning, grocery shopping, cooking, …) and on chilling me out.

4. Have a work timetable and carry it out strictly

Despite some companies already sets you a work timetable, normally they will give you the freedom of work whenever you want within reasonable limits. So this is when you have to discipline yourself and stick to working hours. You can also try to fit your timetable around people living with you, therefore you will avoid becoming very unsociable. Don’t get up too early or too late, design timetable which you can feel comfortable with.

5. Try to be available as much as you can

This is a very important point to have in mind when you are a telecommute worker: availability. Try to be available for your company as much as you can, at least during working hours. There are loads of ways you can be contacted by: phone, mail, IM, VoIP, … It’s very frustrating when you need a guy who you are paying for and you can’t find him/her.

Image | TylerIngram

2011 Porsche Boxster Spyder

May 30th, 2010 0 comments

2011 Porsche Boxster Spyder. 320-hp, 3.4-liter flat-six

La cultura de la propina en los Estados Unidos

February 14th, 2010 4 comments

Una propina consiste en el pago voluntario como recompensa por un buen trato recibido. Generalmente estos pagos van dirigidos a empleados del sector servicios (camareros, taxistas, …). En Europa es bastante común dejar una parte del cambio como propina cuando la atención por parte del servidor ha sido excepcional y por lo consiguiente el cliente se siente muy satisfecho por ello. En mi caso suelo dejar algo de propina cuando en un restaurante me sirven extraordinariamente bien, es decir, en muy pocas ocasiones. Y con esto no quiero decir que me traten mal ni mucho menos. En muchos restaurantes se incluye en la factura un cargo extra por el servicio (normalmente viene descrito en concepto de cubierto), el cual por ley el cliente está en pleno derecho a no pagar en caso de que el servicio no haya sido lo suficientemente bueno.

En los Estados Unidos la cultura de la propina es bastante peculiar, incluso puede resultar un tanto chocante para el visitante. Es un objeto de opiniones sin límites y dispares, aunque está más que asumido resignadamente por la sociedad estadounidense. Aquí la propina entra en un escenario donde deja de ser voluntaria y pasa a ser una obligación moral. Tal es dicha obligación, que si no se deja propina la sensación equivale a marcharse del establecimiento sin pagar. Esta práctica aceptada por la sociedad establece que es necesario propinar a la persona que te sirve una cantidad comprendida entre el 10% y el 20% del importe total de la factura. Es muy probable que si en un restaurante no dejas nada de propina el camarero te exija su gratificación, ya que lo consideran como una buena parte de su sueldo. Y digo una buena parte de su sueldo porque en los Estados Unidos un camarero normalmente cobra el minimum wage establecido por cada estado, entonces la mayoría de las veces la recaudación de propinas puede llegar a superar al propio salario. De hecho las propinas se incluyen en la declaración fiscal como ingresos (al menos un 8%), un invento del orwelliano IRS (Internal Revenue Service) para intentar subsanar los agravios producidos en la economía sumergida del país, porque… ¿cuanto dinero se mueve al año en los Estados Unidos en concepto de propinas? Obviamente este sistema es el negocio perfecto para el dueño del restaurante, puesto que no necesita pagar a sus empleados un salario relativamente alto, ya que éstos se complementan gracias a la “voluntad” de los clientes y evitan el tener que abonar una cantidad bastante importante de impuestos.

En mi opinión cuando una propina deja de ser voluntaria deja de ser propina. He vivido experiencias totalmente opuestas en otros países como Japón, donde el hecho de dejar una propina puede llegar a ser incluso ofensivo para el camarero. Personalmente pienso que los gastos del servicio deberían de estar incluido siempre en el precio que aparece en el menú, como también lo están la mesa y el mantel que se predispone para el cliente. Además, el buen servicio es aquel que resulta totalmente transparente para el consumidor, no se trata de ofrecer una adulación extrema por el mero hecho de conseguir una propina mayor.

Un argumento, que por cierto no me gusta nada, a favor de las propinas obligatorias en USA se basa en que el salario medio de un camarero es bastante bajo. Aunque no me da exactamente igual, me temo decir que este problema no atañe al cliente. Puestos así hasta se puede considerar como una desigualdad de oportunidades respecto a otros trabajadores de sectores diferentes y con sueldos bajos. De este modo, ¿por qué no propinamos a una señora de la limpieza o a un cajero de de un supermercado?

También cabe decir que el sistema proclive a calcular una propina basada proporcionalmente al total de la factura me parece un tanto irracional. Siguiendo la regla del 20%, si en un restaurante pido una botella de vino valorada en $40 necesitaría pagar $8 en concepto de propina. Sin embargo, si pido otra botella valorada en $400, el gasto correspondiente a la propina asciende a $80. ¿Realmente supone al camarero una carga mayor de trabajo traer una botella más cara o más barata? A mi modo de ver, esta fórmula carece de sentido.

Por suerte o degracia y debido al carácter intangible del asunto, seguiré propinando a diestro y siniestro mientras esté por Estados Unidos, remitiéndome al proverbio de San Ambrosio de Milán, cuando estés en Roma, haz como los romanos.

Integrating Yahoo r3 with Phing

December 21st, 2009 21 comments

Phing Yahoo r3Yahoo r3 is a powerful tool for building websites which could require multiple languages or dimensions. The r3 outputs may be plain text files, web templates, configuration files or even source code. Sometimes maintaining a big site translated into different languages can become a nightmare, but r3 lets you do it on an easy way. It offers a neat and powerful command line interface which will make your life easier. It can also be managed by using a web interface.

I know this could be a somewhat confusing thing to explain, so I’m going to try to give an example of what you can do with it. At Weblogs SL, we have a platform which handles instances of 37 blogs in 2 languages (Spanish and Portuguese), so we have to maintain 37×2 = 74 sites. They almost share the same layout structure, but sometimes we need to make specific changes on certain site (maybe a customized header or sidebar). r3 lets you do all this kind of things by specializing templates for a particular site/language. Coming back to our example, we have two dimensions: blog and language. Once we have created the dimensions, we can generate all the templates. These raw templates are parseable by the template engine included within our platform, so they are processed by the application afterwards. We can also put all the “static variables” for each blog (such as blog titles, URLs, paths, …) during this pre-build process.

So after far too much research, we came up with Yahoo r3, but we still had an itch to scratch: how can we integrate this into our continuous integration workflow? We are using Phing (and Java Ant) for building our sites, so it was nice to have some Phing tasks to work with r3. So I wrote these two tasks:

r3GenerateTask.php

require_once 'phing/Task.php';
/**
 * r3 Generate Task
 *
 * PHP version 5
 *
 * @category  Phing Task
 * @package   phing
 * @author    Alfonso Jimenez
 * license   http://www.gnu.org/licenses/gpl.html GPL
 *
 */

class r3GenerateTask extends Task
{
    /**
     * path to r3 workspace
     *
     * var  string
     */

    protected $r3Workspace;

    /**
     * init method
     *
     * @return boolean
     */

    public function init()
    {
        return true;
    }

    /**
     * main method
     *
     * @return void
     */

    public function main()
    {
        $command = 'r3 -c '. $this->Workspace .' generate -av';
        $output  = array();
        $return  = null;

        try {
            exec($command, $output, $return);

            foreach ($output as $line) {
                $this->log($line, Project::MSG_VERBOSE);
            }

            if ($return !== 0) {
                throw new BuildException('Task exited with code'. $return);
            }
        } catch (BuildException $e) {

            $op = Project::MSG_WARN;

            if ($this->quiet === true) {
                $op = Project::MSG_VERBOSE;
            }

            $this->log($e->getMessage(), $op);
        }
    }
}

r3SetVarTask.php

require_once 'phing/Task.php';

/**
 * r3 setVar Task
 *
 * PHP version 5
 *
 * category Phing Task
 * package phing
 * author Alfonso Jimenez <yo@alfonsojimenez.com>
 * license http://www.gnu.org/licenses/gpl.html GPL
 *
 */

class r3SetVarTask extends Task {
    /**
     * path to r3 workspace
     *
     * var string
     */

    protected $r3Workspace;

    /**                                              
     * dimension                                      
     *                                                
     * @var string                                    
     */
                                             
    protected $dimension;                            

    /**                                              
     * variable key                                  
     *                                                
     * @var string                                    
     */
                                             
    protected $key;                                  

    /**                                              
     * variable value                                
     *                                                
     * @var string                                    
     */
                                             
    protected $value;                                

    /**                                              
     * sets the r3 workspace path                    
     *                                                
     * param string $r3Workspace                    
     *                                                
     * return void                                  
     */
                                             
    public function setr3Workspace($r3Workspace)      
    {                                                
        $this->r3Workspace = $r3Workspace;            
    }                                                

    /**                                              
     * sets dimension                                
     *                                                
     * param string $dimension                      
     *                                                
     * return void                                  
     */
                                             
    public function setDimension($dimension)          
    {                                                
        $this->dimension = $dimension;                
    }                                                

    /**                                              
     * sets the variable key                          
     *                                                
     * param string $key                            
     *                                                
     * return void                                  
     */
                                             
    public function setKey($key)                      
    {                                                
        $this->key = $key;                            
    }                                                

    /**                                              
     * sets the variable value                        
     *                                                
     * param string $value                          
     *                                                
     * return void                                  
     */
                                             
    public function setValue($value)                  
    {                                                
        $this->value = $value;                        
    }                                                

    /**
     * init method
     *            
     * @return boolean
     */
             
    public function init()
    {                    
        return true;      
    }                    

    /**                  
     * main method        
     *                    
     * @return void      
     */
                 
    public function main()
    {                    
        $command = ‘r3 -c ‘. $this>r3Workspace .var set ‘. $this>dimension
                   .’ ‘. $this>key .’ ‘. $this>value;                      
        $output  = array();                                                  
        $return  = null;                                                      

        try {                                                                
            exec($command, $output, $return);                                

            foreach ($output as $line) {                                      
                $this->log($line, Project::MSG_VERBOSE);
            }

            if ($return !== 0) {
                throw new BuildException(‘Task exited with code’. $return);
            }
        } catch (BuildException $e) {

            $op = Project::MSG_WARN;

            if ($this->quiet === true) {
                $op = Project::MSG_VERBOSE;
            }

            $this->log($e->getMessage(), $op);
        }
    }
}

If you want to use these tasks in your Phing file, you have to place them in /usr/share/php/phing/extended/tasks/ first. Then you can call them by writing the following tag-commands:

<taskdef name=”r3-generate” classname=”extended.tasks.r3GenerateTask” />
<taskdef name=”r3-setVar” classname=”extended.tasks.r3SetVarTask” />

<r3-generate r3Workspace=”${workspace.dir}”></r3>
<r3-setVar r3Workspace=”${workspace.dir}” dimension=”${dimension}” key=”var_key” value=”${var_value}”></r3>

Let’s see an example of a real Phing file. Imagine that we have to write a task which needs to do the following steps:

  1. Get a Yahoo r3 workspace from a SVN repository (http://svn.test.com/trunk/r3)
  2. Build the Yahoo r3 workspace
  3. Move the generated templates into a certain directory
  4. Clean up the temporary files

So we can straightforward write a Phing task in order to follow this sequence of steps:

<?xml version="1.0"?>
<project name="Yahoo r3 Templates Build" basedir="." default="build">

   <property name="tmp.dir" value="/tmp/template" />
   <property name="templates.dir" value="/home/r3/templates" />
   <property name="svn" value="http://svn.test.com/trunk/r3" />

   <target name="build" depends="init, generate, clean" />

   <target name="init">
      <taskdef name="r3-generate" classname="extended.tasks.r3GenerateTask" />

      <mkdir dir="${tmp.dir}" />
      <svncheckout svnpath="/usr/bin/svn" repositoryurl="${svn}" todir="${tmp.dir}"/>
   </target>

   <target name="generate">
      <r3-generate r3Workspace="${tmp.dir}"></r3-generate>
   </target>

   <target name="clean">
      <copy todir="${templates.dir}">
        <fileset dir="${tmp.dir}/htdocs">
           <include name="**" />
        </fileset>
      </copy>

      <delete dir="${tmp.dir}" includeemptydirs="true" failonerror="true" />
   </target>
</project>

The Ibracadabra Show starts

July 27th, 2009 23 comments

Zlatan Ibrahimovic - FC Barcelona - Barça

How should a microblog search engine be?

July 15th, 2009 3 comments

LensLately people have been talking too much about searches on microblogging services. It’s been said that even Google is launching a new microblog search engine in the next few months. Some services exist already such as Twingly or Twitter Search (Summize), but none of them answer my queries as I would like. As a normal user, I would insert into a microblog search engine two type of queries: What’s happening right now? or What’s being said about ____ at the moment?, since it doesn’t make sense to look for information about the capital of Zimbabwe or if I want to know everything about a certain family of birds. It may be possible to guess one of these questions using a microblog search service, but I would use a classic search engine though.

Imagine that you’re a frustated Manchester United fan and you want to know what’s going on regarding your favourite football team. So you go to Twitter Search and look for the terms “Manchester United”. The results will leave you stunned because of the multiple kind of information found. Despite receiving hundreds of results each minute, 90% of the found messages are crap. You’ll get lots of duplicated messages, spam from the media Twitter accounts using twitterfeed, messages written in languages that you probably don’t understand (Chinese, Spanish, Italian, Arabic, …), messages written by “irrelevant” users and so so so much crap.

How should a microblog search engine be? Are we retrieving useful information from these kind of sources?

phpredis, 2 Fast 2 Furious

June 2nd, 2009 5 comments

phpredisRedis (REmote DIctionary Server) is a persistent key-value database with built-in net interface written in ANSI-C for Posix systems. Whilst it may at first seem like the wheel is being reinvented here, the need for something beyond a simple key-value database is pretty clear. It’s possible to use Redis like a replacement of memcached, with the main difference being the dataset is stored persistently – not volatile data – and Redis introduces new data structures such as list and sets. Furthermore, it implements atomic operations in order to interoperate with these data structures.

I released a PHP extension called phpredis a couple of weeks ago, which works as a PHP client API for Redis. The project is hosted at Google Code at the moment, and you can get the code directly from the SVN repository: http://phpredis.googlecode.com/svn/trunk/.

Despite a vanilla PHP client library already exists, I felt the need to write it since a PHP extension normally performs better and I wanted to make the most of Redis potential.

Let’s see a snippet of how to make a simple operation to Redis using the PHP client:

    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    $redis->set('key', 27);

    echo $redis->get('key'); // it should print 27

    $redis->incrby('key', 3);

    echo $redis->get('key'); // it should print 30

The code above was quite obvious, it stored a value associate to key and it increments its value by 3. Let’s see another snippet a bit more complex, for example using a list:

    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    $redis->lPush('list', 'val');
    $redis->lPush('list', 'val2');
    $redis->lPush('list', 'val3', 1);

    echo $redis->lPop('list', 1); // it should print val3
    echo $redis->lPop('list'); // it should print val2
    echo $this->lPop('list'); //it should print val

Notice that depending on the last optional parameter (0 by default) it’s possible to append/extract an element to/from the tail or to/from the head of the list.

There is a list including all the available methods. At the moment, I’m working on the implementation of more new Redis commands and on the support for complex data structures such as arrays and PHP objects.

Apart from phpredis, there are more client API for languages as Perl, Python, Ruby and Erlang. You can find this and more at the Redis project homepage. Redis has been written by Salvatore Sanfilippo who I’m chuffed to bits with.

Made in Heaven

June 1st, 2009 4 comments

Josep Guardiola - Portada de El Periódico de Catalunya

The dessert

May 27th, 2009 2 comments

FC Barcelona vs Manchester United - Champions League Final : Messi, Iniesta and Henry

The main course

May 23rd, 2009 1 comment

Liga 2008/2009 FC Barcelona - Barça