03 abril 2021

Japoneando 2016 y 2018 (y trabajos y esas cosas)

 


Alabados y alabadas sean vuecencias y vuecencios. Hete aquí que esta vez sí tengo una excusa de rechupete para haber permitido que el tejido arácnido campe a sus anchas por este blog: nada menos que una especie de bicho que dicen que pulula por ahí, que ha puesto el mundo entero patas arriba, y que por supuestísimo impidió cumplir con el ritual familiar del viaje a tierras nipónicas el año pasado (y tiene toda la pinta de que este año también). Así pues, no habiendo tal, no podía haber Japoneando 2020, ¿verdad?

Mas hete aquí que hace poco, el pasado día 1 de abril, se cumplieron cinco años de un majestuoso evento que cambió para siempre la manera en la que aporreo teclas a cambio de billetes con una "e" rara dibujada, lo que me ha hecho pensar que igual podría volver a escribir un poco sobre ello para añadir un par de piezas de información interesante que se quedaron en el tintero en aquellas calendas. De paso os hablaré un poco de mi situación laboral actual, y como premio a vuestra paciencia, pondré también un par de fotos de los viajes japonésidos de 2016 y 2018, que no fueron debidamente plasmados en este renqueante glob.


Las entrevistas, reloaded

Si habéis leído la entrada bloguera recién enlazada veréis que explicaba sucintamente en qué consistieron las siete entrevistas que me hicieron en Stack Overflow antes de fiarse de mí lo suficiente como para contratarme. Algunas de ellas eran un tanto complejas y requerían escribir/diseñar código en tiempo real, pero por requisitos de confidencialidad y tal no daba muchos detalles.

Pues bien, como podréis imaginar, a estas alturas ya me da bastante igual (además dudo mucho que sigan usando las mismas pruebas para las entrevistas de hoy en día), así que en rigurosísima exclusiva, he aquí una disección más detallada de las susodichas.

La primera entrevista fue introductoria con un señor de RRHH, así que pasamos directamente a la...

Segunda entrevista: sírvase usted comprimir

La segunda entrevista era la prueba de programación sencilla. Se me pidió lo siguiente: Escribir, en cualquier lenguaje de programación, una rutina de compresión "run-length encoding" de un byte. Es decir, si en los datos a comprimir aparece el byte 89 repetido 34 veces, en los datos comprimidos deben aparecer estos dos bytes: 34 89.

