tag:blogger.com,1999:blog-198757582024-03-03T19:25:25.180-05:00PuroguramuNotas sobre programas, programación y lo que programoUnknownnoreply@blogger.comBlogger167125tag:blogger.com,1999:blog-19875758.post-57523361010656431062022-07-04T14:04:00.003-05:002023-05-18T09:10:29.228-05:00Cómo usar docx2html en angular<div class="separator" style="clear: both; text-align: center;"><br /></div><p>¿Quieres usar este procesador de documentos word en Angular? Te cuento el procedimiento que seguí y me funcionó. </p><p><a href="https://puroguramu.akcademia.xyz/posts/como-usar-docx2html-en-angular/" target="_blank">Cómo usar docx2html en Angular</a><br /></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-34043034139616968832022-06-26T00:49:00.007-05:002022-06-26T00:51:06.952-05:00Cómo forzar el idioma de Jenkins a Inglés<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3D-jRcm3RceoFP4J9IJoz8YFs8hs6CVwMG8olxUrze15nJx6AzOq4atCQG_8Wi8al5lxPEVdUUkK5tHnI7_-19K7DLhFET7R9C7oTWkj_OVaJzh4e_ItU_eEwwmVtTWKdCOyHOegxy12j-LgEiOxIkWHDs6Wv_pOiEGpSO4zBiCX6zE8Gg/s808/jenkins-english.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="416" data-original-width="808" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3D-jRcm3RceoFP4J9IJoz8YFs8hs6CVwMG8olxUrze15nJx6AzOq4atCQG_8Wi8al5lxPEVdUUkK5tHnI7_-19K7DLhFET7R9C7oTWkj_OVaJzh4e_ItU_eEwwmVtTWKdCOyHOegxy12j-LgEiOxIkWHDs6Wv_pOiEGpSO4zBiCX6zE8Gg/w640-h330/jenkins-english.png" width="640" /></a></div><br /><p><br /></p><p>¿Quieres forzar a que Jenkins use inglés para seguir mejor la documentación? Te cuento el procedimiento que seguí.</p><p><a href="https://puroguramu.akcademia.xyz/posts/como-forzar-jenkins-a-ingles/" target="_blank">Cómo forzar el idioma de Jenkins a Inglés</a> </p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-5763611735496697902022-06-24T17:09:00.006-05:002022-06-24T17:09:58.627-05:00Cómo instalar Jenkins en Windows<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBSRb45zzZOc8_y-CzeHetE52wKdOoM6xxJmbQzQhnohQY8-ox4Eeciir67I_E1vFHtSkjESe3U4AozIjfhcPgkir3I38IDxVKtJJiyjR388kNc2nZtmrD9Fow00K9O6C6PqS7x8j7uqDDzpFDM1Uji5Rs5JOGZk9KVAxLJmYDrZBu3iEmg/s808/jenkins-on-windows.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="416" data-original-width="808" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyBSRb45zzZOc8_y-CzeHetE52wKdOoM6xxJmbQzQhnohQY8-ox4Eeciir67I_E1vFHtSkjESe3U4AozIjfhcPgkir3I38IDxVKtJJiyjR388kNc2nZtmrD9Fow00K9O6C6PqS7x8j7uqDDzpFDM1Uji5Rs5JOGZk9KVAxLJmYDrZBu3iEmg/w640-h330/jenkins-on-windows.png" width="640" /></a></div><br /><strong style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px;"><br /></strong><p></p><p><strong style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px;">¿Quieres instalar este poderoso servidor de automatizaciones en una máquina windows?</strong><span style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px;"> Te cuento el procedimiento que seguí y me funcionó tanto en Windows Server 2019. Para Windows 10 Home Edition fue necesario hacer un parche previo.</span></p><p><a href="https://puroguramu.akcademia.xyz/posts/como-instalar-jenkins-en-windows/" target="_blank">Cómo instalar Jenkins en Windows</a> </p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-34240676866805639522022-03-12T00:50:00.005-05:002022-03-12T00:52:02.643-05:00Link hacia Whatsapp<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://puroguramu.akcademia.xyz/link-to-whatsapp.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="467" data-original-width="800" height="374" src="https://puroguramu.akcademia.xyz/link-to-whatsapp.jpg" width="640" /></a></div><br /><p></p><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;"><strong>¿Quieres crear un link que abra un chat en Whatsapp?</strong> Te cuento cómo lo solucioné con HTML.</p><ul style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Lo que necesitaba era que en el whatsapp del usuario se abriera un chat hacia cierto número y con un texto prestablecido.</li><li>Encontré que debía formar un url con un formato similar a <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">https://api.whatsapp.com/send?phone=51999888777&text=Hola</code><ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>El <strong>número de teléfono</strong> indicado por <em>phone</em> debe incluir el código del país (51 en este ejemplo)</li><li>El <strong>texto</strong> indicado por <em>text</em> debe ser <strong>url compatible</strong>, es decir que se pueda indicar a través del url.<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Puedes usar una herramienta como <a href="https://www.urlencoder.org/" rel="noopener noreffer" style="background-color: transparent; color: #2d96bd; overflow-wrap: break-word; text-decoration-line: none;" target="_blank">URLEncoder</a> para convertir tu texto. Incluso puedes poner emojis! 🙂</li><li>Si usas javascript para generar el enlace, la función <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">encodeURI</code> hace el trabajo.</li></ul></li></ul></li><li>De ese modo, es posible formar un enlace como este:</li></ul><div class="highlight" style="background-color: white; color: #161209; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-height: 1.4em; margin: 0.5rem 0px;"><div class="chroma open" style="position: relative;"><div class="code-header language-html" style="align-items: center; background: rgb(237, 237, 237); box-sizing: border-box; color: #9c9c9c; display: flex; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: bold; justify-content: space-between; width: 800px;"><span class="code-title" style="padding: 0.4rem; width: 756.938px;"><span class="arrow fas fa-chevron-right fa-fw" style="-webkit-font-smoothing: antialiased; display: inline-block; font-family: "Font Awesome 5 Free"; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1; padding: 0px 0.2rem; text-align: center; text-rendering: auto; transform: rotate(90deg); transition: transform 0.2s ease 0s; width: 1.25em;"></span></span><span class="copy" data-clipboard-text="<a href="https://api.whatsapp.com/send?phone=51999888777&text=Hola%21%20%F0%9F%91%8D%F0%9F%99%82">Saludar por Whatsapp</a>
" style="display: inline; padding: 0.4rem;" title="Copiar al portapapeles"><span class="far fa-copy fa-fw" style="-webkit-font-smoothing: antialiased; display: inline-block; font-family: "Font Awesome 5 Free"; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; line-height: 1; text-align: center; text-rendering: auto; width: 1.25em;"></span></span></div><div class="table-wrapper" style="max-height: 12000px; overflow: auto hidden; transition: max-height 0.8s cubic-bezier(0.5, 0, 1, 0) 0s;"><table style="background: rgb(245, 245, 245); border-collapse: collapse; border-spacing: 0px; border: none; margin: 0px; max-width: 100%; padding: 0px; white-space: nowrap; width: 947.141px;"><tbody><tr style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin: 0px; padding: 0px;"><td style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none; margin: 0px; padding: 0px;"><pre class="chroma" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; font-family: monospace, monospace; font-size: 1em; margin-bottom: 0px; margin-top: 0px; padding: 0.25rem 0px 0.25rem 0.5rem; tab-size: 4;" tabindex="0"><code class="language-html" data-lang="html" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px;"><span class="p" style="color: #a9a9b3;"><</span><span class="nt" style="color: #2b77fa;">a</span> <span class="na" style="color: #2b77fa;">href</span><span class="o" style="color: #f19b04;">=</span><span class="s" style="color: #24a443;">"https://api.whatsapp.com/send?phone=51999888777&text=Hola%21%20%F0%9F%91%8D%F0%9F%99%82"</span><span class="p" style="color: #a9a9b3;">></span>Saludar por Whatsapp<span class="p" style="color: #a9a9b3;"></</span><span class="nt" style="color: #2b77fa;">a</span><span class="p" style="color: #a9a9b3;">></span>
</code></pre></td></tr></tbody></table></div></div></div><ul style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Cuando el usuario hace clic en el enlace, le aparece un diálogo para permitirle ir a la app whatsapp (si está instalada), donde abrirá el chat correspondiente al número indicado y con el texto indicado pre llenado.</li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://puroguramu.akcademia.xyz/screenshot-whatsapp-hola.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="55" data-original-width="221" height="55" src="https://puroguramu.akcademia.xyz/screenshot-whatsapp-hola.png" width="221" /></a></div><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;">¿Conoces otro modo de hacer esto, o quizás de manera más sencilla? Puedes compartirlo en los comentarios 🙏</p><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;"><br /></p><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;"><i>Publicado originalmente en <a href="https://puroguramu.akcademia.xyz/posts/link-to-whatsapp/" target="_blank">AKC Puroguramu</a></i></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-67974698869630617192022-03-12T00:46:00.003-05:002022-03-12T00:48:19.067-05:00Solución al Vue Router y Vuex descontinuados para Vue2<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgwz4cOeswNK4Gp6SX9HCpz-TGTTpBS6nS4GEbqoGG4vrQYUrF0C9ZvOQmTHoALPKpGcynkEjknD9yPJT9UYCLPRE4U6TicilraZBxVa2P0iduFOhc_T1OHVabhuU5UvA1evEEIcSP8p5GrKdxO2SlbJBsOK68TwFJnCvSCQD7tqSWrAcumQg=s730" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="487" data-original-width="730" height="426" src="https://blogger.googleusercontent.com/img/a/AVvXsEgwz4cOeswNK4Gp6SX9HCpz-TGTTpBS6nS4GEbqoGG4vrQYUrF0C9ZvOQmTHoALPKpGcynkEjknD9yPJT9UYCLPRE4U6TicilraZBxVa2P0iduFOhc_T1OHVabhuU5UvA1evEEIcSP8p5GrKdxO2SlbJBsOK68TwFJnCvSCQD7tqSWrAcumQg=w640-h426" width="640" /></a></div><br /><p></p><p><strong style="color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px;">¿Tienes alguna aplicación vue2 que ha dejado de funcionar de pronto?</strong><span face="system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161209; font-size: 16px;"> </span><span face="system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161209; font-size: 16px;">Te cuento cómo solucioné la incompatibilidad que se presentó para vue-router y vuex.</span></p><ul style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Hoy noté que una de las aplicaciones que desarrollé con <strong>vue2</strong> estaba caída 🙈.<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Revisando la consola, noté que no encontraba <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">https://unpkg.com/vue-router@4.0.14/dist/vue-router.js</code>.</li><li>Ese era el destino final que correspondería al que le indicaba en mi código: <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">//unpkg.com/vue-router/dist/vue-router.js</code>.<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Cuando se indica así te lleva a la última versión, que al parecer ya no es más vue2 compatible.</li></ul></li></ul></li><li>Al parecer, la versión 4 de vue-router se ha vuelto <strong>vue3 compatible por default</strong>, así que hay que indicar explícitamente la versión vue2 compatible que uno quiere usar.</li><li>Pasé a indicar la <strong>versión 3 de vue-router</strong> y ya funcionó esa parte<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>De <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">//unpkg.com/vue-router/dist/vue-router.js</code> a <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">//unpkg.com/vue-router@3</code>. 👍🙂</li></ul></li><li>Luego pase a resolver el issue similar para el caso de <strong>vuex</strong>.<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Allí, también tuve tuve que indicar explícitamente la versión vue2 compatible (casualmente también es la 3)<ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>De <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">//unpkg.com/vuex</code> a <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">//unpkg.com/vuex@3</code>.</li></ul></li></ul></li><li>En mi caso, estos dos cambios fueron suficientes para que la aplicación volviera a estar operativa. ✌️🙂</li></ul><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;">¿Has encontrado alguna versión más reciente de estos paquetes que sea vue2 compatible? Puedes compartirlo en los comentarios 🙏</p><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;"><br /></p><p style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px;"><i>Publicado originalmente en <a href="https://puroguramu.akcademia.xyz/posts/solucion-vue-router-vuex-descontinuados-vue2/" target="_blank">AKC Puroguramu</a></i></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-91657258836144973512022-03-12T00:43:00.004-05:002022-03-12T00:43:48.343-05:00Hugo: Tips para publicar un post con un video de youtube<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhrrfEs5d7H9lSz3hgU_SugOr_ADYE_Q15g8ocRf8OQZNVdhZvEmco7Dh2_52jZbLqx08bC4RvZOngYpRhL-31VJIBQwJ4t3zKrLifZulFH-PSKPj02s3bdh3YBCh0mnrQX5Ix7HE8Cc3pu1vjF9Z3QlDrO5dhAJg-KJKuaZ0O2KEqQEQIPLg=s1493" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="1493" height="168" src="https://blogger.googleusercontent.com/img/a/AVvXsEhrrfEs5d7H9lSz3hgU_SugOr_ADYE_Q15g8ocRf8OQZNVdhZvEmco7Dh2_52jZbLqx08bC4RvZOngYpRhL-31VJIBQwJ4t3zKrLifZulFH-PSKPj02s3bdh3YBCh0mnrQX5Ix7HE8Cc3pu1vjF9Z3QlDrO5dhAJg-KJKuaZ0O2KEqQEQIPLg=w640-h168" width="640" /></a></div><br /><span style="color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, PingFang SC, Microsoft YaHei UI, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial, sans-serif;"><br /></span></div><ul style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Uso <a href="https://gohugo.io/" rel="noopener noreffer" style="background-color: transparent; color: #2d96bd; overflow-wrap: break-word; text-decoration-line: none;" target="_blank">Hugo</a>, con el tema <a href="https://hugoloveit.com/" rel="noopener noreffer" style="background-color: transparent; color: #2d96bd; overflow-wrap: break-word; text-decoration-line: none;" target="_blank">LoveIt</a>, para publicar un blog como este.</li><li>Para mostrar un video se puede usar el shortcode <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">youtube</code></li></ul><div class="highlight" style="background-color: white; color: #161209; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-height: 1.4em; margin: 0.5rem 0px;"><div class="chroma open" style="position: relative;"><div class="code-header language-markdown" style="align-items: center; background: rgb(237, 237, 237); box-sizing: border-box; color: #9c9c9c; display: flex; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: bold; justify-content: space-between; width: 800px;"><span class="code-title" style="padding: 0.4rem; width: 756.938px;"><span class="arrow fas fa-chevron-right fa-fw" style="-webkit-font-smoothing: antialiased; display: inline-block; font-family: "Font Awesome 5 Free"; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1; padding: 0px 0.2rem; text-align: center; text-rendering: auto; transform: rotate(90deg); transition: transform 0.2s ease 0s; width: 1.25em;"></span></span><span class="copy" data-clipboard-text="{{< youtube XaKhz3iAxqQ >}}
" style="display: inline; padding: 0.4rem;" title="Copiar al portapapeles"><span class="far fa-copy fa-fw" style="-webkit-font-smoothing: antialiased; display: inline-block; font-family: "Font Awesome 5 Free"; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; line-height: 1; text-align: center; text-rendering: auto; width: 1.25em;"></span></span></div><div class="table-wrapper" style="max-height: 12000px; overflow: auto hidden; transition: max-height 0.8s cubic-bezier(0.5, 0, 1, 0) 0s;"><table style="background: rgb(245, 245, 245); border-collapse: collapse; border-spacing: 0px; border: none !important; margin: 0px; max-width: 100%; padding: 0px; white-space: nowrap; width: 800px;"><tbody><tr style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none !important; margin: 0px; padding: 0px;"><td style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: none !important; margin: 0px; padding: 0px;"><pre class="chroma" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; font-family: monospace, monospace; font-size: 1em; margin-bottom: 0px; margin-top: 0px; padding: 0.25rem 0px 0.25rem 0.5rem; tab-size: 4;" tabindex="0"><code class="language-markdown" data-lang="markdown" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px;">{{<span class="p" style="color: #a9a9b3;"><</span> <span class="nt" style="color: #2b77fa;">youtube</span> <span class="na" style="color: #2b77fa;">XaKhz3iAxqQ</span> <span class="p" style="color: #a9a9b3;">></span>}}
</code></pre></td></tr></tbody></table></div></div></div><ul style="background-color: white; color: #161209; font-family: system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Para obtener una featured imagen para el post del video, se puede usar <a href="http://www.get-youtube-thumbnail.com/" rel="noopener noreffer" style="background-color: transparent; color: #2d96bd; overflow-wrap: break-word; text-decoration-line: none;" target="_blank"># Get YouTube Video Thumbnail Image</a><ul style="list-style-type: disc; margin: 0.5rem 0px; padding-left: 2.5rem;"><li>Requiere el url del video</li></ul></li><li>Para mostrar la feature image en el listado del home pero no dentro del post (ya que el video ya lo tiene), se puede usar en el front matter <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">featuredImagePreview</code> en lugar de <code style="background: rgb(245, 245, 245); color: #e74c3c; display: inline-block; font-family: "Source Code Pro", Menlo, Consolas, Monaco, monospace, system-ui, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei UI", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 0.875rem; line-break: anywhere; max-width: 100%; overflow-wrap: break-word; padding: 0px 0.4rem;">featuredImage</code></li></ul><p><br /></p><p><i>Publicado originalmente en <a href="https://puroguramu.akcademia.xyz/posts/2022/01/hugo-youtube-post/" target="_blank">AKC Puroguramu</a></i></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-63415728654166633512021-03-21T22:42:00.018-05:002021-07-22T01:08:09.992-05:00Reflexiones sobre la autoeficacia<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGI6BQ4wRiI7uIbDSRE-85JJdwR5nOlFWgH4mfbQOE8yoHuvZKoQ8qiZ_oFl9_KZ5Z5c18aygIjVom06kEIDVtKeLcghdaI7ws4MLCodT3yk2d1Hq6jvv6eN4RIPlxCUOSuIwx/s4000/IMG_20210110_201004.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4000" data-original-width="3000" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGI6BQ4wRiI7uIbDSRE-85JJdwR5nOlFWgH4mfbQOE8yoHuvZKoQ8qiZ_oFl9_KZ5Z5c18aygIjVom06kEIDVtKeLcghdaI7ws4MLCodT3yk2d1Hq6jvv6eN4RIPlxCUOSuIwx/w300-h400/IMG_20210110_201004.jpg" width="300" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><div><br /></div>Hay un concepto que me parece interesante. <b>Autoeficacia</b>. Es la creencia de uno mismo de ser capaz de realizar algo. <br /><br />Si lo has hecho muchas veces antes, es prácticamente del 100%. O si has hecho algo parecido. O si has visto que lo han conseguido antes personas con las que te identificas, como familares o amigos. <br /><br />Esto explica por qué muchos eligen en la vida la misma profesión que sus familiares o amigos, o gente cercana de su comunidad. Porque su ejemplo de éxito les da un mayor nivel de autoeficacia para andar ese mismo camino. <br /><br />Si es tu primera vez enfrentando algo que tiene muchos aspectos desconocidos, quizás sientas un nivel de autoeficacia muy bajo o de 0%. <br /><br />Aunque no necesariamente. Los emprendedores, por ejemplo, pueden sentir una autoeficacia muy alta o de 100% aún cuando no tengan ninguna certeza del camino que están tomando o de las cosas que les tocará hacer. Simplemente confían en que serán capaces de sortear las dificultades que aparezcan, cuando aparezcan, si es que aparecen, aunque no sepan de antemano cuáles serán. <br /><br />Tener un alto nivel de autoeficacia es algo muy positivo a la hora de enfrentar un problema. <br /><br />Sentir que puedes hacerlo, aunque ahora no sepas exactamente cómo, es un gran super poder.<div><br /></div><div>Pienso que se apoya en tus experiencias exitosas enfrentando lo desconocido. Si siempre has ido a la segura, por caminos pautados, probablemente te cueste más. O también si has tenido experiencias desafortunadas al respecto.<br /><br />Cuando sientes un nivel bajo de autoeficacia, puedes tender a <b>procrastinar</b>; a entretenerte haciendo otras cosas. A otros esto le puede parecer inútil, perezoso o evasivo, pero en realidad indica que estás buscando formas de sentir la autoeficacia que te está faltando. Logros que alcances en un juego, o ver cómo otros logran algo, o evocar logros pasados, o imaginarlos en el futuro, etc. Básicamente, estas tratando de visualizar que puedes. <br /><br />El empeño en alcanzar la <b>perfección</b> también sería una búsqueda de sentir mayor autoeficacia. Pero el perfeccionista cae en la trampa de confundir la herramienta con la solución. Y en el afan de tener todo perfecto como requisito para hacer cualquier cosa. <br /><br />Haciendo cosas, y resolviendo problemas con un inventario imperfecto es que la autoeficacia se fortalece. <br /><br />Cuando navegas en la red, ves mucha búsqueda de estar preparado, de dominar algo, de tener el mejor inventario de habilidades posible, las mejores herramientas. <br /><br />Tener el mejor martillo no es el problema, sino lo que podamos construir usando ese martillo. Tener el mejor martillo seguramente ayudaría, pero es importante tener claro cuál es la herramienta y cuál lo que queremos construir. <br /><br />Cuál es el mejor lenguaje de programación? Tal vez éste lo sea. Y el mejor framework?. Quizás esté otro. Y la persona con el mejor curriculum? A lo mejor esta. Resulta que la mayoria de veces, nos dedicamos más a tener perfectos esos detalles, porque buscamos aumentar nuestro nivel de autoeficacia. Pero si distinguimos que son herramientas para conseguir solucionar algo, entonces tendremos más comprensión de la realidad, más tolerancia cuando las dificultades no se inclinen ante nuestras habilidades, y más tolerancia a nuestras imperfecciones y a las de los demás. Sobre todo cuando alguien "menos perfecto" usando las herramientas "menos perfectas" es quien logra solucionar los problemas con éxito.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-87220389290178673122019-11-07T12:06:00.002-05:002020-06-26T11:48:30.169-05:00Nodemon indica puerto ocupado: una soluciónUsando nodemon en express:<br />
<br />
<b>package.json
</b><br />
<pre> ...
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon ./bin/www"
},
...
</pre>
<br />
A veces me pasa que indica que el puerto ya está ocupado. Entonces, procedo a matar el proceso para comenzar otra vez.<br />
<br />
<pre>$ lsof -i:3000
$ kill 1234
</pre>
<pre>$ npm run dev</pre>
<br />
Donde 3000 sería el puerto y 1234 el PID del proceso.
<br />
<br />
Una forma de aliviar la molestia:<br />
<br />
<pre>$ kill $(lsof -i:3000 -t); npm run dev
</pre>
<br />
Otra forma es usar kill-port y un delay.
<br />
<br />
<pre>$ npm install --save-dev kill-port
</pre>
<br />
<b>package.json
</b><br />
<pre> ...
"scripts": {
"start": "node ./bin/www",
"dev": "<span style="background-color: yellow;">kill-port 3000</span> && nodemon <span style="background-color: lime;">--delay 1</span> ./bin/www"
},
...
</pre>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-30459756887269750002019-09-29T02:15:00.002-05:002019-11-05T12:23:10.984-05:00Vue Simple App: Sin webpack<div style="text-align: center;">
<i>Vue, Router, Vuex y Vuetify, pero sin webpack</i></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHtE88l8BbwyIelGtlqJMNiyBMK98oupNSXBrWoby1AqWMWdFE6kWnxEFwexzCWV4cOYk9IlmrYV0kkmHlysKRZ46TL_zFCo8njKELxl3_Nobi-gwRvelp6VT2jrQAUIvDlUNz/s1600/vuejs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="400" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHtE88l8BbwyIelGtlqJMNiyBMK98oupNSXBrWoby1AqWMWdFE6kWnxEFwexzCWV4cOYk9IlmrYV0kkmHlysKRZ46TL_zFCo8njKELxl3_Nobi-gwRvelp6VT2jrQAUIvDlUNz/s320/vuejs.png" width="320" /></a></div>
<i>[Actualizado el 2019/11/05: "Carga dinámica"]</i><br />
<br />
Tal vez no tenga ninguna razón técnica importante para preferir prescindir de <b>webpack</b> al desarrollar una aplicación web.<br />
<br />
Tal vez sea solamente nostalgia por los viejos tiempos, donde simplemente importabas librerías en la página y la magia podía aparecer.<br />
<br />
Tal vez no sea mala idea tener esa capa extra que cargar en el viaje, y aceptarla a cambio de los caramelos que nos regala.<br />
<br />
Pero a mi me molesta un poco.<br />
<br />
Preferiría no tener que usarla si puedo evitarlo.<br />
<br />
Siento que hay que tener cuidado cuando algo aumenta la complejidad. Mayor velocidad o comodidad pueden ser justificaciones. Pero hay que estar atentos a no limitar la diversidad de opciones.<br />
<b><br /></b>
Una de las cosas que me gusta de<b> Vue</b> es que puedo empezar muy simple, importando la librería en la página. Y luego, si el problema lo amerita, ir escalando la solución hacia algo más y más complejo. Es como empezar descalzo si quiero, o con sandalias, e ir cambiando según lo amerite el terreno.<br />
<br />
La mayoría de tutoriales parece estar de acuerdo en que usar <b><i>vue create</i></b> es la opción más práctica. Sin embargo, algo que descubrí es que también se puede llegar a elaborar soluciones relativamente complejas sin usar un transpilador.<br />
<br />
Esta es una guía en un proceso de desarrollo simple que nos permita usar <b>Vue</b>, <b>Router</b>, <b>Vuex</b> y <b>Vuetify</b>, sin necesitar la complejidad extra de webpack.<br />
<h2>
HTML5</h2>
Un lugar simple donde empezar.
<br />
<script src="https://gist.github.com/akobashikawa/f3e6a1e34648aaed3edd0f79033ea883.js"></script>
<br />
HTML5: <a href="https://codepen.io/akobashikawa/pen/NWKVazJ">https://codepen.io/akobashikawa/pen/NWKVazJ</a><br />
<h2>
HTML5 + Vue</h2>
Importar vue y desarrollar un script en la misma página.<br />
<script src="https://gist.github.com/akobashikawa/54dc2e9dfca3aba0a8473180464b23b9.js"></script>
<br />
HTML5 + Vue: <a href="https://codepen.io/akobashikawa/pen/aborLgW">https://codepen.io/akobashikawa/pen/aborLgW</a><br />
<h2>
HTML5 + Vue + Router</h2>
Importar Vue Router para organizar la navegación.<br />
<br />
Eso también nos empuja a organizar el contenido en componentes, si es que no lo hemos hecho ya.<br />
<script src="https://gist.github.com/akobashikawa/34a65c7e4a56e8f35f0a50932699d7fb.js"></script>
HTML5 + Vue + Router: <a href="https://codepen.io/akobashikawa/pen/qBWGVEp">https://codepen.io/akobashikawa/pen/qBWGVEp</a><br />
<h2>
HTML5 + Vue + Router + Vuex</h2>
Importar Vuex para compartir un estado general entre los componentes.<br />
<script src="https://gist.github.com/akobashikawa/c756289edd1b6bd889044e8796061957.js"></script>
HTML5 + Vue + Router + Vuex: <a href="https://codepen.io/akobashikawa/pen/pozmdby">https://codepen.io/akobashikawa/pen/pozmdby</a><br />
<div>
<h2>
HTML5 + Vue + Router + Vuex + Vuetify</h2>
<div>
Para darle un look de app con Material Design.</div>
<div>
<br />
<script src="https://gist.github.com/akobashikawa/ddd1ecebab3a88ef7cf36090e8785732.js"></script>
</div>
<div>
HTML5 + Vue + Router + Vuex + Vuetify: <a href="https://codepen.io/akobashikawa/pen/bGbyYod">https://codepen.io/akobashikawa/pen/bGbyYod</a><br />
<h2>
Módulos</h2>
<div>
<div>
Cuando más componentes van apareciendo y el largo del archivo va haciendo complicada la edición, parece una señal para sacar el código javascript a otro archivo.</div>
<div>
<br /></div>
<div>
Javascript soporta <i>import</i>. Pero hay que usarla dentro de un <i><b>módulo</b></i>.</div>
<div>
<br />
<script src="https://gist.github.com/akobashikawa/be4a0a5663c0bfc82af5da8ffa8b7662.js"></script>
</div>
<div>
<a href="https://github.com/akobashikawa/vue-simple-app">https://github.com/akobashikawa/vue-simple-app</a><br />
<br />
<h2>
Carga dinámica</h2>
</div>
</div>
<div>
Algo que ocurre con los módulos declarados normalmente, es que se carga toda la estructura de dependencias desde el inicio.</div>
<div>
<br /></div>
<div>
Para prevenirlo, y que cada módulo se pueda cargar cuando se necesita y no antes, se puede usar la técnica de declarar el componente como resultado de una función:</div>
<div>
<br /></div>
<div>
Antes:<br />
<pre style="border-radius: 3px; box-sizing: border-box; line-height: 1.45; margin-bottom: 16px; overflow-wrap: normal; overflow: auto; padding: 16px;"><code style="background: initial; border-radius: 3px; border: 0px; box-sizing: border-box; color: #24292e; display: inline; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow-wrap: normal; overflow: visible; padding: 0px; word-break: normal;">import Counter from './Counter.js';</code><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-color: initial; border-image: initial; border-radius: 3px; border-style: initial; box-sizing: border-box; line-height: inherit;">
</span></pre>
Después:<br />
<pre style="background-color: #f6f8fa; border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; font-size: 13.6px; line-height: 1.45; overflow-wrap: normal; overflow: auto; padding: 16px;"><code style="background: initial; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; overflow-wrap: normal; overflow: visible; padding: 0px; word-break: normal;">const Counter = () => import('./Counter.js');</code></pre>
</div>
<div>
<br /></div>
<div>
<h2>
Conclusión</h2>
<div>
Es posible desarrollar vue apps de relativa complejidad sin necesidad de usar webpack.</div>
<div>
<br /></div>
<div>
Me parece que este esquema puede simplificar el inicio de un proyecto. Aún cuando la versión para producción pueda requerir webpack para las optimizaciones, se podría usar esto durante el desarrollo.</div>
<div>
<br /></div>
<div>
¿Qué ventajas o desventajas ves hacerlo de este modo?, ¿te parece que puede facilitar la depuración?, ¿crees que en el futuro los navegadores carguen los scripts de un modo que no sea necesario empaquetarlos como actualmente?</div>
</div>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-58971853143422315952019-09-27T17:08:00.001-05:002019-09-27T17:08:08.678-05:00Ajedrez MentalA menudo hay profesionales que discuten y resuelven problemas simplemente hablando. Incluso problemas muy complejos. Sin apoyarse en anotar algo en el papel o la pizarra que está a su lado.<br />
<br />
Tal vez se vea un símbolo de status profesional. Un aviso de que somos lo suficientemente expertos para prescindir de esas herramientas.<br />
<br />
Pero, de vez en cuando, te encuentras con alguien que sí las aprovecha y el resultado es notable.<br />
<br />
Me parece que intentar resolver un problema solamente hablando es como jugar ajedrez mentalmente. Puede ser impresionante como show, pero tiene algunas desventajas para considerar:<br />
<ul>
<li>Además de la tarea de buscar la mejor jugada, se gasta energia mental en mantener una imagen compartida del tablero.</li>
<ul>
<li>Es más fácil que pierdas de vista una pieza</li>
<li>Es más difícil evaluar una posicion</li>
<li>Es más difícil explorar algo complejo, o arriesgado, o de mucha profundidad</li>
</ul>
<li>Al no haber algo tangible, es más vulnerable a las relaciones de poder de los participantes</li>
<ul>
<li>Es más fácil ceder ante el experto que insistir en tu punto de vista, aunque sientas que el experto está equivocado</li>
<li>Es difícil que alguien se anime a decirle al campeón que la posición de las piezas no es la que el dice</li>
<li>Hay expertos o campeones que pueden usar esto para intentar atarantar a quienes tienen menos poder</li>
</ul>
</ul>
<br />
En cambio, al usar papel o una pizarra es como jugar ajedrez con un tablero físico<br />
<ul>
<li>Visible para todos</li>
<ul>
<li>Cualquiera que pase puede verlo y darse una idea de la situación</li>
<li>Es más fácil ver las piezas</li>
</ul>
<li>Tienes más energía mental disponible</li>
<ul>
<li>Es más fácil evaluar una posición</li>
<li>Es más fácil descubrir algo que no esperabas</li>
<li>Puedes explorar variantes más complejas o arriegadas</li>
</ul>
<li>Puedes anotar las partidas y revisarlas luego</li>
<ul>
<li>Aprender</li>
<li>Explorar variantes</li>
</ul>
<li>Es menos vulnerable a las relaciones de poder</li>
<ul>
<li>Con una prueba evidente, es más fácil rebatir a un experto o campeón que se haya equivocado</li>
</ul>
</ul>
<br />
Pienso que usar anotaciones para apoyar una conversación o una explicación debería ser la regla y no la excepción.<br />
<br />
Quizás habría que estar atento cuando alguien que pudiendo usar anotaciones no lo hace. Podría estar tratando de ocultar algo.<br />
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-42837058322621711932019-09-14T23:51:00.000-05:002019-09-18T23:28:11.471-05:00Sobre desarrollo de software<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkj5qkIJycIkJhgTvkt7-ulP2w64NLIbB3i5nuutCtk2n7H96h0hgaQgOP7AOwqG6wTic2SIbuj9u1Zrkfg8LHpBlerIDYK5IbvlydWpRvuX28jVgJIpcXHYGK7koE-UBZYdtX/s1600/kisspng-sisyphus-clip-art-firefighting-5aeb1d4ce15576.454939431525357900923.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="947" data-original-width="1250" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkj5qkIJycIkJhgTvkt7-ulP2w64NLIbB3i5nuutCtk2n7H96h0hgaQgOP7AOwqG6wTic2SIbuj9u1Zrkfg8LHpBlerIDYK5IbvlydWpRvuX28jVgJIpcXHYGK7koE-UBZYdtX/s400/kisspng-sisyphus-clip-art-firefighting-5aeb1d4ce15576.454939431525357900923.png" width="400" /></a></div>
<div style="text-align: center;">
<i><br /></i></div>
<div style="text-align: center;">
<i>La administración de la energía creativa sería la clave para un proyecto exitoso</i></div>
<br />
Desarrollar software es un proceso que se viene descubriendo.<br />
<br />
Hay quienes han intentado amoldarlo a un esquema como el que se sigue en la ingeniería o la arquitectura. Parece funcionar en algunos casos, pero no ha resultado satisfactorio siempre.<br />
<br />
Aún hoy, décadas después de creada la ingeniería de software o las ciencias de la computación, a veces no es claro por qué un proyecto de desarrollo que parece bueno fracasa. O por qué uno que parece absurdo temina triunfando sobre todas las demás opciones.<br />
<br />
Algo que hay que tener en cuenta es que el software no solamente debe correr en la computadora, sino en el sistema determinado por las personas que lo usen.<br />
<br />
La <i>ingeniería de software</i> y <i>las ciencias de la computación</i> suelen concentrarse en cómo crear algoritmos que corran eficientemente en una computadora. La <i>UX</i>, o <i>experiencia de usuario</i>, se concentra en cómo sintonizar con las necesidades reales de las personas que usarán la solución que se desarrolla.<br />
<br />
Desarrollar software no es como realizar una tarea, donde cada paso es sobre terreno conocido. Es más como resolver un problema. Es decir, es como avanzar por una curva cuyo curso no es evidente. Hay que recurrir a la experiencia pero también a la intuición. Como cuando se hace arte.<br />
<br />
Me parece que la mejor manera de desarrollar software es iterádamente, iniciando con una base muy simple y luego ir evolucionando para alcanzar lo que se requiere.<br />
<br />
Esto requiere un proceso de desarrollo que sea sostenible y escalable. <i>Sostenible </i>significa que se pueda repetir una y otra vez el ciclo de mejora. <i>Escalable </i>significa que puede soportar el siguiente estado de evolución del producto.<br />
<br />
Muchos desarrolladores se preocupan mucho por si el producto es escalable. De si podrá soportar diez veces más usuarios, o cien veces más datos. Creo que más importante que la escalabilidad del producto es la escalabilidad del proceso para desarrollar el producto.<br />
<br />
Creo que la razón principal por la que los proyectos de desarrollo de software a menudo fracasan es porque no logran formar un proceso de desarrollo escalable. Suelen usar un esquema de producción en línea, como en una fábrica donde cada pieza es conocida, en lugar de espiral, como en un laboratorio donde cada pieza se está ensayando sobre un diseño que se va descubriendo. Conforme la complejidad aumenta, distintas partes del proyecto van cayendo bajo su propio peso, hasta que todo colapsa. O sigue adelante con montones de parches y apuntalamientos de emergencia que hacen que no sea posible continuar con su evolución de manera clara.<br />
<br />
Quizás esto se pueda ver mejor considerando que existe una <i>energía creativa</i>. Es la energía con la que se cuenta para convertir una idea en un producto de software.<br />
<br />
Mientras no se llega a un un producto concreto, la energía creativa va disminuyendo. Es como cuando un móvil se va empujando. Para que gane altura o gane velocidad, hay que gastar energía empujándolo contra la gravedad o la fricción. Cuanto más largo es el salto, más fuerza, velocidad y energía se requieren.<br />
<br />
Pero cada vez que se llega a un producto concreto, ganamos un nuevo punto de apoyo para dar el siguiente paso desde allí. Esta energía permite ir por una siguiente versión. Es más fácil, y más sostenible, llegar al quinto escalón desde el cuarto que desde el primero.<br />
<br />
Podemos ilustrar esto imaginando que el proyecto es como llevar una bola de nieve cuesta arriba. Al inicio, reunimos nieve de aquí y de acá y empezamos a rodar esa bola inicial fácilmente. Conforme la bola crece, va requiriendo más energía. Entonces llegamos a una pequeña meseta. Eso nos permite recuperar energía, apreciar lo que hemos recorrido y ver mejor cómo continuar. Luego seguimos subiendo, gastando energía hasta que lleguemos a la siguiente meseta, donde nos recuperamos. En el viaje, vamos decidiendo si necesitamos ayuda de más personas para seguir empujando la bola, despejando el camino, apuntalando, etc. Cada vez requerirá más energía poder avanzar y llegar a una meseta segura. Puede ser que esa meseta sea la cima, y el proyecto llegue así a buen término. Puede ser que no sea la cima pero una meseta cercana y aceptable. O puede ser que no se encontró una meseta a tiempo y, sin un apoyo adecuado ni energía para continuar, la bola se tuvo que soltar, yéndose cuesta abajo.<br />
<br />
<i>Versionado frecuente</i>. Una buena estrategia es tener mesetas frecuentes. Es decir, sacar versiones completamente funcionales frecuentemente. No importa si es un paso corto si podemos continuar andando. Los pasos acrobáticos son un lujo que puede no ser sostenible. Los periodos de desarrollo largos que no concretan van consumiendo la energía riesgosamente.<br />
<br />
<i>Ir ligero (LEAN)</i>. Otra buena estrategia es mantener la bola en un tamaño manejable. Es decir, ir dejando atrás aquello que ya no es necesario para que siempre podamos avanzar con los recursos que tenemos.<br />
<br />
<i>Dividir y vencer</i>. Otra buena estrategia es dividir el trabajo en varias bolas que lleguen a la cima. Es decir, poder separar el proyecto en partes independientes y fáciles de manejar que puedan ser conectadas luego.<br />
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 10pt; margin-top: 0pt;">
<span id="docs-internal-guid-979c16fc-7fff-f300-8351-bf836ddf03e8"><i>Testing (TDD)</i>. Otra buena estrategia es apuntalar el avance de la bola. Es decir, contar con pruebas de código o de flujo que validen el estado del proyecto. Se pueden poner luego de que la bola ya alcanzó cierta posición pero suele ser mejor estrategia ponerlas primero y luego mover la bola hacia allí.</span><br />
<span id="docs-internal-guid-979c16fc-7fff-f300-8351-bf836ddf03e8"><br /></span>
<span id="docs-internal-guid-979c16fc-7fff-f300-8351-bf836ddf03e8"><i>Sinergia</i>. Otra buena estrategia es rodar armoniosamente la bola. Es decir, que cada persona del equipo sintonice con el propósito del proyecto, y tenga la autonomía que le permita usar sus habilidades con maestría para colaborar en su realización.</span><br />
<br />
<i>La trampa del perfeccionismo</i>. Una estrategia no muy buena es querer empezar con un montón de nieve demasiado grande. Es decir, requerimientos iniciales demasiado complejos, por número o por dificultad. Son más firmes las bolas de nieve que van creciendo y haciéndose redondas por su propio rodar. A menudo, querer empezar con algo que parezca perfecto para impresionar a los demás suele conducir a parálisis por análisis: el proyecto empieza a procrastinar, la energía creativa se diluye, y finalmente no despega.<br />
<br />
<i>La trampa de la temeridad</i>. Otra estrategia no muy buena es ignorar la ayuda de apuntalamientos y confiar únicamente en el propio esfuerzo para mantener la bola en curso. Es decir, no tener pruebas que permitan verificar que se está donde se debe estar. Implementar pruebas requiere algo de energía creativa, pero luego permite ahorrar mucha más.<br />
<br />
<i>La trampa de la insensibilidad</i>. Otra estrategia no muy buena es ignorar que quienes ruedan la bola son personas. Es decir, se cae en tentación de creer que bastan las herramientas, las técnicas o la infraestructura, o la capacidad de hacer algo, para que ese algo se pueda realizar, ignorando que hay un aspecto social, con una voz que debe ser escuchada y honrada. Hay redes de confianza que deben ser tejidas y mantenidas, para que las personas puedan realizarlo.</div>
Hay proyectos con pendientes de dificultad muy llevaderos, donde parece que se puede ir con facilidad hacia cualquier dirección y se llega a la cima de un modo predecible.<br />
<br />
Hay otros proyectos donde el terreno no es parejo, la nieve es irregular y sopla la ventisca.<br />
<br />
Llevar exitosamente la bola de nieve a la cima no depende solamente de cuánta gente la empuja ni cuánta fuerza tenga. Depende de ser capaz de llegar oportunamente a las mesetas adecuadas. Es entender el terreno, el clima, la nieve, la gente, su fuerza, sus habilidades, y poder manejar todo eso.<br />
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-62776885352854088602019-01-11T10:35:00.000-05:002019-01-11T10:35:01.894-05:00Resultados del 2018 Ionic SurveyResultados del 2018 Ionic Survey:<br />
<br />
<a href="https://ionicframework.com/survey/" rel="nofollow" target="_blank">https://ionicframework.com/survey/</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-27207295881317616632018-12-31T14:59:00.002-05:002018-12-31T15:01:42.728-05:00Hello Jenkins: Como rootEn el post <a href="https://akcaprendiendo.blogspot.com/2018/12/hello-jenkins.html" target="_blank">Hello Jenkins</a>, exploré cómo podría automatizar el deploy de un site estático simple con ayuda de Jenkins.<br />
<br />
Este site estático está alojado en mi directorio web personal ~/public_html. Para que Jenkins pudiera hacer pull allí, fue necesario que tuviera derechos sobre los archivos de ese directorio, así que opté por agregarlo a mi grupo de usuario.<br />
<br />
Ahora exploro cómo sería si quisiera que Jenkins pudiera hacer pull en el directorio web /var/www.<br />
<br />
En mi Jenkins, proyecto hello-jenkins, Configuration, Source Code Management:<br />
<br />
<ul>
<li>En <b>Aditional Behaviours</b>, pruebo agregar:</li>
<ul>
<li><b>Chek out to a sub-directory</b></li>
<ul>
<li>Local sub-directory for repo:<br />/var/www/html/demos/hello-jenkins/</li>
</ul>
</ul>
</ul>
<div>
<span style="background-color: #f4cccc;">Una prueba muestra un error de acceso al directorio</span>. Probé agregar jenkins al grupo sudo y tambien visudo, pero no pude solucionarlo.</div>
<div>
<br /></div>
<div>
Opto por agregar el siguiente script en <b>Build</b>:</div>
<div>
<ul>
<li>echo "hello-jenkins build"</li>
<li>cd /var/www/html/demos/hello-jenkins</li>
<li>sudo git pull</li>
</ul>
<span style="background-color: #d9ead3;">Hago la prueba y funciona como se espera</span>. Se hace pull al hello-jenkins en mi directorio personal public_html/ y tambien en el directorio web /var/www/.<br />
<br />
<br />
<div style="text-align: center;">
<i><a href="https://akcaprendiendo.blogspot.com/2018/12/hello-jenkins-como-root.html" target="_blank">Post original en https://akcaprendiendo.blogspot.com/2018/12/hello-jenkins-como-root.html</a></i></div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-55862327311686866112018-12-30T23:28:00.005-05:002018-12-30T23:36:03.036-05:00Hello Jenkins<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAi-CYHp2HMe7i2BRmjXAoPQBN-sDCdzGHrCo3Coc6lFoeMwjTXzpKa5AixBZp4CNA9lP0SD1HOmeUAZF-H5QmXr3fFnGPu1fCbRX9k0JFY_VtA6QyPf_qPijQtYfvTsC3CpUadA/s1600/jenkins-ci_512.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAi-CYHp2HMe7i2BRmjXAoPQBN-sDCdzGHrCo3Coc6lFoeMwjTXzpKa5AixBZp4CNA9lP0SD1HOmeUAZF-H5QmXr3fFnGPu1fCbRX9k0JFY_VtA6QyPf_qPijQtYfvTsC3CpUadA/s320/jenkins-ci_512.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
En días recientes estuve viendo un poco de <i>Continuous Integration / Continuous Deployment</i> (CI/CD), con <b>Jenkins</b>.<br />
<br />
La idea que he captado es que Jenkins corre en el servidor donde normalmente ejecutamos a mano los pasos para deployar un proyecto. Luego configuramos las cosas para que Jenkins las haga por nosotros.<br />
<br />
Por ejemplo, puedo tener en mi hosting un site estático hello-jenkins, cuyo repositorio está en GitHub. Luego que hago push en el repo desde mi máquina local debo entrar a la consola de mi hosting y hacer pull. Quizás alguna cosa más, como bower o npm, dependiendo de la complejidad del proyecto.<br />
<br />
Empezaré con un simple site estático llamado <b>hello-jenkins</b>.<br />
<br />
<ul>
<li>En mi local, creo el proyecto hello-jenkins</li>
<li>En <b>GitHub</b>, creo el repositorio <a href="https://github.com/akobashikawa/hello-jenkins" target="_blank">hello-jenkins</a></li>
<li>En mi local, establezco al repo en GitHub como mi remoto y hago push</li>
<li>En mi hosting, clono el repo de GitHub</li>
<li><a href="https://rulokoba.me/~rulo/demos/hello-jenkins/">https://rulokoba.me/~rulo/demos/hello-jenkins/</a></li>
</ul>
<div>
Ahora, haré un cambio y un <b>deploy manual</b>.</div>
<div>
<ul>
<li>En mi local, agrego un title, commit y push</li>
<li>En mi hosting, hago pull</li>
<ul>
<li>Lo pesado de esta tarea es cuando no estoy logueado a la consola. Es necesario hacer ssh, ubicar la carpeta y hacer pull.</li>
<li>Si Jenkins vive en este servidor, podría hacerlo por mi ante una señal. Por ejemplo, cuando se hace un push en GitHub.</li>
</ul>
<li><a href="https://rulokoba.me/~rulo/demos/hello-jenkins/">https://rulokoba.me/~rulo/demos/hello-jenkins/</a></li>
</ul>
<div>
En el hosting, tengo instalado Jenkins siguiendo la guía de:</div>
</div>
<div>
<ul>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-16-04" target="_blank">How To Install Jenkins on Ubuntu 16.04</a></li>
<ul>
<li>Jenkins tiene una aplicación web que permite administrarlo a través del browser</li>
</ul>
<li>Además tiene instalado los plugins para Git y GitHub.</li>
</ul>
<div>
En mi Jenkins, creo el job hello-jenkins:</div>
</div>
<div>
<ul>
<li>Elijo <i>create new jobs</i></li>
<li><i>Enter an item name</i>: hello-jenkins</li>
<li>Elijo <i>Freestyle project</i></li>
<li>OK</li>
<li>En la sección de consiguración:</li>
<ul>
<li>Source Code Management</li>
<ul>
<li>Git</li>
<ul>
<li><i>Repository URL</i>: https://github.com/akobashikawa/hello-jenkins.git</li>
<li><i>Credentials</i>: none</li>
<li>Additional Behaviours</li>
<ul>
<li>Check out to a sub-directory</li>
<ul>
<li><i>Local sub-directory for repo</i>:<br />/home/rulo/public_html/demos/hello-jenkins/</li>
<li>Para que jenkins pueda escribir en este directorio se le puede agregar al grupo del usuario y reiniciar jenkins:</li>
<ul>
<li>$ sudo usermod -a -G rulo jenkins</li>
<li>$ sudo systemctl stop jenkins</li>
<li>$ sudo systemctl start jenkins</li>
</ul>
</ul>
</ul>
</ul>
</ul>
<li>Build Triggers</li>
<ul>
<li>GitHub hook trigger for GITScm polling</li>
</ul>
<li>Build (opcional)</li>
<ul>
<li>Execute shell</li>
<ul>
<li>Command</li>
<ul>
<li>echo "hello-jenkins build"</li>
</ul>
</ul>
</ul>
</ul>
</ul>
<div>
En el repo de GitHub, <i>Settings</i>:</div>
</div>
<div>
<ul>
<li>Webhooks</li>
<ul>
<li>Add webhook</li>
<ul>
<li><i>Payload URL</i>: http://myjenkins_url/github-webhook<span style="background-color: yellow;">/</span></li>
<ul>
<li>Es importante el trailing / al final</li>
</ul>
<li><i>Content type</i>: application/json</li>
<li>Which events would you like to trigger this webhook?</li>
<ul>
<li>[x] Let me select individual events.</li>
<ul>
<li>[x] Pushes</li>
<ul>
<li>[x] Pull requests</li>
</ul>
</ul>
</ul>
<li>[x] Active</li>
<li>Add webhook</li>
<li>Es importante que GitHub pueda encontrar a Jenkins ya configurado</li>
</ul>
</ul>
</ul>
<div>
Para probar, manualmente:</div>
</div>
<div>
<ul>
<li>En mi Jenkins, en el projecto hello-jenkins, wlijo Build Now</li>
<li>En <i>Build History</i> aparecerá un nuevo item numerado, y le hago click.</li>
<li>Elijo <i>Console Output</i> para ver la salida</li>
</ul>
<div>
Para probar el build automático:</div>
</div>
<div>
<ul>
<li>En mi local, hago un cambio, commit y push al repo</li>
<li>En <i>Build History</i> aparecerá un nuevo item numerado, y le hago click.</li>
<li>Elijo <i>Console Output</i> para ver la salida</li>
</ul>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<i><a href="https://akcaprendiendo.blogspot.com/2018/12/hello-jenkins.html" target="_blank">Post original en https://akcaprendiendo.blogspot.com/2018/12/hello-jenkins.html</a></i></div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-42819664323215820412018-09-18T11:35:00.000-05:002018-09-18T11:35:32.662-05:00Solucionando conexión de strapi a mLab<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrnAwjsjITGrJ7kuunbobFrs2q9iWsP_DGgkZgeCV6NKPu4YRA_4Mmpqz8f5kK6uO-yLk8tu8Vprj3nX7K-vZ3Bei4qbjOo_kDQHJsxm1AX1ICqtpDvphD0jcVGEJDqcELcNpt/s1600/strapi-mlab-2-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="296" data-original-width="1600" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrnAwjsjITGrJ7kuunbobFrs2q9iWsP_DGgkZgeCV6NKPu4YRA_4Mmpqz8f5kK6uO-yLk8tu8Vprj3nX7K-vZ3Bei4qbjOo_kDQHJsxm1AX1ICqtpDvphD0jcVGEJDqcELcNpt/s400/strapi-mlab-2-3.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<a href="https://strapi.io/" rel="nofollow" target="_blank">Strapi</a> es un framework para node que facilita la creación de un cms.<br />
<ul>
<li>Como base de datos puede usar mongo, mysql, postgres.</li>
<li>Como frontend puede usar vue, react, angular.</li>
<li>El panel de administración luce bastante similar al de wordpress.</li>
<li>Tiene un plugin para servir los datos con graphql.</li>
<li>El idioma se puede configurar a español.</li>
</ul>
<div>
<a href="https://mlab.com/" rel="nofollow" target="_blank">mLab</a> es un servicio que provee acceso a bases de datos mongo.</div>
<div>
<ul>
<li>Tiene una capa de uso gratuita (via AWS de Amazon)</li>
</ul>
</div>
<h2>
Instalación simple</h2>
<div>
<ul>
<li>Para usarlo con mongo, debe estar iniciado el servicio localmente</li>
<li>$ node --version</li>
<ul>
<li>Se requiere al menos la versión 9</li>
</ul>
<li>$ npm install -g strapi@alpha</li>
<ul>
<li>Por alguna razón, recomiendan que trabajemos con la versión más fresca</li>
</ul>
<li>$ strapi --version</li>
<ul>
<li>Actualmente 3.0.0-alpha.14.1.1</li>
</ul>
<li>$ strapi new myapp</li>
<ul>
<li>Creará la estructura de directorios.</li>
<li>Hay que elegir como base de datos a mongo e indicar los parámetros</li>
<ul>
<li>Esta data se guarda en <b>myapp/config/environments/development/database.json</b></li>
<li>La base de datos aún no se crea en este punto</li>
</ul>
</ul>
<li>$ cd myapp</li>
<li>$ strapi start</li>
<ul>
<li>Creará la base de datos</li>
<li>Iniciará el server</li>
<li><a href="http://localhost:1337/" rel="nofollow" target="_blank">http://localhost:1337</a></li>
</ul>
</ul>
<h2>
Problema con mongo externo</h2>
</div>
<div>
Por alguna razón, cuando se indica que se conecte a una base de datos mongo externa para development, strapi devuelve un error.</div>
<div>
<br /></div>
<div>
Encuentro que en la configuración para production hay una propiedad extra uri.</div>
<div>
<br /></div>
<div>
Cuando se usa esta propiedad uri en la configuración para development, ya es posible conectarse a una base de datos mongo externa, como mlab, por ejemplo.</div>
<h2>
Solución</h2>
<div>
<ul>
<li>$ strapi new myapp</li>
<ul>
<li>Crear la aplicación indicando una base de datos mongo local</li>
<li>Esto aún no creará ninguna base de datos</li>
</ul>
<li>Editar myapp/config/environments/development/database.json y agregar la propiedad uri:</li>
<li>$ cd myapp</li>
<li>$ strapi start</li>
</ul>
<div>
La configuración sería similar a:</div>
</div>
<div>
<pre>{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-hook-mongoose",
"settings": {
"client": "mongo",
"uri": "mongodb://username:password@hostname.mlab.com:12345/dbname",
"host": "hostname.mlab.com",
"srv": false,
"port": "12345",
"database": "dbname",
"username": "username",
"password": "password"
},
"options": {
"authenticationDatabase": "",
"ssl": false
}
}
}
}</pre>
</div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-78487153054036560752017-12-13T12:29:00.000-05:002017-12-13T12:57:13.754-05:00Test de internet con ping en NodeJS<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnj0KhRfyKsiar2jEkRG-vl3raKrrBzj4miuUFJ0YrfrnY9rCAVH6mNtGghhNBVET87NzSYJCrLRigRIViT8xCsreTMnBimGOkg9XT9qe0OCxdwyHlFPlQcUfu2tcckoIaMbLx/s1600/Ping-Tester-Pro-Full-9.52-for-APK-android-and-windows-300x300.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="300" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnj0KhRfyKsiar2jEkRG-vl3raKrrBzj4miuUFJ0YrfrnY9rCAVH6mNtGghhNBVET87NzSYJCrLRigRIViT8xCsreTMnBimGOkg9XT9qe0OCxdwyHlFPlQcUfu2tcckoIaMbLx/s200/Ping-Tester-Pro-Full-9.52-for-APK-android-and-windows-300x300.jpg" width="200" /></a></div>
<br />
En estos días he tenido intermitencias en el servicio de internet.<br />
<br />
Mi forma de comprobarlo es entrar en una consola y hacer ping a un host, como google.com, y ver si está ok o no.<br />
<br />
<pre>$ ping google.com -t
</pre>
<br />
El -t permite que el ping se haga indefinidamente, hasta que se presione CTR + C.<br />
<br />
Sin embargo, quería una forma de mostrar los cambios de estado, a qué hora ocurrían y cuánto duraban.<br />
<br />
Programé esta solución usando nodejs:<br />
<br />
<a href="https://gist.github.com/akobashikawa/1e6d906bc9d44f630206994874ab2fd4">GitHub Gist: Internet test with ping in NodeJS</a><br />
<br />
<pre>const ping = require('ping');
let host = '8.8.8.8';
if (process.argv[2]) {
host = process.argv[2];
} else {
console.log("Syntax: \nnode ping-test-ifchanges-host host");
}
console.log("Testing host: " + host);
let isAlivePrev = false;
let nowPrev = new Date();
function doPing() {
ping.sys.probe(host, isAlive => {
if (isAlive !== isAlivePrev) {
let now = new Date();
let diff = (now.getTime() - nowPrev.getTime())/1000;
let timestamp = now.toISOString() + ' after: ' + diff + ' s';
console.log("\n"
+ host + ': '
+ (isAlive ? ' OK' : ' KO')
+ ' ' + timestamp);
isAlivePrev = isAlive;
nowPrev = now;
} else {
process.stdout.write('.');
}
});
}
setInterval(doPing, 1000);
</pre>
<br />
Para correrlo en consola:
<br />
<br />
<pre>$ node ping-test-ifchanges-host google.com</pre>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPVnPWZZUlG6L9jEVtTLp-OqF9E50zeuTxnX9UMkAvCZRH9PnvHDswBUP8xscU8E_IhBDm1VRvs6SlCnVCBiUfUkciRi9e86tCgEF97t1A0bXwULQAtANG5Kvt9hLAsNzi6PGq/s1600/Screenshot+2017-12-13+12.51.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1114" data-original-width="1564" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPVnPWZZUlG6L9jEVtTLp-OqF9E50zeuTxnX9UMkAvCZRH9PnvHDswBUP8xscU8E_IhBDm1VRvs6SlCnVCBiUfUkciRi9e86tCgEF97t1A0bXwULQAtANG5Kvt9hLAsNzi6PGq/s320/Screenshot+2017-12-13+12.51.42.png" width="320" /></a></div>
<h3>
Idea</h3>
<div>
<i>setInterval() </i>establece un llamado, cada 1000 ms, a <i>doPing()</i>, que hace un ping al host que se haya indicado y revisa si hay un cambio de estado.</div>
<div>
<br /></div>
<div>
Si hay un cambio de estado, anota el tiempo y muestra las diferencias respecto al tiempo anterior.</div>
<div>
<br /></div>
<div>
Si no hay cambio de estado, imprime simplemente un punto.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-83866588050153593482017-12-04T13:55:00.003-05:002017-12-04T14:04:20.519-05:00CSS: Checkbox hack para controles personalizados¿Cómo aplicar un estilo como respuesta a un click, usando sólamente CSS?<br />
<br />
Se puede hacer con el <b><i>checkbox hack</i></b>.<br />
<br />
<h3>
</h3>
<h3>
Principio</h3>
<ul>
<li>Un label asociado a un input puede recibir el click por él</li>
<ul>
<li>Puede haber varios labels para un mismo input</li>
<li>Ocultando el input (difícil de personalizar), queda el label para contener un control más fácil de personalizar</li>
</ul>
<li>La pseudoclass <i>:checked</i> permite ubicar un checkbox seleccionado</li>
<li>El selector <i>aaa + bbb</i> permite seleccionar un <i>bbb </i>que esté (declarado) inmediatamente después de un aaa</li>
</ul>
<h3>
Patrón 1</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge5OvcQJ46KllOuTAKl-kAMsPWI_lxt8BI-Xn4pU95yaFmsn3D1ebM9RQELEh-YMu3JSD_EXCHjXljBnBwh_AYD8fCJf51foy2iBgIkAlLXkwF2wYBOW9cDIt7t-WgomKwQLTNdA/s1600/checkbox-hack-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="755" height="84" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge5OvcQJ46KllOuTAKl-kAMsPWI_lxt8BI-Xn4pU95yaFmsn3D1ebM9RQELEh-YMu3JSD_EXCHjXljBnBwh_AYD8fCJf51foy2iBgIkAlLXkwF2wYBOW9cDIt7t-WgomKwQLTNdA/s320/checkbox-hack-1.png" width="320" /></a></div>
HTML:<br />
<pre><input id="checkbox-control" type="checkbox">
<label for="checkbox-control">Control</label>
</pre>
<br />
CSS:<br />
<pre>#checkbox-control<span style="background-color: yellow;">:checked</span> <span style="background-color: #fff2cc;">+ label</span> {...}
</pre>
<h3>
Patrón 2</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZihU5OpbZsfSkKSSF2PiHat6HsjB0x0z_WTvbUIjIbt6lPgWSe0T6FJMgnWlR9mT3Eih0Vr_5te5pt-ftp_JfJKV8nhuMJ2XySm1IVmwjsHFxXst-nuQi0ka1rlc6RGI5ISrj5Q/s1600/checkbox-hack.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="220" data-original-width="1010" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZihU5OpbZsfSkKSSF2PiHat6HsjB0x0z_WTvbUIjIbt6lPgWSe0T6FJMgnWlR9mT3Eih0Vr_5te5pt-ftp_JfJKV8nhuMJ2XySm1IVmwjsHFxXst-nuQi0ka1rlc6RGI5ISrj5Q/s320/checkbox-hack.png" width="320" /></a></div>
HTML:<br />
<pre><label for="checkbox-control">Control</label>
<input id="checkbox-control" type="checkbox">
<div class="target">Target</div>
</pre>
<br />
CSS:<br />
<pre>#checkbox-control<span style="background-color: yellow;">:checked</span> <span style="background-color: #fff2cc;">+ .target</span> {...} </pre>
<h3>
Patrón 3</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjME560aLhNs8cR58S0GXhNqm9IFd0CEixxHnRIKEDi8Fmq0Ky8R1jVsqBdZrf2ieC8Tcvszc-Z7xnqCAuIW37VV9Hs0DL83jM1FRTB3qAlMhrugUo5ZjExtgc05bhs4a_MF_fcng/s1600/checkbox-hack-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="195" data-original-width="1130" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjME560aLhNs8cR58S0GXhNqm9IFd0CEixxHnRIKEDi8Fmq0Ky8R1jVsqBdZrf2ieC8Tcvszc-Z7xnqCAuIW37VV9Hs0DL83jM1FRTB3qAlMhrugUo5ZjExtgc05bhs4a_MF_fcng/s400/checkbox-hack-3.png" width="400" /></a></div>
HTML:<br />
<pre><input id="checkbox-control" type="checkbox">
<label for="checkbox-control">Control</label>
<div class="target">Target</div>
</pre>
<br />
CSS:<br />
<pre>#checkbox-control<span style="background-color: yellow;">:checked</span> <span style="background-color: #fff2cc;">+ label</span> {...}
#checkbox-control<span style="background-color: yellow;">:checked</span> <span style="background-color: #fff2cc;">+ label + .target</span> {...}
</pre>
<h3>
Ideas de aplicación</h3>
<div>
<ul>
<li>Checkbox personalizado</li>
<ul>
<li>Toggle</li>
</ul>
<li>Tabs</li>
<li>Dropdown menu</li>
<li>Dot control para slider</li>
<li>Árbol desplegable</li>
</ul>
</div>
<div class="codepen" data-default-tab="html,result" data-embed-version="2" data-height="258" data-pen-title="A check studio" data-slug-hash="WXmdGp" data-theme-id="0" data-user="akobashikawa">
<i>Ver unos ejemplos en <a href="https://codepen.io/akobashikawa/pen/WXmdGp/">A check studio</a>, en <a href="https://codepen.io/">CodePen</a></i></div>
<script async="" src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<br />
<h3>
</h3>
<h3>
Referencias</h3>
<div>
<ul>
<li>Stuff you can do with the “Checkbox Hack”<br /><a href="https://css-tricks.com/the-checkbox-hack/" rel="nofollow" target="_blank">https://css-tricks.com/the-checkbox-hack/</a></li>
<li>:checked<br /><a href="https://css-tricks.com/almanac/selectors/c/checked/" rel="nofollow" target="_blank">https://css-tricks.com/almanac/selectors/c/checked/</a></li>
<li>CSS Selector Reference<br /><a href="https://www.w3schools.com/cssref/css_selectors.asp" rel="nofollow" target="_blank">https://www.w3schools.com/cssref/css_selectors.asp</a></li>
</ul>
</div>
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-59299941418505299682017-10-18T17:19:00.001-05:002017-10-18T18:07:41.090-05:00La solución imperfecta<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLoJhYD5Opu9ErSQtazVewnNVVnTAm5wXW3z_O7qJ3XYzLjPOWkLX2kdAzk4UbiB6sCBBikA0W3mWQmjZNf3JBo_Vjl-gjqEbKurHhkt_XqYLNB5MzTN_cWpeJIDjTUXzhfYwW/s1600/01-frog-day-gallery.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1063" data-original-width="1600" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLoJhYD5Opu9ErSQtazVewnNVVnTAm5wXW3z_O7qJ3XYzLjPOWkLX2kdAzk4UbiB6sCBBikA0W3mWQmjZNf3JBo_Vjl-gjqEbKurHhkt_XqYLNB5MzTN_cWpeJIDjTUXzhfYwW/s320/01-frog-day-gallery.jpg" width="320" /></a></div>
<br />
¿Por qué el mundo esta lleno de soluciones imperfectas?<br />
<br />
Porque la solución depende del contexto.<br />
<br />
Digamos que tienes cinco minutos para ordenar la salida de un sistema y un plugin ya listo que lo hace.<br />
<br />
El algoritmo hace una ordenación simple tipo burbuja pero cumple con lo que necesitamos.<br />
<br />
Si tuvieras un par de horas, quizas podrías hacer desde cero un plugin con el mejor algoritmo de ordenación posible.<br />
<br />
Si tuvieras una hora, quizás podrías modificar este plugin y mejorar el algoritmo de ordenación.<br />
<br />
Si tuvieras media hora, quizás podrías buscar si alguien más ha hecho ese plugin.<br />
<br />
Pero tienes cinco minutos.<br />
<br />
Poner este plugin te llevará un minuto, un pequeño test otro minuto, y ya estás gastando tiempo en analizar las alternativas. Alternativas que requieren más tiempo del que dispones. Y todas con un <i>quizás</i>. No existen. Sólo existe este plugin imperfecto, aquí y ahora.<br />
<br />
No se trata de usar las respuestas de un libro de texto. Se trata de la vida real, retándote a hacer lo mejor que puedas con lo que tienes disponible en este momento.<br />
<br />
Lo eliges. No es la respuesta perfecta, pero es la solución. En este contexto, <b>es</b> la respuesta.<br />
<br />
Te gustaría que alguien te comprenda por usar una respuesta no optima.<br />
<br />
Ahora te parece tan obvio.<br />
<br />
Realizar una solución imperfecta es mejor que una respuesta perfecta que no se puede realizar.<br />
<br />
Lo aceptas, y sigues adelante. Quizás en la siguiente iteración la puedas mejorar.<br />
<br />
También es un <i>quizás</i>. Pero es es un <i>quizás</i> con algo corriendo.<br />
<br />
<hr />
<i><span style="font-size: xx-small;">Imagen de http://news.nationalgeographic.com/content/dam/news/2017/04/27/frog-gallery/01-frog-day-gallery.jpg</span></i>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-3071925138156680842017-08-28T19:16:00.000-05:002017-08-29T11:12:25.201-05:00El problema de la sobrecarga innecesaria<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglgx9_VLPKlKzZo_dggRCd05VJV3R29pSSZym2nivuRPc29qmulhiHhepwIpnXsjPKx0CVVH4eKkE40PkN9z2EwvcvEMJWMuLIH7tdu2ZvnnbvTlu4RIF0EhNc9K5JnO-A2dwv/s1600/overload.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="278" data-original-width="360" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglgx9_VLPKlKzZo_dggRCd05VJV3R29pSSZym2nivuRPc29qmulhiHhepwIpnXsjPKx0CVVH4eKkE40PkN9z2EwvcvEMJWMuLIH7tdu2ZvnnbvTlu4RIF0EhNc9K5JnO-A2dwv/s320/overload.jpg" width="320" /></a></div>
<h2>
Problemas reales</h2>
Pienso que resolver problemas es una cuestión de prueba y error.<br />
<br />
Que no es como te lo enseñan en la escuela, donde aprendes a copiar soluciones de los libros de texto.<br />
<br />
Resolver un problema es como andar a tientas por una habitación a oscuras, tratando de llegar a la puerta.<br />
<br />
Lo que te dan los libros de texto son como escenarios prefabricados de juegos con finales conocidos. Llenos de cosas que los maestros han puesto y con rutas de solución que ellos ya conocen.<br />
<br />
En los problemas reales, puede haber más de una ruta de solución. O ninguna.<br />
<br />
También encontraras montones de cosas que te sirven mezcladas con cosas innecesarias. Y necesitarás aprender a notar cuál es cuál.<br />
<br />
Enfrentarte a problemas reales despierta cierto sentido. Aprendes a escuchar al problema. Aprendes a buscar dentro de ti. Aprendes a construir caminos.<br />
<h2>
Patrones</h2>
Conforme vas resolviendo problemas, te das cuenta que se repiten ciertos patrones para solucionarlos.<br />
<br />
Identificar estos patrones ayuda a catalogar las soluciones y facilitar su reutilización.<br />
<br />
Por ejemplo:<br />
<ul>
<li><b><i>Qué tal si divido el problema en partes</i></b>. Si varias de esas partes me son familiares, podría avanzar por allí.</li>
<li><b><i>Qué tal si solo considero algunos detalles</i></b> (eso se llama abstracción). A lo mejor veo más claro en esa versión simplicada.</li>
</ul>
<div>
Ayuda dividir el trabajo web en partes separadas.<br />
<br />
También ayuda quitar de en medio una problemática innecesaria.</div>
<h2>
MVC</h2>
<div>
Modelo-Vista-Controlador es un patrón de desarrollo web que divide el trabajo en tres areas:</div>
<div>
<ul>
<li>Vista: la interfaz de usuario, HTML, CSS, Javascript</li>
<li>Modelo: los datos que la Vista mostrará</li>
<li>Controlador: el que orquesta las actuaciones de la Vista y el Modelo</li>
</ul>
<div>
Se trata del patrón <i>Qué tal si divido el problema en partes</i>. La idea es concentrarse en cierto aspecto del desarrollo para simplificar el trabajo.</div>
</div>
<h2>
Componentes</h2>
<div>
El desarrollo de un site o una aplicación web, no es una tarea definida. Es un problema cuyas tareas hay que ir descubriendo en el camino, durante sucesivas iteraciones. No es ir de la A a la Z y ya. Es ir por las letras de un mensaje desconocido, fallando y acertando mientras se va haciendo más claro.</div>
<div>
<br /></div>
<div>
Para iterar con agilidad, necesitamos poder hacer cambios con facilidad.</div>
<div>
<br /></div>
<div>
¿Ayuda MVC en esto?</div>
<div>
<br /></div>
<div>
MVC ayuda a enfocarse en cierto aspecto del problema y a organizar todas las cosas en esas tres grandes areas. Pero esa virtud también tiene su inconveniente. La navegación por el mar de las posibilidades se vuelve muy, muy pesada. Cierto que sabemos donde queda cada cosa y eso es muy bueno. Pero, por otro lado, la implementación de cada idea se vuelve engorrosa.</div>
<div>
<br /></div>
<div>
Imaginamos las cosas naturalmente como componentes, pero en MVC cada solución o variante que imaginemos tiene que ser dividida en tres partes antes de poder implementarlas. Es un ejercicio constante de traducción entre lo que imaginas y lo que haces para producirlo.</div>
<div>
<br /></div>
<div>
Está bien, pero quizás podría ser mejor.</div>
<div>
<br /></div>
<div>
Entran los componentes.</div>
<div>
<br /></div>
<div>
¿Qué tal si dividimos las cosas no por areas M, V, C, sino por funcionalidades, por componentes?</div>
<div>
<br /></div>
<div>
Es parecido a decir, que tal si en lugar de tener carpetas css, js, images, tenemos varias carpetas home, contact, menu, header, product, etc, cada una representando una funcionalidad o conteniendo otras carpetas de funcionalidades.</div>
<h2>
Confusiones papistas</h2>
<div>
<i>Más papista que el Papa</i>, dice un refrán. En algunos proyectos hay personas que adoptan esta actitud de defender algo como cierto porque sí, porque así es.</div>
<div>
<br /></div>
<div>
Gente que toma MVC como una biblia o estresa al equipo que obvia una ceremonia del scrum.</div>
<div>
<br /></div>
<div>
Lo importante es honrar el por qué de las cosas. MVC busca claridad. Scrum busca bienestar del equipo.</div>
<div>
<br /></div>
<div>
¿Los componenentes podrían hacerlo mejor? ¿Podríamos sentirnos menos estresados? Probemos.</div>
<h2>
El problema en el Frontend</h2>
<div>
<div>
Este es más o menos el flujo de trabajo que se sigue al desarrollar web:</div>
<ol>
<li><b>Se propone un diseño gráfico base</b><br />Algunos insisten en querer tener todo resuelto en este punto, pero es crear falsas expectativas y sufrimiento innecesario.<br />Es importante que el cliente entienda que el desarrollo es iterativo (hablando de eso, también es importante que el equipo de desarrollo lo entienda ^^).</li>
<li><b>El diseño gráfico se maqueta con HTML, CSS y Javascript</b><br />Los datos son hardcodeados.<br />Algunos insisten en querer maquetar directamente sobre un framework, pero es crear lastre mental innecesario, además de amarrar la maqueta a ese ambiente.</li>
<li><b>La maqueta es vuelta template, según el framework que se va a usar</b><br />Los datos son mockupeados. Es decir provisto por endpoints que devuelven data hardcodeada.<br />Algunos insisten en hacer endpoints reales de una vez, pero también es crear lastre mental innecesario tratar de enfrentar más de un problema a la vez.</li>
<li><b>La aplicación es provista de datos reales</b><br />Ya que las anteriores etapas han resuelto una cosa a la vez, se reduce bastante el número de posibilidades de error en este punto.</li>
<li><b>El cliente quiere un cambio</b><br />Procedemos a iterar.</li>
</ol>
<div>
Aquí es donde se presenta el problema. En la atención de los cambios.<br />
<br />
Como las revisiones ya se están haciendo con datos reales, las circunstancias presionan para no ir al paso 1, sino iterar sobre el paso 4.<br />
<br />
No se actualiza la propuesta gráfica, ni la maqueta en puro HTML. Se percibe como demasiado engorroso. Se hacen los cambios directamente sobre el template con toda la infraestructura corriendo.<br />
<br />
Paradójicamente, eso no es más rápido, ni más seguro.<br />
<br />
Para hacer cualquier cambio en el template, con la infraestructura corriendo, tienes todo un ecosistema de base de datos, modelos y controladores funcionando... innecesariamente.<br />
<br />
Resolver un cambio en un template es un problema más complicado porque tienes que cargarte mentalmente de todas las convenciones y protocolos del framework, y de todas las circunstancias y problemas que otras areas estén atravesando (que la configuración del entorno ha variado, que <i>por ahora</i> no uses este endpoint sino este otro, que hay un servicio que se ha caído y <i>debemos esperar</i>, etc, etc).<br />
<br />
En cambio, hacer los cambios sobre la maqueta es un problema aislado, más sencillo y rápido de resolver.<br />
<br />
Creo que es mejor resolver los problemas en la maqueta y luego recién llevar esa solución al template.<br />
<br />
<span style="background-color: #fff2cc;">Si el paso de convertir una maqueta a template no fuera manual sino automático (o si no existiera), creo que sería más sencillo y rápido hacer cambios de UI.</span></div>
</div>
<div>
<br /></div>
<div>
<a href="https://github.com/akobashikawa/juno-cheerio">juno-cheerio</a> y <a href="https://github.com/akobashikawa/unophp">unophp</a> han sido algunas iniciativas personales para automatizar el paso 3. La idea de unophp se puede adaptar incluso para WordPress.</div>
<div>
<br /></div>
<div>
Pero por ahora, tenemos este problema en Frontend: cómo atender con más facilidad los cambios que se requieren durante las iteraciones del proyecto.</div>
<h2>
Antipatrón</h2>
<div>
Yo diría que es un antipatrón que el frontend requiera que todo el motor del proyecto, con su base de datos, endpoints, etc, deba estar corriendo para hacer sus cambios.</div>
<div>
<br /></div>
<div>
Es complejidad innecesaria para esa tarea.</div>
<div>
<br /></div>
<div>
Entiendo que en Integración Contínua se prueban las cosas sobre infraestructuras reales corriendo. Es porque necesitan hacer pruebas en ese nivel. Pero hacer el desarrollo en ese mismo nivel no me parece lo más optimo.<br />
<br />
Sería mejor poder aislar esa parte a voluntad, poder crear un entorno donde no exista otra complejidad más allá de lo que quieres resolver, hacer el cambio, y luego, mágicamente, incorporarlo al proyecto completo.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-2898728912926300202017-08-09T12:27:00.000-05:002017-08-12T23:48:35.285-05:00UX para todo(s)<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaAWamP_iTVw6ziKgLq0CbkKXb1R6yrm3zdblEZvg8i6Axac2s3eLlZ9Yl_zKuD8mHPEwn7FoGD-kMkEPCGwlb6ciNKOh5vKlHWR-VHxaLdALrfZwF8a6QlmAoYGKRFfDlSFjp/s1600/UX+para+todos.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="540" data-original-width="960" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaAWamP_iTVw6ziKgLq0CbkKXb1R6yrm3zdblEZvg8i6Axac2s3eLlZ9Yl_zKuD8mHPEwn7FoGD-kMkEPCGwlb6ciNKOh5vKlHWR-VHxaLdALrfZwF8a6QlmAoYGKRFfDlSFjp/s400/UX+para+todos.png" width="400" /></a></div>
<br />
<b>Nota</b>: Por favor, lee esto con la mente abierta. Si eres frontend, creo lo entenderás. Si eres backend, por favor, no me malinterpretes; también he hecho algo de backend y muchos de mis amigos son backend. No tengo nada en contra de los backend. Excepto quizás la optimización prematura, el overkill (pero eso es algo que se ve en todas partes), y esto.<br />
<br />
Encuentro que hay una discusión entre frontend y backend. Entre los chicos que hacen las interfaces para el usuario y los que preparan la data que se mostrará.<br />
<br />
Es más o menos así: los backend pretenden que los frontend tienen que usar sus apis cómo a ellos les de la gana de hacerlas.<br />
<br />
Por supuesto pueden esgrimir un montón de argumentos; que el mejor modelamiento de las tablas, que la auto documentación, que la optimización, etc.<br />
<br />
Lo que yo digo es solamente esto: imagínate que los frontend pretendiéramos que los usuarios tienen que arreglárselas para usar las interfaces que nos diera la gana de hacer.<br />
<br />
¿Que así es como haces tus interfaces de usuario? Detente, stop, para un momento.<br />
<br />
Por supuesto que durante muchos años se ha hecho así; con la dictadura de los diseñadores sometiendo al usuario y obligándoles a aprender que la opción que buscaban estaba nada más a cuatro clicks de distancia, debajo de un menú desplegable que actuaba cuanto pulsabas la tecla alt después de escape (bueno quizás no tanto, pero seguramente captas la idea).<br />
<br />
Pero la abundante oferta de aplicaciones y la despiadada elección de los consumidores ha hecho que recapacitemos y escuchemos al usuario y qué tipo de experiencia realmente le ayuda a conseguir lo que necesita. Porque lo que la UX busca no es que las interfaces sean más bonitas (es un malentendido de marketing); lo que busca es que las interfaces puedan dar lo que se necesita sin obligar a hacer un esfuerzo innecesario.<br />
<br />
Además, mira el nombre, "interfaz de usuario", no dice "interfaz del programador frontend". No se supone que debas sentirte cómodo programándola; quizás tengas suerte y sea entretenido, estimulante, o quizás no y sea un dolor de cabeza y un verdadero desafío cómo resolver una interacción; lo importante es que el usuario pueda sentirse cómodo usándola, sin esfuerzos innecesarios.<br />
<br />
Pues bien, del mismo modo, la API que se entrega a los frontend es la interfaz con la que nos comunicamos con la fuente de datos. Una buena API no es aquella que sea cómoda o fácil de programar para los backend; puede que lo sea, si se organizan bien, pero es un rollo interno, que no debe atravesar la interfaz. Porque recordemos que se trata de una interfaz: la comodidad y facilidad deben estar del lado de quién la va a usar.<br />
<br />
Un backend debería hacer con el frontend el mismo ejercicio que el frontend hace con el usuario. Observarlo, ver cómo va a usar la API, conversar con él acerca de sus necesidades reales, empatizar.<br />
<br />
No creo que necesitemos una especie de Frontend eXperience (no más siglas, por favor), sino que comprendamos que los mismos principios que venimos a reconocer como válidos al aplicar UX son aplicables también a la hora de desarrollar interfaces para otros desarrolladores. Puede ser un API REST, o puede ser una librería, o un framework, o cualquier herramienta en general.<br />
<br />
<b>En una interfaz, la comodidad y facilidad deben estar del lado de quién la va a usar.</b> Creo que es el principio que guia a la UX y está ayudando a crear más software realmente valioso para los usuarios. Y creo que es hora que apliquemos lo mismo a la relación frontend-backend (y en todas aquellas donde veamos una interfaz), y ayude a crear herramientas realmente valiosas para desarrollar mejor mejores aplicaciones.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-80685038929180641142017-06-30T14:20:00.002-05:002017-07-06T13:15:46.881-05:00Problemas vs Tareas<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjToztxoOaF1l4QaUra8Y0sEoWjhXa2K4hJFOoD04NKAOUQpMgb6dZ-rJgstuQcqUUoQ-1KMfUAjsjYbhy8TKGBJAbNwcH3dDXlpRfx0Q2nC6jSlFjq9Ny9T-1gv9v8ypgVh5mp/s1600/problemas-vs-tareas.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="360" data-original-width="504" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjToztxoOaF1l4QaUra8Y0sEoWjhXa2K4hJFOoD04NKAOUQpMgb6dZ-rJgstuQcqUUoQ-1KMfUAjsjYbhy8TKGBJAbNwcH3dDXlpRfx0Q2nC6jSlFjq9Ny9T-1gv9v8ypgVh5mp/s320/problemas-vs-tareas.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Resolvemos problemas cada día. Pero a veces no sabemos qué lo estamos haciendo, ni cómo. Y otras, nadie parece valorarlo.<br />
<br />
¿Qué es un <b>problema</b>? Algo cuya solución no es evidente.<br />
<br />
Si la solución fuera evidente ya no sería un problema, sino una <b>tarea</b>.<br />
<br />
Por ejemplo, si fuera un pintor, tengo los utensilios y la habilidad para pintar tanta area de pared cada hora, ¿cuánto me demoraré en pintar cierta pared?, pues tanto tiempo. El camino es conocido y está libre. Es una tarea.<br />
<br />
En cambio, sería un problema si alcanzar alguna parte de la pared no fuera evidente.<br />
<br />
O, si en lugar de ser un pintor de brocha gorda tuviera que pintar un retrato. ¿Qué espera mi cliente?, ¿cuál será la pose adecuada para esta persona?, son preguntas cuya respuesta no es evidente. Es un problema.<br />
<br />
<h3>
Lo evidente</h3>
¿Qué es evidente? Depende de tus conocimientos y habilidades. Algo evidente para una persona puede no serlo para otra.<br />
<br />
Cuando pagas con un billete algo que cuesta menos, es evidente para un adulto que le tienen que dar vuelto. Pero no es tan evidente para un niño que está aprendiendo a comprar en la calle.<br />
<br />
Tampoco es evidente que se tenga que distinguir entre problemas y tareas. Pero espero que notes la utilidad de notar la diferencia.<br />
<br />
<h3>
Notando la diferencia</h3>
A veces llamamos problemas a tareas que se realizan rutinariamente. O tratamos a quienes resuelven problemas como si estuvieran realizando tareas rutinarias.<br />
<br />
Para no formar falsas expectativas, es importante distinguir qué es una tarea y qué es un problema.<br />
<br />
Cuando te enfrentas a un problema, sueles encontrar un <b>no</b> dándote el primer encuentro. Este no, muestra que la respuesta no es evidente y aclara que no se trata de una tarea.<br />
<br />
Si <b>fallas</b> al realizar una tarea, es que en realidad se trataba de un problema.<br />
<br />
Entonces, casi como por instinto, pasas a preguntarte cosas. Si hay algo que se parezca a alguna tarea que conoces. Quizás resolviendo eso primero se aclare cuál es el siguiente paso. O tal vez se trate de dividir el problema en partes conocidas. O, a lo mejor, se pueda expresar alguna parte en términos de algo que ya conozca.<br />
<br />
Intentas, fallas, pruebas otra cosa, aciertas, y así vás construyendo un camino hacia la solución.<br />
<br />
Cuando realizas una tarea, no aparecen <b>ese tipo de preguntas</b>. Si aparecen, entonces no es una tarea, sino un problema.<br />
<br />
<h3>
Resolviendo</h3>
Resolver un problema requiere un trato diferente que realizar una tarea.<br />
<br />
Resolver un problema requiere ciertas habilidades adicionales a las que se necesitan para realizar tareas.<br />
<br />
Debes ser capaz de aceptar un reto, de imaginar alternativas, de probar un plan y fallar en el intento, de reconocer la información que un intento fallido te puede estar dando, de ubicarte en ese viaje.<br />
<br />
<h3>
Estimando</h3>
¿Cuánto tiempo te toma hacer una tarea? Tanto tiempo.<br />
<br />
<b>¿Cuánto tiempo te toma resolver un problema? No lo sé, depende del problema.</b><br />
<br />
Pero, un momento, ¿en los <b>exámenes, </b>acaso no hay <i>problemas </i>que hay que resolver en cierto tiempo? Sí, pero en realidad <b>no son problemas</b> para quién propone la prueba, que ya los ha resuelto tantas veces que sabe cuánto es lo que se suele tardar en resolverlo. Sería más correcto llamarlas <b>preguntas</b>.<br />
<br />
Un estudiante que no ha estudiado el tema ni practicado preguntas similares, puede tardar mucho más tiempo en resolver una pregunta, porque para él sería realmente un problema. En cambio, otro estudiante, que ha estudiado el tema y practicado ese tipo de preguntas hasta que le resulten tareas, tardará mucho menos.<br />
<br />
Puedes ser muy habil realizando tareas y saber cuánto te toma hacerlas. Pero ¿qué pasa cuando te enfrentas a cuestiones cuya respuesta no es evidente?.<br />
<br />
Resolver un problema no es un tour al mercado de un pueblo conocido, sino un viaje de exploración. ¿Cuánto tiempo te tomará entrar al bosque desconocido y encontrar allí la fruta que me gusta?<br />
<br />
No se puede <b>presupuestar </b>un problema. Sólo se pueden presupuestar tareas.<br />
<br />
Si necesitas presupuestar un problema, busca a alguien para quien ese problema sea solo una tarea. O que maneje el proceso para convertir problemas en tareas.<br />
<br />
<h3>
Agile</h3>
<div>
En el desarrollo agile se trata de tomar un problema y determinar tareas lo más pronto posible para poder presupuestar sobre eso.</div>
<div>
<br /></div>
<div>
Para resolver un problema, se asigna una cantidad pequeña de tiempo y recursos para dar un pequeño paso cada vez. Es como una apuesta. Puede que alcance para resolver algo, puede que no, pero es un riesgo limitado y calculado. Viendo el resultado, podemos decidir si volvemos a apostar por lo mismo o cambiamos de número.<br />
<br />
<h3>
<b>Preparación</b></h3>
Saber cómo manejar un problema es importante, pero hay que reconocer que si no hay alguien capaz de realizar las tareas que surgirán, el problema no se podría resolver.<br />
<br />
Familiarizarnos con las tareas nos da más oportunidades de encontrar cosas conocidas al enfrentar un problema.<br />
<br />
Nuestro repertorio de tareas conocidas puede ser visto como un vocabulario que nos ayuda a expresar una solución.<br />
<br />
Conocer más número de tareas ciertamente puede ayudar. Pero, igual que con las palabras del lenguaje, es importante saber usar eficazmente aquellas que tengamos disponibles.<br />
<br />
<br />
<h3>
Herramientas</h3>
Es común que se entregue un problema a alguien y se lo deje solo, a ver cómo lo resuelve. Y lo resolvemos, a veces sin saber exactamente cómo. Así aprendimos a interpretar el mundo, a hablar, a tratar con otras personas y situaciones.<br />
<br />
Sin embargo, puede ser útil visualizar las cosas que usamos cuando resolvemos problemas. Estas son las que yo suelo distinguir.<br />
<br />
<b>Contexto</b>. Es un conjunto de <i>consideraciones</i> que tenemos en cuenta a la hora de tratar con algo. Para <i>abstraer</i>, quitamos consideraciones. Por ejemplo, al tratar con formas geométricas, podemos dejar de lado el peso o el color. Tener claro el contexto y saber aplicar abstracciones ayuda a resolver problemas.<br />
<br />
<b>Analogías</b>. Es encontrar un contexto paralelo que ya conozcamos y representar allí nuestro problema, resolverlo, y luego volver al contexto inicial para representar allí la solución.<br />
<br />
<b>Semejanza</b>. <i>Así abajo como es arriba</i>. Es encontrar analogías dentro del mismo contexto. (También se podría decir que una analogía es una semejanza entre contextos.)<br />
<br />
<b>Patrones</b>. Son como figuras que vemos repetirse en diversos contextos.<br />
<br />
<h3>
Conclusión</h3>
Resolver problemas es una actividad que requiere una disposición mental y unas habilidades distintas a hacer algo rutinario.<br />
<br />
Pienso que muchas trabas y malentendidos en el desarrollo de proyectos se deben a que no se entiende está diferencia de la actividad creativa.<br />
<br />
Creo que hacer la distinción entre problemas, como algo cuya solución no es evidente, y tareas, como una actividad plenamente determinada, es útil para visualizar mejor lo que tenemos frente a nosotros. Para resolver el problema de los problemas.<br />
<br />
<br />
<div style="text-align: center;">
<i>Transcrito de <a href="http://rulokoba.blogspot.pe/2017/06/problemas-vs-tareas.html">http://rulokoba.blogspot.pe/2017/06/problemas-vs-tareas.html</a></i></div>
<br /></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-27004237949207490252017-06-02T17:22:00.000-05:002017-06-02T17:23:57.574-05:00Jugando con asteriscos en CSSInspirado por el logo de JWT, se me ocurrió jugar a formar asteriscos como una rotación de una barra.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://cdn.auth0.com/blog/jwt/logo-400.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="400" data-original-width="400" height="320" src="https://cdn.auth0.com/blog/jwt/logo-400.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Logo JWT</td></tr>
</tbody></table>
<br />
<br />
<iframe allowfullscreen="true" allowtransparency="true" frameborder="no" height="265" scrolling="no" src="//codepen.io/akobashikawa/embed/NgWWOW/?height=265&theme-id=0&default-tab=result&embed-version=2" style="width: 100%;" title="CSS Asterisks">See the Pen <a href='https://codepen.io/akobashikawa/pen/NgWWOW/'>CSS Asterisks</a> by Rulo Kobashikawa (<a href='https://codepen.io/akobashikawa'>@akobashikawa</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>Para el caso de 6 líneas, probé crear con Sass un mixin que escriba el código repetitivo.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-25118726447118228962017-05-30T00:31:00.000-05:002017-05-30T00:31:02.467-05:00Simplificando el desarrolloWebpack, Babel, TypeScript, Gulp, Sass, Stylus, Pug, son algunas de las cosas que se ven en el desarrollo frontend hoy en día.<br />
<br />
Pug (Jade) permite escribir una especie de html sin brackets, que se ve más limpio y legible, y luego es traducido a <b>html</b>.<br />
<br />
Sass y Stylus hacen algo parecido con el <b>css</b>.<br />
<br />
CoffeeScript lo hacía con el <b>javascript</b>. Pero parece que va cayendo en deshuso, frente a TypeScript y ES6.<br />
<br />
Pug te permite escribir html de manera más clara y sencilla y está bien.<br />
<br />
Styles te permite escribir css de manera más clara y sencilla y está bien.<br />
<br />
CofeeScript te permite escribir javascript de manera más clara y sencilla y también está bien.<br />
<br />
Está bien que produzcas html, css o javascript de la manera que te resulte más cómoda y fácil de mantener.<br />
<br />
Sospecho que muchos programadores provenientes de otras canteras, resintieron tanto las incomodidades de los brackets, y puntos y comas, que usaron sus potentes habilidades para construir herramientas que les recordaran sus lenguajes preferidos.<br />
<br />
Además, herramientas como Gulp, Babel y Webpack pueden automatizar el proceso de traducción.<br />
<br />
Pero entonces comenzó a complicarse la cosa.<br />
<br />
Si miramos las cosas desde una perspectiva más amplia, lo que ha sucedido es que se ha creado una capa adicional entre el programador y el código. Una capa de pre procesado.<br />
<br />
¿Qué pasa cualdo alguien más quiere participar en el desarrollo de un proyecto como este? Esta persona conoce todo lo necesario para actuar en la capa del código html/css/javascript.<br />
<br />
-- Pero no, un momento, no puedes hacer eso.<br />
<br />
-- ¿Por qué no?<br />
<br />
-- Porque yo escribo en mi hermoso pug/stylus/coffeescript para producir ese horrible html/css/javascript y no se me ocurre cómo hacerlo en sentido inverso para que tus cambios actualicen los míos.<br />
<br />
-- Bueno, me voy a ayudar a otro proyecto.<br />
<br />
¿Y para qué publicas un proyecto en GitHub, como open source, y en inglés, si no es para facilitar que otras personas puedan colaborar contigo para evolucionar una idea que te apasiona?<br />
<br />
Entonces, no tiene mucho sentido restringir esa facilidad con herramientas que no todo el mundo quiere usar, aunque tú las adores.<br />
<br />
Lo que debería haber en tu proyecto compartido es cosas que sean fáciles de compartir: html, css y javascript. Producidos con las herramientas que gustes; pug, sublime, atom, notepad o dreamweaver. Pero, así como no puedes exigir que alguien use dreamweaver, sublime o atom para poder participar en tu proyecto open source, tampoco deberías exigir que usen tal o cual pre procesador.<br />
<br />
<b>El efecto de encarecer las cosas</b><br />
<br />
Imagina que tienes una cita con una chica que te gusta. Por alguna razón, lo comentas en casa, a tu abuela. Ella se opone, por varias razones importantes:<br />
<br />
-- No sabe cocinar; ¿cómo te va a atender después?<br />
<br />
-- Pero, abue...<br />
<br />
-- Además es demasiado flaca; con esas caderas sufrirá mucho para tener hijos<br />
<br />
-- ¡Es sólo una cita, abuela!<br />
<br />
Si sales con alguien pensando en si se casarán, ves todo con otros ojos. Hasta los defectos más pequeños se convierten en gigantes cuando los proyectas sobre la pantalla de un futuro de deberás soportar todos los días.<br />
<br />
La abuela piensa así porque en su época, donde vivía, una cita era algo muy importante y costosa, pagada con el dinero que la familia ahorraba con esfuerzo, así que no podías estar en plan de "salir para ir conociéndonos".<br />
<br />
<br />
Algo así aparece en el proceso de desarrollo cuando un proceso es caro de hacer.<br />
<br />
Antes, con un simple editor de texto y el navegador, podías moverte rápidamente entre el html y los resultados, probando diversas librerías, plugins, etc, con mucha agilidad. Como ir en bicicleta.<br />
<br />
Ahora, es un camión. Si quieres probar y jugar con una librería, un plugin, etc. ya no puedes hacerlo directamente, como antes. Debes traducir mentalmente el html de la documentación del plugin, y calcular tu código para que produzca el html que se requiere. Son dos lenguajes en la cabeza y un paso extra para depurar. Es como caminar con ayuda de un espejo.<br />
<br />
Así que ya no tienes citas por diversión. Todo se vuelve más serio.<br />
<br />
Cómo el builder establece de antemano dónde irá cada cosa hasta el fin de los tiempos, con ese mal ejemplo la gente empieza a sentirse presionada a hacer el código limpio directamente. De pronto, la elaboración progresiva de soluciones, la refactorización y la restructuración de directorios quedan al margen de la ley, porque son más caros.<br />
<br />
Además, la gente empieza a usar Gulp y Webpack como herramientas con las que pueden instaurar un régimen de código opinionado ("así es cómo se deben hacer las cosas, tontos").<br />
<br />
Y todo empezó con el afán de trabajar más cómodos. De buenas intenciones está hecho el camino al infierno... como reza el dicho.<br />
<br />
<br />
Creo que es importante mantener un punto de vista amplio acerca de las cosas que hacemos en desarrollo. Del mismo modo que un máximo en cada división de una empresa no garantiza un máximo de la empresa en conjunto, una mejora en un aspecto individual no garantiza que todo el proceso de desarrollo será mejor. Los máximos locales no garantizan máximos globales. Producir html rápidamente no garantiza que mantenerlo será igual de rápido. Es mejor un enfoque holístico.<br />
<br />
Creo que una buena referencia para tomar decisiones es considerar el número de pasos, capas y herramientas que significa corregir un bug, o introducir un cambio. Un problema se puede resolver de muchas maneras. Es posible usar un cañón para matar moscas. Pero es una buena idea empezar con las soluciones más simples primero.<br />
<br />
Y, construir las cosas de modo que no obstruya los siguientes pasos. Evitar los compromisos innecesarios y mantener el camino libre y fresco para avanzar progresivamente. Ya que el viaje es el camino.<br />
<br />
<div style="text-align: center;">
<i>Transcrito de <a href="http://rulokoba.blogspot.pe/2017/05/simplificando-el-desarrollo.html">http://rulokoba.blogspot.pe/2017/05/simplificando-el-desarrollo.html</a></i></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-1421735690247156462017-05-24T12:07:00.000-05:002017-05-24T12:22:13.924-05:00Emponderar a los usuarios<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVT1-zIjEDbgaUIvercKmDeGOOlc41qT_XMK6s8dea1lJcQTCV7w0T8V-O5_0F5wnJC0D7wL9ICeY4ei8yCe6alDC7w8mf_KWdyPVVLGtactCR13T61rxMt1-ML-TkANlglMzN/s1600/lego-composer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVT1-zIjEDbgaUIvercKmDeGOOlc41qT_XMK6s8dea1lJcQTCV7w0T8V-O5_0F5wnJC0D7wL9ICeY4ei8yCe6alDC7w8mf_KWdyPVVLGtactCR13T61rxMt1-ML-TkANlglMzN/s320/lego-composer.png" width="320" /></a></div>
Cuando estaba en la universidad, retomé el contacto con las computadoras después de un largo tiempo y conocí el <b>DOS </b>de Microsoft.<br />
<br />
Estaba frente a una pantalla negra con el prompt <b>C:\></b> esperando a que ingresara algo. Cuando lo hacía, me respondía.<br />
<br />
Me sentía fascinado.<br />
<br />
Aprendí a usar casi todos los comandos de la consola, y a programar nuevos comandos.<br />
<br />
<ul>
<li>En la consola <b>command</b>, se pueden ejecutar comandos cuyas salidas pueden ser entradas de otros comandos.</li>
<li>Se pueden crear fácilmente nuevos comandos <b>batch </b>ejecutables desde la consola. Ya que los batch son archivos de texto simple y la consola tiene algunos comandos para generarlos.</li>
<li>Un comando podría generar nuevos comandos dinámicamente. Es decir, un batch se podría generar dentro de la rutina de un comando y ser ejecutado luego dentro del mismo comando.</li>
<li>Los programas de <b>pantalla completa</b>, aunque impresionantes, rompen el esquema de reutilización de comandos al apropiarse de toda la interfaz.</li>
</ul>
<div>
Más tardee, conocí <b>Linux </b>y la consola de comandos <b>bash</b>, donde se pueden observar puntos similares.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
En la interfaz gráfica de <b>Windows</b>, en cambio:</div>
<div>
<ul>
<li>En el escritorio, se pueden ejecutar <b>aplicaciones</b>, pero estas ejecuciones son <b>aisladas </b>y no se puede realizar ejecuciones compuestas donde la salida de una aplicación sea la entrada de otra, dinámicamente.</li>
<li>No hay herramientas para construir fácilmente nuevos programas desde el escritorio. Las aplicaciones no son interpretadas, sino ejecutadas desde un <b>binario</b>, y construir ese binario requiere conocimientos y herramientas especializadas.</li>
<li>No hay una forma sencilla de construir aplicaciones que puedan generar otras aplicaciones dinámicamente, dentro de su ejecución. No es sencillo construir compiladores.</li>
<li>La reutilización de las características de una aplicación es difícil. Cada característica está pegada a la aplicación. Cada mejora de características requiere una nueva versión realizada principalmente por quienes la programaron.</li>
</ul>
<div>
Algo parecido se puede decir de las interfaces gráficas de Linux (Gnome) y de la Mac (OSX), que vine a conocer luego.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
En la interfaz gráfica de la <b>Web</b>, en el browser, se muestra una aplicación:</div>
<div>
<ul>
<li>Cómo hacer que la aplicación sea un entorno donde se puedan ejecutar <b>componentes </b>que puedan componerse para formar nuevos componentes?</li>
<li>Cómo hacer que sea fácil crear componentes con los componentes presentes en el entorno?</li>
<li>Cómo hacer que un componente pueda generar dinámicamente otros componentes dentro de su ejecución?</li>
<li>Cómo prevenir que un componente pueda apropiarse de la interfaz?</li>
</ul>
<div>
<br /></div>
</div>
<div>
Me parece distinguir que ese conjunto de características facilita que un sistema pueda ser <b>extendido </b>con la participación de sus usuarios.</div>
<div>
<br /></div>
<div>
El conjunto de comandos DOS y bash, puede ser fácilmente extendido por sus usuarios. Habrá programadores capaces de hacer nuevos binarios, pero la capacidad de hacer scripts, batch o bash, está disponibles de inmediato.</div>
<div>
<br /></div>
<div>
El conjunto de aplicaciones en Windows (o Gnome, o OSX) no puede ser fácilmente extendido por sus usuarios. Sólo puede serlo a través de programadores capaces de hacer nuevos binarios.</div>
<div>
<br /></div>
<div>
Uno se puede preguntar si esta limitación es puesta <b>a propósito</b>.</div>
<div>
<br /></div>
<div>
Al limitar que los usuarios puedan extender el sistema que usan, las empresas proveedoras de software se aseguran el papel de intermediarios, entre los usuarios y las soluciones que los usuarios requieren.</div>
<div>
<br /></div>
<div>
Y es conocido en el <b>comercio </b>que el <b>intermediario </b>siempre gana.</div>
<div>
<br /></div>
<div>
Así que me parece que la cuestión de limitar la extensibilidad del sistema por parte de los usuarios puede ser algo diseñado.</div>
<div>
<br /></div>
<div>
Sin embargo, ¿por qué ocurre también en la interfaz gráfica de Linux?. Siendo la comunidad Linux un fuerte representante del movimiento de <b>software libre</b> (promotor de dar a la gente la libertad de usar el software como quiera), esperaría que hubieran escritorios que permitieran componer aplicaciones visualmente, siguiendo la filosofía de composición de comandos que está presente en la consola.</div>
<div>
<br /></div>
<div>
Quizás sea que están distraidos por las complejidades de otros problemas.<br />
<br /></div>
<div>
<br /></div>
<div>
Pero me parece que resolver esta situación sería muy interesante. Un escritorio así, emponderaría a los usuarios para crear cosas, sus propias cosas, y compartirlas en comunidad.</div>
<div>
<br /></div>
<div>
A mediados de los 80, <a href="https://en.wikipedia.org/wiki/HyperCard"><b>Hypercard</b></a>, de <b>Bill Atkinson</b>, fue una aplicación gráfica que facilitaba a los usuarios la creación de sus propias soluciones y a compartirlas. Atkinson insistió en que se distribuyera de modo <b>gratuito </b>y <b>Apple </b>insistió en encontrarle alguna manera de obtener ganancias. Finalmente, el desarrollo de Hypercard se estancó y <b>Steve Jobs</b> canceló su desarrollo, cuando volvió a mediados de los 90.</div>
<div>
<br /></div>
<div>
Aunque hoy hay fans que recuerdan el legado de Hypercard, me parece que se enfocan más en las <b>cualidades técnicas</b> (como la interfaz gráfica, que sirvió de inspiración a <b>VisualBasic </b>y otras herramientas), que en la <b>cualidad social</b> de emponderar a los usuarios para hacer sus propias soluciones.</div>
<br />
<br />
Quizás sea posible implementar la idea en la web, usando componentes que puedan componerse para formar nuevos componentes, tanto a mano como dinámicamente.<br />
<br />
Quizás <b>React </b>pueda ser una buena opción para eso. (Sin embargo, la forma en que se suele usar React, con <b>Webpack </b>para generar compilados, parece una especie de barrera. A veces parece como si las compilaciones fueran una forma de dejar fuera a los demás y ponerse uno como intermediario.)<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div style="font-size: medium; font-style: normal; margin: 0px;">
<br /></div>
<div style="font-size: medium; font-style: normal; margin: 0px;">
<br /></div>
<div style="margin: 0px; text-align: center;">
<i><span style="font-size: x-small;">Transcrito de <a href="http://rulokoba.blogspot.pe/2017/05/un-entorno-que-empondere-los-usuarios.html">http://rulokoba.blogspot.pe/2017/05/un-entorno-que-empondere-los-usuarios.html</a></span></i></div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-19875758.post-65926436548419870672017-05-18T13:01:00.003-05:002017-05-18T13:19:50.954-05:00Programando tu propia comida<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjnAz_xiTD1tFOAYmJk2vqQySA1Q09iNblUC9a6_ppd6ohezJOtQ2IntvW1Qd_I0gCs0ntcxKldW30QIRTNfduUcsAwwUmMcoRkV0pTyOuCO-xaU14RrfhxH4PQrw5FsWmSQ6Y/s1600/OldSchoolProgramming-small.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjnAz_xiTD1tFOAYmJk2vqQySA1Q09iNblUC9a6_ppd6ohezJOtQ2IntvW1Qd_I0gCs0ntcxKldW30QIRTNfduUcsAwwUmMcoRkV0pTyOuCO-xaU14RrfhxH4PQrw5FsWmSQ6Y/s1600/OldSchoolProgramming-small.png" /></a></div>
En un inicio, si alguien tenía una <b>computadora </b>era para <b>programar </b>algo que solucionara su problema en particular.<br />
<br />
Habían recetas de soluciones que se compartían entre la gente que programaba.<br />
<br />
Cuando mucha gente trabajaba sobre cierto programa, se iban estableciendo costumbres y estándares para facilitar la comunicación entre las personas.<br />
<br />
Nuevas formas de programar fueron emergiendo para facilitar que más gente pudiera programar soluciones más complejas con más facilidad.<br />
<br />
Poco a poco, ya no fue necesario conocer de electrónica, ni de cuestiones específicas del hardware de la computadora. Luego, no fue necesario usar siglas mnemotécnicas sino expresiones muy parecidas al inglés.<br />
<br />
Entonces, en algún momento, alguien notó que una computadora podía tener usuarios que no programaran, sino que usaran interfaces simples para realizar acciones sin componer nuevos programas.<br />
<br />
Más tarde, alguien más notó que esos programas con interfaces simples podrían ser vendidos. Y luego, que para asegurar la dependencia podían limitar la posibilidad de hacer nuevos programas.<br />
<br />
El <b>software comercial</b> permite resolver muchos problemas. Pero cada nueva característica, cada mejora, depende de que el proveedor del programa lo incorpore en la siguiente versión, por la que tendremos que pagar.<br />
<br />
El <b>software libre</b> aparece como una respuesta a esta situación. Al obligar a que el código fuente de cada programa este disponible y cada usuario tenga la libertad de modificarlo y redustribuirlo, ayudó a que quienes tuvieran el conocimiento técnico suficiente pudieran ayudar con la evolución del software.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBLbQaAg6sMC66vCNMFyi3FZvKbkp-axF2Wiv8m0_K6Cp-MI7CYDc39bC7iu37E4VYGUCkoSe3nitG8VeJoCALC5WzrXu8gVnTDKmx2Ji0C8zuHccTqjQzVaIp65jZVULyPo-f/s1600/learning-new-programming-language-.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBLbQaAg6sMC66vCNMFyi3FZvKbkp-axF2Wiv8m0_K6Cp-MI7CYDc39bC7iu37E4VYGUCkoSe3nitG8VeJoCALC5WzrXu8gVnTDKmx2Ji0C8zuHccTqjQzVaIp65jZVULyPo-f/s320/learning-new-programming-language-.jpg" width="320" /></a></div>
Sin embargo, <b>la barrera es muy alta</b>. El software actual, comercial o libre, sigue el esquema de aplicaciones paquete de muy difícil manufactura. Se necesita avanzados conocimientos de programación para lograr algo así. Además, son productos de uso final que difícilmente se comunican entre sí y que prácticamente no se pueden desagregar ni componer para formar nuevas soluciones.<br />
<br />
A fines de los '80, <b>Apple</b>, una empresa con el estilo de proveer productos de cómputo que los usuarios no pueden alterar ni extender, tuvo un producto llamado <b>Hypercard</b>, creado por <b>Bill Atkinson</b>, que permitía a los usuarios componer visualmente secuencias de acciones y expresar los detalles en el lenguaje <b>Hypertalk</b>, muy simple y fácil de leer y escribir. Es decir, creó un entorno que permitía que los usuarios finales pudieran hacer programas para solucionar sus problemas particulares. Como antes, apareció una comunidad que compartía sus recetas.<br />
<br />
Por alguna razón, está iniciativa no recibió el apoyo adecuado. Las siguientes versiones del producto limitaban las capacidades de creación y buscaba colocar a Apple como intermediario, otra vez, de las soluciones que la comunidad de usuarios era capaz de realizar por si misma.<br />
<br />
Cuando <b>Steve Jobs</b> (precisamente, uno de los primeros en notar cómo hacer negocios con el software) regresó a la dirección, uno de los proyectos que canceló fue el de Hypercard.<br />
<br />
Cosas como Hypercard necesitan una comunidad de usuarios emponderados, capaces de crear soluciones cuya explotación no puedes controlar.<br />
<br />
Hay proyectos que tomaron la posta de ciertas ideas de Hypercard. Como VisualBasic, con su interfaz visual. Pero parece que siempre orientados a programadores, no a un público laico.<br />
<br />
Parece más probable que una iniciativa que herede el espíritu de Hypercard provenga del software libre que del software comercial.<br />
<br />
<br />
Hoy, el software comercial ha logrado que prácticamente cada persona cuente con una computadora en la mano. Gracias a ella puede consumir los productos que les preparan. La barrera técnica para preparar esos productos es tan alta y los consumidores tan ávidos de soluciones que se ha vuelto notoria la falta de capacidad para cubrir esa demanda.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3S6JiU-n28PpOr0jSNjfWMAajqDATFULTbAuKy73HATec-20XkKm4XivTUDCC1rNhP7w2h0NnL-QoTOwfQ-RacZC-amMwvWJxlVjSpv0HHJIhAaGva2giNtiCX1kx81FNATwI/s1600/workers-on-an-industrial-cooking-services-company-in-the-spanish-island-F72DMY.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3S6JiU-n28PpOr0jSNjfWMAajqDATFULTbAuKy73HATec-20XkKm4XivTUDCC1rNhP7w2h0NnL-QoTOwfQ-RacZC-amMwvWJxlVjSpv0HHJIhAaGva2giNtiCX1kx81FNATwI/s320/workers-on-an-industrial-cooking-services-company-in-the-spanish-island-F72DMY.jpg" width="320" /></a>Es como si hubiera pocos <b>restaurantes </b>para muchos <b>comensales</b>.<br />
<br />
La comunidad de <b>programadores</b>, que son como los cocineros, ha optado por buscar modos de mejorar su respuesta, optimizando la forma en que programan, automatizando procesos, etc.<br />
<br />
Los <b>gobiernos </b>están promoviendo la enseñanza de programación para aumentar el número de programadores. Es como aumentar el número de chefs y restaurantes.<br />
<br />
Y sigue el aumento de <b>gente con nuevas ideas</b> de aplicaciones. Son como comensales con nuevas ideas de platillos, buscando chefs que los entiendan, o incluso financiandose un pequeño restaurante para poder ofrecer al mundo ese platillo que imaginan.<br />
<br />
Ellos necesitan programadores porque, a diferencia del mundo de los comensales que también pueden cocinar, en el mundo de las aplicaciones es tan alta la valla de entrada que es como si sólo existieran cocinas industriales y ollas gigantes y sólo ingredientes al por mayor. La poca gente que puede preparar sus alimentos son los que saben hacer sus propias hogueras y utensilios para cocinar. O las que comen sushi.<br />
<br />
¿Qué podemos hacer en este escenario?<br />
<br />
Además de los cocineros tratando de cocinar más rápido y de los gobiernos tratando de hacer más cocineros, hay otras iniciativas en curso.<br />
<br />
Hay el equivalente a <b>cocinas comunitarias</b>, donde cocineros pueden alquilar un espacio.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOODhlFxpWqN_zL5L3BLGbpP8ogRHQsc8iaOYnbvhFo-91gVHR-FSmTnTWal4fml-MmtQCnNg-PGtUbhywH_FzZdmyMUiq_fkM8os05Hiw01CI0Iuua6GpnYFhVZ6xD3OCzbei/s1600/food_machine_304x562.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOODhlFxpWqN_zL5L3BLGbpP8ogRHQsc8iaOYnbvhFo-91gVHR-FSmTnTWal4fml-MmtQCnNg-PGtUbhywH_FzZdmyMUiq_fkM8os05Hiw01CI0Iuua6GpnYFhVZ6xD3OCzbei/s320/food_machine_304x562.jpg" width="173" /></a></div>
Hay el equivalente a <b>máquinas expendedoras</b>, donde se pueden conseguir golosinas, cafe o sandwich. Administradores de contenido que te permiten combinar algunas opciones para armar un refrigerio.<br />
<br />
Los avances en <b>inteligencia artificial</b> están permitiendo máquinas expendedoras capaces de preparar algunas comidas básicas. Es decir, acciones simples como encender las luces, monitorear el refrigerador, sintonizar la tv o hacer consultas en Google, obedeciendo comandos en el lenguaje del usuario.<br />
<br />
<br />
Quizás a estas alturas ya hayas notado qué ha pasado y qué se podría hacer.<br />
<br />
Es como si se hubiera convencido a todo el mundo que la única forma de comer decentemente es en un restaurante o comprando algo hecho por un cocinero profesional.<br />
<br />
¿Qué vendría a ser Hypercard? Quizás algo así como una máquina expendedora pero no de comida, sino de pequeños utensilios para cocinar, o de partes modulares para armar esos utensilios, y de ingredientes al por menor.<br />
<br />
El símil deja ver que así como todo el mundo puede cocinar aprendiendo unas pautas básicas, la programación podría ser algo más asequible también.<br />
<br />
El poder de la inteligencia artificial también podría ayudar, si se le permitiera disgregar soluciones existentes y componerlas en nuevas soluciones y a la comunidad de usuarios compartirlas libremente.<br />
<br />
La clave es una <b>libertad efectiva</b> para <b>componer nuevos programas</b> a partir de otros, y de poder <b>compartirlos libremente</b>.<br />
<br />
Si no puedes cocinar, dependes de alguien más para algo que debería ser una libertad básica.<br />
<br />
No digo que no haya restaurantes. Tampoco que atendamos restaurantes usando expendedoras. Digo que no debe ser prohibitivo cocinar uno mismo.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-hOSG9t9XfAGiUqlMfFlbEOtYsNrAbBNiVgr8n_FPozGEPCJTNBOh_KW6PSAjb3FM7PdC4nwnGO9VKReLKkRcZGyBvLIWdlZG50D2aBQERkHvTIyo59yYA1fTPnPKH96sLVM9/s1600/NGI-CFPWI-web.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-hOSG9t9XfAGiUqlMfFlbEOtYsNrAbBNiVgr8n_FPozGEPCJTNBOh_KW6PSAjb3FM7PdC4nwnGO9VKReLKkRcZGyBvLIWdlZG50D2aBQERkHvTIyo59yYA1fTPnPKH96sLVM9/s320/NGI-CFPWI-web.jpg" width="320" /></a></div>
Cada persona debe tener la libertad, y el poder, de resolver sus propios problemas, sin intermediarios.<br />
<br />
Programar debe ser una actividad al alcance de cualquier persona.<br />
<br />
Porque cada cambio en el mundo nace de una persona, no de un rebaño.<br />
<br />
Y el mundo está necesitando cambios significativos más rápido de lo que se le puede proveer.<br />
<br />
Necesitamos herramientas de programación más asequibles. El equivalente a una cocina de hogar o una hornilla. Ollas pequeñas y personales. Ingredientes al por menor. Recetas familiares.<br />
<br />
Necesitamos liberar la creatividad de las personas para descubrir nuevas experiencias y soluciones... nuevos sabores.<br />
<br />Unknownnoreply@blogger.com0