<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Código Banana: El blog de Platanus - Medium]]></title>
        <description><![CDATA[Sobre desarrollo y emprendimiento desde nuestra experiencia en Platanus. https://platan.us - Medium]]></description>
        <link>https://medium.com/platanus?source=rss----71beb3926ac5---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Código Banana: El blog de Platanus - Medium</title>
            <link>https://medium.com/platanus?source=rss----71beb3926ac5---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 04:24:42 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/platanus" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[El computín que tiene el 2%]]></title>
            <link>https://medium.com/platanus/el-comput%C3%ADn-que-tiene-el-2-d37585d96d71?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/d37585d96d71</guid>
            <category><![CDATA[startup]]></category>
            <dc:creator><![CDATA[Andrés Matte]]></dc:creator>
            <pubDate>Thu, 26 Nov 2020 13:44:16 GMT</pubDate>
            <atom:updated>2020-11-26T13:44:16.170Z</atom:updated>
            <content:encoded><![CDATA[<p>He conversado con hartas y hartos Ingenieros de Software recién egresados de la universidad.</p><p>Cuando me cuentan que un tipo les ofreció hacer una app para armar su negocio, una de mis primeras preguntas es:</p><p>— “¿Y qué te ofreció?”<br>— “Un 2% de la empresa”<br>— “Shiu… la estai cagando compadre…”</p><p><a href="https://plata.news/blog/el-computin-que-tiene-el-2/">Seguir leyendo</a></p><p><a href="https://plata.news/blog/el-computin-que-tiene-el-2/">El computín que tiene el 2%</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*GDnbk1VUIbWIQpZImPKRgQ.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d37585d96d71" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/el-comput%C3%ADn-que-tiene-el-2-d37585d96d71">El computín que tiene el 2%</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Qué hace un Trainee en Platanus]]></title>
            <link>https://medium.com/platanus/qu%C3%A9-hace-un-trainee-en-platanus-87684ab3af0d?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/87684ab3af0d</guid>
            <category><![CDATA[trainee]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[internships]]></category>
            <category><![CDATA[platanus]]></category>
            <dc:creator><![CDATA[Milan Rafaeli]]></dc:creator>
            <pubDate>Thu, 02 Jul 2020 19:04:14 GMT</pubDate>
            <atom:updated>2020-10-04T14:57:37.237Z</atom:updated>
            <content:encoded><![CDATA[<p>Hoy se cumple un año desde que hice mi práctica en Platanus. Viendo el número de personas que está postulando para el próximo período de <a href="https://platan.us/jobs">trainees</a> me motivé (quizás un poco tarde), a contar mi historia y la experiencia que tuve durante el programa.</p><p>La verdad es que cuando postulé no me tenía mucha fe. Soy ingeniero comercial, y a pesar de que tomé varios cursos de programación en la u y siempre me ha gustado harto el mundillo de las startups, <em>nica</em> pensé que podía llegar a quedar en una empresa full de desarrollo de software tan bacán como Platanus. Postulé igual, total no perdía mucho… y para mi sorpresa, quedé.</p><h4>Primer Día</h4><p>Ese día llegué 15 min antes, estaba bien nervioso, no tenía idea de qué iba a hacer o si me la iba a poder, era mi primera experiencia de desarrollo real en una empresa.</p><p>Entré a la oficina y me recibió el equipo entero. Siempre había tenido una imagen muy distinta de cómo sería mi primer trabajo. Me imaginaba todos muy formales, con camisa y corbata trabajando en cubículos apretados.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/828/1*jlMIBE3sOZzwRa9MCHxGYA.png" /><figcaption>Cómo me imaginaba en la oficina</figcaption></figure><p>En Platanus no es así (en mi casa todavía no pueden entender que vaya con <em>shorts</em> y chalitas a la pega). Todos son muy buena onda, y da lo mismo si eres founder, developer o practicante todos trabajamos en el mismo lugar. De hecho no hay ningún puesto con nombre, todos se pueden sentar donde quieran y eso hace muy fácil integrarse rápido en el equipo.</p><p>Después de las presentaciones y el infaltable <em>tour</em> por el lugar, me dieron una mini clase de cómo funcionaban algunas de las cosas entretes que hay en la oficina, como <a href="https://blog.platan.us/qu%C3%A9-hemos-aprendido-de-un-mono-que-pone-las-reglas-en-la-oficina-61ba5f3fcec6">Ham</a> y <a href="https://blog.platan.us/jugando-a-tener-un-kiosco-684ec5232bcc">Refreshments</a>. Se me pasó rapidísima la mañana en todo este proceso de <em>setup.</em></p><p>Ya con todo listo y antes de seguir con la próxima etapa, fui a prepararme un cafecito. Mientras esperaba la taza, entra la Jesús (que hasta ese minuto no la había conocido), se acerca a saludarme y me pregunta cómo estoy, yo medio nervioso respondo con un:</p><blockquote><em>“Muy bien, ¿Y </em><strong><em>usted</em></strong><em>?…”</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W1KWLWBcLKVYLKYI0r1sYg.jpeg" /></figure><p>Primer día y ya la había cagado. No pasó piola. <strong>Slack estaba en 🔥</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/506/1*5WLrT793aXGHR0e3M5XqmA.png" /><figcaption>Perdón Jesús</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/630/1*uXYYWxwfMfS0VOk3qgXnxw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/316/1*ikcN0bTgGQ5tGTlaAWtvWA.png" /></figure><p>Hasta el día de hoy me molestan por haber tratado de usted a la Jesús.</p><h4>El proyecto</h4><p>A las 12 tuve mi primera reunión para hablar sobre el proyecto en el que trabajaría el resto del semestre.</p><p>Sorteo Amigo Secreto es una página bien conocida que tiene Platanus. Todos los años llegan millones de usuarios de todo el mundo y este año querían probar algo nuevo: Una plataforma para que los usuarios del sorteo pudieran encontrar regalo fácilmente.</p><p>Desde el día uno ya estaba motivado. Me identifiqué al tiro con el problema que queríamos resolver. Siempre he tenido dolores de cabeza cuando tengo que pensar en regalos para mis amigos, especialmente cuando se trata de un regalo para mi polola. Pero por lejos lo que más me motivó, fue la forma en que me hicieron parte del proyecto.</p><p>Algo que me encanta de Platanus, es que uno no viene solo a programar sino a <strong>resolver un problema</strong>. Me llamó mucho la atención que incluso como practicante, mi opinión y mis ideas eran importantes para la construcción del producto final. Mas encima lo que estaba haciendo iba a ser usado por miles de personas!</p><h4>Resultados</h4><p>Terminamos el semestre con algo en producción: el <a href="https://bazar.sorteoamigosecreto.com/landing/show?name=Platanus">Bazar del amigo secreto</a> (incluso me dejaron ponerle nombre). Tuvimos más de 220.000 usuarios!</p><p>En todo este proceso aprendí montón. Desde cómo trabajar con diseñadores hasta metodologías de desarrollo. Pero lo más importante fue aprender sobre cómo llegar a puerto con una idea a través de iteraciones pequeñas y mejoras continuas.</p><p>Lo más difícil de estudiar y trabajar part-time durante este proceso fue balancear bien los tiempos. Era tan entretenido el proyecto que se hacía fácil dedicarle más tiempo a éste y dejar un poco de lado el estudio. Pero eso mismo es lo que lo hace tan especial.</p><p>Esta experiencia me sirvió un montón para darme cuenta lo mucho que me gusta desarrollar software y crear productos bacanes. Así fue como terminé trabajando en Platanus, donde ya voy a cumplir un año. Jamás lo hubiese imaginado un tiempo atrás mientras estudiaba para mis ramos de finanzas en comercial.</p><p>Si te gusta la computación y te hace falta un empujón para saber si es lo que quieres hacer, te recomiendo 100% que postules al <a href="https://platan.us/jobs">programa</a>. Siempre estamos buscando postulantes y personas bacanes para que se unan al equipo!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=87684ab3af0d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/qu%C3%A9-hace-un-trainee-en-platanus-87684ab3af0d">Qué hace un Trainee en Platanus</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cabras ¿Por qué nos tiramos para abajo?]]></title>
            <link>https://medium.com/platanus/cabras-por-qu%C3%A9-nos-tiramos-para-abajo-841b2e1681fb?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/841b2e1681fb</guid>
            <category><![CDATA[mujeresemprendedoras]]></category>
            <category><![CDATA[motivación]]></category>
            <category><![CDATA[síndrome-del-impostor]]></category>
            <category><![CDATA[tecnología]]></category>
            <category><![CDATA[mujeres-en-tecnología]]></category>
            <dc:creator><![CDATA[Fernanda Sepulveda]]></dc:creator>
            <pubDate>Fri, 19 Jun 2020 22:32:25 GMT</pubDate>
            <atom:updated>2020-06-19T22:32:24.995Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/933/1*pqhjtdOBUkBFsWZ2JCsZDA.png" /><figcaption>Ilustración por <a href="https://icons8.com/">https://icons8.com</a>.</figcaption></figure><p>No me malinterpreten. Cuando escribo esto no intento caer en el cliché de “Amiga <em>eris</em> seca hazlo público”. O quizás sí. La verdad es que quiero exponer algo que me ha estado dando vueltas en el último tiempo: para las mujeres en STEM, principalmente en el área <em>techi</em>, existe una tendencia a <em>echarnos para abajo</em> → vale decir, no aceptar y renegar nuestras propias capacidades.</p><p>El síndrome del impostor es algo que se da en mujeres, y es principalmente un problema de género, pues se explica en gran parte por cómo la sociedad inculca ciertos comportamientos o expectativas. Y muchas veces la sociedad se esmera en hacernos sentir que nuestra opinión no vale mucho o estamos equivocadas. Porque “no sabemos lo suficiente”. Pero<strong> ¿es realmente así?</strong>.</p><p>Es ampliamente sabido que el porcentaje de mujeres en roles técnicos es bajo. Un estudio realizado por Fundación Por una Carrera y Clio Dinámica Consultores determinó que las mujeres egresadas de carreras técnicas en Chile entre los años 2013–2017 era aproximadamente un 12% (frente al 88% de egresados hombres). No quiero ahondar en por qué hay tan pocas mujeres en STEM, si no que quiero ahondar en cómo hacer un mejor lugar para el pequeño 12% que decidió seguir una carrera en el área.</p><p>¿Si ya sabes programar no es eso un logro? ¿que hayas pasado muchos cursos en el área no es un logro?¿que tengas un título o que estés por sacarlo no es un logro?. Y no, no creo que sean situaciones atribuidas a la suerte. Pensamientos del tipo “ah, es que ese ramo lo pasé porque en la segunda prueba justo entró lo que había estudiado la hora antes, tuve mucha suerte”. <strong>STOP</strong>. Ese ramo lo pasaste por todo el contexto y trabajo que hay detrás también.</p><p>Volviendo a ese mismo tema, hay personas y personas: aquellos que les gusta dedicarse de lleno a lo que hacen y hacerlo perfecto (perfeccionistas) y otras más dispersas que prefieren dedicarse dependiendo de sus gustos o inquietudes en hartas cosas a la vez. Una alumna matea, que se preocupa de pasar bien sus ramos y que tiende a ser perfeccionista, ¿en qué minuto va a tener tiempo para aprender el último framework de moda de javascript?.</p><p>Muy probablemente esa alumna terminó el <em>getting started</em> de la documentación y no le dio el tiempo para seguir aprendiendo por los miles de <em>quehaceres</em> de la vida académica. Por eso si le preguntan “cachas X framework” te van a decir que no. Sin embargo, esa alumna pasó cursos teóricos mucho más difíciles. Continuar más allá del <em>getting started</em> es solo cosa de tiempo, porque la capacidad y background de conocimientos ya están ahí. Ya tienes los logros y tienes que partir validándote a ti misma para dar el siguiente paso.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/933/1*qLRqTR22di7sqWcQdw7z4w.png" /><figcaption>Ilustración por <a href="https://icons8.com/">https://icons8.com</a>.</figcaption></figure><p>Les recomiendo el libro <em>The Secret Thoughts of Successful Women: Why Capable People Suffer from the Impostor Syndrome and How to Thrive in Spite of It </em>— de Valerie Young. Para cualquier mujer en cualquier etapa de su carrera. Me gusta porque no es el típico libro <em>bullshit</em> de “¿cómo ser exitosa?” si no que es lo contrario: <strong>Ya eres exitosa, ahora date cuenta</strong>.</p><h3>Hablemos un poco de emprendimiento</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/933/1*DHYw5bLAJO9JCYgKdBfL5w.png" /><figcaption>Ilustración por <a href="https://icons8.com/">https://icons8.com</a>.</figcaption></figure><p>En 2014 solo existía un 3% de mujeres en cargos de CTO en EEUU, según un estudio de Forbes . Han pasado 6 años desde entonces y la situación no ha cambiado tanto, y bueno, no estamos en EEUU. En el paper del 2017 “<em>Funding challenges of Latin American women start-up founders in the technology industry” </em>se hizo un estudio con datos de StartUp Chile, donde se analiza que en general las mujeres emprendedoras prefieren no levantar capital en base a este tipo de inversión, y que esto podría ser una causa de la baja cantidad de postulaciones que existen (además de otros factores que se analizan también en ese artículo).</p><p>Un dato más reciente es que en Platanus Ventures, del total de postulaciones solo un 15% de <em>founders</em> o socias son mujeres. La diferencia aquí con este dato y los anteriores, es que ya no estamos enfocados solo al puesto de CTO, si no que podría ser cualquiera de los roles típicos de un socio<em> </em>en un startup. El número de mujeres postulando a Platanus Ventures con el rol de CTO es contado con las manos (un porcentaje cercano al 2%). A pesar de ser cifras bajas, tengo fe de que estos números aumenten.</p><p>Lo cierto es que mientras más mujeres emprendedoras y en cargos gerenciales hayan, más posible es lograr una igualdad real, pues nos acercamos más a la equidad (según algunos estudios algo antiguos sobre el área). Sin embargo, no es algo fácil, porque el área del emprendimiento al menos en Chile sigue siendo marcadamente <em>masculina. </em>En el mundo de emprendedores chilenos aún está muy marcado el “business man” de traje y corbata. Hay estudios que sostienen que una cultura de emprendimiento más andrógeno permite más inclusión de la mujer (esto lo tratan más en detalle en este artículo “<em>Entrepreneur‐mentality, gender and the study of women entrepreneurs</em>”, se basa mucho en las comparaciones de lo “femenino” y “masculino”).</p><h3>Ya hablamos del éxito, ahora hablemos del fracaso</h3><p>Si sólo con leer la palabra fracaso te duele el estomago, no eres la única. Hasta hace no mucho, era una palabra que me llenaba de un terror terrible. Sin embargo ahora hago un simple proceso mental: ¿cuáles son mis expectativas sobre mí misma?. OK, y si no las cumplo ¿qué pasará?. Muy probablemente nada. No se quemará mi casa, no se abrirá un agujero en la tierra, no moriré de combustión espontánea. De hecho, del fracaso puedes aprender y crecer aún más.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/933/1*8yOa_Uho3iTPTcrKeOkeqA.png" /><figcaption>Ilustración por <a href="https://icons8.com/">https://icons8.com</a>.</figcaption></figure><p>El miedo a fracasar siempre es una piedra de tope que impide avanzar. Sin embargo, creo que el verdadero fracaso es quedarte con esa incertidumbre del “¿qué pudo pasar?”. Partiendo desde el nivel más básico: “quiero decir algo pero sé que no me escucharán”, pasando por el “quiero postular pero sé que no quedaré” o “quiero emprender pero sé que fracasaré”. Es cierto que hay que ser realistas. Por ejemplo, ¿si sabes que algo fracasará, es porque la idea es mala o es porque tu crees que no <em>das la talla</em>?. Si es solo lo segundo, entonces <strong>dale con todo</strong>. Es mejor descubrir tus límites y aprender de ellos para seguir creciendo. Así puedes descubrir qué es lo que te falta para <em>dar la talla</em>. Y en el mejor de los casos, y el más probable, es que <em>das la talla</em> y sea un éxito.</p><h3>Para terminar este popurrí de ideas</h3><p>Finalmente para terminar quería contar una anécdota. El año pasado me contactó una reclutadora de Google. Fue una gran sorpresa que llegaran a mí, siendo que yo no postulé a nada. Me sentí muy alabada por ello. Luego del primer correo acepté hablar y busqué un poco cuál era el proceso de selección. Encontré varios tests estándar, nada del otro mundo (similares a las pruebas de ramos de Estructuras de datos o de Bases de datos). Era muy abordable, como una prueba cualquiera de la universidad.</p><p>Entonces me pregunté: ¿es el logro de mi vida ir a trabajar a Google?. En mi retrospectiva también venía el pensamiento “No, no, me estoy diciendo esto porque me da miedo fracasar en la prueba. OBVIO que todo el mundo quiere entrar a Google. OBVIO que es el camino”. Mientras más leía el material de estudio, más segura estaba de que <em>daba la talla.</em> Y así mismo más segura estaba de que Google no es lo que yo quería. <strong>Y no estoy loca por no quererlo</strong>.</p><p>El día de hoy sueño con lograr algo mejor para mi comunidad local. Como una persona introvertida (se me nota mucho ¿no?), hablar en público, voluntariados y reuniones sociales son actividades muy agotadoras. Sin embargo, de a poco trato de ser parte de la comunidad de forma más pro-activa, con el fin de ser un aporte.</p><p>Creo que es importante la sororidad entre mujeres. Creo que es importante ir derribando estereotipos de género. Creo que el sexo de una persona no es algo que condiciona tu capacidad como ser humano. Y creo firmemente que al seguir en el área <em>techi</em> con estos ideales (que muchos me han dicho, muy “idealizados”) quizás algún día llegue a hacer un cambio.</p><p>No me siento ni remotamente cerca de ser una <em>role-model</em> para las siguientes generaciones. Pero sí me siento capaz de hablar y dar consejo cuando alguna compañera lo necesite. Y si eres tan introvertida como yo (como para hablar o pedir consejo), mi consejo final es que estés segura de ti misma. Por muy cliché que suene, <strong>¡empodérate!</strong>. Descubre qué es lo que te falta y sigue aprendiendo. Nunca pares, que no será en vano.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/932/1*wowWQMIhJQGAqN72bOfAvA.png" /><figcaption>Ilustración por <a href="https://icons8.com/">https://icons8.com</a>.</figcaption></figure><ul><li>Kuschel, K., Lepeley, M., Espinosa, F. and Gutiérrez, S. (2017), “Funding challenges of Latin American women start-up founders in the technology industry”, Cross Cultural &amp; Strategic Management, Vol. 24 №2, pp. 310–331. <a href="https://doi.org/10.1108/CCSM-03-2016-0072">https://doi.org/10.1108/CCSM-03-2016-0072</a></li><li>C. Brush et. al. <a href="https://www.forbes.com/sites/babson/2014/09/30/women-entrepreneurs-bridging-the-gender-gap-in-venture-capital/#672e9bd43360">Women entrepreneurs: Bridging the gender gap in venture capital</a>. The Diana Project, 2014.</li><li>Miri Lerner, Candida Brush, Robert Hisrich, “Israeli women entrepreneurs: An examination of factors affecting performance”, Journal of Business Venturing, Volume 12, Issue 4, 1997, Pages 315–339, ISSN0883–9026, <a href="https://doi.org/10.1016/S0883-9026(96)00061-4.">https://doi.org/10.1016/S0883-9026(96)00061-4</a></li><li>Bruni, A., Gherardi, S. and Poggio, B. (2004), “Entrepreneur‐mentality, gender and the study of women entrepreneurs”, Journal of Organizational Change Management, Vol. 17 №3, pp. 256–268.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=841b2e1681fb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/cabras-por-qu%C3%A9-nos-tiramos-para-abajo-841b2e1681fb">Cabras ¿Por qué nos tiramos para abajo?</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[No necesitas Inteligencia Artificial ni Blockchain]]></title>
            <link>https://medium.com/platanus/no-necesitas-inteligencia-artificial-ni-blockchain-4bc6b32173df?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/4bc6b32173df</guid>
            <category><![CDATA[emprendimiento]]></category>
            <category><![CDATA[startup]]></category>
            <dc:creator><![CDATA[Andrés Matte]]></dc:creator>
            <pubDate>Fri, 29 May 2020 15:51:34 GMT</pubDate>
            <atom:updated>2020-05-29T15:54:59.246Z</atom:updated>
            <content:encoded><![CDATA[<p>Un cliente de <a href="http://platan.us/">Platanus</a> me contó una historia terrible.</p><p>Habían seleccionado a su startup en una aceleradora chilena. Al poco andar, tuvo una reunión con los encargados. Le informaron que tenía que cambiar lo que hacía su startup o no podía seguir en el programa.</p><p>— Pero cómo, ¿y qué voy a hacer?<br> — Hay hartos temas interesantes… ¿por qué no haces algo con Inteligencia Artificial?</p><p>No podía creer lo que me estaba contando. Una aceleradora conocida aconsejando tan mal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qr5QHDd5OxAsbKNc4ecgXQ.jpeg" /></figure><h3>La tecnología</h3><p>Este experto estaba aconsejando iniciar una startup a partir de una tecnología.</p><p>No tengo nada en contra de la IA. Tampoco contra ninguna otra nueva tecnología. Si hubiesen dicho que usen “páginas web” para empezar un negocio, estaría igualmente en desacuerdo. Blockchain, IOT o tenedores. Da lo mismo.</p><p>No puedes iniciar un producto con la tecnología como motivación. No si quieres que alguien lo use.</p><p>En los ’90 la tecnología de moda era Internet. Salieron miles de empresas que usaban la tecnología como excusa para lanzar un producto.</p><p>Ya sabemos qué pasó con eso. La burbuja puntocom. La gran mayoría murió. Muy pocas sobrevivieron.</p><p>Es como sacarse la lotería. En una de esas tienes suerte y le achuntas a lo que resulta. Pero yo no apostaría años de mi vida en eso. Demasiado improbable.</p><p>Por más sexy que se vea una tecnología, no es razón suficiente para empezar un producto.</p><h3>La solución</h3><p>Otro error muy común es enamorarse de la solución. Los famosos “productos en búsqueda de problemas”.</p><p>Un caso bien increíble es Juicero.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*cQtgPp_Dz0GwhMUR.jpg" /></figure><p>Juicero es una máquina que exprime jugo. Pero no solo eso. Es una máquina inteligente. Se conecta al WiFi, tiene una app para smartphone, te avisa cuando el jugo va a vencer, y un montón de otras cosas tecnológicas entretenidas.</p><p>Al principio costaba $700 dólares. Después bajó a $400.</p><p>Parece que hacer esta máquina fue un desafío ingenieril gigante. No por nada se demoraron 3 años desde que tuvieron la idea hasta que lanzaron el producto. Necesitaron más de $120 millones de dólares.</p><p>También vendían las bolsas que traían el jugo a ser exprimido por la máquina.</p><p>Y bueno, todo se derrumbó cuando Bloomberg sacó un video que mostraba que podías exprimir la bolsa con las manos.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5F08uWvdb8YW0xtOh7M7FA.png" /><figcaption>¿No me creen? Lean <a href="https://www.cnet.com/news/juicero-is-still-the-greatest-example-of-silicon-valley-stupidity/">esto</a>.</figcaption></figure><p>Parece que alguien se había enamorado de la solución.</p><p>Por más <em>bacán</em> que haya sido la máquina, había una solución mucho más barata: exprimir con la mano.</p><p>Terminó siendo un problema por el que muy poca gente estaba dispuesta a pagar.</p><p>Y los que pagaron seguro se arrepintieron después de ver el video.</p><h3>El problema</h3><p>La mayor razón por la que una startup muere es porque no existe suficiente gente que quiera su producto.</p><p>Si empezamos un negocio desde la tecnología o desde la solución, lo más probable es que muera por esa razón.</p><p>Para empezar un producto <strong>lo más importante es partir resolviendo un problema</strong>. Sin ese elemento, va a fracasar tarde o temprano.</p><p>Ojalá sea un problema que tenga harta gente. Así el negocio puede ser grande.</p><p>Ojalá sea un problema que te guste resolver. Así duras harto tiempo intentando resolverlo.</p><p>Y ojalá sea un problema que tú mismo tengas. Así estás 100% seguro de que existe.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4RO5XSWbULjYG_GdTbi7JQ.png" /></figure><p>En <a href="http://ventures.platan.us/">Platanus Ventures</a> nunca te vamos a pedir que uses Inteligencia Artificial ni Blockchain. Te vamos a empujar a que soluciones un problema. Algo que al menos un grupo pequeño de usuarios necesite con urgencia.</p><p>El resto es puro adorno.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4bc6b32173df" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/no-necesitas-inteligencia-artificial-ni-blockchain-4bc6b32173df">No necesitas Inteligencia Artificial ni Blockchain</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SAFE: qué es y cómo funciona]]></title>
            <link>https://medium.com/platanus/safe-qu%C3%A9-es-y-c%C3%B3mo-funciona-36d0dea7068f?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/36d0dea7068f</guid>
            <category><![CDATA[emprendimiento]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[venture-capital]]></category>
            <dc:creator><![CDATA[Andrés Matte]]></dc:creator>
            <pubDate>Thu, 09 Apr 2020 14:11:31 GMT</pubDate>
            <atom:updated>2020-06-01T16:13:57.786Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*P_EVcht4d_FPQsPFV1J3dA.png" /></figure><p>Un <strong>SAFE</strong> es medio difícil de entender, así que lo intentaré de explicar con un caso concreto.</p><p>SAFE significa: <em>Simple Agreement for Future Equity</em>.</p><p>Es un instrumento de inversión muy útil para startups que están en una etapa temprana.</p><p>Se trata de:</p><ul><li>El inversionista da X monto de plata ahora</li><li>La startup promete que en el futuro (cuando levante plata) le dará una cierta cantidad de acciones de la empresa (no se sabe exactamente cuántas al momento de firmar)</li></ul><p>La startup debe negociar dos cosas con el inversionista: cuánta plata va a poner ahora y el “Cap de valorización” (hay otros SAFE en los que hay que negociar más cosas. Por ejemplo, una “tasa de descuento”. En este post explicaré el SAFE solo con Cap).</p><p>La plata invertida y el Cap determinan cuántas acciones tendrá el inversionista antes de que se levante capital. Cuánto tendrá, viene dado por la siguiente relación:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/510/1*P7BZqzWwFMYHVXYawVhvkQ.png" /></figure><p>Donde P es el porcentaje de la empresa al que apunta el inversionista.</p><h3>En la práctica</h3><p>Veamos un ejemplo.</p><p>Un inversionista A ofrece 65,000 USD con un Cap de 650,000 USD. El inversionista apunta a tener el 10% de las acciones antes del levantamiento de capital.</p><p>Por ahora, la startup recibe 65,000 USD para usarlos como quiera y el inversionista se queda con el SAFE (un documento).</p><p>¿Cuántas acciones podría tener el inversionista A (x)? Tenemos que ver la siguiente relación:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XRlFQa4FygD2jLn14tQqkg.png" /></figure><p>En humano: se debe cumplir que el número de acciones del inversionista sean el 10% del total <strong>antes</strong> de que un inversionista meta plata en una ronda de inversión. Ojo que las acciones x serán acciones nuevas. Los <em>founders</em> no le venden acciones al inversionista.</p><p>Es super importante que el inversionista <strong>aún no tiene las acciones</strong>. Se queda con un SAFE que equivale a una promesa. Legalmente, los <em>founders</em> siguen teniendo el 100% de la empresa.</p><h3>Ronda de inversión</h3><p>Hagamos un <em>fast-forward</em>.</p><p>Supongamos que al emprendimiento le ha ido bien, y un año después decide levantar plata. Quieren hacer una expansión agresiva, así que apuntan a levantar 20 millones de dólares a un <em>pre-money valuation </em>de 65 millones.</p><p>El lenguaje sería: “Quiero levantar 20 millones a una valorización <em>pre-money </em>de 65 millones / <em>post-money</em> de 85 millones.”</p><p>Se juntan con un inversionista B, y este decide invertir los 20 millones en la empresa.</p><p>Como resultado de esa operación surgen varias preguntas.</p><ul><li>¿Qué porcentaje de la empresa tiene el inversionista A?</li><li>¿Qué porcentaje de la empresa tienen ahora los <em>founders</em>?</li><li>¿Qué porcentaje de la empresa tiene el inversionista B?</li></ul><p>Para determinar el resultado final hay que recurrir a dos pasos. El primero es para ver cuánto tendrá el inversionista A, y el segundo para ver cómo quedará todo con la entrada del inversionista B.</p><p>Vamos a las matemáticas.</p><h4>Paso 1</h4><p>Supongamos que los <em>founders</em> son los únicos que tienen acciones y que son 1,000,000. Recordemos que el inversionista A puso 65,000 USD con un Cap de 650,000 USD.</p><p>Si honramos a la ecuación de más arriba, tenemos:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/462/1*79vHvpU4Ps_7HI0Ew3fT3A.png" /></figure><p>Si despejamos x , entonces llegamos a x = 111,111.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dk2eb0bHE-mLZhPKaGEoKQ.png" /></figure><p>El inversionista A tiene ahora 111,111 acciones. Los <em>founders</em> se quedan con sus 1,000,000 de acciones iniciales. El total de acciones es 1,111,111.</p><p>¿Cómo influyó el Cap en esto? En el fondo, hizo que el dueño del SAFE pudiera comprar acciones de la empresa a un precio mucho más barato que el inversionista B.</p><p>Este escenario nunca es el resultado final, y nunca se “dejará hasta acá” en la vida real. Es solo un paso teórico para entender cómo queda todo después de la inversión.</p><h4>Paso 2</h4><p>El inversionista B decide invertir 20 millones de dólares. Ahora tenemos que hacer unos cálculos.</p><p>Tenemos:</p><pre>Pre-money valuation = 65,000,000 USD (la valoración acordada)<br>Total raise = 20,000,000 USD (lo que invirtió el inversionista)</pre><p>Ahora, tenemos que calcular el precio por acción <strong>antes</strong> de que el inversionista nuevo meta su plata.</p><pre>Acciones totales = 1,111,111<br>Precio por acción = pre-money valuation / acciones totales = 58.5 USD</pre><p>Como dijimos que el emprendimiento valía 65 millones de dólares, entonces el precio por acción es de 58.5 dólares.</p><p>El inversionista B decide invertir 20 millones de dólares, entonces:</p><pre>Acciones inversionista B = 20,000,000 USD / 58.5 USD ~= 341,880 acciones</pre><p>Perfecto, sabemos cuántas acciones le corresponden al inversionista B.</p><p>El resultado final sería como el de esta tabla:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YJgILFfoZDOvC4MPDjem_g.png" /></figure><p>Como puedes ver, los <em>founders</em> ahora tienen un 68.82%, y el inversionista A 7.65%. Tienen el mismo número de acciones, pero distintos porcentajes. Ambos diluyeron su participación con la entrada del nuevo inversionista.</p><p>Pero fue el tremendo negocio para el Inversionista A. Puso 65,000 USD, y hoy día tiene un 7.65% de una empresa de 85 millones de dólares. O sea, su parte vale 6.5 millones de dólares.</p><p><em>Not bad.</em></p><h3>¿Por qué el SAFE es buena idea?</h3><ul><li>El documento es super estándar, muy fácil y rápido de redactar. <a href="http://ycombinator.com/">Y Combinator</a> tiene un template en el que hay que cambiar el nombre de la empresa, el monto a invertir, el Cap, firmar y depositar la plata. Y ya está. Es muy rápido para un inversionista meter plata en emprendimientos así. Te evitas un <em>cacho</em> legal bien grande, porque en realidad no se hace ningún movimiento de acciones aún.</li><li>El inversionista tiene algún grado de protección si la empresa vale menos que el Cap. Mira la siguiente sección. Igual, este no es el caso al que apunta un inversionista. Es como un premio de consuelo.</li><li>Para los <em>founders</em> es muy fácil saber cuánto están cediendo de la empresa antes de la serie A.</li></ul><h3>Pero no se detiene ahí…</h3><p>Si no has entendido el caso del ejemplo, te sugiero que lo entiendas bien primero antes de pasar para acá. Se vuelve más enredado aún.</p><h4>¿Qué pasa si el pre-money valuation es menor que el Cap del SAFE?</h4><p>En este caso, la fórmula de las acciones no corre. Ups.</p><p>Si el Cap es mayor, en el paso 1 el inversionista A se queda con el número de acciones que equivalen a monto_invertido / pre-money valuation. O sea, si tiene un SAFE de 1 dólar con un Cap de 10 dólares, y el pre-money valuation es 2 dólares, el Cap no corre. Como puso 1 de 2 dólares, en el paso 1 se queda con aproximadamente el 50% de las acciones.</p><h4>Las acciones de los empleados</h4><p>Cuando una startup está partiendo, usualmente se les ofrece <em>equity</em> a los primeros empleados. Un porcentaje de la empresa. Como hay pocas lucas, seguramente tienen menos sueldo, por lo que se les compensa con un cierto número de acciones.</p><p>¿Cómo queda el mono del SAFE cuando se meten esos sujetos?</p><p>No es muy distinto. Sus acciones se consideran <em>common shares</em>, como las de los <em>founders</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Iu9cLb2zhVv50OnV0ZhdqQ.png" /></figure><p>Si te fijas, ahora habían más <em>common shares</em> (1,100,000). Por lo tanto, para lograr el 10%, al inversionista A le corresponden más acciones (122,222).</p><p>Recuerda que el esquema de acciones nunca va a quedar así, porque para que se termine el SAFE tiene que entrar un inversionista a meter plata por equity.</p><h4>Más de un SAFE con distintos Cap</h4><p>Imagínate el emprendimiento firma dos SAFE en distintos momentos.</p><p>El primero: 5,000 USD con un Cap de 25,000 USD (<em>founders</em> ceden el 20% de la empresa)</p><p>El segundo: 10,000 USD con Cap de 100,000 USD (<em>founders</em> ceden el 10% de la empresa)</p><p>En total, los <em>founders</em> han cedido el 30% de la empresa para levantar 15,000 USD.</p><p>¿Cómo queda el mono?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IgEEG5QN3DcUYJNQgGd2iQ.png" /></figure><h4>¿Post-money SAFE o pre-money SAFE?</h4><p>Uf, me costó un entender esta.</p><p>Mi resumen es:</p><ul><li>En el <em>pre-money</em> SAFE, para calcular cuántas acciones le corresponden al dueño del documento, <strong>no</strong> se consideran las nuevas acciones creadas por los otros SAFE (o por otros documentos convertibles).</li><li>En el <em>post-money</em> SAFE, <strong>sí</strong> se considera la cantidad de nuevas acciones creadas por los otros SAFE.</li></ul><p>¿Qué implica?</p><p>Que con <em>pre-money</em>, los SAFE <strong>sí</strong> se diluyen entre sí al momento de convertir.</p><p>En el <em>post-money</em> <strong>no</strong> se diluyen entre sí. Solo se diluyen con el ingreso del <em>new money</em>.</p><p>¿Por qué es importante para los fundadores de startups?</p><p>Con el <em>pre-money</em> nunca se sabe bien cuánto porcentaje de tu empresa has cedido hasta ahora. Como los SAFE se diluyen entre sí, cuánto has dado depende de los SAFE que has firmado y de los que firmarás en el futuro.</p><p>Con el <em>post-money</em>, sabes perfecto cuánto porcentaje has dado, porque los distintos SAFE no se diluyen entre ellos. Es más transparente para todos. Lo malo es que los fundadores asumen toda la dilución y no se comparte con los dueños de los SAFE.</p><h3>¿Quieres saber más?</h3><p>Hay mucho que aprender acá. Si te interesa, lee esto:</p><ul><li><a href="https://d1l6icgp8w0hse.cloudfront.net/assets/ycdc/Primer%20for%20post-money%20safe%20v1.1-32d79cea6fa352fe6578b492bd285240b3421fd721d2e268ca9b8c8e391e86f7.docx">Post Money Safe User Guide de YC</a></li><li><a href="https://www.ycombinator.com/documents/">Documentos YC</a></li><li><a href="https://www.youtube.com/watch?v=Dk6JNTDec9I">Understanding SAFEs and Priced Equity Rounds by Kirsty Nathoo</a></li><li><a href="https://safegenie.io/">SAFE Genie</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=36d0dea7068f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/safe-qu%C3%A9-es-y-c%C3%B3mo-funciona-36d0dea7068f">SAFE: qué es y cómo funciona</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cómo crear una API REST en Rails testeada, documentada y con buenas prácticas en 1 minuto y 54…]]></title>
            <link>https://medium.com/platanus/c%C3%B3mo-crear-una-api-rest-en-rails-testeada-documentada-y-con-buenas-pr%C3%A1cticas-en-1-minuto-y-54-4839009318a0?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/4839009318a0</guid>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[rails-api]]></category>
            <category><![CDATA[rubygems]]></category>
            <dc:creator><![CDATA[Leandro Segovia]]></dc:creator>
            <pubDate>Fri, 03 Apr 2020 17:12:30 GMT</pubDate>
            <atom:updated>2020-04-03T18:05:28.997Z</atom:updated>
            <content:encoded><![CDATA[<h3>Cómo crear una API REST en Rails testeada, documentada y con buenas prácticas en 1 minuto y 54 segundos.</h3><p>Por la precisión del tiempo en el título se darán cuenta de que no estoy hablando de una estimación. Casi 2 minutos es realmente el tiempo que me tomó crear la típica API de blog posts con sus comentarios.</p><h4>Los modelos:</h4><pre>class Blog &lt; ApplicationRecord<br> has_many :comments<br>end</pre><pre>class Comment &lt; ApplicationRecord<br> belongs_to :blog<br>end</pre><h4>Los endpoints:</h4><pre>GET     /api/v1/blogs<br>POST    /api/v1/blogs<br>GET     /api/v1/blogs/:id<br>PUT     /api/v1/blogs/:id<br>DELETE  /api/v1/blogs/:id</pre><pre>GET     /api/v1/comments/:id<br>PUT     /api/v1/comments/:id<br>DELETE  /api/v1/comments/:id<br>GET     /api/v1/blogs/:blog_id/comments<br>POST    /api/v1/blogs/:blog_id/comments</pre><p>Suponiendo que me creen el “casi 2 minutos”, imagino que estarán pensado que en ese tiempo no se puede hacer nada o quizás, con mucha fe y velocidad, se podría algo como esto:</p><pre>class BlogsController &lt; ApplicationController<br>  before_action :set_blog, only: [:show, :update, :destroy]</pre><pre>  def index<br>    <a href="http://twitter.com/blogs">@blogs</a> = Blog.all</pre><pre>    render json: <a href="http://twitter.com/blogs">@blogs</a><br>  end</pre><pre>  def show<br>    render json: <a href="http://twitter.com/blog">@blog</a><br>  end</pre><pre>  def create<br>    <a href="http://twitter.com/blog">@blog</a> = Blog.new(blog_params)</pre><pre>    if <a href="http://twitter.com/blog">@blog</a>.save<br>      render json: <a href="http://twitter.com/blog">@blog</a>, status: :created<br>    else<br>      render json: <a href="http://twitter.com/blog">@blog</a>.errors, status: :unprocessable_entity<br>    end<br>  end</pre><pre>  def update<br>    if <a href="http://twitter.com/blog">@blog</a>.update(blog_params)<br>      render json: <a href="http://twitter.com/blog">@blog</a><br>    else<br>      render json: <a href="http://twitter.com/blog">@blog</a>.errors, status: :unprocessable_entity<br>    end<br>  end</pre><pre>  def destroy<br>    <a href="http://twitter.com/blog">@blog</a>.destroy<br>  end</pre><pre>  private</pre><pre>  def set_blog<br>    <a href="http://twitter.com/blog">@blog</a> = Plop.find(params[:id])<br>  end</pre><pre>  def blog_params<br>    params.require(:blog).permit(:title, :body)<br>  end<br>end</pre><p>A simple vista parece suficiente pero veamos algunos problemas:</p><ul><li>En cada endpoint se está especificando el status que debe retornar. Un poco verboso siendo que en un CRUD común y corriente un POST a la colección siempre devuelve un HTTP status code 201 y un GET a un recurso un 200, ¿verdad?</li><li>En el update o create se están manejando los errores de validación ¿Eso quiere decir que en todos los endpoints donde tenga validaciones voy a tener la misma lógica? ojalá que no.</li><li>Para devolver la respuesta se usa render json: .... Esto es un poco peligroso (a nivel de buenas prácticas) porque anima al desarrollador a no respetar una estructura. Es decir, invita a tener formatos de respuesta diferentes en los distintos endpoints de la API. Poco estándar, ¿no?</li><li>El BlogsController hereda directamente de ApplicationController. Esto es malo porque, salvo que nuestra app sea solo una API, de ahí también heredan los controllers de nuestra aplicación web. El problema con esto es que si tenemos solo un controlador base (el ApplicationController), muchos métodos globales de la app no tendrán sentido en el contexto de la API y viceversa.</li><li>No hay manejo de versiones. Quizás hoy no es un problema pero si mañana tenemos que sacar la versión 2 de está increíble y original idea, vamos a extrañar no haber manejado este problema de entrada.</li><li>No hay documentación. Una API no documentada es una que no se usa. Nada más que decir.</li><li>Y los endpoints de los comentarios?</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/267/1*Ih7yTQx38Qy94Xp3FxyviQ.gif" /></figure><ul><li>Finalmente, el mayor problema es que la API no funciona! ¿¡cómo!?, ¿¡dónde!? En el método set_blog escribí por error Plop en lugar de Blog . Sí, ni lo digan… Esto con tests no pasaba.</li></ul><p>Imagino que a esta altura ya estarán pensando: bueno ya, ¿cómo hiciste para crear una API que no tenga los problemas mencionados anteriormente en ese tiempo? La respuesta es: ¡no lo hice! La gema <a href="https://github.com/platanus/power_api">Power API</a> que desarrollamos en <a href="https://platan.us/">Platanus</a> lo hizo por mí.</p><h4>La prueba:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/941/1*QpBApkKdfkrTXK-261UE_Q.gif" /></figure><h4>El resultado:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*qpHEWH-dnos64YsnaBsigQ.gif" /></figure><h4>Explicación en pasos:</h4><p>1 ~ Ejecuté el instalador de la gema:</p><pre>rails g power_api:install</pre><p>Es necesario correr este comando para tener el setup inicial sobre el que se apoyará nuestra API. Puedes ver el detalle de lo que se genera/instala/configura <a href="https://github.com/platanus/power_api/tree/main-structure#initial-setup">aquí</a>.</p><p>2 ~ Generé el controller de blogs</p><pre>rails g power_api:controller blog --allow-filters --use-paginator --version-number=1 --attributes=title body</pre><p>Esto agrega el controlador:</p><pre>class Api::V1::BlogsController &lt; Api::V1::BaseController<br>  def index<br>    respond_with paginate(filtered_collection(Blog.all))<br>  end</pre><pre>  def show<br>    respond_with blog<br>  end</pre><pre>  def create<br>    respond_with Blog.create!(blog_params)<br>  end</pre><pre>  def update<br>    respond_with blog.update!(blog_params)<br>  end</pre><pre>  def destroy<br>    respond_with blog.destroy!<br>  end</pre><pre>  private</pre><pre>  def blog<br>    <a href="http://twitter.com/blog">@blog</a> ||= Blog.find_by!(id: params[:id])<br>  end</pre><pre>  def blog_params<br>    params.require(:blog).permit(<br>      :title,<br>      :body<br>    )<br>  end<br>end</pre><p>El serializer:</p><pre>class Api::V1::BlogSerializer &lt; ActiveModel::Serializer<br>  type :blog</pre><pre>  attributes(<br>    :title,<br>    :body<br>  )<br>end</pre><p>Los tests:</p><pre>require ‘swagger_helper’</pre><pre>describe ‘API V1 Blogs’, swagger_doc: ‘v1/swagger.json’ do<br>  path ‘/blogs’ do<br>    get ‘Retrieves Blogs’ do<br>      description ‘Retrieves all the blogs’<br>      produces ‘application/json’</pre><pre>      let(:collection_count) { 5 }<br>      let(:expected_collection_count) { collection_count }</pre><pre>      before { create_list(:blog, collection_count) }</pre><pre>      response ‘200’, ‘Blogs retrieved’ do<br>        schema(‘$ref’ =&gt; ‘#/definitions/blogs_collection’)</pre><pre>        run_test! do |response|<br>          expect(JSON.parse(response.body)[‘data’].count).to eq(expected_collection_count)<br>        end<br>      end<br>    end</pre><pre>    post ‘Creates Blog’ do<br>      description ‘Creates Blog’<br>      consumes ‘application/json’<br>      produces ‘application/json’<br>      parameter(name: :blog, in: :body)</pre><pre>      response ‘201’, ‘blog created’ do<br>        let(:blog) do<br>          {<br>            title: ‘Some title’,<br>            body: ‘Some body’<br>          }<br>        end</pre><pre>        run_test!<br>      end<br>    end<br>  end</pre><pre>  path ‘/blogs/{id}’ do<br>    parameter name: :id, in: :path, type: :integer</pre><pre>    let(:existent_blog) { create(:blog) }<br>    let(:id) { existent_blog.id }</pre><pre>    get ‘Retrieves Blog’ do<br>      produces ‘application/json’</pre><pre>      response ‘200’, ‘blog retrieved’ do<br>        schema(‘$ref’ =&gt; ‘#/definitions/blog_resource’)</pre><pre>        run_test!<br>      end</pre><pre>      response ‘404’, ‘invalid blog id’ do<br>        let(:id) { ‘invalid’ }<br>        run_test!<br>      end<br>    end</pre><pre>    put ‘Updates Blog’ do<br>      description ‘Updates Blog’<br>      consumes ‘application/json’<br>      produces ‘application/json’<br>      parameter(name: :blog, in: :body)</pre><pre>      response ‘200’, ‘blog updated’ do<br>        let(:blog) do<br>          {<br>            title: ‘Some title’,<br>            body: ‘Some body’<br>          }<br>        end</pre><pre>        run_test!<br>      end<br>    end</pre><pre>    delete ‘Deletes Blog’ do<br>      produces ‘application/json’<br>      description ‘Deletes specific blog’</pre><pre>      response ‘204’, ‘blog deleted’ do<br>        run_test!<br>      end</pre><pre>      response ‘404’, ‘blog not found’ do<br>        let(:id) { ‘invalid’ }</pre><pre>        run_test!<br>      end<br>    end<br>  end<br>end</pre><p>El resultado:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/1*-2vUeDFBol1KZhkvZ9wQnA.png" /></figure><p>3 ~ Generé el controller de comments</p><pre>rails g power_api:controller comment --attributes=body --parent-resource=blog</pre><p>Este paso es similar al anterior pero, por haber especificado la opción --parent-resource=blog, el recurso se creará “nesteado” en blogs</p><pre>class Api::V1::CommentsController &lt; Api::V1::BaseController<br>  def index<br>    respond_with comments<br>  end</pre><pre>  def show<br>    respond_with comment<br>  end</pre><pre>  def create<br>    respond_with comments.create!(comment_params)<br>  end</pre><pre>  def update<br>    respond_with comment.update!(comment_params)<br>  end</pre><pre>  def destroy<br>    respond_with comment.destroy!<br>  end</pre><pre>  private</pre><pre>  def comment<br>    <a href="http://twitter.com/comment">@comment</a> ||= Comment.find_by!(id: params[:id])<br>  end</pre><pre>  def comments<br>    <a href="http://twitter.com/comments">@comments</a> ||= blog.comments<br>  end</pre><pre>  def blog<br>    <a href="http://twitter.com/blog">@blog</a> ||= Blog.find_by!(id: params[:blog_id])<br>  end</pre><pre>  def comment_params<br>    params.require(:comment).permit(<br>      :body<br>    )<br>  end<br>end</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/824/1*SvBPD6WdHqCfGmN7oUBoaw.png" /></figure><p>4 ~ Generé la documentación</p><pre>rails rswag:specs:swaggerize</pre><p>Gracias a la gema <a href="https://github.com/rswag/rswag">rswag</a> que incluye Power API podemos generar, a partir de los tests, la documentación. Esto se hace con el comando anterior.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/971/1*LBW-0nzxEQCkjqZwMlqfaw.png" /></figure><p>5 ~ Corrí los tests</p><pre>bundle exec rspec spec/integration</pre><p>Para probar que todo se creó correctamente.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/625/1*R3f6McQompW9gRyHWHn3Hg.png" /></figure><p>6 ~ Levanté el server.</p><pre>rails s</pre><p>Para probar manualmente que todo funcionó bien :)</p><p>Ahora que parece que todo funcionó correctamente, repasemos una vez más los problemas que encontré en la versión inicial para confirmar que la gema los resuelve:</p><blockquote>En cada endpoint se está especificando el status …</blockquote><p>Ya no es necesario porque la gema incluye un <a href="https://github.com/platanus/power_api/blob/master/app/responders/api_responder.rb">api_responder</a> que maneja el HTTP status code desde los HTTP verbs.</p><blockquote>En el update o create se están manejando los errores de validación…</blockquote><p>No se hace más en el controller ya que se usa un <a href="https://github.com/platanus/power_api/blob/master/app/controllers/concerns/api/error.rb">concern</a> que viene incluido para manejar excepciones.</p><blockquote>Para devolver la respuesta se usa render json: .... Esto es un poco peligroso (a nivel de buenas prácticas) porque anima al desarrollador a no respetar una estructura…</blockquote><p>Ahora se utilizan serializers de la gema <a href="https://github.com/rails-api/active_model_serializers">Active Model Serializers</a> configurada para devolver respuestas con el formato de <a href="https://jsonapi.org/">json api</a>.</p><blockquote>El BlogsController hereda directamente de ApplicationController …</blockquote><p>Power API genera una estructura que permite que cada versión de la API tenga su propio BaseController que además hereda de uno pensado para el manejo exclusivo de APIs.</p><blockquote>No hay manejo de versiones…</blockquote><p>El manejo de versiones lo hacemos con la gema <a href="https://github.com/bploetz/versionist">versionist</a>.</p><blockquote>No hay documentación…</blockquote><p>La creamos con <a href="https://github.com/rswag/rswag">rswag</a>.</p><blockquote>Finalmente, el mayor problema es que la API no funciona!</blockquote><p>Power API genera los specs ;)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4839009318a0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/c%C3%B3mo-crear-una-api-rest-en-rails-testeada-documentada-y-con-buenas-pr%C3%A1cticas-en-1-minuto-y-54-4839009318a0">Cómo crear una API REST en Rails testeada, documentada y con buenas prácticas en 1 minuto y 54…</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[El trabajo en los tiempos de pandemia]]></title>
            <link>https://medium.com/platanus/el-trabajo-en-los-tiempos-de-pandemia-a06ba240eca2?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/a06ba240eca2</guid>
            <category><![CDATA[trabajo-remoto]]></category>
            <category><![CDATA[coronavirus]]></category>
            <category><![CDATA[remote-working]]></category>
            <dc:creator><![CDATA[Diego Fernández]]></dc:creator>
            <pubDate>Fri, 20 Mar 2020 17:59:26 GMT</pubDate>
            <atom:updated>2020-03-20T17:59:26.729Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8PcaPzRlygAoQm3M-A22DA.jpeg" /></figure><p>El 3 de marzo se anunció el primer caso de COVID-19 en Chile. El día siguiente en la mañana en el Slack de la oficina se anunciaban un par de medidas que debíamos seguir por precaución, como por ejemplo no saludarnos ni de mano ni de beso en la mejilla. Fue raro, uno está acostumbrado a esas interacciones todos los días, pero será, es necesario.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/489/1*DvLOjUBEr3nVZxAbktCMcA.png" /><figcaption>Se produjeron algunas situaciones incómodas 😬</figcaption></figure><p>El resto de la semana, sin ponernos de acuerdo, estuvimos casi todos trabajando desde la casa. Había ansiedad, nos lo estábamos tomando en serio. Ese viernes en nuestra reunión semanal lo conversamos y decidimos oficializarlo: estaríamos todos trabajando remoto hasta nuevo aviso.</p><p>Siempre hemos sido amigos del trabajo remoto, casi todos lo hacíamos al menos una vez a la semana y algunos compañeros van a la oficina solo un par de veces al año. Pero varios estamos acostumbrados a ir a la oficina bien seguido. Nos gusta vernos las caras, pelear con la cafetera, comer la comida de la Vicky (nuestra chef que nos cocina exquisito). El cambio no nos entusiasmaba mucho que digamos. Pero igual, concordamos en que era lo mejor, así que filo, démosle.</p><h3>La pega</h3><p>En la oficina tenemos una sala especial para reuniones o presentaciones. Ahí hay una tele con un aparatito de Google con una cámara para que sea llegar y presentar a los de la sala y a quién se conecte al <em>meet. </em>Para los que están ahí mismo es bien cómodo, aunque para los remotos de repente podía ser molesto cuando hablaba mucha gente junta con un solo micrófono en la sala. Ya no podíamos usar el aparatito, obviamente, así que cada uno de su compu desde la casa no más. No fue tanta diferencia igual, y apuesto que los que desde siempre han sido remotos están más que felices por el cambio.</p><p>Muchas reuniones de <em>sprint</em> con clientes ya se hacían por videollamada, pero a algunos tuvimos que convencerlos. La experiencia es un poco distinta, pero a menos que necesites “pizarrear”, todo bien.</p><h3>El office y after-office</h3><p>Aunque por el lado operativo no hemos tenido mucho problema, se nota un cambio anímico de repente. No poder salir mucho y el constante flujo de información sobre la situación a nivel mundial te tiran pa abajo igual.</p><p>Dado lo anterior y que no podemos ir a la oficina, tuvimos un par de actividades bien choras para hacer más amena la semana remota:</p><ul><li>Salió la idea de tener una <em>Remoto Party™️. </em>¿Qué es eso? No sé. Una llamada pa conversar cada uno con su chela, jugar algún juego de mesa de alguna manera (?), que sé yo, la idea era hacer algo. Al final decidimos bajarnos todos un juego online.<br>Teníamos un canal de slack, <em>#pl-games, </em>medio botado la verdad. Lo revivimos y nos organizamos ahí para ver que juego íbamos a jugar: Worms. Nos conectamos por Discord y como éramos hartos al principio alguien que estuviera jugando <em>streameaba, </em>así todos veíamos y comentábamos la partida. Incluso armamos dos partidas simultáneas, fue bien entrete.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*YDfqv5bXfdX4HC8XpCn8YA.png" /><figcaption>Equipo amarillo dando cátedra ahí</figcaption></figure><ul><li>Jaime, en su afán de que todos seamos tan fan de Zalo Reyes como él, preguntó si había alguna manera de tener una especie de radio en que cualquiera de nosotros pudiera ir encolando canciones y que todos estuviéramos escuchando lo mismo. La respuesta fue Discord + bots.<br>Así fue como salieron dos radios, una con música más de bus de paseo de curso/fogata y otra con música en inglés. Debo decir que mi playlist personal creció harto con este experimento.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*zfPaXmwOu0fL0j0mpLoNuA.png" /><figcaption>Temazo</figcaption></figure><p>Gran parte de las empresas <em>techi</em> tenemos la suerte de estar pintadas para el trabajo remoto. En estos tiempos difíciles es sumamente importante que aprovechemos esa oportunidad y aportemos de esta manera a disminuir las probabilidades de contagio. Siempre se puede hacer algo para hacer este cambio más llevadero 😄.</p><p>Si alguna empresa quiere implementar más trabajo remoto pero tiene dudas o necesita ayuda, felices de aportar por ese lado.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a06ba240eca2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/el-trabajo-en-los-tiempos-de-pandemia-a06ba240eca2">El trabajo en los tiempos de pandemia</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Por qué un _ puede ahorrarte un 50% de memoria]]></title>
            <link>https://medium.com/platanus/por-qu%C3%A9-un-puede-ahorrarte-un-50-de-memoria-c140518b78e9?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/c140518b78e9</guid>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Juan Ignacio Marquez]]></dc:creator>
            <pubDate>Mon, 09 Mar 2020 13:33:31 GMT</pubDate>
            <atom:updated>2020-03-09T13:33:31.268Z</atom:updated>
            <content:encoded><![CDATA[<p>Como muchas veces durante la semana, estaba revisando un <em>Pull Request </em>y me llegó un trocito de código que me quedó dando vueltas. “Si en vez de un punto pones un guión bajo debería ahorrarse mucha memoria, cierto?”</p><p>Resultó ser que sí, por lo que me animé a escribir este post para compartirles la enseñanza.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*0EVO1pcxXqP742xq.png" /><figcaption>© geek &amp; poke, <a href="http://geek-and-poke.com/">http://geek-and-poke.com</a></figcaption></figure><h3>Veamos este ejemplo en Rails</h3><p>Tenemos 3 modelos AdminUser , BankMovement y BankMovementCheck. El último es un modelo intermedio para que un usuario pueda marcar los movimientos bancarios. Las relaciones son las siguientes:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/869/1*peT-ZMH7jPcCKvuJAlV2Xg.png" /></figure><p>Ahora, supongamos que queremos saber si un movimiento fue marcado por un user en específico: <strong>¿En qué se diferencian estos dos métodos?</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/34f73b5211e90621f38ee4c65e46fabe/href">https://medium.com/media/34f73b5211e90621f38ee4c65e46fabe/href</a></iframe><p>Como lo anticipa la introducción, la única diferencia es que a la izquierda de la igualdad se cambio un <strong>punto </strong>por un<strong> guión bajo</strong>.</p><h4>Ok, ¿y cómo afecta esto a Boca?</h4><p>Aunque la diferencia en código sea literalmente de 1 caracter, el significado detrás de cada método es <strong>muy diferente. </strong><em>Hint</em>: El primero es mucho más ineficiente que el segundo.</p><p>Lo que realmente los diferencia es que en el primer método estamos <strong>cargando el </strong><strong>admin_user en memoria para consultar por su id</strong>. En cambio en el segundo, solo se está accediendo al atributo admin_user_id de la instancia bank_movement_check (que se carga en ambos métodos). Es decir, nuestro método eficiente se ahorra la carga de un objeto completo.</p><h4>Muy bonito, quiero ver los números.</h4><p>Para ejemplificar lo significativa que es esta diferencia, veamos un análisis (no científico) en cuanto a consultas, uso de memoria y tiempo de ejecución.</p><h4>Consultas</h4><p>Nuestro método eficiente _marked_by_user? (con _ al inicio de su nombre) hace una consulta menos a la base de datos</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/96cf6e0e214e30440531114280fc007f/href">https://medium.com/media/96cf6e0e214e30440531114280fc007f/href</a></iframe><h4>Memoria</h4><p>Utilizando gema <a href="https://github.com/michaelherold/benchmark-memory">benchmark/memory</a> probamos el uso de memoria de ambos métodos, tanto al ser ejecutados por primera vez como para N ejecuciones consecutivas:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pOyRWO5qgMi-6if9PVnPcw.png" /></figure><p>Podemos ver que el uso de memoria baja de <strong>2.325M</strong> a <strong>1.230M </strong>para la primera llamada al método, lo que significa un ahorro de casi un 50% 🤯. Por su parte, en llamadas consecutivas la baja es de <strong>30.776k</strong> a <strong>15.019K</strong>.</p><p>La abismal diferencia entre el primer intento y los siguientes se debe a que el objeto (o parte de él) permanece cargado en memoria/caché y no es necesario cargarlo completo como en el primer intento.</p><h4>Tiempo</h4><p>Ahora utilizando la librería <a href="https://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html">Benchmark</a> de Ruby, medimos los tiempos de ejecución:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hsaUfA3PRZ0hNRsER9SktA.png" /></figure><p>Nuevamente el ahorro es significativo. El método ineficiente toma <strong>0.022013s</strong> mientras que el eficiente <strong>0.010956s</strong> , es decir, casi el doble de tiempo. Para los siguientes intentos, la diferencia es aun mayor, el método eficiente hace la tarea en aproximadamente <strong>un tercio</strong> del tiempo.</p><p>Nuevamente el caché y la memoria hacen que haya una diferencia importante entre la primera llamada al método y las siguientes.</p><h3>Conclusión</h3><p>Un <strong>ínfimo</strong> cambio en el código nos trajo un <strong>tremendo</strong> <em>boost</em> en <em>performance</em>. Imagina el impacto de esto en una app con cientos o millones de operaciones como esta. Lo importante a rescatar es que <strong>vale la pena</strong> estar atento a estos detalle y a qué está haciendo realmente nuestro código. Si bien este ejemplo es en Ruby, en todos los lenguajes y <em>frameworks</em> existen estas sutilezas como esta.</p><p>¿Cómo encontrar problemas de este estilo al desarrollar o probar?</p><ul><li>Siempre analiza la consola en búsqueda de consultas innecesarias</li><li>Instala plugins de <em>memory-profiling </em>y <em>performance</em> en general, pueden ayudar a detectar métodos o <em>endpoints</em> ineficientes. En Platanus usamos <a href="https://scoutapm.com/">Scout</a></li><li>Intenta entender qué hace tu código a más bajo nivel</li><li>Realiza <em>Code Review, </em>siempre pueden aparecer sugerencias como esta!</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c140518b78e9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/por-qu%C3%A9-un-puede-ahorrarte-un-50-de-memoria-c140518b78e9">Por qué un _ puede ahorrarte un 50% de memoria</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Manteniendo la historia limpia usando git rebase]]></title>
            <link>https://medium.com/platanus/manteniendo-la-historia-limpia-usando-git-rebase-5cceecd5367a?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/5cceecd5367a</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[good-practices]]></category>
            <category><![CDATA[git]]></category>
            <category><![CDATA[clean-code]]></category>
            <dc:creator><![CDATA[Raimundo Herrera]]></dc:creator>
            <pubDate>Thu, 16 Jan 2020 18:09:00 GMT</pubDate>
            <atom:updated>2020-01-16T18:09:00.796Z</atom:updated>
            <content:encoded><![CDATA[<p>Un beneficio que tiene interactuar día a día con otros desarrolladores es que podemos potenciar entre nosotros las buenas prácticas y mejorar en nuestra forma de programar. En Platanus tenemos herramientas que nos permiten mantener el código limpio y ordenado.</p><p>Pero los estándares no bastan, para asegurar la calidad tenemos un proceso de <strong>revisión de código</strong>. Como utilizamos GitHub, este proceso lo realizamos por medio de <em>pull requests</em> y es muy típico que, a pesar de usar <em>linters,</em> hayan detalles que se nos pasen al escribir código.</p><p>En esta dinámica de revisión, los comentarios y solicitudes de cambios abundan, muchas veces se trata de un <em>refactor, </em>sacar un <em>typo</em>, o mejoras menores, pero a la hora de programar esos cambios, una duda muy natural surge:</p><blockquote>¿cómo deberían verse estos cambios en los commits del pull request?</blockquote><p>El problema radica en que muchas veces los <em>commits</em> para arreglar esos cambios se ven como:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LEQaZZVSTdwdck7cDu7y-w.png" /><figcaption>El verdadero cambio está en el primer commit, el segundo no aporta mucho</figcaption></figure><p>Pero no es deseable incluir ese tipo de commits en la historia de un repositorio, porque no tienen que ver realmente con lo que se cambió en la lógica del proyecto. Lo único que se logra es <strong>contaminar la historia</strong> y hacer menos útil ese historial.</p><p>No solo ensucian la historia, también dificultan la revisión, ya que cuando se revisa un pull request commit a commit, quien revisa puede encontrar un <em>typo</em> en un commit anterior, y después se da cuenta que subieron otro commit que lo soluciona. Todo un enredo que hace que la revisión sea menos fructífera.</p><p>Aquí es donde git nos hace la vida más fácil con rebase. Esta herramienta tiene múltiples usos, pero uno que encuentro particularmente útil es el de editar la historia de commits en una <em>branch</em>, y explicaré una forma de usarlo.</p><p>Existe el comando git rebase --interactive ‘&lt;commit_hash&gt;^’ que nos permite reescribir la historia en la rama actual desde el commit al que corresponde ese <em>hash,</em> hasta el último. Al ejecutarlo se abre en la consola un documento con la planificación para este rebase, que corresponde a una lista de los commits correspondientes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YYCp3n4eDm5MDhgvzSRlAA.png" /><figcaption>Así se ve el archivo de texto que se abre en el terminal con la planificación del rebase</figcaption></figure><p>A la izquierda de cada commit aparece una palabra que es la acción a realizar. Por defecto aparece pick que corresponde a seleccionar el commit sin cambiarlo. Si uno quiere cambiar la historia puede cambiar esa palabra por una serie de opciones: edit para modificarlo, reword para cambiar el mensaje, drop para descartar ese commit, squash para juntar ese commit con otro, entre otras.</p><p>Me voy a detener en edit que es el que más uso. Una vez que uno cambió en el documento la palabra pick por edit en los commits que quiere modificar, puede guardar y cerrar.</p><p>Comúnmente el editor de texto que aparece es vim, a menos que la variable de entorno EDITOR del terminal señale otro, por lo que para editar el texto se presiona la tecla i seguido de lo que se quiere escribir, y para terminar se puede apretar la tecla esc para luego escribir :wq o :x.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Cr6ZeaIMKTcKslglpSRMYQ.png" /><figcaption>Cambié los dos primeros pick, uno por edit y el otro por reword</figcaption></figure><p>Cuando se cierra la planificación se ejecuta realmente el comando, y empieza la magia. Una forma fácil de imaginarse lo que hace el comando es que está viajando al pasado. Git se encarga de ejecutar la acción especificada en cada commit, partiendo desde el más viejo. Cuando la acción es pick no hace nada, porque el commit se mantiene, pero cuando la acción es edit, se detiene en ese commit, como si los commits posteriores aún no ocurrieran.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/568/1*gES_dx47D36VBrQ2QaLqxw.jpeg" /><figcaption>Algo así está pasando</figcaption></figure><p>En ese momento es cuando uno puede editar lo que está pasando. El commit ya está hecho, pero git nos permite modificarlo <em>in situ</em>. Una forma es la siguiente:</p><ol><li>Editar y guardar los archivos que queremos cambiar</li><li>Hacer git add de los cambios que queremos agregar</li><li>Añadir esos cambios al commit que estamos editando, por medio de git commit —-amend —-no-edit</li></ol><p>Hay que considerar que realmente el commit ya se hizo, lo que se está haciendo es pararse justo después de que se realizó, y hacer un amend a este commit, es decir, añadirle más cambios, pero sin cambiar nada más, ni el mensaje.</p><p>Una vez que ya se está satisfecho con los cambios realizados, hay que indicar que puede continuar, y eso se hace por medio de git rebase —-continue. Así el comando sigue realizando las acciones que correspondan sobre los commits restantes, hasta llegar al último.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j0x4xspWqNur2qjntN1CGw.png" /><figcaption>Aquí se ve el ejemplo completo. Tip: En el log se puede obtener el hash de cada commit.</figcaption></figure><p>Otra de las acciones que mencioné antes es reword, que en vez de modificar el contenido de cada commit, permite modificar el mensaje. La acción squash en términos simples se puede usar para mezclar uno o varios commits que no se quieren mantener, en el anterior. Es una forma alternativa de mantener la historia limpia.</p><p>Ahora solo queda hacer push de la rama con los cambios, pero al intentar hacerlo es probable que sea rechazado:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rQgnaCz-oh_DtDsRNEs4rw.png" /><figcaption>Esto pasa porque la historia no coincide con lo que se había subido anteriormente en esa rama.</figcaption></figure><p>No hay que preocuparse, se puede forzar con git push —-force o el más seguro git push —-force-with-lease origin &lt;branch_name&gt;, que evita pisar el trabajo ajeno y nos asegura subir cambios en la rama correcta. <em>Disclaimer</em>: no suelo recomendar utilizar comandos con <em>flags</em> como esos, pero como estamos en una rama distinta a la principal y los cambios son solicitados en el pull request, no debería haber problema. Igual <strong><em>tengo</em></strong> que recomendar usar el comando con cuidado y en la rama que corresponde, nunca en <em>master</em>.</p><p>En lo personal me gustan los repositorios ordenados y poder navegar por los commits. La gran gracia de usar rebase de la forma que vimos es que la historia del repositorio queda mucho más limpia que agregando un commit por cada mini cambio que nos pidan en la revisión. Para los obsesivos como yo, no solo es útil, es necesario.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5cceecd5367a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/manteniendo-la-historia-limpia-usando-git-rebase-5cceecd5367a">Manteniendo la historia limpia usando git rebase</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Qué hemos aprendido de un mono que pone las reglas en la oficina]]></title>
            <link>https://medium.com/platanus/qu%C3%A9-hemos-aprendido-de-un-mono-que-pone-las-reglas-en-la-oficina-61ba5f3fcec6?source=rss----71beb3926ac5---4</link>
            <guid isPermaLink="false">https://medium.com/p/61ba5f3fcec6</guid>
            <dc:creator><![CDATA[Andrés Matte]]></dc:creator>
            <pubDate>Fri, 27 Sep 2019 19:19:27 GMT</pubDate>
            <atom:updated>2019-09-27T19:19:27.484Z</atom:updated>
            <content:encoded><![CDATA[<p>La Vicky, una chef de primera, nos hace almuerzo todos los días. Pero los cupos son limitados. Solamente hay 12 puestos, y ya somos más de 40 trabajando en la oficina!</p><p>Como la oficina empezó a crecer, tener que decidir cada día quiénes almorzaban se hizo un problema. <a href="https://blog.platan.us/antes-el-malo-era-yo-55fad36b1868">Agustín lo solucionó haciendo la primera versión de Ham.</a></p><p>Ham (el mono) es un bot de Slack que elige a los que almorzarán la comida de la Vicky.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eq38UzwQQVbNV8_LBeyfdQ.png" /><figcaption>Ham, el mono</figcaption></figure><h4>¿Cómo funciona?</h4><p>El mono nos pregunta por Slack todos los días a las 3 pm si queremos almorzar el día siguiente en la oficina. Tipo 8 pm sortea quienes serán los que almorzarán.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ecr2txVBPtzROiEtqSMdmA.png" /><figcaption>Hay que responderle “sí” o “no”</figcaption></figure><p>Si quedas en el almuerzo, se te descuenta “karma”. El karma es como un sistema de “puntos” o una “moneda” de los almuerzos. No puedes decirle al mono que quieres almorzar si no tienes karma!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*il_kYRKfoRE_50687y5Kfg.png" /><figcaption>El mono avisa por el canal de Slack #cooking cuando hace el sorteo</figcaption></figure><p>A medida que usábamos la primera versión de Ham, surgieron algunas oportunidades y problemas. Y como somos muchos computines en la oficina, empezamos a atacarlos <a href="https://emojipedia.org/personal-computer/">💻</a>.</p><p>No sé cuándo terminamos de solucionar problemas y cuándo empezamos a hacer experimentos económico-sociales, pero la cosa se nos escapó de las manos (para bien).</p><p>Ham terminó siendo un laboratorio para probar dinámicas sociales con activos digitales. Les quiero contar sobre algunos de los experimentos, lecciones y situaciones que hemos vivido con el mono.</p><h3>1. Confianza</h3><p>Hubo un momento en que la confianza en Ham se estaba yendo a la cresta. La gente apostaba karma en cualquier cosa. Algunas personas aparecían mágicamente con mucho karma.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/256/1*NHWT6edfu7QhNh18HO_ENg.png" /><figcaption>Teníamos una card en Trello sobre eso</figcaption></figure><p>Había una sensación de guata de que había algo raro. ¿Por qué yo valoro muchísimo más mi karma que otras personas? ¿Por qué algunos están en modo casino todo el rato? ¿Por qué la gente en modo casino igual almuerza harto?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*Q9IUB9YvJWKu2daxLYecmw.png" /><figcaption>Y almorzaba harto este sujeto</figcaption></figure><p>Con Griffero decidimos descubrir qué pasaba.</p><p>Implementamos que en el canal de Slack <em>#karma-audit</em> (yo le quería poner <em>#karma-blockchain</em>) se avisara cada vez que alguien traspasaba un karma o un almuerzo.</p><p>Dos horas después entendimos nuestra sensación de güata.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/1*7dUtgEcLDGY_Ft_8B5JY6Q.jpeg" /></figure><p>Se confirmaban los rumores. Cuando alguien se iba de la oficina, le transfería mucho karma a algunas personas.</p><p>Fome igual.</p><p>No estaba prohibido por las reglas. Nada ni nadie decía que no se podía hacer. Pero claramente alteraba el sistema. Algunos quedaban con mucho karma y tenían rienda suelta para gastar.</p><p>Pero bueno, desde que implementamos<em> #karma-audit </em>el juicio público hizo lo suyo y estas transferencias fueron mucho menos comunes.</p><p>Igual pusimos un límite de transferencia de 5 karmas al día por si acaso 👹.</p><p><strong>Lección 1:</strong> la sensación de que todos jugamos con las mismas reglas es necesaria para que la gente confíe y le haga caso a un sistema.</p><p><strong>Lección 2: </strong>en un sistema que maneja cosas con valor, las “zonas grises” se van a usar. No se puede esperar que todos actúen como uno quiere. Hay que ir cubriendo los casos especiales a medida que aparecen.</p><h3>2. Orden y mercados eficientes</h3><p>Si alguien quedaba para el almuerzo, podía pasar que al final no iba a la oficina o que le salía un almuerzo en otro lado. Obviamente, a esa persona le interesaba recuperar el karma que usó para asegurar su puesto. Entonces intentaba vender su almuerzo.</p><p>Así se empezó a armar un mercado de compra-venta de almuerzos.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/0*8VJOY-BVYvJWtWh_" /></figure><p>Pero el proceso era super desordenado y tenía muchos pasos.</p><ol><li>Tenías que avisar por algún canal que querías vender el almuerzo.</li><li>Otra persona tenía que ver ese mensaje.</li><li>Se tenían que poner de acuerdo de manera explícita entre ellos.</li><li>Había que escribir dos comandos para hacer la transacción: uno para transferir el cupo y otro para transferir el karma.</li></ol><p>Siempre habían malos entendidos. No se respetaba el orden de los que decían que compraban, las transacciones no eran atómicas (alguien podía transferir el puesto y el otro no transferir el karma) y se perdía mucho tiempo.</p><p>Justo llegó Felipe a hacer su práctica. Decidimos atacar el problema. Armamos un equipo con Boris, Memo y Felipe, y desarrollamos un mercado de almuerzos automatizado.</p><p>Fue un éxito.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/728/1*h69RUVHw7J85PwZ-Yx9B1w.png" /></figure><p>Hoy día es una de las funcionalidades que más se usa.</p><p>“Formalizar” el mercado con software nos trajo hartos beneficios:</p><ul><li>Se hizo todo más ordenado</li><li>Perdemos menos tiempo coordinando</li><li>Se respeta el orden de llegada</li><li>Nadie puede hacerse el tonto y no transferir el karma</li></ul><h3>3. Escasez</h3><p>Hace un tiempo, cuando uno empezaba a trabajar en la oficina, se te asignaban 1000 puntos de karma. El almuerzo costaba 1 karma. O sea, tenías para 1000 almuerzos.</p><p>Pero 1000 es como mucho. La gente apostaba en juegos de cachipún, resultados de partidos de fútbol, compraba almuerzos por 10 karma, etc. No había una sensación real de escasez.</p><p>Decidimos experimentar un poco acá.</p><p>De manera absolutamente totalitaria, con Griffero le bajamos el karma a todo el mundo. Si tenías 1000, después de la expropiación quedabas como con 30. Las proporciones entre todos se mantenían eso sí.</p><p>Arriesgado igual. Me sorprendió que nadie terminara muy enojado.</p><p>Pero resultó. El karma ya no se gasta en cualquier cosa. Es algo que la gente valora más.</p><p><strong>Lección:</strong> la escasez de un activo es necesaria para que este tenga valor. Si no es escaso, lo más probable es que valga muy poco (hola Venezuela).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/752/1*PXP1o4z1B5C6lSqNM_I5qw.png" /><figcaption>Ahora soy bien pobre</figcaption></figure><h3>4. Experimento socialista</h3><p>Pero ahora teníamos un nuevo problema. ¿Qué pasa si a alguien se le acaba el karma? Antes tenías 1000, no había que preocuparse mucho del futuro. Pero ahora todos tenían entre 20 y 40. Eso significaba que en 3 o 4 meses podíamos quedarnos todos sin karma y nadie podría almorzar. Ups.</p><p>Entonces, ¿cómo lo hacemos para que no lleguemos a cero karma? Evaluamos hartas opciones, pero nos la jugamos con que Ham juntara todo el karma que se gastaba en almuerzos y que lo repartiera entre todos a fin de mes.</p><p>Había un pequeño problema eso sí. Si proyectamos el sistema al infinito, pasaría que los que almuerzan poco van a ser muy adinerados, y los que almuerzan mucho van a tener 0 karma durante gran parte del mes.</p><p>Para solucionarlo decidimos estimular un poco el gasto. Pusimos un límite a la riqueza. Lo máximo que puedes tener es 40 de karma. Con esto creamos un incentivo para que los ricachones almuercen en la oficina y compartan con la gente. También se consigue que los pobres reciban más karma en la repartija mensual. Bien socialista igual.</p><p>A mí parecer funciona bien. El sistema parece estar en equilibrio.</p><h3>5. Darle el poder a la gente</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*ywo356Bqp0wjc1UHKJ2D6Q.jpeg" /><figcaption>Trump citó a Bane de Batman alguna vez</figcaption></figure><p>Durante un tiempo, hubo una sensación de que los que venían menos a la oficina no eran seleccionados por Ham para los almuerzos. Era fome. Había harta decepción en los que estaban trabajando harto remoto y venían a la oficina de vez en cuando.</p><p>Antes de lanzarnos a solucionar el problema, nos hicimos algunas preguntas. ¿Qué queremos arreglar? ¿Qué queremos mejorar? Nos dimos cuenta de que no podíamos definir una solución sin tener eso muy claro. Teníamos que definir nuestra “función objetivo” a optimizar. Nos fuimos en una volada media filosófica y llegamos a la conclusión de que el mantra tenía que ser:</p><p><em>Los que almuerzan poco en la oficina deben tener la oportunidad de almorzar cuando así lo decidan.</em></p><p>El almuerzo es un espacio para compartir con el resto de la oficina. Sería bueno que haya un poco de rotación de los comensales.</p><p>¿Cómo le damos más poder de decisión al usuario para aumentar su probabilidad de quedar en el almuerzo? Como somos un poco ludópatas, decidimos implementar <strong>apuestas</strong>.</p><p>Ahora, además de preguntarte si quieres almorzar el día siguiente, Ham te da la opción de apostar. Eso significa que puedes apostar 10 karmas si quieres para el almuerzo del día siguiente. Si apuestas más que el resto, quedas sí o sí!</p><p>Así se consigue un buen <em>trade-off</em>. ¿Quieres asegurarte el almuerzo? Entonces tienes que gastar más karma. Pero tienes que ser responsable, o te puedes quedar sin almuerzo hasta el mes siguiente! Ya ha pasado que alguien se queda sin karma por gastar mucho. Como diría el Tío Ben de Spiderman, “un gran poder conlleva una gran responsabilidad”.</p><p>Esta movida fue más capitalista. Le quitamos responsabilidad de decisión al Estado primate y se lo dimos a las personas.</p><h3>¿Qué vamos a hacer ahora?</h3><p>Hay algunas ideas dando vuelta. Por ejemplo, que uno pueda ganar karma por hacer buenas acciones en la oficina.</p><p>Pero ni idea cómo va a seguir esto. Hace 2 años era imposible pensar que Ham iba a ser lo que es ahora. Tampoco es fácil imaginar lo que va a ser en 2 años más.</p><p>Pero siendo bien honestos, el 99% del problema ya está solucionado. Estamos metiéndole mucha ingeniería a esto porque lo pasamos bien y porque nos gusta hacer experimentos con activos digitales. Hemos aprendido harto así.</p><p>Y quién sabe! Quizás con algún nuevo experimento esto se transforma en algo que se pueda vender.</p><p>Si te interesa saber cómo está funcionando Ham y los almuerzos ahora, puedes entrar a <a href="https://la-guia.platan.us/cultura-platanus/lunch">La Guía de Platanus</a> a mirar.</p><p>¿De dónde sacamos tiempo para hacer estas cosas? En Platanus los viernes los dedicamos a hacer cosas que nos hagan una mejor empresa. Ham cae en esa categoría.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=61ba5f3fcec6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/platanus/qu%C3%A9-hemos-aprendido-de-un-mono-que-pone-las-reglas-en-la-oficina-61ba5f3fcec6">Qué hemos aprendido de un mono que pone las reglas en la oficina</a> was originally published in <a href="https://medium.com/platanus">Código Banana: El blog de Platanus</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>