Esta semana he estado curiosamente rondando dos temas / ¿debates? que, no me lo puedo creer, son mutuamente incompatibles. Me hace gracia también que como muchos de los temas que surgen en las RRSS (p. ej., calidad en el código), son cíclicos y con más edad que Jordi Hurtado:
a) ¿Tienen sentido las entrevistas técnicas en las que el candidato tiene que escribir algoritmos de bajo nivel en una pizarra?
b) ¿El no-code y/o la inteligencia artificial nos va a sustituir a los programadores en algún momento (cercano)?
¿Pero cómo es posible que se puedan estar dando ambos comentarios simultáneamente?
Entrevistas técnicas: testeando habilidades distintas de las de tu futuro trabajo, de un modo distinto a como realizaras tu trabajo.
Vamos con el primer topic. Viene de este artículo de Gergely Orosz, Engineering Manager @ Uber:
Data Structures & Algorithms I Actually Used Working at Tech Companies
Para aquellos de vosotros un poco más ajenos a este mundo: hay una parte del syllabus de ingeniería de computación / software que es el estudio estructuras de datos y algoritmos para resolver distintos problemas (p. ej., ordenar datos de manera eficiente), íntimamente ligados a estas estructuras de datos. Por otro lado, es bastante típico en casi cualquier proceso de selección para un puesto de programación, el enfrentarse en directo, en una pizarra, a resolver un problema determinado con estas estructuras de datos y algoritmos. ¿Tiene esto sentido? La mayor parte de las veces, no.
¿Cómo de relevantes son estas pruebas de cara al trabajo que vas a realizar?
Normalmente... poco relevantes. Sucede lo siguiente, que explica muy bien Derek Jones (Software Engineer @ Google):
Algorithms were important because computers were not yet fast enough to solve common problems at an acceptable rate; developers knew the time taken to execute common instructions and instruction timings were a topic of social chit-chat amongst developers (along with the number of registers available on a given cpu). Memory capacity was often measured in kilobytes, every byte counted. (...) When it comes to algorithm implementation, developers are now spoilt for choice; why waste time implementing the ‘low’ level stuff when there were plenty of other problems waiting to be implemented.
Puedo hablar por mi propia experiencia, además: 2,5 años de doctorado + 6 como ingeniero software y prácticamente nunca he tenido que implementar ninguna de estas soluciones de bajo nivel "a mano". Es más, si es que hasta el mismo artículo de Orosz viene a decir eso mismo en múltiples lugares:
Caching, crawling, and handling the varying website load were much more difficult things to crack.
The difficulty was more on the product side, than anything.
Sorting is an algorithm family I rarely had an excuse to implement or needed to use in-depth.
Nadie dice que no sea interesante saber qué pasa bajo el capó, o que incluso pueda ser necesario en determinados momentos. Por ejemplo, el siguiente libro, aparte de ser todo un placer de lectura y un pozo de sabiduría, es una ayuda brutal en la comprensión de casi cualquier problema con bases de datos (es decir, en cualquier app) y computación distribuida :
Designing Data-Intensive Applications
¿Pero hacer que estructuras de datos y algoritmos sea una parte central en el proceso de contratación de una persona?¿Tiene sentido eso?
¿Acaso programamos de memoria?
Entonces, no, la mayoría de las veces se está testeando unas habilidades de la candidata que no van a ser relevantes en el puesto al que accede. Pero, incluso aunque lo fueran en determinados momentos... ¿y la manera en que se testean? ¿Implementar un algoritmo sin posibilidad de consultar (ni bibliografía ni por supuesto internet, esto es... de memoria), y en una pizarra? WTF.
No programamos de memoria, los entornos de desarrollo nos ayudan con la sintaxis y tenemos a mano todo el vasto conocimiento del universo cuando vamos a afrontar un problema. Una buena ingeniera, antes de esbozar una solución a un problema (tanto más si es un problema de rendimiento, en una parte crítica o a una gran escala), se repasaría lo que han hecho otros, "standing on the shoulders of giants". Que cuando programamos no somos code-monkeys que se lanzan a escribir lo primero que se les ocurre... por lo general hay un proceso de análisis previo.
Y luego... esto otro, para sorpresa de nadie, el performance anxiety:
Tech Sector Job Interviews Assess Anxiety, Not Software Skills
A new study from North Carolina State University and Microsoft finds that the technical interviews currently used in hiring for many software engineering positions test whether a job candidate has performance anxiety.
Y ya, para rizar el rizo, el colofón final, un sesgo:
...the format may also serve as a barrier to entire classes of candidates. For example, in our study, all of the women who took the public interview failed, while all of the women who took the private interview passed.
Y otro más...
...it gives a particularly large advantage to people who can afford to take the time to focus solely on preparing for an interview process that has very little to do with the nature of the work itself.
O sea, que no solo tenemos que andar adquiriendo habilidades y desechándolas en un entorno tremendamente líquido:
sino que además nos echamos una piedra más en la mochila sólo para pasar la entrevista.
¿Pero por qué se hacen estas entrevistas?
Pura inercia: busca en Google "tech interview questions". ¿Qué tipo de cuestiones aparecen?¿Cuáles son las que pregunta Google?
Virtue-signaling y elitismo. Es un pensamiento terroríficamente erróneo y funciona de la siguiente manera: si una candidata es capaz de superar esta complicada prueba de Trivial... ¿cómo no va a ser capaz de operar correctamente en el día a día?
Developers are drawn to complexity like moths to a flame — frequently with the same result.
Fundamentals of Software Architecture: An Engineering Approach
Al margen de la inmensa cantidad de candidatas válidas que dejas atrás, en el pecado llevas la penitencia porque con lo que sueles quedarte entonces es con una ingeniera que sobre-ingenieriza, que reinventará la rueda cada dos por tres, en lugar de ser pragmática.
Proxy más cómodo para evaluar: estas cuestiones son fáciles de preguntar y fáciles de verificar su resultado, hay poco que interpretar.
La (mi) alternativa
Si tengo la suerte de que el candidato ya tiene código público reciente (que ojo porque esto también es un sesgo hacia aquellos que tienen más tiempo disponible) y que el candidato considera que refleja bien cómo trabaja en la realidad (porque ojo también, cuando programamos por hobby, lo hacemos de una manera muy distinta a como lo hacemos en un entorno laboral), entonces uso eso como prueba técnica. Simplemente le pido que se lo cuente al equipo (y así veo como interaccionamos y algo de comunicación, aunque le sigo dando mucho más valor a la comunicación escrita que tenga sobre ese proyecto).
Si no, le pido que haga un trabajo en casa. Ese trabajo:
No requiere necesariamente que implemente nada, pero eso no quiere decir que sea más sencillo. Se trata de producir un documento, un análisis técnico, como los que hacemos en el equipo cuando vamos a implementar algo grande / complejo. El candidato elige de entre un conjunto de problemas que nosotros ya hemos resuelto, y realiza un análisis técnico de ese problema: objetivos, soluciones a considerar... (formato heredado de uno de los mejores jefes que he tenido ever, Diego García en Unlimiteck).
Por ejemplo, esta es una prueba técnica en Bistrohub:
No tiene fecha de entrega.
Para intentar no beneficiar a la gente que tiene más tiempo disponible, les pido que me cuenten cuántas horas han podido dedicar cuando lo entregan (y les animo a no dedicar más de una jornada total de trabajo).
Por último, vienen a contárselo al equipo con el que van a trabajar, que se lo habrá leído previamente y le harán algunas preguntas, como haríamos en una reunión normal y corriente.
Con esto testeo a las candidatas en un problema totalmente relevante al puesto al que aplican, buscando las cualidades que de verdad me interesan (cómo afrontan un problema antes de programar, cómo se expresan por escrito), en una configuración similar a las que tendrán, y de una manera un poquito más justa, no beneficiando en demasía a aquellas que tienen más tiempo para prepararse.
También tiene sus inconvenientes y es que la evaluación es algo más lenta y no siempre es cristalina, pero lo cierto es que me ha funcionado muy bien en cuanto a la gente que me ha traído al equipo.
En cuanto al GPT-3 y/o el no-code... nada nuevo.
Pensando en quitarse de encima el código, esto dice Robert C. Martin "Uncle Bob" en su "Código Limpio", en dos mil ocho:
Interfaces gráficas para programar existen desde los 70... O sea que el no-code verdaderamente no trae nada nuevo. Los intentos de programar sin código (porque ojo, no-code no es no-programar) son los Visual Programming Languages VPLs y en cuanto la lógica de negocio se complica un poco, acaban no siendo muy buena idea:
Visual History Of Visual Programming Languages
Eso no quiere decir que para pequeños usos, pequeñas integraciones, un Integromat no nos saque las castañas del fuego cómodamente.
Algo similar ocurre con GPT-3 (o cualquier otra herramienta de generación automatizada de código):
Me ha hecho especial gracia porque he visto un caso parecido con uno de los ejemplos reales que han dado vueltas por ahí en Twitter:
Atentos a cómo se va complicando la descripción de la app con lenguaje natural...
La IA nos va a venir genial de múltiples maneras a los que construimos software:
Automatizando el testeo de las apps, como centinela.ai de Unlimiteck.
Avisándonos de posibles errores mediante análisis semántico de nuestro código, como DeepCode.
O incluso permitiéndonos una subida del nivel de abstracción, de una manera similar a como cuando dejamos ensambladorvatrás y ahora programamos en lenguajes de más alto nivel.
Pero por definición, dudo muchísimo que podamos ser sustituidos alguna vez: un ingeniero de software no es simplemente un traductor a un lenguaje arcano como es el código. Para cualquier aplicación no trivial, hay complejidad intrínseca a la tarea de expresar su comportamiento con detalle. El código es precisamente el lenguaje formal que nos facilita expresar correctamente con todo detalle qué queremos que pase: con la IA permitiéndonos expresar eso como inferencias en lugar de como conjuntos de reglas en algunos puntos, o pudiendo hacerlo a niveles más altos de abstracción.