Pues bien, esta es la implementación que yo escribí, así en tiempo real, durante la entrevista (el lenguaje es C#, por supuesto):

byte[] RLE(byte[] input)
{
    var output=new List<byte>();

    byte lastChar = input[0];
    byte currentCount = 1;    
    
    foreach(byte theChar in input)
    {
        if(theChar == lastChar)
        {
            currentCount++;
            if(currentCount==255)
            {
                output.Add(255);
                output.Add(theChar);
                currentCount = 0;
            }
        }
        else 
        {
            output.Add(currentCount);
            output.Add(lastChar);
            lastChar = theChar;
            currentCount = 1;
        }
    }

    if(currentCount!=0)
    {
       output.Add(currentCount);
       output.Add(lastChar);
    }

    return output.ToArray();
}

No, no tengo memoria de ordenador. Lo que ocurre es que como no acababa de creerme lo que me estaba pasando (Stack Overflow entrevistándome, WTF) tomé nota de absolutamente todo.

Por supuesto no lo saqué a la primera, tuve que darle unas cuantas vueltas, pero tampoco tardé un tiempo exagerado. Algunas preguntas que me hicieron una vez terminé:

  • ¿Qué ocurre si la entrada es muy grande (del orden de GBs)?
  • ¿Puede este algoritmo producir una salida que sea más grande que la entrada?
  • ¿Para qué tipo de entradas es apropiado este algoritmo?
  • ¿Qué cambios habría que hacer si quisiéramos codificar repeticiones de bytes? (por ejemplo que "ABAB" produjera "2 AB")
Lo que no apunté es lo que yo respondí a estas preguntas, pero bueno, ahora digo eso de "lo dejo como ejercicio para el lector" y quedo la mar de bien.

Tercera entrevista: sírvase usted permutar

La tercera entrevista era la de programación compleja: Escribir una rutina que genere todas las permutaciones posibles de una colección de datos. Ahí es nada.

Aquí debo confesar que hice un poquito de trampa, pero sólo un poquito. Resulta que en cuanto supe que Stack Overflow me iba a entrevistar me lancé a buscar información sobre la compañía por todos los internetes. Uno de los sitios que visité fue Glassdoor, una wepe en la que la gente publica opiniones y datos sobre empresas en las que trabaja o ha trabajado; uno de los datos que se puede publicar es precisamente preguntas de entrevista, y casualmente, la susodicha permutatrónica pregunta estaba publicada por lo que yo ya "medio esperaba" que me la iban a preguntar y venía preparado.

Pero eso sí, cuando vi la pregunta en Glassdoor NO busqué directamente la solución, sino que me tomé un tiempo para resolverla yo mismo tranquilamente y a mi ritmo (al fin y al cabo me convenía estar "entrenado" para este tipo de preguntas). Así que la "trampa" no fue proporcionar una solución que no era mía, sino haber resueltto la pregunta antes de la entrevista y sin el estrés asociado a la misma (y durante la entrevista no copié la solución, sino que la escribí desde cero otra vez).

Y en cuanto a mi implementación, hela aquí, como dije en la entrada de hace un lustro está basada en recursividad (quito un elemento de la colección, vuelvo a ejecutar la rutina, y añado el elemento a todas las permutaciones devueltas), es C# con uso y abuso de LINQ:

IEnumerable<int[]> GetAllPermutationsOf(int[] input)
{
    if(input.Length<=1)
        return new[] {input};

    var output = new List<int[]>();

     foreach(item in input)
     {
         var inputWithoutItem = input.Except(new[] { item });
         var permutationsWithoutItem = GetAllPermutationsOf(inputWithoutItem);
         foreach(var permutation in permutationsWithoutItem) 
         {
             var permutationWithItem = (new[] {item}).Concat(permutation);
             output.Add(permutationWithItem);
         }
     }

     return output.ToArray();
}

Y en cuanto a las preguntas post-cosa:
  • ¿Cómo comprobarías que la salida es correcta?
  • ¿Hasta qué tamaño de entrada es capaz de tratar esta rutina?
  • Aproximadamente, ¿cuánto tarda la rutina en ejecutarse en relación al tamaño de la entrada?
Y tras ello, pues eso, prueba superada de forma 99% honesta.

Cuarta entrevista: sírvase usted pingpongar

Sí, en efecto, la cuarta entrevista fue esa en la que fracasé estrepitosamente. Vamos a ver qué pasó.

El tema eran las bases de datos. La pregunta inicial: Diseña una estructura de base de datos que almacene resultados de partidas de ping-pong. Algo en principio bastante inocente. Este es el pseudo-SQL que acabé sacando:

create table Players (
    Id int not null identity primary key,
    FullName nvarchar(max) not null
)

create table PlayerMatch (
    MatchId int,
    PlayerId int,
    TeamNumber int
)

create table Matches (
    Id int not null identity primary key,
    Team1FinalScore int not null,
    Team2FinalScore int not null,
    WinnerTeamNumber int not null, --1 or 2,
    IsDoubleMatch bit,
    Date datetime
)

Todo bien hasta que de repente llegó el "fatality". Nada menos que esto:

Escribe una consulta que devuelva los primeros cinco jugadores por porcentaje de victorias (partidas ganadas/partidas jugadas), pero sólo los que hayan jugado al menos diez partidas.

To-ma-cas-ta-ña.

Y eso, lo que ya expliqué en su día: me quedé bloqueado y no fui capaz casi ni de empezar. Y me dio mucha rabia porque después de la entrevista, al día siguiente ya más tranquilo, fui capaz de sacarlo tras dedicarle un rato.

Por suerte el entrevistador entendió que fue un bloqueo situacional (¿ese término existe?), y eso combinado con el hecho de que realmente no necesitaban un gurú del SQL permitió que el proceso entrevistático continuara.

Quinta entrevista: sírvase usted buscar

La quinta entrevista consistía en esbozar una característica de sitio web completa. En concreto: Diseña, de forma simplificada, una posible implementación del cuadro de búsqueda de Stack Overflow. Es decir, que tenía que tener en cuenta todas las capas de aplicación necesarias.

Esta no me costó mucho. Mi solución tenía un poco de HTML+JavaScript (Angular, que es lo que yo tenía fresco en ese momento)...

<input type="text" id="searchBox"/>
<ul id="searchResults" style="visibility: hidden";>
<li ng-repeat="result in searchResults">{{result}}</li>
<p style="redAndError">Error when retrieving data!</p>
</ul>

$("#searchBox").on("keypress", function(element, key) {
    if(element.text.length < 3)
return;

    $http.post("server/search?text="+element.text)
        .success(function(data) {
            scope.searchResults = data.results;
            $(element).visible = true;
        }.failure(function(data) {
            
        }
});

...más un poquito de C#...

public ActionResult Search(string text)
{
    var results = searchEngine.GetSearchResults(text);
    return Json(results);
}

public string[] GetSearchResults(string searchText)
{
    searchText = searchText.Where(ch => char.IsAlphaOrDigit(ch)).ToString();

    var questionResults = db.Questions.Where(q => q.Title.Contains(searchText));
    var answerResults = db.Answers.Where(q => q.Title.Contains(searchText));
    var tagResults = db.Tags.Where(q => q.Name.Contains(searchText));

    var results = questionResults.Concat(answerResults).Concat(tagRsults)
        .Distinct().ToArray();
    return results;
}

...y un diseño de base de datos que era simplemente las tablas Questions, Answers y Tags con un campo Title/Name. Como veis todo muy cogido por los pelos pero suficiente para demostrar que sabía de lo que hablaba.

No tengo apuntadas preguntas posteriores para esta entrevista pero recuerdo una: ¿Cómo implementarías la búsqueda de forma que soporte etiquetas con guiones o puntos cuando éstos no se incuyen en el texto buscado? (ejemplo: "sqlserver" debe encontrar "sql-server", "aspnet" debe encontrar "asp.net"). Mi respuesta: la solución más eficiente es almacenar el nombre de la etiqueta dos veces, una de ellas normalizada (sin caracteres especiales) que es la que se usará para las búsquedas. ¿Pero esto no incrementará el espacio usado por la base de datos? Sí, pero para un sitio como Stack Overflow lo importante es la velocidad, y hoy en día los discos duros son baratos. Aparentemente, respuesta correcta.

Sexta entrevista: sírvase usted comprar

La última entrevista de caracter técnico fue la de diseño de un producto a alto nivel. La pregunta, de forma aproximada: Imagina que eres un "product manager" en Amazon y te piden que diseñes la funcionalidad del botón de compra en un click. ¿Qué tendrías en cuenta? Digo de forma aproximada porque esta prueba fue más bien una conversación en la que a veces yo daba algunas ideas y otras veces el entrevistador daba otras y yo tenía que desarrollarlas. Algunas de las ideas que surgieron:
  • Es muy fácil que el usuario se confunda y pulse el botón sin realmente querer hacer la compra, lo cual resultará en muchas peticiones de cancelación, ¿cómo gestionamos esto? Esta era una pregunta de "idea feliz" que por suerte tuve: cuando se pulsa el botón en realidad no se gestiona el pedido inmediatamente, sino que se espera unos segundos, durante los cuales el usuario puede pulsar el botón de cancelación y aquí no ha pasado nada. Tuve esa idea porque había leído en algún sitio que así es precisamente como funciona el botón de "cancelar envío de mensaje" de GMail.
  • ¿Qué es necesario para que el usuario vea y pueda usar el botón? La cuenta debe tener configurado un método de pago y una dirección de envío; si no, al pulsar el botón se puede mostrar un aviso tipo "gracias por tu compra pero primero debes terminar de configurar tu cuenta".
  • ¿Qué pasa si el usuario ya tenía otros artículos en el carro de compra? Mejor dejar el carro de compra como está y realizar el pedido sólo para el artículo que se está visualizando, lo contrario sería bastante confuso.
  • ¿Y si el usuario quiere comprar más de una unidad del artículo? En ese caso lo más probable es que el usuario no use el botón de compra en un click sino que use el carro de compra de manera tradicional. Además, si implementamos el "período de gracia" mencionado antes se pueden agrupar varios clicks en un mismo pedido.
  • ¿Qué métricas podrían usarse para comprobar si la funcionalidad tiene éxito? Porcentaje de pedidos y devoluciones con ambos métodos (botón de un click y carro de compra), cuántos usuarios pulsan repetidamente el botón, cuántas quejas hay por la funcionalidad.
  • ¿Cómo se podría segmentar el uso para las métricas? Usuarios novatos vs avanzados, artículos físicos vs digitales, ubicación de los compradores, artículos baratos vs caros.
Y así, pasando esta entrevista básicamente ya estaba dentro, ya que la última fue con el jefazo de ingeniería que simplemente quería saber quién era ese españolito que estaba armando tanto revuelo.

Historias sorprendentes: de cómo me destoptalicé para seguidamente automatticarme

Habiéndoos iluminado con los entresijos de las entrevistas para mi primer trabajo usamericano-remoto, procedo a contaros qué pasó con el segundo y cómo llegué al actual tercero.

Acto 1: Selección

En Japoneando 2019 os explicaba que en noviembre de 2017, a los 19 meses de empezar a stackear, la delicada situación económica de la empresa forzó el despido del 25% de la plantilla entre los que por desgracia me encontraba yo. A los pocos días, y casi simultáneamente, ocurrieron dos cosas:
  1. Me puse en contacto con un ex-colega de Stack que se había ido a Toptal unos meses antes, por si me podía más o menos enchufar en la susodicha. Me dijo que en efecto estaban buscando gente y que movería algunos hilos.
  2. Recibí un email de una señora de RRHH de Automattic, diciéndome que a través de una persona conocida en Stack habían recibido una lista con los nombres y direcciones de email de las personas despedidas (antes de hacer eso Stack nos pidió permiso y yo accedí, ojo) y me invitaban a iniciar un proceso de selección para uno de los puestos de ingeniería que tenían vacantes, saltándome la (aparentemente larga) cola de la gente que se había apuntado a través de la web de la empresa. Por supuesto acepté.
Empecé así dos procesos de selección simultáneos, y aunque el de Automattic iba bien, al final ganó Toptal porque gracias a la recomendación de mi amigo fue un proceso abreviado en el que me salté las entrevistas técnicas. Me despedí amistosamente de mi contacto en Automattic y en diciembre de 2017 empecé a trabajar en Toptal.

Acto 2: Trabajando

En Toptal no estaba mal, aunque yo encontraba eso del Ruby (on Rails, concretamente) bastante raruno y no acababa de convencerme eso de que la empresa no corriera con ningún gasto más allá del sueldo y que no hubiera ningún tipo de encuentros presenciales (quizá estaba mal acostumbrado por mi experiencia en Stack), pero bueno, eran cosas "sobrevivibles". 

Y aunque en general la gente con la que trabajaba era muy maja, hubo algún episodio raruno como aquel señor que sabía mucho (no lo digo sarcásticamente, el tío era bueno de verdad) al que le pregunté por chat cómo funcionaba cierta parte del código un tanto enrevesada, tras varios intentos no conseguí entenderlo y sugerí que pasáramos a videoconferencia, pero se enfadó y dijo "no, tú no tienes ni la más básica idea de programación y no quiero hablar más contigo". Os lo juro. Bastante perplejo, le dije a mi jefe (o "team lead" como lo llaman ellos) lo que había pasado y su reacción fue simplemente... "bueno, voy a intentar explicártelo yo". Ciertamente no era lo que yo esperaba.

Pero en fin, yo tengo un caracter bastante tranquilón y cosas como esa no me afectan demasiado. Seguí con lo mío hasta que a los casi exactamente dos años pasó algo que lo puso todo patas arriba otra vez.

Acto 3: PANIK

No sé si es que realmente mi intelecto no fue capaz de interiorizar las peculiaridades del Ruby ese. No sé si inconscientemente me saboteé a mí mismo por el bajón de haber perdido el trabajo en Stack (¿tras dos años? Jolineses...) Pero el caso es que exactamente el día 2 de enero de 2020, durante lo que yo pensaba que iba a ser una reunión rutinaria, mi jefe me comunicó que mi rendimiento no era el esperado y que me ponían en un "performance improvement plan" de un mes, uséase: chaval, o espabilas o de patitas en la calle.

Acepté (qué remedio, la alternativa era dejar el trabajo casi en tiempo real) pero teniendo muy claro que aquello no pintaba nada bien. Así que frenéticamente rebusqué en el historial de mi correo el que había sido mi contacto de Automattic durante el proceso de selección con los susodichos, lo encontré, escribí un mensaje en plan "Hola, que después de dos años lo he pensado mejor y me gustaría volver a probar suerte con Automattic, ¿podemos continuar donde lo dejamos?", lo envié y recé al dios de los ateos para que ese señor del que usted me habla siguiera en la empresa.

Y se ve que el ddla me escuchó... porque recibí una respuesta tal que "Hola, pues sí, por nosotros encantado; en breve recibirás acceso a un repositorio de GitHub e instrucciones para realizar la prueba de programación".

Antes de seguir, un inciso. No voy a entrar (en esta entrada al menos) en los detalles del proceso de selección de Automattic, pero básicamente se compone de tres fases: entrevista inicial vía chat, prueba corta de programación a realizar en diferido (típicamente corregir y optimizar un plugin "ficticio" de WordPress) en un tiempo de unas seis horas, y proyecto medio/largo pagado (¡sí, pagado!) a realizar también en diferido en un tiempo de unas 40 horas. Un sistema bastante peculiar en el que si no eres contratado nunca llegas a videohablar con nadie.

Pues bien, dos años atrás había superado la entrevista inicial y la primera prueba de programación, pero justo cuando iba a empezar la segunda recibí la oferta de Toptal. Lo que me ofreció Automattic en esta "segunda ronda" era saltarnos la entrevista inicial pero hacer otra vez la susodicha primera prueba (distinta, claro está). Acepté encantado, claro está también.

Y ocurrió que en una especie de coincidencia cósmica, casi el mismo día que Toptal me comunicó "prueba no superada, adiós muy buenas" como yo me venía temiendo, Automattic me comunicó que había superado la primera prueba de programación y daba comienzo la segunda.

Acto 4: Final feliz

La segunda prueba de programación está pensada para que la haga gente que ya tiene otro trabajo, que la hará sacando ratitos de aquí y allá, y que por tanto llevará semanas o incluso meses para ser completada (mientras el candidato dé señales de vida al menos una vez por semana, todo bien). Pero como yo estaba recién desempleadito, tardé sólo un par de semanas. Pasadas las cuales recibí el mensaje chatero de la muerte (o más bien, el que "me devolvió a la vida"): muy bien, nos mola tu gramola, en breve recibirás una oferta para unirte a nosotros. Y fue casi dicho y hecho: recibí/acepté la oferta el 26 de febrero, y el 2 de marzo (el 1 era domingo, cachis) me uní a Automattic, concretamente al equipo encargado de WooCommerce.

Y bueno, visto en perspectiva un año después, puedo decir que casi me alegro de que Toptal me diera la patada. En Automattic me han comprado un ordenador nuevo (es un Mac pero bueno, tampoco me voy a quejar, y de todas formas le he puesto Windows), me pagan el alquiler de la oficina a la que huyo de los decibelios infantiles que pueblan mi casa, programo en PHP (que no es lo ideal pero es mil veces mejor que el Ruby ese, en mi opinión claro), hay un par de reuniones de equipo/empresa al año (cuando no hay pandemiomiums, por supuestérrimo) y no hay gente que sabe tanto que incluso sabe demasiado. Ah, y he recuperado el sueldo que tenía en Stack (en Toptal, encima, era inferior).

Y colorin colorado... espero que este cuento no termine tan abruptamente como los dos anteriores, la verdad (por ahora no parece que vaya ni remotamente a ser el caso).

Ahora sí: ¡Japoneando (en tiempos pretéritos)!

Puues lo dicho: como recompensa a vuestra paciencia (¿de verdad aún seguís ahí?) procedo a publicar unas cuantas fotos de los viajes niponizantes de 2016 y 2018, que no recibieron la correspondiente entrada bloguera "because reasons". Revisar estas fotos en un momento como este ha tenido su puntito doloroso, así que espero que os gusten.


- ¡Aquí está! Gracias, qué haría yo sin ti
- Cuando me dijiste que necesitabas ayuda para "encontrar una puerta trasera de difícil acceso" me imaginaba algo más cibernético, la verdad...


- Pues lo ha hecho usted genial, ¡contratado!
- Gracias, pero creo que ha habido una confusión. Cuando vi la oferta para un "artista gráfico" pensaba más bien en Fotochof y maquetación de internetes.


- ¿Qué es esto?
- Un reactor de fusión, pero está estropeado y... no cumple con su fusión.
- Espera, ¿has desarrollado tecnología del siglo XXIII sólo para poder hacer un chiste malo?
- No es culpa mía, me lo ha contagiado un tío español que tengo.


- En este estudio no cobraréis por vuestro trabajo, pero recibiréis mucha visibilidad en la industria, lo que os permitirá...
- ¡Eh, quieto parao, Wenceslao! Que esa milonga ya nos la conocemos.


- ¿Qué? ¿Se oye algo?
- Están negociando un soborno del copón para construir una megaurbanización en mitad de la Plaza Mayor. Con esto los hundimos, no volverá a votarlos nadie.
- Huy... tú eres nuevo en esto de la política, ¿verdad?


- Sí, la moto está muy bien, pero yo preferiría una como la de la abuela...
- Te aguantas, aquí el cubicaje va en función de la edad.


- ¡Mamáaaa! ¡Que ese coche está atravesando la cuarta dimensión y papá está ahí impertérrito!


- Pues sí, el coche me lo estoy comprando a plazos, ¿cómo lo has adivinado?


- Este trabajo está muy bien, pero encuentro que la gente aquí está muy polarizada... como si todo fuera o blanco o negro.


- ¿Estás seguro de que nos teníamos que bajar en Liliput? Creo que no podremos ni salir de la estación...


- Qué ciervo más mono, ¿de dónde es?
- Uf, me da miedo responder pero... de Nara.
- Pues... gracias.
- ¡Aaargh, mira que lo sabía!


- ¡Ajá! ¡Hemos pillado a Wataru con las manos en la masa!


- Menudo pringao, eso es algo que a mí nunca me pasará.


- Hemos ido al parque y se ha montado un pollo...
- ¿Ah sí? Cuenta, ¿qué ha pasado?
- Pues lo que te estaba contando, que se ha montado un pollo... en mi brazo.


- Me temo que Raito se ha roto... ¿aún tenemos el ticket de compra?


- Tío, te lo juro, no me puedo quitar Japón de la cabeza.
- Yo tampoco, ¡pero con mucho más estilo que tú, juo juo!


- Cuidadín, un respeto con el ingeniero jefe en escaleras a ninguna parte.


- Atentos... en cuanto el camarero doble la esquina, nos levantamos y salimos pitando en plan simpa de la muerte. Preparados, listos...


- Señoras y señores, esta es Mayu, la sobrina más guapísima de todo Japón.
- Uf, quita, yo me voy, que todos los años haces la misma foto y ya cansa.


- Tirad fuerte de la campana, que si no el camarero no vendrá nunca.



- ¡Mi teléfono está ardiendo y es culpa tuya!
- ¿Y a mí qué me cuentas? Te dije bien claro que podías usarlo pero que no te metieras en foros de política.


- ¡Votad al señor de los guantes blancos! Es el único político al que nunca pillarán robando (porque gracias a los guantes no dejará huellas)


Takoyaki Wanaka, parada obligatoria en toda jornada de deambulamiento por Osaka que se precie.


- Es la niña la que elige el pastel, y es el pastel el que elige quién quiere que sea la niña el pastel.
- ¿Pero qué...? ¿De dónde ha salido este señor tan raro?


En España tenemos a mucha gente que se pasa la jornada laboral sin hacer nada. En Japón están más avanzados y han automatizado el proceso.


- Japón mola mucho. Es la leche, es la p...
- ¿La pera?
- Eeeh... sí, sí, eso mismo.


- Buenas, quiero un ordenador que sea realmente ÉPICO.
- No se hable más, tengo exactamente lo que necesita.


- ¿Que quieres jugar al Space Invaders? Bueeeno, cómo te gustan los juegos retro con su pantallita y su mandito y... ¡ARGH!


Y hasta aquí puedo leer, digo, escribir. Portaos bien y quizá vuelva a publicar algo un eón de estos.