<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: José M. Alarcón 🌐</title>
    <description>The latest articles on DEV Community by José M. Alarcón 🌐 (@jmalarcon).</description>
    <link>https://dev.to/jmalarcon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F98625%2F233b0cdf-7890-4932-a536-eb50f7c5c8c4.jpg</url>
      <title>DEV Community: José M. Alarcón 🌐</title>
      <link>https://dev.to/jmalarcon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jmalarcon"/>
    <language>en</language>
    <item>
      <title>Compartir código en Visual Studio: proyectos compartidos o librerías</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Fri, 02 Oct 2020 07:44:18 +0000</pubDate>
      <link>https://dev.to/campusmvp/compartir-codigo-en-visual-studio-proyectos-compartidos-o-librerias-2547</link>
      <guid>https://dev.to/campusmvp/compartir-codigo-en-visual-studio-proyectos-compartidos-o-librerias-2547</guid>
      <description>&lt;p&gt;La manera tradicional de compartir código entre proyectos en Visual Studio siempre ha sido la creación de &lt;strong&gt;bibliotecas de código&lt;/strong&gt; , es decir, ensamblados en forma de DLL que permiten la reutilización de clases entre proyectos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : el término original en inglés es "library" y se suele traducir al español erróneamente como "librería". En realidad la traducción y el término correcto en español es "biblioteca", &lt;a href="https://www.microsoft.com/en-us/language/Search?&amp;amp;searchTerm=library&amp;amp;langID=736&amp;amp;Source=true&amp;amp;productid=0" rel="noopener noreferrer"&gt;en todas sus acepciones&lt;/a&gt;. Se trata del típico "false friend" inglés/español. En el título he puesto "librería" porque seguramente será lo que busquéis la mayoría. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Este es el camino a seguir en la mayor parte de las ocasiones ya que creamos una DLL con la funcionalidad requerida a compartir entre varias aplicaciones, y simplemente añadiendo una referencia a dicha DLL (o el proyecto, si está en una misma solución) a otro de nuestros proyectos en Visual Studio ya tenemos la funcionalidad que necesitábamos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-01.png" alt="Añadir una referencia a un proyecto"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La verdad es que esto es muy cómodo, pero no siempre es lo que queremos. En ocasiones lo que nos interesa es compartir funcionalidad entre proyectos &lt;strong&gt;compartiendo directamente el código fuente&lt;/strong&gt;. A lo mejor no nos interesa distribuir otra DLL con el producto final, o tal vez queremos ir tocando al código original en función de las necesidades y que éste evoluciones por igual en todos los proyectos que lo usan. También puede ser muy útil cuando quieres usar el mismo código genérico en varios proyectos que se enfocan y compilan para plataformas diferentes.&lt;/p&gt;

&lt;p&gt;Para solucionar este tipo de problemas, en Visual Studio 2013 update 2 (en &lt;a href="https://devblogs.microsoft.com/somasegar/visual-studio-2013-update-2-rc-windows-phone-8-1-tools-shared-projects-and-universal-windows-apps/" rel="noopener noreferrer"&gt;abril de 2014&lt;/a&gt;) se introdujo un nuevo tipo de proyectos: &lt;strong&gt;los proyectos compartidos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;El archivo de un proyecto compartido tiene la extensión &lt;strong&gt;&lt;code&gt;.shproj&lt;/code&gt;&lt;/strong&gt; y al contrario que en el caso de una biblioteca, &lt;strong&gt;lo que se utiliza es directamente el código fuente, no la DLL resultante&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por lo tanto, &lt;strong&gt;el código fuente de ese proyecto compartido es como si formase parte de nuestro proyecto actual&lt;/strong&gt; , no de un proyecto aparte, de modo que se compila como cualquier otro archivo de nuestro proyecto y forma parte del ensamblado final de la aplicación. Para entendernos, es como si tuviésemos una subcarpeta con esos archivos de código dentro de nuestro proyecto. Al final obtenemos una sola DLL. Pero es un proyecto independiente que podemos usar en varios sitios a la vez.&lt;/p&gt;

&lt;p&gt;Por ejemplo, en &lt;strong&gt;&lt;a href="https://miis.azurewebsites.net/" rel="noopener noreferrer"&gt;mi proyecto Open Source MIIS&lt;/a&gt;&lt;/strong&gt;, un CMS basado en archivos, quería compartir algún código entre éste y otro &lt;em&gt;side-project&lt;/em&gt; comercial que tengo, &lt;strong&gt;&lt;a href="https://iismailer.com/" rel="noopener noreferrer"&gt;IISMailer&lt;/a&gt;&lt;/strong&gt;, pero no quería tener una biblioteca común que distribuir y además al mismo tiempo me interesaba poder tocarle al código en cualquiera de los dos proyectos y que ambos se beneficiaran de los añadidos. La solución: usar un proyecto compartido.&lt;/p&gt;

&lt;p&gt;En este caso le llamé &lt;code&gt;IISHelpers&lt;/code&gt;, y aquí podemos verlo en el código fuente de MIIS abierto en Visual Studio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-02.png" alt="Un proyecto compartido y otro qu elo referencia en Visual Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El recuadro de arriba es el proyecto compartido en sí, que se ve como un proyecto aparte (porque lo es) pero se comporta como si el código estuviese dentro del proyecto principal, desde el cual se hace referencia. Esto último podemos verlo si desplegamos las referencias del proyecto principal, en donde se ve con el mismo icono de proyecto compartido que arriba. La forma de añadirla es la habitual, simplemente lo elegimos desde la pestaña "Proyectos".&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo crear un proyecto compartido en Visual Studio
&lt;/h2&gt;

&lt;p&gt;Crear uno de estos proyectos es de lo más sencillo desde VS2015 (antes no lo era tanto), y consiste simplemente en elegirlo en la lista de plantillas de proyecto que tiene Visual Studio al añadir un nuevo proyecto desde una solución, así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-03.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-03.gif" alt="Animación que muestra cómo agregar un proyecto compartido a una solución en Visual Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora solo resta añadir la referencia en otro proyecto para que forme parte de éste.&lt;/p&gt;

&lt;p&gt;Por regla general es fácil y directo (ahora te cuento cuándo no). Basta con ir a agregar una referencia y elegir el proyecto compartido dentro de la pestaña de "Proyectos compartidos", así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-04.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-04.gif" alt="Añadiendo referencia a un proyecto compartido"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta animación primero añado a la solución un proyecto compartido existente, y luego añado una referencia a éste desde el proyecto principal.&lt;/p&gt;

&lt;h2&gt;
  
  
  No aparecen referencias a proyectos compartidos en proyectos web en VS2017
&lt;/h2&gt;

&lt;p&gt;Visual Studio 2017 añadió un bug a la hora de manejar proyectos compartidos desde aplicaciones Web. Simplemente no aparece la pestaña de "Proyectos compartidos" al agregar una referencia y por lo tanto no podemos agregarla visualmente tal y como se observa en la animación anterior.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En Visual Studio 2019 lo han solucionado y funciona perfectamente también proyectos web. Esperemos que dure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por suerte solucionarlo es relativamente sencillo, pero engorroso. Lo que tenemos que hacer es editar manualmente el archivo del proyecto al que queremos añadir el proyecto compartido. Partiendo de la base de que ya has añadido el proyecto compartido a la solución, ahora debes abrir con un editor de texto (el mismo bloc de notas nos vale) el archivo &lt;code&gt;.csproj&lt;/code&gt; que tiene la definición de tu proyecto de C# (&lt;code&gt;.vbproj&lt;/code&gt; en el caso de Visual Basic .NET). Dentro de este archivo XML debes localizar los nodos &lt;code&gt;&amp;lt;import&amp;gt;&lt;/code&gt; y debes añadir entre éstos un nuevo nodo import que apunte al archivo &lt;code&gt;.projitems&lt;/code&gt; de tu proyecto compartido, usando rutas relativas o absolutas para ello, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Import Project="..\..\MiProyCompartido\MiProyCompartido.projitems" Label="Shared" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-07.png" alt="Nodo import del archivo de proyecto de C#"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto le indica a Visual Studio que debe cargar ese proyecto compartido como referencia. El archivo &lt;code&gt;.projitems&lt;/code&gt; contiene una lista con todos los archivos de código del proyecto compartido y la manera en la que debe actuar el compilador con ellos (puedes abrirlo para comprobarlo).&lt;/p&gt;

&lt;p&gt;Si ahora abres la solución en Visual Studio verás que el proyecto de código compartido está ahí, al igual que su referencia y todo funciona como cabría esperar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Muy importante&lt;/strong&gt; : como a los proyectos compartidos se accede a través de su ruta, es importante que si los movemos de sitio lo tengamos en cuenta y los cambiemos tanto en los archivos &lt;code&gt;.sln&lt;/code&gt; o como en los &lt;code&gt;.csproj&lt;/code&gt; que hagan referencia a los mismos, o Visual Studio no podrá cargarlos. Por eso son mejores las rutas relativas que las absolutas, pero de todos modos puede ser un engorro. De hecho esta es una de las mayores "pegas" del uso de este tipo de proyectos. Ahora bien, si tenemos un entorno de desarrollo estable y los archivos de proyecto los tenemos siempre en los mismos sitios, no debería haber problema. Pero debes tenerlo en cuenta, sobre todo si compartes proyectos con más miembros de un equipo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Referencias a archivos individuales
&lt;/h2&gt;

&lt;p&gt;Un último detalle para terminar. Si lo único que necesitas compartir de esta manera son uno o dos archivos, quizá lo del proyecto compartido sea un poco "matar moscas a cañonazos". Desde las primeras versiones de Visual Studio existe una manera de compartir archivos individuales de manera parecida, para reutilizarlos como si fueran parte del proyecto actual aunque estén en otro lado. Se trata de la opción &lt;code&gt;Añadir como vínculo&lt;/code&gt; que se ofrece al agregar un archivo existente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-06.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jasoft.org%2FBlog%2Fimage.axd%3Fpicture%3D%2F2019%2FVS-proyectos-compartidos-06.gif" alt="Añadir referencia como vínculo a un archivo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De esta manera el archivo se utiliza directamente desde donde esté, fuera del proyecto, pero se compila como un archivo de código fuente más. O sea, consigue lo mismo que los proyectos compartidos pero archivo a archivo, lo cual está bien si solo son como mucho un par de ellos (más se hace inmanejable y es mejor recurrir a los proyectos compartidos).&lt;/p&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

</description>
      <category>visualstudio</category>
      <category>dotnet</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Cómo solucionar el error "java.lang.NoClassDefFoundError" en Java</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Fri, 02 Oct 2020 07:40:33 +0000</pubDate>
      <link>https://dev.to/campusmvp/como-solucionar-el-error-java-lang-noclassdeffounderror-en-java-4343</link>
      <guid>https://dev.to/campusmvp/como-solucionar-el-error-java-lang-noclassdeffounderror-en-java-4343</guid>
      <description>&lt;p&gt;La excepción en el hilo "main" del tipo &lt;code&gt;java.lang.NoClassDefFoundError&lt;/code&gt; es uno de los errores más comunes que te puedes encontrar al programar en Java. Y también una de las que más quebraderos de cabeza te pueden ocasionar dependiendo de la circunstancia que la cause.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exception in thread "main" java.lang.NoClassDefFoundError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependiendo del tamaño de tu aplicación, resolver este error puede ser más o menos difícil (cuanto más grande más complicado, lógicamente).&lt;/p&gt;

&lt;p&gt;Vamos a ver a continuación las causas más comunes de que se produzca este error y cómo podemos intentar resolverlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué significa este error y por qué se produce?
&lt;/h2&gt;

&lt;p&gt;Antes de nada es necesario que sepamos a qué se debe la aparición de este error. Como su propio nombre indica, este error se produce cuando &lt;a href="https://www.campusmvp.es/recursos/post/que-es-la-maquina-virtual-de-java-o-java-virtual-machine.aspx"&gt;la máquina virtual de Java&lt;/a&gt; no es capaz de encontrar la definición de una clase de la que depende el programa para su funcionamiento. Es decir, cuando su &lt;code&gt;ClassLoader&lt;/code&gt; no es capaz de encontrar la clase en su árbol de carga actual.&lt;/p&gt;

&lt;p&gt;Si el programa compiló sin problema, quiere decir que la clase se encontró a la hora de compilar, pero luego, en ejecución, no aparece por ningún lado, lo cual puede parecer una cosa muy extraña, pero existen diversos motivos para que pueda ocurrir.&lt;/p&gt;

&lt;p&gt;Para empezar, tiene mucho que ver el funcionamiento del &lt;code&gt;ClassLoader&lt;/code&gt;. Sin profundizar ni entrar en mucho detalle (info detallada &lt;a href="http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html"&gt;aquí&lt;/a&gt;), este objeto funciona de manera jerárquica, de modo que hay varios &lt;code&gt;ObjectLoader&lt;/code&gt; a diferentes niveles que localizan y cargan clases. Por ello, por ejemplo, incluso aunque una clase se encuentre, dependiendo del nivel en el que aparezca, si la estamos usando en un nivel inferior es posible que se produzca el temido error que nos ocupa. O puede que si hay dos versiones diferentes del mismo paquete instaladas en el sistema, que se produzca también (generando lo que se conoce como el &lt;a href="https://tech-read.com/2009/01/13/what-is-jar-hell/"&gt;JAR Hell&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Hay muchas posibilidades. Para solucionar el problema, primero hay que determinar el motivo por el que está ocurriendo, y luego actuar en consecuencia.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Es interesante notar que la excepción &lt;code&gt;java.lang.ClassNotFoundException&lt;/code&gt;, que se parece mucho a la que estamos tratando, solo se produce cuando intentamos cargar en tiempo de ejecución una clase utilizando su nombre. Son excepciones distintas aunque conceptualmente parecidas. Esta última es menos frecuente. La que nos ocupa tiene una ventaja y es que sabemos que durante la compilación la clase estaba presente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Principales motivos para que se produzca la excepción &lt;code&gt;NoClassDefFoundError&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Por orden de importancia, los principales motivos de la excepción son:&lt;/p&gt;

&lt;h3&gt;
  
  
  1.- El paquete no está disponible en el &lt;em&gt;Classpath&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Esta es quizá la más común de las situaciones y se produce porque la JVM no es capaz de encontrar el paquete correspondiente en &lt;a href="https://docs.oracle.com/javase/tutorial/essential/environment/paths.html"&gt;el &lt;em&gt;Classpath&lt;/em&gt; de Java&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si falta el archivo &lt;code&gt;.jar&lt;/code&gt; o se ha renombrado (por ejemplo, se cambia de &lt;code&gt;miPaquete.jar&lt;/code&gt; a &lt;code&gt;miPaquete-v2.jar&lt;/code&gt;), la JVM no es capaz de encontrarlo. En estos casos lo más sencillo es simplemente localizar el paquete y copiarlo a donde debería estar (o dejarle el nombre antiguo).&lt;/p&gt;

&lt;p&gt;Si tienes dudas sobre dónde está ubicado el &lt;code&gt;Classpath&lt;/code&gt; puedes mostrar por pantalla la ruta usando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.getproperty("java.classpath")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otra opción de emergencia para salir de dudas sobre si estamos yendo al sitio adecuado es lanzar el programa especificando manualmente la ruta desde la que se van a cargar los paquetes locales, usando la opción &lt;code&gt;-classpath&lt;/code&gt; (o &lt;code&gt;-cp&lt;/code&gt;, abreviada) al ejecutar el programa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java -cp C:\java\MisClases miPrograma
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De este modo estaremos seguros de que, a pesar de estar usando la ruta correcta y tener en ella el paquete apropiado, el programa no es capaz de cargar la clase, así que debemos ver otras posibilidades.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : La opción &lt;code&gt;-cp&lt;/code&gt; también puede hacer referencia a archivos &lt;code&gt;.jar&lt;/code&gt; directamente, uno o varios nombres separados por comas. Es habitual cuando una aplicación depende de código Java compilado (bibliotecas externas) que el &lt;code&gt;classpath&lt;/code&gt; se mantenga apuntando al JRE de Java y luego se agregue con &lt;code&gt;-cp&lt;/code&gt; la referencia a los archivos &lt;code&gt;.jar&lt;/code&gt; de esas bibliotecas de terceros, que no forman parte del JRE sino que se distribuyen conjuntamente con la aplicación.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.- Faltan permisos suficientes
&lt;/h3&gt;

&lt;p&gt;Algún problema de permisos puede estar impidiendo que se puedan cargar las clases de un archivo &lt;code&gt;.jar&lt;/code&gt; y que se produzca la excepción &lt;code&gt;NoClassDefFoundError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Debes asegurarte de que el usuario actual tiene permisos suficientes para acceder a los archivos. Esto es especialmente importante en el caso de que algún paquete sea compartido y por lo tanto pueda tener unos permisos establecidos por otro usuario, sin haber creado permisos que aseguren el acceso por parte de todos los usuarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.- Falta alguna dependencia de terceros
&lt;/h3&gt;

&lt;p&gt;Alguna dependencia del programa, por ejemplo una biblioteca nativa, no está disponible en el equipo actual, pero sí lo estaba en el equipo en el que se compiló.&lt;/p&gt;

&lt;p&gt;Determina cuál es mirando el log de errores e instálala en el equipo actual.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.- Falta de visibilidad entre niveles de la jerarquía del ClassLoader
&lt;/h3&gt;

&lt;p&gt;En J2EE, como hemos explicado antes, la falta de visibilidad de la clase entre los diferentes niveles de la jerarquía en el proceso de carga puede provocar esta situación.&lt;/p&gt;

&lt;p&gt;Esta es una situación compleja y puede dar bastante trabajo solucionarla, así que en lugar de escribir una larguísima explicación aquí te remito al &lt;a href="https://javaeesupportpatterns.blogspot.com.es/2012/08/javalangnoclassdeffounderror-parent.html"&gt;excelente artículo de Pierre-Hugues Charbonneau en el blog de Java EE Support Partners&lt;/a&gt;, que lo explica detalladamente y con un ejemplo real paso a paso.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.- Un script de inicialización sobrescribe a ClassPath
&lt;/h3&gt;

&lt;p&gt;Una posibilidad menos frecuente, pero que puede darse es cuando un &lt;em&gt;script&lt;/em&gt; de inicialización del programa está sobrescribiendo la variable de entorno &lt;code&gt;Classpath&lt;/code&gt;, lo cual hace que el resto del programa no pueda encontrar los archivos &lt;code&gt;.jar&lt;/code&gt; apropiados.&lt;/p&gt;

&lt;p&gt;Prueba con lo comentado en el punto 1 para ver si se está usando la ruta correcta.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.- Errores en un bloque de inicialización estática
&lt;/h3&gt;

&lt;p&gt;Si el programa utiliza un &lt;a href="https://www.c-sharpcorner.com/UploadFile/3614a6/static-initialization-block-in-java/"&gt;bloque de inicialización estática&lt;/a&gt; (por ejemplo, es típico con clases de tipo Singleton, que no permiten más que una instancia), es posible que no se encuentre alguna referencia que se use desde ahí.&lt;/p&gt;

&lt;p&gt;Puedes saberlo si en el archivo de log del error aparece referenciada la clase &lt;code&gt;ExceptionInInitializerError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por ejemplo, si en un bloque estático de inicialización se declara una clase de tipo Singleton que se inicializa a sí misma en dicho bloque, y se produce un error, al querer utilizar la clase posteriormente desde el programa se produce un error de tipo &lt;code&gt;NoClassDefFoundError&lt;/code&gt;, y en el log aparecerá la mencionada &lt;code&gt;ExceptionInInitializerError&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.- JDK desconfigurado o mal instalado
&lt;/h3&gt;

&lt;p&gt;Si alguna de las variables &lt;code&gt;ClassPath&lt;/code&gt;, &lt;code&gt;JAVA_HOME&lt;/code&gt; o &lt;code&gt;PATH&lt;/code&gt; está mal establecida debido a algún problema de la instalación de Java, vamos a obtener errores de tipo &lt;code&gt;NoClassDefFoundError&lt;/code&gt;, por supuesto. En este caso habría que reinstalar el &lt;em&gt;runtime&lt;/em&gt; de Java para solucionarlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  No están todos los que son pero sí son todos los que están
&lt;/h2&gt;

&lt;p&gt;En este artículo hemos procurado repasar las causas y las soluciones más comunes para este error habitual a la hora de programar en Java. Dependiendo de lo que lo esté causando puede ser muy fácil o muy complicado de arreglar.&lt;/p&gt;

&lt;p&gt;Los puntos que hemos comentado son los más comunes, pero existen todavía algunas situaciones más que lo pueden producir, si bien son menos habituales.&lt;/p&gt;

&lt;p&gt;Una buena recomendación, no solo para este caso, sería que procures utilizar siempre algún entorno integrado de desarrollo como NetBeans o Eclipse, ya que con sus ayudas integradas minimizan mucho las situaciones difíciles y los posibles errores. Aún así, va a ser inevitable que ocurran cosas como esta de vez en cuando. Si es tu caso, espero que al menos este artículo te ayude y proporcione alguna pista para solucionarlo.&lt;/p&gt;

</description>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>TypeScript contra JavaScript: ¿cuál deberías utilizar?</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Fri, 11 Sep 2020 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/typescript-contra-javascript-cual-deberias-utilizar-5gg</link>
      <guid>https://dev.to/campusmvp/typescript-contra-javascript-cual-deberias-utilizar-5gg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post publicado originalmente en &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/post/typescript-contra-javascript-cual-deberias-utilizar.aspx"&gt;campusMVP&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Salvo que hayas vivido debajo de una piedra durante los últimos años, si te dedicas a algo relacionado con el desarrollo web Front-End, seguro que has escuchado hablar de &lt;strong&gt;TypeScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TypeScript es un lenguaje de programación construido por encima de JavaScript&lt;/strong&gt;. Este superconjunto de JavaScript dota al lenguaje de varias características adicionales que hacen que podamos escribir código con menos errores, más sencillo, coherente y fácil de probar.&lt;/p&gt;

&lt;p&gt;Desde su creación por parte de Microsoft en 2012, la adopción de TypeScript no ha hecho más que crecer. En especial desde que Google decidió adoptarlo como lenguaje por defecto para desarrollar con Angular.&lt;/p&gt;

&lt;p&gt;Esta es la evolución del interés por TypeScript en los últimos años en España:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Yy7G6t5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-ts-trends-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Yy7G6t5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-ts-trends-01.png" alt="Gráfica de Google Trends con las tendencias de búsqueda"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Su subida es &lt;strong&gt;imparable&lt;/strong&gt; (el pico hacia abajo del final, son las navidades de 2019, época en la que todas las búsquedas que no sean regalos bajan mucho 😉). Según &lt;a href="https://2019.stateofjs.com/javascript-flavors/#javascript_flavors_section_overview"&gt;The State of JavaScript para el año 2019&lt;/a&gt;, el 58,5% de los desarrolladores Web Front-End lo ha utilizado ya en alguna ocasión y tiene interés en usarlo en su día a día en el futuro:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7JnMDccx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7JnMDccx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-01.png" alt="Uso de TypeScript"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y desde que se puede utilizar con Node.js también está subiendo mucho en el servidor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pero ¿qué es TypeScript exactamente?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.campusmvp.es/recursos/post/JavaScript-ECMAScript-ES6-Existe-ES7-Aclarando-las-diferentes-versiones-del-lenguaje.aspx"&gt;ECMASCript 6 o posterior&lt;/a&gt; añadió muchas características al JavaScript clásico (ECMAScript 5), como una sintaxis mucho más clara para programación orientada a objetos y muchas nuevas funcionalidades que no existían antes: promesas, programación asíncrona, símbolos, etc. Aún así, presenta limitaciones y dificultades. TypeScript va un paso más allá y añade más funcionalidad a ES, como tipado fuerte, anotaciones o módulos.&lt;/p&gt;

&lt;p&gt;Como TypeScript es un superconjunto de JavaScript, &lt;strong&gt;todo el código escrito en JavaScript es válido para TypeScript&lt;/strong&gt;. Pero lo contrario no es cierto. Es decir, como los navegadores no entienden TypeScript, es necesario &lt;strong&gt;compilarlo&lt;/strong&gt; (la palabra correcta es "transpilarlo") a JavaScript antes de usarlo en un navegador.&lt;/p&gt;

&lt;p&gt;El siguiente esquema ilustra muy bien el concepto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uMKprbfK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uMKprbfK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2020/1T/TypeScript/typescript-vs-javascript-02.png" alt="Esquema que muestra cómo ES6+ añade cosas a JavaScript y TypeScript a ES6+"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TypeScript se puede transpirlar a cualquier variante de JavaScript/ECMAScript que deseemos. Por ejemplo, si sabemos que nuestro proyecto va a trabajar en navegadores antiguos podemos forzar que se compile a ECMAScript 5 (el JavaScript clásico, soportado por todos los navegadores, incluso Internet Explorer). Sin embargo, si tenemos claro que los usuarios van a emplear navegadores relativamente recientes, podemos generar un código final más sencillo apoyado en ECMAScript 6 o posterior.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : por si te lo estabas preguntando ¿eso no lo hace también &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt;, que nos ayuda a usar características nuevas de ES en JS clásico? En efecto, así es. Pero Babel no tiene verificación de tipos ni otras de las características avanzadas que ofrece TypeScript (ahora las veremos), y además son 100% compatibles. De hecho TypeScript tiene un plugin pensado específicamente para trabajar con Babel. Así que si usas Babel puedes seguir haciéndolo con TypeScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Características de JavaScript comparadas con las de TypeScript
&lt;/h2&gt;

&lt;p&gt;Para ofrecerte un resumen fácil de ver de las características en las que TypeScript mejora a las de JavaScript/ECMAScript, te dejo la siguiente tabla comparativa:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;JavaScript&lt;/th&gt;
&lt;th&gt;TypeScript&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tipado estático&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No existe: las variables se pueden cambiar de tipo al vuelo, en cualquier momento&lt;/td&gt;
&lt;td&gt;Es un lenguaje fuertemente tipado por lo que debemos indicar en todos los casos el tipo de dato a manejar y se producen errores si lo cambiamos. También soporta inferencia de tipos en las declaraciones, fijándolos a partir de ahí.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tipos genéricos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No existen.&lt;/td&gt;
&lt;td&gt;Permite crear código reutilizable basado en tipos genéricos (no confundir con la ausencia de tipado fuerte o estático en JavaScript).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tipado estructural&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No existe.&lt;/td&gt;
&lt;td&gt;Permite crear estructuras en base a interfaces de modo que podamos trabajar con una estructura de datos predefinida que no se salga de ciertos parámetros, pero al mismo tiempo permite la flexibilidad de usar estructuras equivalentes con tipos diferentes. &lt;a href="https://www.typescriptlang.org/docs/handbook/type-compatibility.html"&gt;Más info&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tipos enumerados&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Se pueden simular con clases sencillas, pero no dan, ni de lejos, la misma robustez.&lt;/td&gt;
&lt;td&gt;TypeScript permite definir enumeraciones y mantener la robustez al utilizarlas de modo que no nos podamos salir de ellas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tuplas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sin soporte&lt;/td&gt;
&lt;td&gt;Soporta Tuplas como tipo básico de datos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modularización&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Soporta módulos a partir de ECMAScript 6, pero el soporte de módulos en los navegadores es todavía reciente.&lt;/td&gt;
&lt;td&gt;Ofrece soporte para módulos directamente en el lenguaje.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Programación orientada a Objetos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Basada en prototipos, con sintaxis compleja en ES5, y sintaxis simplificada en ES6+.&lt;/td&gt;
&lt;td&gt;Ofrece una sintaxis muy similar a la de otros lenguajes como C# o Java, y además añade capacidades inéditas en ECMAScript, como las clases abstractas, modificadores de acceso, tipos enumerados...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interfaces&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No hay soporte&lt;/td&gt;
&lt;td&gt;En TypeScript las interfaces son esenciales y permiten crear multitud de escenarios avanzados.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Espacios de nombres&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Se pueden simular de manera básica&lt;/td&gt;
&lt;td&gt;Soporte total integrado en el lenguaje, nos ayuda a organizar mejor el código y evitar conflictos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Decoradores&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No hay soporte&lt;/td&gt;
&lt;td&gt;Ofrece un soporte integrado para esta característica lo que facilita enormemente la escritura de código basada en aspectos y la inyección de dependencias.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Tooling&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Todo esto está muy bien, pero quedarse sólo en ello sería dejar fuera casi lo más importante: el gran soporte de &lt;strong&gt;herramientas en tiempo de desarrollo&lt;/strong&gt; que tiene TypeScript, es decir, lo que se conoce popularmente como &lt;strong&gt;&lt;em&gt;tooling&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lo principal que hay que saber es que TypeScript integra &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29"&gt;un componente llamado tsserver y un protocolo del mismo nombre&lt;/a&gt; que encapsula al compilador y otros servicios del lenguaje y los expone como un servicio para los editores de código. Esto proporciona una gran capacidad para validar el código a medida que se escribe y ofrecer ayuda contextual (conocida como &lt;strong&gt;&lt;em&gt;Intellisense&lt;/em&gt;&lt;/strong&gt; ) al programador mientras programa.&lt;/p&gt;

&lt;p&gt;Ello nos proporciona una capacidad enorme para crear código con menos errores y para recibir ayuda durante todo el proceso de desarrollo.&lt;/p&gt;

&lt;p&gt;Todos los principales editores de código, como &lt;strong&gt;Atom&lt;/strong&gt; , &lt;strong&gt;Sublime&lt;/strong&gt; , &lt;strong&gt;EMacs&lt;/strong&gt; , &lt;strong&gt;NeoVim&lt;/strong&gt;... y por supuesto &lt;strong&gt;&lt;a href="https://code.visualstudio.com/docs/languages/typescript"&gt;Visual Studio Code&lt;/a&gt;&lt;/strong&gt;, incluyen soporte para esta característica.&lt;/p&gt;

&lt;p&gt;Si te interesa saber más, el programador alemán &lt;strong&gt;Felix Becker&lt;/strong&gt; dio una charla muy interesante sobre el tema en el FOSDEM de 2019: &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=tqw-BRJq9ZM"&gt;Advanced TypeScript Tooling at Scale&lt;/a&gt;&lt;/strong&gt; (en inglés, &lt;em&gt;obviously&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;¿En JavaScript se puede conseguir algo similar? Pues sí, pero implica documentar absolutamente todo lo que escribas con &lt;a href="https://jsdoc.app/"&gt;JSDoc&lt;/a&gt; y que tu editor te dé soporte para ello (la mayoría lo hace). Es decir, no es directo ni mucho menos automático.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;De hecho, ¿sabes cómo obtener en Visual Studio Code un mejor &lt;em&gt;Intellisense&lt;/em&gt; para JavaScript? Pues poniendo el comentario &lt;code&gt;//@ts-check&lt;/code&gt; en la primera línea de tus archivos &lt;code&gt;.js&lt;/code&gt;. Si partimos del hecho de que el código JavaScript es código TypeScript válido, lo puede compilar como TypeScript y usar tsserver por detrás 😉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Ventajas de TypeScript
&lt;/h2&gt;

&lt;p&gt;Podemos resumir las principales ventajas de TypeScript en esta lista:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Es fácil de aprender&lt;/strong&gt; , y todo el equipo puedo ponerse al día con él en poco tiempo. Aunque antes se debe conocer a fondo JavaScript, o sea, que no es para principiantes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convierte a JavaScript en un lenguaje "adulto"&lt;/strong&gt; , equiparable en muchos aspectos con Java o C#. De hecho, puedes empezar poco a poco: escribiendo JavaScript y añadiendo paulatinamente TypeScript mezclado con el anterior, ya que es 100% compatible con JS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permite desarrollar sin preocuparse por el soporte de ciertas características&lt;/strong&gt; nuevas que se incorporan a las diferentes versiones de ECMAScript, ya que luego se traduce el código para que funcione con versiones más antiguas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora la ayuda contextual&lt;/strong&gt; mientras escribes código, ya que es más rico en información que JavaScript. En editores que lo soportan (y hay muchos), notarás una gran diferencia y disminuirá los errores que cometas tú y tu equipo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permite crear código estandarizado&lt;/strong&gt; en todo el equipo de trabajo, dejando mucho menos margen para los problemas y para hacerlo crecer en el futuro a medida que haya mejor soporte nativo en los navegadores para ciertas características.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Funciona bien con las librerías y &lt;em&gt;frameworks&lt;/em&gt; de Front-End&lt;/strong&gt; que estés utilizando. Algunas, como Angular, Ember o Aurelia le sacan especial partido, e incluso el uso combinado de TypeScript + React se está convirtiendo en norma.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Desventajas de TypeScript
&lt;/h2&gt;

&lt;p&gt;No todo iba a ser maravilloso (aunque la mayoría sí). Veamos las principales "pegas":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;La curva de aprendizaje es mayor que la de JavaScript&lt;/strong&gt;. No es que sea especialmente complejo, pero desde luego no es como un lenguaje de &lt;em&gt;scripting&lt;/em&gt; normal. Para empezar necesitas conocer bien JavaScript, pues en el fondo está basado en éste. Pero además implementa muchos otros conceptos avanzados propios de otros lenguajes como C# o Java, por lo que algunas cosas pueden llegar a costar a los que vienen tan solo de un &lt;em&gt;background&lt;/em&gt; en Web. De todos modos se puede aprender rápido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sistema de tipos algo complicado&lt;/strong&gt;. Precisamente su principal ventaja, el tipado fuerte, es también fuente de frustración puesto que si quieres sacarle todo el partido te obliga a anotar los tipos en todas partes (puede resultar tedioso) y resta de la innegable flexibilidad que tienen los tipos débiles de JavaScript. Obviamente cada enfoque tiene sus ventajas e inconvenientes, y encontrar el equilibrio entre ambos puede ser complicado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Se debe compilar&lt;/strong&gt;. TypeScript, como ya he dicho antes, no es un lenguaje soportado directamente por los navegadores y por lo tanto se debe transpilar a JavaScript/ECMAScript convencional antes de desplegarlo. Eso añade un paso más al trabajo normal, aunque por supuesto se automatiza en todas las ocasiones, bien directamente el compilador nativo del lenguaje (`&lt;code&gt;tsc --watch&lt;/code&gt;), o bien mediante el &lt;em&gt;tooling&lt;/em&gt; normal: npm, Grunt o Webpack entre otras herramientas. De esta manera es casi transparente para nosotros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivos &lt;code&gt;.d.ts&lt;/code&gt;&lt;/strong&gt; : para trabajar de la mejor forma posible con bibliotecas/módulos de terceros es necesario disponer archivos de "definición de ambiente" (con extensión &lt;code&gt;.d.ts&lt;/code&gt;) y no todas los tienen o no son de la calidad que cabría esperar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falsa sensación de seguridad&lt;/strong&gt;. Como TypeScript te da comprobación de tipos en tiempo de compilación y detecta muchos posibles errores antes de que ocurran, alguno programadores llegan a pensar que el código TypeScript es seguro al 100% y no les va a dar problemas al desplegarlo si ha compilado bien. Pero se olvidan de que por debajo sigue estando JavaScript, así que puede pasar de todo. Desde luego la seguridad del código va a mejorar, pero no es infalible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Entonces ¿uso JavaScript o TypeScript?
&lt;/h2&gt;

&lt;p&gt;A ver, como en tantas otras cosas, no se puede afirmar nada con total rotundidad, pero una buena regla aproximativa sería que &lt;strong&gt;para proyectos pequeños&lt;/strong&gt; usar TypeScript es un poco "matar moscas a cañonazos", por lo que quizá no merezca la pena.&lt;/p&gt;

&lt;p&gt;Ahora bien, &lt;strong&gt;en proyectos medianos o grandes&lt;/strong&gt; , y sobre todo si están involucradas varias personas, escribir el código en TypeScript ofrece grandes ventajas (ver más arriba) que se van a notar a corto y a largo plazo.&lt;/p&gt;

&lt;p&gt;Si trabajas con &lt;strong&gt;Angular y otros &lt;em&gt;frameworks&lt;/em&gt; similares&lt;/strong&gt; , usar TypeScript es casi una obligación. De hecho, en el caso de Angular, estás escrito en este lenguaje y la documentación promueve claramente su uso. Además casi toda la literatura, &lt;em&gt;posts&lt;/em&gt; y ejemplos están escritos con TypeScript.&lt;/p&gt;

&lt;p&gt;Por eso &lt;strong&gt;&lt;a href="https://www.campusmvp.es/catalogo/Product-Herramientas-avanzadas-para-desarrollo-Web-Front-End_243.aspx"&gt;mi consejo sería que aprendieses TypeScript&lt;/a&gt;&lt;/strong&gt; para ver qué valor le puedes sacar. La mayor parte de los que empiezan a programar con el lenguaje enseguida se vuelven "dependientes" y acaban por usarlo para casi todo.&lt;/p&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Java: ¿Por qué no me funciona la comparación de cadenas? Literales, clases y el repositorio de cadenas</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Wed, 13 Nov 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/java-por-que-no-me-funciona-la-comparacion-de-cadenas-literales-clases-y-el-repositorio-de-cadenas-57o4</link>
      <guid>https://dev.to/campusmvp/java-por-que-no-me-funciona-la-comparacion-de-cadenas-literales-clases-y-el-repositorio-de-cadenas-57o4</guid>
      <description>&lt;p&gt;Una pregunta habitual de los que comienzan con &lt;strong&gt;Java&lt;/strong&gt; (e incluso en entrevistas de trabajo para puestos que usan este lenguaje) tiene que ver con las comparaciones entre cadenas de texto. Si vienes de otros lenguajes puedes estar acostumbrado a comparar cadenas con el operador igualdad &lt;code&gt;==&lt;/code&gt; o, simplemente, te puede parecer la forma más evidente y obvia de hacerlo.&lt;/p&gt;

&lt;p&gt;Sin embargo, consideremos un código como este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = new String("campusMVP");
String s2 = new String("campusMVP");
System.out.println(s1 == s2); //Devuelve false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aunque las cadenas son idénticas y obtienes dos objetos &lt;code&gt;String&lt;/code&gt; idénticos, la comparación devuelve &lt;code&gt;false&lt;/code&gt; 🤔&lt;/p&gt;

&lt;p&gt;En este otro ejemplo similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "campusMVP";
String s2 = new String("campusMVP");
System.out.println(s1 == s2); //Devuelve false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;devuelve &lt;code&gt;false&lt;/code&gt; también.&lt;/p&gt;

&lt;p&gt;Sin embargo esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "campusMVP";
String s2 = "campusMVP";
System.out.println(s1 == s2); //Devuelve true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;devuelve &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Es más, un caso más común sería el de comparar el resultado de una función que devuelve una cadena, con otra cadena cualquiera. Algo así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "OK";
if (s1 == FuncionQueDevuelveCadena()) {
    System.out.println("¡Coinciden!");
}
else {
    System.out.println("No coinciden"));
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bien, lo curioso del fragmento anterior es que, &lt;strong&gt;dependiendo de lo que haga la función y aunque la cadena devuelta sea exactamente la misma&lt;/strong&gt; en ambos casos, &lt;strong&gt;el resultado puede ser &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;¿A qué es debido esto?&lt;/p&gt;

&lt;h2&gt;
  
  
  El funcionamiento de las cadenas en Java - Repositorio o &lt;code&gt;Pool&lt;/code&gt; de cadenas
&lt;/h2&gt;

&lt;p&gt;Las cadenas en Java son una especie aparte. Tienen muchos detalles que es preciso conocer para entenderlas (por ejemplo, que &lt;a href="https://www.campusmvp.es/recursos/post/cadenas-mutables-e-inmutables-en-java-cuando-usar-string-stringbuilder-y-stringbuffer.aspx" rel="noopener noreferrer"&gt;son inmutables&lt;/a&gt;, o &lt;code&gt;Final&lt;/code&gt; en Java, o que internamente se pueden &lt;a href="https://www.campusmvp.es/recursos/post/cadenas-compactas-en-java-9.aspx" rel="noopener noreferrer"&gt;codificar en memoria de varias formas&lt;/a&gt;). Conocerlas bien es un paso indispensable para dominar el lenguaje.&lt;/p&gt;

&lt;p&gt;Un concepto sencillo una vez que lo entiendes, pero que no todo el mundo tiene claro es &lt;strong&gt;la forma de instanciarlas&lt;/strong&gt; dependiendo de cómo se declaren.&lt;/p&gt;

&lt;p&gt;Básicamente tenemos dos maneras de declarar una cadena: con un literal o instanciando una clase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String literal = "campusMVP";
String clase = new String("campusMVP");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En ambos casos lo que obtenemos es lo mismo: una clase &lt;code&gt;String&lt;/code&gt; con una cadena dentro (que no es más que una matriz de caracteres en memoria). Sin embargo, hay una gran diferencia entre hacerlo de una forma o la otra.&lt;/p&gt;

&lt;p&gt;Cuando se declara una cadena de manera &lt;strong&gt;literal&lt;/strong&gt; por primera vez, &lt;a href="https://www.campusmvp.es/recursos/post/que-es-la-maquina-virtual-de-java-o-java-virtual-machine.aspx" rel="noopener noreferrer"&gt;la JVM&lt;/a&gt; la coloca en un espacio especial denominado &lt;strong&gt;repositorio de cadenas&lt;/strong&gt; ( &lt;strong&gt;&lt;em&gt;string pool&lt;/em&gt;&lt;/strong&gt; en inglés). Este repositorio contiene una &lt;strong&gt;copia única&lt;/strong&gt; de las diferentes cadenas declaradas como literales en el código. Aquí la palabra importante es "única". Como las cadenas son inmutables, si declaras más de una vez la misma cadena no tiene sentido tenerla varias veces en memoria, así que &lt;strong&gt;la siguiente vez que la declares&lt;/strong&gt; lo que hace la JVM es ir al repositorio de cadenas y localizarla, &lt;strong&gt;devolviendo una referencia al mismo objeto &lt;code&gt;String&lt;/code&gt;&lt;/strong&gt; que en la primera declaración. OJO: es el mismo objeto, no una copia. Por eso al escribir esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "campusMVP";
String s2 = "campusMVP";
String s3 = new String(s1);
System.out.println(s1 == s2); //true
System.out.println(s1 == "campusMVP"); //true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En todos los casos la comparación se realiza con éxito. Lo que ocurre es que &lt;strong&gt;en todos los casos se usa el mismo objeto &lt;code&gt;String&lt;/code&gt; exactamente&lt;/strong&gt;. En la línea 1, en la primera declaración, se almacena en el repositorio de cadenas. En la línea 2, la segunda declaración del literal, la JVM va al repositorio y mira si ya existe la misma cadena de antes. Como en este caso sí que existe, lo que hace es devolver una referencia a la misma cadena que en la línea 1. ¡Por eso son iguales! Porque no solo representan los mismos caracteres, sino que son de hecho la misma clase (y apuntan a la misma matriz en memoria). En la línea 4, cuando se hace la comparación en &lt;code&gt;s1&lt;/code&gt; y el mismo literal, vuelve a pasar lo mismo: la JVM localiza el literal en el repositorio de cadenas y devuelve la misma referencia, por eso es &lt;code&gt;true&lt;/code&gt; de nuevo.&lt;/p&gt;

&lt;p&gt;Se puede ver visualmente mejor en esta figura, que trata de representar la situación:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-literales.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-literales.png" alt="El repositorio de cadenas de Java"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto funciona incluso con la combinación de varios literales. La JVM es lo suficientemente inteligente como para hacer que estas dos cadenas sean la misma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "campusMVP";
String s2 = "campus" + "MVP";
System.out.println(s1 == s2); //true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pesar de que podría parecer que hay 3 cadenas en el repositorio de cadenas, y que devolvería dos objetos diferentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaración de cadenas como clases
&lt;/h2&gt;

&lt;p&gt;Sin embargo, cuando declaramos una cadena usando una clase (con &lt;code&gt;new String()&lt;/code&gt;), la operación es diferente. Lo que se hace es asignar en memoria el espacio necesario para la cadena y devolver la clase que permite manejarla. &lt;strong&gt;No se pasa por el repositorio de cadenas&lt;/strong&gt; para nada.&lt;/p&gt;

&lt;p&gt;Por ello este fragmento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = new String("campusMVP");
String s2 = new String("campusMVP");
System.out.println(s1 == s2); //Devuelve false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;devuelve &lt;code&gt;false&lt;/code&gt; en la comparación. Se trata de dos cadenas diferentes, aunque internamente representen los mismos caracteres:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-clases.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-clases.png" alt="Imagen que muestra dos cadenas iguales, pero en dos posiciones de memoria diferentes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : lo sé, es absurdo declarar cadenas de esta manera envolviendo un literal con una clase &lt;code&gt;String&lt;/code&gt;. Y de hecho, raramente lo verás hecho por ahí. Pero es que hay infinidad de maneras de obtener clases &lt;code&gt;String&lt;/code&gt; en una variable: desde transformar un literal hasta sacarlas de una base de datos. Solo pongo el ejemplo de esta manera para que se entienda lo que quiero explicar, no para indicar que esta es una manera recomendada de declarar las cadenas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;¿Qué ocurre si tenemos dos cadenas literales y queremos compararlas con &lt;code&gt;==&lt;/code&gt; sin considerar mayúsculas y minúsculas?&lt;/p&gt;

&lt;p&gt;Podríamos hacer esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = "campusMVP";
String s2 = "campusMVP";
System.out.println(s1.toLowerCase() == s2.toLowerCase()); //false!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso la comparación devuelve &lt;code&gt;false&lt;/code&gt;, ya que lo que obtenemos son dos cadenas idénticas pero representadas por dos objetos diferentes. &lt;strong&gt;El operador &lt;code&gt;==&lt;/code&gt; compara referencias a objetos&lt;/strong&gt; y en este caso, aunque los datos que contienen son los mismos, no se trata del mismo objeto. Incluso siendo &lt;code&gt;s1&lt;/code&gt; y &lt;code&gt;s2&lt;/code&gt; el mismo objeto &lt;code&gt;String,&lt;/code&gt;la operación &lt;code&gt;toLowerCase()&lt;/code&gt; lo que hace es generar una nueva cadena a partir de la misma cadena original, pero se trata de dos objetos &lt;code&gt;String&lt;/code&gt; diferentes en memoria. Es como el caso anterior. Al no ser literales, no se obtienen desde el repositorio de cadenas aunque ya existan allí.&lt;/p&gt;

&lt;p&gt;Por eso es tan peligroso comparar cadenas con &lt;code&gt;==&lt;/code&gt;. Aunque las cadenas sean idénticas, como lo que se comparan son referencias a objetos &lt;code&gt;String&lt;/code&gt; y no el valor subyacente, solo devuelven &lt;code&gt;true&lt;/code&gt; para cadenas iguales cuando se refieren al mismo literal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt; : no utilices nunca el operador &lt;code&gt;==&lt;/code&gt; para comparar cadenas si quieres hacerlo bien en Java.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Y entonces ¿cómo comparo cadenas con seguridad?
&lt;/h2&gt;

&lt;p&gt;Pues &lt;strong&gt;con el método &lt;code&gt;equals()&lt;/code&gt;&lt;/strong&gt; que tienen todos los objetos. De hecho, es heredado de &lt;code&gt;Object&lt;/code&gt;, la clase base "raíz" de todas las existentes. Este método lo que hace es comparar el estado interno de dos objetos para ver si son iguales, mientras que &lt;code&gt;==&lt;/code&gt; lo que hace es comparar las referencias.&lt;/p&gt;

&lt;p&gt;En el caso de las cadenas, lo que hace es comparar que las dos matrices de caracteres que contienen los objetos &lt;code&gt;String&lt;/code&gt; que comparamos sean iguales, que es realmente lo que nos interesa por regla general.&lt;/p&gt;

&lt;p&gt;Así, para comparar dos cadenas cualquiera con seguridad debes usar este método:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = new String("campusMVP");
String s2 = new String("campusMVP");
System.out.println(s1.equals(s2)); //Devuelve true
System.out.println(s1.equals("campusMVP")); //Devuelve true
System.out.println("campusMVP".equals(s1)); //Devuelve true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero es que &lt;strong&gt;da igual cómo obtengamos la cadena final&lt;/strong&gt; : siempre devuelve &lt;code&gt;true&lt;/code&gt; si las cadenas que representan los dos objetos son iguales, por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = new String("campusMVP");
String s2 = new String("CAMPUSMVP");
System.out.println(s1.equals("campus" + "MVP")); //Devuelve true
System.out.println(s1.toLowerCase().equals(
            s2.toLowerCase()
        )); //Devuelve true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso sí que podemos comparar las dos cadenas en minúsculas para ver si son iguales.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusión 2&lt;/strong&gt; : las comparaciones de cadenas en Java hazlas siempre con &lt;code&gt;equals()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  "Internalizando" objetos de tipo cadena
&lt;/h2&gt;

&lt;p&gt;Esto es ya casi una curiosidad más que otra cosa. Pero es que, aunque no es algo que se use muy habitualmente, existe la posibilidad de hacer que los objetos de tipo &lt;code&gt;String&lt;/code&gt; que tengamos se "internalicen" de modo que pasen a formar parte del &lt;em&gt;pool&lt;/em&gt; de cadenas de texto, como si los hubiésemos declarado como literales.&lt;/p&gt;

&lt;p&gt;Esto se consigue gracias al &lt;strong&gt;método &lt;code&gt;intern()&lt;/code&gt;&lt;/strong&gt; que tienen las cadenas. Lo que hace este método es lo mismo que ocurre cuando se declara una cadena literal: va al repositorio de cadenas y mira si ya existe la misma cadena ahí (en caso negativo la crea), y devuelve como resultado una referencia a la cadena preexistente, en lugar de crear una nueva.&lt;/p&gt;

&lt;p&gt;Si llamamos a &lt;code&gt;intern()&lt;/code&gt;, así, por ejemplo esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String s1 = new String("campusMVP");
String s2 = new String("campusMVP");
System.out.println(s1.intern() == s2.intern()); //Devuelve true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Devolverá &lt;code&gt;true&lt;/code&gt; ya que &lt;code&gt;intern()&lt;/code&gt; devuelve como resultado de la llamada la misma referencia a la misma cadena del &lt;em&gt;pool&lt;/em&gt; de cadenas.&lt;/p&gt;

&lt;p&gt;Es decir, &lt;code&gt;intern()&lt;/code&gt; lo que hace es desligar el objeto de los datos originales y asignarle el mismo dato que hay en el repositorio de cadenas. Visualmente sería algo así (fíjate en la cadena &lt;code&gt;s3&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-intern.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F4T%2Fjava-cadenas-intern.png" alt="Dibujo que muestra cómo una variable se desasigna de la ubicación en memoria original y se apunta a la misma cadena en el repositorio de cadenas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Para qué vale esto de &lt;code&gt;intern()&lt;/code&gt;?&lt;/strong&gt; Bueno, como decía, realmente pocas veces lo vas a utilizar, pero esto podría ayudarte a ahorrar mucha memoria en los casos en los que vas a generar muchas cadenas y un gran número de las cuales van a ser iguales.&lt;/p&gt;

&lt;p&gt;Por ejemplo, imagínate que vas a obtener desde una base de datos muchos miles de registros de pedidos de clientes, y que tienes un número bastante limitado de clientes y de productos, lo que pasa que hacen muchos pedidos de lo mismo. "Internalizando" las cadenas evitarías tener los mismos nombres de cliente y de pedidos duplicados miles de veces en memoria, dejando tan solo unas pocas copias de los mismos dentro del repositorio de cadenas y ahorrando potencialmente mucha memoria, sobre todo si los nombres son largos.&lt;/p&gt;

&lt;p&gt;Como &lt;strong&gt;nota técnica adicional&lt;/strong&gt; sobre esto decir que, hasta Java 7, ya hace muchos años (se lanzó en 2011), el espacio disponible para almacenar las cadenas en el &lt;em&gt;pool&lt;/em&gt; era limitado y además no entraba dentro de la &lt;a href="https://www.campusmvp.es/recursos/post/Modelos-de-gestion-de-memoria-II-Garbage-collector.aspx" rel="noopener noreferrer"&gt;recolección de basura&lt;/a&gt;. Eso significaba que si abusabas mucho del "interning" podrías acabar con una excepción de tipo &lt;code&gt;OutOfMemory&lt;/code&gt;, lo cual podría provocar un desastre en tu aplicación. Es por esto que en muchos artículos que encontrarás por ahí sobre este tema, y que están anticuados, te recomiendan no usar &lt;code&gt;intern()&lt;/code&gt;. La realidad es que, a partir de Java 7, y por lo tanto en la práctica totalidad de las aplicaciones Java que vas a encontrar por ahí, &lt;strong&gt;el repositorio de cadenas se guarda ya en &lt;a href="https://www.campusmvp.es/recursos/post/Que-son-los-tipos-por-valor-y-por-referencia-en-NET-y-C.aspx" rel="noopener noreferrer"&gt;el "montón" (o &lt;em&gt;heap&lt;/em&gt;)&lt;/a&gt;&lt;/strong&gt; (es decir, en memoria dinámica), por lo que no hay problemas de límites y además puede ser reclamada por el recolector de basura. Además en Java 13 (de septiembre de 2019) se permite también &lt;a href="https://dev.to/campusmvp_es/java-13-ya-disponible-2i0o-temp-slug-8150137"&gt;la devolución al sistema operativo de memoria dinámica no utilizada&lt;/a&gt;, con lo que incluso está más optimizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;Las cadenas de texto son "bichos raros" en casi todos los lenguajes, pero en Java especialmente, al poder actuar a la vez como literales y como objetos, pero al mismo tiempo presentan diferencias a la hora de utilizarlas y en especial de compararlas.&lt;/p&gt;

&lt;p&gt;Por ello las comparaciones de cadenas deben evitar el uso del operador &lt;code&gt;==&lt;/code&gt; (que compara referencias de objetos y no sus datos) y emplear en cambio el método &lt;code&gt;equals()&lt;/code&gt;. Además es importante conocer el funcionamiento interno de las cadenas, las implicaciones que tiene y cómo podemos optimizar el uso de memoria cuando manejamos cadenas de gran tamaño (o muchas) con valores idénticos.&lt;/p&gt;

&lt;p&gt;Te de dejado &lt;a href="https://repl.it/@jmalarcon/Comparacion-de-cadenas" rel="noopener noreferrer"&gt;un pequeño patio de juegos&lt;/a&gt; para que puedas comprobar el funcionamiento de todo lo explicado y probar a realizar cambios y ver cómo funcionan.&lt;/p&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

</description>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Intl: la API de localización nativa de JavaScript</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Tue, 30 Jul 2019 22:54:00 +0000</pubDate>
      <link>https://dev.to/jmalarcon/intl-la-api-de-localizacion-nativa-de-javascript-5288</link>
      <guid>https://dev.to/jmalarcon/intl-la-api-de-localizacion-nativa-de-javascript-5288</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Artículo publicado originalmente en &lt;a href="https://www.jasoft.org/Blog/post/intl-la-api-de-localizacion-nativa-de-javascript.aspx"&gt;JASoft.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como seguramente ya tengas claro, la traducción y la localización son conceptos relacionados &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/post/como-localizar-aplicaciones-con-c-y-net.aspx#traducci-n-y-localizaci-n-dos-conceptos-distintos"&gt;pero muy distintos&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Para traducir tu aplicación basada en Web mucho me temo que no te queda más remedio que usar archivos de lenguaje de algún tipo y alguna biblioteca especializada. Sin embargo para la &lt;strong&gt;localización&lt;/strong&gt; , es decir, la adaptación de la aplicación a las particularidades de cada idioma, &lt;strong&gt;todo lo que necesitas viene incluido con tu navegador&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El objeto Intl
&lt;/h2&gt;

&lt;p&gt;Mucha gente no lo sabe, pero JavaScript dispone de un objeto global específico para ayudarnos con la localización de aplicaciones a otros idiomas y culturas: &lt;strong&gt;&lt;code&gt;Intl&lt;/code&gt;&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ovku7pho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-001.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ovku7pho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-001.png" alt="El objeto Intl mostrado en la consola de Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos usar sus diferentes objetos asociados, mostrados en la figura anterior, para averiguar mucha información sobre localización en cualquier idioma.&lt;/p&gt;

&lt;p&gt;Vamos a verlos...&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.Collator: para comparar cadenas de texto
&lt;/h2&gt;

&lt;p&gt;El &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator"&gt;objeto &lt;code&gt;Collator&lt;/code&gt;&lt;/a&gt; sirve para hacer comparaciones de cadenas teniendo en cuenta las particularidades locales.&lt;/p&gt;

&lt;p&gt;Raramente se utiliza ya que no suele ser necesario, gracias a que la clase &lt;code&gt;string&lt;/code&gt; tiene un método específico para llevar a cabo este tipo de comparaciones: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare"&gt;&lt;strong&gt;&lt;code&gt;localeCompare()&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Solo lo utilizaremos si tenemos que realizar muchísimas comparaciones en un bucle o algo así (algo muy poco habitual), ya que nos daría más rendimiento. En el resto de los casos puedes hacer caso omiso de él.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.DateTimeFormat: para dar formato a fechas y horas
&lt;/h2&gt;

&lt;p&gt;Como su propio nombre sugiere, nos ayuda a dar formato a las fechas y las horas según las particularidades de cada país.&lt;/p&gt;

&lt;p&gt;Como todos los objetos de &lt;code&gt;Intl&lt;/code&gt; se instancia pasándole como argumento una cadena de texto en formato &lt;a href="https://en.wikipedia.org/wiki/Codes_for_constructed_languages"&gt;IETF BCP 47&lt;/a&gt;, que suena muy complicado pero en general no es más que el nombre abreviado internacional del idioma (&lt;code&gt;es&lt;/code&gt;, &lt;code&gt;en&lt;/code&gt;, &lt;code&gt;it&lt;/code&gt;...) para idiomas genéricos, o lo anterior seguido de un guión y la abreviatura del país/cultura en mayúscula (&lt;code&gt;es-ES&lt;/code&gt;, &lt;code&gt;es-AR&lt;/code&gt;, &lt;code&gt;en-US&lt;/code&gt;, &lt;code&gt;en-UK&lt;/code&gt;...). Como ves, muy fácil.&lt;/p&gt;

&lt;p&gt;Así que, por ejemplo, para obtener una fecha bien formateada en varios idiomas sólo tenemos que hacer esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var fecha = new Date(2019, 6, 30, 16, 30, 0);
var dtfEs = new Intl.DateTimeFormat('es-ES');
var dtfEnUs = new Intl.DateTimeFormat('en-US');
var dtfArMa = new Intl.DateTimeFormat('ar-MA');
console.log(dtfEs.format(fecha));
console.log(dtfEnUs.format(fecha));
console.log(dtfArMa.format(fecha));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;que nos devolverá por consola esa fecha (29 de julio de 2019, fíjate en que los meses se numeran desde el 0) en español, inglés americano y árabe de Marruecos (que tienen un formato bien complicado):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wf3rUV_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-002.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wf3rUV_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-002.png" alt="El resultado de los formatos anteriores"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fíjate en que no nos devuelve la hora, ni tampoco hemos podido controlar el formato exacto de cada componente que queremos obtener. Eso lo controlaremos gracias a las &lt;strong&gt;opciones del constructor&lt;/strong&gt; , que he omitido en el fragmento anterior.&lt;/p&gt;

&lt;p&gt;Todos los objetos de &lt;code&gt;Intl&lt;/code&gt; tienen un segundo argumento opcional para las opciones (valga la redundancia). En el caso de &lt;code&gt;DateTimeFormat&lt;/code&gt; tiene un montón de propiedades posibles que no voy a detallar porque &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Parameters"&gt;las tienes en la MDN&lt;/a&gt;. Pero vamos a ver un ejemplo de cómo usarlos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var fecha = new Date(2019, 6, 30, 16, 30, 0);
var opciones = {
        weekday: 'long',
        month: 'long',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        timeZoneName: 'long'
    };
var dtfEs = new Intl.DateTimeFormat('es-ES', opciones);
var dtfEnUs = new Intl.DateTimeFormat('en-US', opciones);
var dtfArMa = new Intl.DateTimeFormat('ar-MA', opciones);
console.log(dtfEs.format(fecha));
console.log(dtfEnUs.format(fecha));
console.log(dtfArMa.format(fecha));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;con el resultado siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hl_It-XR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-003.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hl_It-XR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-003.png" alt="El resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fíjate en que este código es exactamente igual al anterior solo que le hemos pasado como segundo argumento del constructor un objeto con las opciones pertinentes. Al haber especificado el formato en el que nos interesaba cada componente de la fecha, incluyendo las horas (para que las muestre), lo ha transformado adecuadamente y con las palabras apropiadas en cada idioma, e incluso escrito de derecha a izquierda en el caso del árabe de Marruecos.&lt;/p&gt;

&lt;p&gt;Si queremos podemos utilizar el método &lt;strong&gt;&lt;code&gt;formatToParts()&lt;/code&gt;&lt;/strong&gt; para obtener cada una de las partes de la fecha, de modo que podamos utilizarlas en cualquier formato personalizado si lo necesitásemos (aunque no te lo recomiendo, pues para eso tienes las facilidades que da el objeto, sin recurrir a formatos propios):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARtGqjfr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-004.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARtGqjfr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-004.png" alt="El método formatToParts te lo da desglosado en una matriz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;y podemos, en cada idioma, obtener exactamente cada parte de la cadena final, en función de las opciones que hayamos elegido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.RelativeTimeFormat: para facilitar la lectura de intervalos de tiempo relativos
&lt;/h2&gt;

&lt;p&gt;Otra necesidad muy común en la mayor parte de las aplicaciones es la de expresar intervalos de tiempo relativos a la fecha actual. Por ejemplo, si tenemos un listado de tareas, en la columna de la fecha de vencimiento podemos poner tal cual la fecha o bien ser mucho más amigables para el usuario y escribir cosas como "Vence en 3 días" o "Caducada hace 5 horas"...&lt;/p&gt;

&lt;p&gt;Esto es mucho más complicado de hacer de lo que parece de una manera consistente, y si además debemos hacerlo en varios idiomas no te quiero ni contar. Por suerte &lt;code&gt;Intl&lt;/code&gt; nos ofrece también funcionalidad apropiada para lograrlo de manera sencilla.&lt;/p&gt;

&lt;p&gt;Al igual que antes, lo único que tenemos que hacer es instanciar la clase pasándole el identificador del idioma a utilizar para la localización:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var rtf = new Intl.RelativeTimeFormat('es-ES');

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ahora podemos obtener los intervalos apropiados en ese idioma llamando al método &lt;code&gt;format()&lt;/code&gt;, y pasándole el número de intervalos y el tipo de intervalo, que es una cadena en ingles. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rtf.format(1, 'day') //dentro de 1 día
rtf.format(-3, 'day') //hace 3 días
rtf.format(0, 'day') //dentro de 0 días
rtf.format(5, 'hour') //dentro de 5 horas

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hV-SjBDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-005.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hV-SjBDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-005.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto es genial y ahorra muchas KB de bibliotecas JavaScript que ya no tendremos que descargarnos.&lt;/p&gt;

&lt;p&gt;Ademñas, en el constructor podemos establecer &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat#Parameters"&gt;algunas opciones&lt;/a&gt; para especificar cómo queremos que generen esos intervalos. Por ejemplo, a mi no me gusta el estilo por defecto que tienen, usando siempre números, así que lo puedo cambiar estableciendo la propiedad &lt;code&gt;numeric&lt;/code&gt; como &lt;code&gt;'auto'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var rtf = new Intl.RelativeTimeFormat('es-ES', { numeric: 'auto' });

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;y así conseguir que, por ejemplo, si es algo de hace un día ponga "ayer" y si es en un día obtenga "mañana", haciéndolo aún más natural:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S_Qh5sC3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-006.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S_Qh5sC3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-006.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como vemos, de gran utilidad.&lt;/p&gt;

&lt;p&gt;Como antes, también existe el método &lt;code&gt;formatToParts()&lt;/code&gt; para obtener una matriz con cada uno de los fragmentos del formato por separado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.NumberFormat: para dar formato a números y dinero
&lt;/h2&gt;

&lt;p&gt;Seguimos con necesidades habituales de localización, en este caso con los números. Como sabes, cada idioma tiene formatos diferentes para muchas cosas con los números y las cantidades monetarias. Por ejemplo, en España los separadores de mil son puntos y el decimal es una coma, y la moneda se pone trás la cantidad. Sin embargo en EEUU es justo al revés: los miles se separan con comas, los decimales con puntos y la moneda va delante de la cantidad.&lt;/p&gt;

&lt;p&gt;¿Cómo gestionamos esto de manera sencilla para cualquier idioma del planeta? Antes era complicadísimo. Ahora es muy sencillo gracias a &lt;code&gt;Intl.NumberFormat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como todos los anteriores se instancia pasándole una cadena con el idioma (si no ponemos nada se usará el idioma del sistema operativo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var nfEs = new Intl.NumberFormat('es-ES');
var nfEn = new Intl.NumberFormat('en-EU');
var nfFr = new Intl.NumberFormat('fr');
console.log(nfEs.format(123456.78));
console.log(nfEn.format(123456.78));
console.log(nfFr.format(123456.78));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;y como podemos comprobar genera los separadores en el formato adecuado a cada caso:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j8u8IaVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-007.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j8u8IaVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-007.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fíjate en cómo los franceses utilizan com separador de miles un espacio, por ejemplo.&lt;/p&gt;

&lt;p&gt;En cuanto &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat#Parameters"&gt;a las opciones&lt;/a&gt; podemos establecer incluso el sistema de numeración que no tiene por qué sel arábigo, el &lt;a href="http://www.currency-iso.org/en/home/tables/table-a1.html"&gt;tipo de moneda&lt;/a&gt; si va a ser una cantidad de dinero, y también la forma de nombrar las monedas, entre otras muchas opciones. La más importante es &lt;code&gt;style&lt;/code&gt; que nos permite seleccionar si queremos mostrar decimales (&lt;code&gt;'decimal'&lt;/code&gt;, valor por defecto), monedas (&lt;code&gt;'currency'&lt;/code&gt;) o porcentajes (&lt;code&gt;'percent'&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Por ejemplo, para mostrar una cantidad en euros o dólares escribiríamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var nfEs = new Intl.NumberFormat('es-ES', {style: 'currency', currency: 'EUR'});
var nfEn = new Intl.NumberFormat('en-EU', {style: 'currency', currency: 'USD'});
var nfFr = new Intl.NumberFormat('fr', {style: 'currency', currency: 'EUR', currencyDisplay: 'name'});
console.log(nfEs.format(123456.78));
console.log(nfEn.format(123456.78));
console.log(nfFr.format(123456.78));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Fíjate en cómo adapta perfectamente el formato a cada idioma y cómo además usa el símbolo o el nombre según las opciones indicadas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---4XwCPJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-008.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---4XwCPJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-008.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.ListFormat: par dar formato a listas
&lt;/h2&gt;

&lt;p&gt;Otra necesidad clásica en las aplicaicones: partir de una lista o &lt;em&gt;array&lt;/em&gt; de elementos y generar una lista legible para cada idioma.&lt;/p&gt;

&lt;p&gt;Por ejemplo, si tenemos esta matriz, que generalmente en una aplicación la habremos obtenido de un servicio remoto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var beatles = ['John', 'Paul', 'George', 'Ringo'];

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;y queremos meterlos en una lista amigable para el usuario para formar la frase: &lt;code&gt;'Los Beatles eran John, Paul, George y Ringo'&lt;/code&gt;. Algo tan simple como esto requiere bastante trabajo si queremos adaptarlo a diversos idiomas. No todos usan las comas para separar y desde luego el último elemento no tiene que ser un "y" tampoco.&lt;/p&gt;

&lt;p&gt;Con &lt;strong&gt;&lt;code&gt;Intl.ListFormat&lt;/code&gt;&lt;/strong&gt; la cosa es muy sencilla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var beatles = ['John', 'Paul', 'George', 'Ringo'];
var lfEs = new Intl.ListFormat('es-ES');
var lfDe = new Intl.ListFormat('de-DE');
console.log(lfEs.format(beatles));
console.log(lfDe.format(beatles));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Como vemos nos devuelve la lista formateada para cada localización, incluyendo en este caso la palabra "y" en el idioma correspondiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MmSAOD41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-009.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MmSAOD41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-009.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por supuesto no siempre querremos que la lista sea inclusiva, sino que a veces podemos necesitar que sea una lista de opciones y que ese "y" se convierta en un "o", por ejemplo. Para cambiar este comportamiento en las opciones del constructor tenemos la propiedad &lt;code&gt;type&lt;/code&gt; que puede tomar los valores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;'conjunction'&lt;/code&gt;, para listas de tipo "y"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'disjunction'&lt;/code&gt; para listas de tipo "o"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'unit'&lt;/code&gt; si la lista es de unidades de medida, que se suelen poner en forma de lista de modo diferente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Así, con la lista anterior podemos poner esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var beatles = ['John', 'Paul', 'George', 'Ringo'];
var lfEs = new Intl.ListFormat('es-ES', {type:'disjunction'});
var lfDe = new Intl.ListFormat('de-DE', {type:'disjunction'});
console.log(lfEs.format(beatles));
console.log(lfDe.format(beatles));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;para tenerla de tipo "o":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--td-vKd6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-010.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--td-vKd6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-010.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si fuesen unidades, por ejemplo la longitud de una viga en una aplicación de construcción pondríamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var medidas = ['3 metros', '12 centímetros'];
var lfEs = new Intl.ListFormat('es-ES', {type:'unit'});
var lfDe = new Intl.ListFormat('de-DE', {type:'unit'});
console.log(lfEs.format(medidas));
console.log(lfDe.format(medidas));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UXUrLhJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-011.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UXUrLhJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-011.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fíjate en un detalle importante: aunque la &lt;strong&gt;localización&lt;/strong&gt; ha funcionado perfectamente porque las listas tienen el formato adecuado para cada idioma, la &lt;strong&gt;traducción&lt;/strong&gt; está mal ya que en alemán sigue poniendo las medidas en español. Obviamente esto no es responsabilidad de &lt;code&gt;Intl&lt;/code&gt; ya que &lt;strong&gt;se trata de traducción y es responsabilidad de la aplicación&lt;/strong&gt;. Antes de crear la lista de cadenas deberemos asegurarnos de que las medidas están en el idioma apropiado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hay &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ListFormat#Parameters"&gt;algunos parámetros más&lt;/a&gt; para las opciones del constructor, pero lo importante es lo que hemos visto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.PluralRules: para pluralización
&lt;/h2&gt;

&lt;p&gt;Esta ya es una característica avanzada. Al contrario que las otras claes que hemos visto no está pensada para pasarle una cadena y que nos las devuelva en plural, sino que es a más bajo nivel. Lo que hace es facilitarnos la forma de plural que corresponde a cada número que se le pase a su método &lt;code&gt;select()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por ejemplo, en español, inglés u otros idiomas occidentales una viga mide 1 metro (singular), 3 metros (plural) o, curiosamente, 0 metros (plural aunque sea cero). Sin embargo en árabe tiene otras acepciones para ciertos números.&lt;/p&gt;

&lt;p&gt;Si lo probamos con la clase &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules"&gt;&lt;code&gt;PluralRules&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var prEs = new Intl.PluralRules('es-ES');
var prMa = new Intl.PluralRules('ar-MA');
console.log('ESPAÑOL:');
console.log(prEs.select(0));
console.log(prEs.select(1));
console.log(prEs.select(3));
console.log(prEs.select(0.5));
console.log('ÁRABE:');
console.log(prMa.select(0));
console.log(prMa.select(1));
console.log(prMa.select(3));
console.log(prMa.select(0.5));

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;veremos lo siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zslnAzkW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-012.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zslnAzkW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/intl/intl-012.png" alt="Resultado del código anterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como puedes observar, para los idiomas occidentales generalmente hay dos posibilidades: &lt;code&gt;'one'&lt;/code&gt; (singular) o &lt;code&gt;'other'&lt;/code&gt; (plural), y con eso podemos decidir si se le pone una "s" al final o no.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : lo anterior es una simplificación enorme ya que en español es mucho más complicado que eso. A veces el plural lleva "s" (gato, gatos), otras veces lleva "es" (flor, flores) y otras veces no lleva nada (¿cuál es el plural de "virus" en español? Pues "virus" también &lt;a href="https://twitter.com/raeinforma/status/306983352148316160?lang=es"&gt;porque es invariable en plural&lt;/a&gt;, al contrario que en inglés, que es "viruses"). En ese sentido otros idiomas como el inglés son mucho más sencillos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pero en otros idiomas la cosa es mucho más complicada, como puedes comprobar con el árabe.&lt;/p&gt;

&lt;p&gt;Por lo tanto, aunque está bien disponer de esta funcionalidad para algunas aplicaciones muy concretas, no nos va a servir de gran ayuda a la hora de generar plurales "serios", así que generalmente no lo vas a utilizar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soporte
&lt;/h2&gt;

&lt;p&gt;El soporte actual de navegadores es ya universal desde hace años, por lo que no deberías tener problemas para usarla. La excepción, como casi siempre, es Internet Explorer, pero incluso éste tiene soporte para la mayor parte de las clases en su versión 11. En &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Browser_compatibility"&gt;esta tabla de MDN&lt;/a&gt; tienes un buen resumen detallado del soporte específico por clase y navegador.&lt;/p&gt;

&lt;p&gt;También tienes &lt;a href="https://github.com/andyearnshaw/Intl.js/"&gt;un polyfill&lt;/a&gt; que puedes utilizar si fuese necesario en estos navegadores antiguos, aunque no es tan potente.&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;Para casi todas las tareas comunes relacionadas con la localización de aplicaciones, JavaScript nos proporciona ayuda integrada y no vamos a necesitar utilizar bibliotecas externas que añaden complejidad, peso y que además con toda seguridad no serán tan buenas como el sistema operativo para estos menesteres. Dado que la API de internacionalización de JavaScript, a través del objeto global &lt;code&gt;Intl&lt;/code&gt;, utiliza por debajo los servicios del sistema operativo para conseguirlo, podemos garantizar resultados rápidos y correctos.&lt;/p&gt;

&lt;p&gt;Deberíamos acostumbrarnos a usa esta API ya que nos ayudará a conectar mejor con nuestros usuarios y a hacer las aplicaciones más amigables.&lt;/p&gt;

&lt;p&gt;Por cierto, si te ha gustado este artículo, te encantará lo que puedes aprender con &lt;strong&gt;&lt;a href="https://www.campusmvp.es/catalogo/Product-Programaci%C3%B3n-avanzada-con-JavaScript-y-ECMAScript_206.aspx"&gt;mi curso de JavaScript avanzado en campusMVP&lt;/a&gt;&lt;/strong&gt;. Anímate a aprender JavaScript en serio y dejar de "tocar de oído" 😊 Además tendrás vídeos prácticos, prácticas sugeridas, evaluaciones, referencias cruzadas, hitos de aprendizaje.... y tendrás &lt;strong&gt;contacto directo conmigo y con el fenómeno Eduard Tomàs para contestar todas tus dudas&lt;/strong&gt; y seguir tu progreso.&lt;/p&gt;

&lt;p&gt;¡Espero que te sea útil!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Artículo publicado originalmente en &lt;a href="https://www.jasoft.org/Blog/post/intl-la-api-de-localizacion-nativa-de-javascript.aspx"&gt;JASoft.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Los mejores editores gratuitos de HTML, CSS y JavaScript (2019)</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Tue, 28 May 2019 10:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/los-mejores-editores-gratuitos-de-html-css-y-javascript-2019-21ln</link>
      <guid>https://dev.to/campusmvp/los-mejores-editores-gratuitos-de-html-css-y-javascript-2019-21ln</guid>
      <description>&lt;p&gt;Hace 5 años, en mayo de 2014, escribí un artículo que enseguida se convirtió en uno de los más populares de &lt;a href="https://www.campusmvp.es"&gt;nuestro blog en campusMVP&lt;/a&gt; y de los más populares sobre el tema en Internet. Se titulaba &lt;a href="https://www.campusmvp.es/recursos/post/Los-10-mejores-editores-gratuitos-de-HTML-CSS-y-JavaScript.aspx"&gt;"Los 10 mejores editores gratuitos (o casi) de HTML, CSS y JavaScript"&lt;/a&gt; y, como su propio nombre indica, nos mostraba una selección de editores de código para la Web que podíamos utilizar gratuitamente.&lt;/p&gt;

&lt;p&gt;Desde entonces &lt;strong&gt;las cosas han cambiado mucho&lt;/strong&gt;. Ya en 2013 la revista &lt;strong&gt;Mashable&lt;/strong&gt; sentenció que era &lt;a href="https://mashable.com/2012/12/11/responsive-web-design/?europe=true"&gt;el año del Responsive Web Design&lt;/a&gt;, aunque en España empezó a explotar en 2014, más o menos cuando escribí ese artículo. La realidad actual es que &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Dise%C3%B1o-Web-Responsive-con-HTML5,-Flexbox,-CSS-Grid-y-Bootstrap_212.aspx"&gt;el RWD es inherente al diseño web&lt;/a&gt;&lt;/strong&gt; y hoy en día es inimaginable diseñar una web sin usarlo.&lt;/p&gt;

&lt;p&gt;¿Y qué tiene esto que ver con los editores? Pues que hace 5 años, sobre todo si eras un principiante, podías permitirte el lujo de &lt;strong&gt;utilizar algún tipo de diseñador visual para crear tus páginas&lt;/strong&gt; o aplicaciones web. &lt;strong&gt;Hoy en día es inviable&lt;/strong&gt;. Vamos, puedes hacerlo, y de hecho la mayor parte de los editores que puse en aquel artículo siguen funcionando, &lt;strong&gt;pero no te van a servir de mucho&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adiós al diseño visual
&lt;/h2&gt;

&lt;p&gt;Los diseños web actuales se realizan de manera que &lt;strong&gt;los elementos se distribuyen de forma totalmente diferente según el ancho&lt;/strong&gt; del &lt;a href="https://dev.to/campusmvp/desarrollo-web-mvil-qu-diferencia-existe-entre-el-viewport-y-la-resolucin-de-pantalla-de-un-dispositivo-1aog"&gt;&lt;em&gt;viewport&lt;/em&gt; del dispositivo&lt;/a&gt; en el que se estén visualizando. Ello implica que no podemos hacer un diseño "visual" distribuyendo los elementos y dejándolos en una posición fija, sino que el diseño parte normalmente de los tamaños de pantalla más pequeños (móviles) y se van variando a medida que crecen éstos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/b2CD0Qrq2ulwY/200w_d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/b2CD0Qrq2ulwY/200w_d.gif" alt="Animación vía Giphy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;diseño web responsivo&lt;/strong&gt; (y el diseño web adaptativo) &lt;strong&gt;requiere escribir el código&lt;/strong&gt; en el editor, tanto el HTML como el CSS y las &lt;em&gt;media queries&lt;/em&gt; correspondientes, y luego ir comprobando en un navegador real el efecto de cada cambio. Gran parte de las veces lo que haces es retocar en tiempo real propiedades CSS usando las herramientas del desarrollador del navegador para afinarlo (por suerte hoy en día los navegadores te dejan enlazar estas herramientas con los archivos originales, y que esos cambios se vean al mismo tiempo en aquéllos también, y por lo tanto en el editor).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hoy, más que nunca, el diseño/desarrollo web es &lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Dise%C3%B1o-Web-Responsive-con-HTML5,-Flexbox,-CSS-Grid-y-Bootstrap_212.aspx"&gt;una disciplina técnica&lt;/a&gt; que requiere &lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-HTML5-y-CSS3-a-fondo-para-desarrolladores_185.aspx"&gt;escribir código&lt;/a&gt;, y no arrastrar y soltar o ver en tiempo real cómo quedan las cosas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Este es el principal motivo de que aquella lista hoy en día sea obsoleta y sobren la mitad de las opciones que proponía por aquel entonces, especialmente los que hacían hincapié en el diseño visual como &lt;strong&gt;Kompozer&lt;/strong&gt; (cuya página ya ni funciona) o &lt;strong&gt;BlueGriffon&lt;/strong&gt; (que se ha convertido en una herramienta para crear eBooks y ya no es gratuito).&lt;/p&gt;

&lt;p&gt;Además, algunos que en aquella época eran lo máximo han ido cayendo un poco en desgracia por la aparición de nuevos productos que se han hecho con el interés de los desarrolladores. En mi opinión, el gran ganador en ese sentido ha sido &lt;strong&gt;Visual Studio Code&lt;/strong&gt; , y los perdedores &lt;strong&gt;Sublime Text&lt;/strong&gt; y &lt;strong&gt;Atom&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eYcv9wsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/sublime-vscode-p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eYcv9wsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/sublime-vscode-p.jpg" alt="Imagen que muestra una pareja enamorada abrazándose en una fiesta, él VSCode y ella representando a los desarrolladores, y un chico con globos y cara de desencanto que es Sublime Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con todo esto en mente os voy a dejar a continuación una lista, más corta, de mis &lt;strong&gt;editores de código gratuitos preferidos para HTML/CSS y JavaScript según tres categorías&lt;/strong&gt; (uso general, aprendizaje y &lt;em&gt;cloud&lt;/em&gt;). En mi humilde opinión son &lt;strong&gt;los mejores&lt;/strong&gt; en cada caso, dentro de los &lt;strong&gt;editores gratuitos&lt;/strong&gt;. Existen algunos de pago, fundamentalmente &lt;strong&gt;&lt;a href="https://www.jetbrains.com/webstorm/"&gt;WebStorm&lt;/a&gt;&lt;/strong&gt; de Jetbrains y quizá &lt;a href="https://www.adobe.com/es/products/dreamweaver.html"&gt;Dreamweaver&lt;/a&gt; de Adobe solo para diseño web, que son buenísimos pero se salen de esta premisa de la gratuidad.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : antes de que me digas que este o aquel editor que te gusta tanto no está en la lista ten en cuenta una cosa: es &lt;strong&gt;mi&lt;/strong&gt; lista, la de &lt;strong&gt;mis&lt;/strong&gt; editores favoritos por diversos motivos, y puede que no los conozca todos o quizá no veo las cosas de la misma manera que tú, pero no es por mala intención o dejadez, sino que es &lt;strong&gt;mi&lt;/strong&gt; lista personal e intransferible. Ahora bien, estaré encantado de que dejes un comentario en la parte de abajo hablando de tu editor favorito que no está en la lista y por qué consideras que debería estar. ¡Gracias!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;¡Allá vamos!&lt;/p&gt;

&lt;h2&gt;
  
  
  Uso general: &lt;strong&gt;&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;&lt;/strong&gt; - El mejor para el día a día y para hacer de todo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sll1EwWB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/vscode.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sll1EwWB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/vscode.png" alt="Imagen de VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He de confesar que cuando salió no hubiera apostado casi nada por él y pensé que iba a ser otro de tantos productos fallidos de Microsoft intentando ser "cool". No podía estar más equivocado. Con el tiempo VSCode se ha convertido en &lt;strong&gt;el editor&lt;/strong&gt; , y ya es el más utilizado por desarrolladores de todo tipo.&lt;/p&gt;

&lt;p&gt;Es gratuito, de código abierto, multiplataforma (Windows, Linux, macOS, ARM y ahora también Web), ágil, rápido y súper-potente. Además tiene infinitas extensiones para poder ampliar su funcionalidad sin que pierda la ligereza que lo caracteriza, e integra soporte para las herramientas más habituales (desde Git o la línea de comandos integrada, hasta Docker).&lt;/p&gt;

&lt;p&gt;No solo se puede usar para programar HTML, CSS y JavaScript, sino que tiene un gran soporte (nativo o con extensiones) para infinidad de lenguajes: &lt;a href="https://dev.to/campusmvp/visual-studio-code-cmo-preparar-un-entorno-de-trabajo-para-net-core-6fh-temp-slug-30306"&gt;plataforma .NET y C#&lt;/a&gt;, Node.js, PHP, Java, Python, C++, Go... además de buen soporte para bibliotecas JavaScript como &lt;a href="https://dev.to/campusmvp/visual-studio-code--angular-cmo-montar-un-entorno-de-desarrollo-productivo-para-este-framework-1mdl-temp-slug-3333534"&gt;Angular&lt;/a&gt;, Vue.js o React, y no solo para programación. Por ejemplo, este artículo lo estoy escribiendo en Markdown usando Visual Studio Code. Prácticamente lo uso para todo en la actualidad, y además lo sincronizo entre todos mis equipos. Su soporte para &lt;a href="https://code.visualstudio.com/blogs/2017/11/15/live-share"&gt;Live Share&lt;/a&gt; incluso te permite trabajar con otros desarolladores en tiempo real en el mismo código.&lt;/p&gt;

&lt;p&gt;En lo que se refiere a HTML, CSS y JavaScript en concreto ofrece grandes características como, por supuesto, la completitud automática de código, soporte para emmet/zencoding, ayuda contextual a medida que escribes, selectores de colores, refactorización de código, depuración sin salir de la herramienta, soporte para Live Server (servir y recargar automáticamente las páginas mientras las editas, con una extensión) y mil cosas más. Demasiadas para enumerarlas.&lt;/p&gt;

&lt;p&gt;Por todo ello, hoy por hoy, Visual Studio Code es mi editor principal y el que recomendaría en casi todos los casos a cualquiera.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprender: &lt;strong&gt;&lt;a href="http://brackets.io/"&gt;Brackets&lt;/a&gt;&lt;/strong&gt; - Ideal para principiantes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2aJSDIQA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/brackets.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2aJSDIQA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/brackets.png" alt="Imagen de Brackets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aunque este editor creado por Adobe no es tan conocido como otros, se lo suelo recomendar a mis alumnos que están empezando con HTML y CSS porque es un editor muy enfocado en estos lenguajes, además de en JavaScript y con algunas facilidades especialmente interesantes para enfocarte mientras comienzas.&lt;/p&gt;

&lt;p&gt;Aparte de las características habituales (ayuda contextual a la escritura, auto-cierre de etiquetas, etc...) posee tres características que lo hacen especialmente interesante para este perfil de iniciación:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live preview&lt;/strong&gt; : integra una combinación de teclas, &lt;code&gt;CTRL+E&lt;/code&gt;, que si la pulsas cuando estás sobre una clase CSS en una etiqueta o sobre una función JavaScript, te muestra directamente en línea, sin cambiar de editor, la definición de la misma permitiéndote además editarla:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KdYc2SqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/brackets-inline.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KdYc2SqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/brackets-inline.gif" alt="El editor en línea de Brackets en acción"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;p&gt;Fueron unos de los pioneros en esto y, aunque pueda parecer algo menor, el hecho de que lo traiga integrado resulta muy cómodo y ayuda mucho cuando estás empezando (en VScode lo puedes conseguir también con la extensión &lt;a href="https://marketplace.visualstudio.com/items?itemName=pranaygp.vscode-css-peek"&gt;CSS Peek&lt;/a&gt; aunque no está tan logrado, y es nativo en el caso de JavaScript).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vista previa de los cambios en tiempo real&lt;/strong&gt;. Basta pulsar un botón para que se abra el navegador y se empiece a servir la página, quedando ésta enlazada con el editor. De este modo, cada vez que hagas cualquier cambio (aún sin grabarlo), se verá reflejado en tiempo real en el navegador, sin necesidad de refrescar. Esto se puede hacer también con otros editores como VSCode, pero necesitas una extensión y es más complicado. Nuevamente un "win" para los principiantes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soporte de serie para preprocesadores CSS (SASS y Less)&lt;/strong&gt;: si además de CSS estás aprendiendo a sacarle partido a estas potentes herramientas, te vendrá muy bien, y nuevamente sin necesidad de extensiones o herramientas externas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiene también posibilidades de refactorización de código JavaScript, y bastantes extensiones (aunque ni de lejos las de VScode) pero quitando dos o tres (Emmet, Git o Beautify, por ejemplo) no merece la pena instalarlas ya que su virtud está precisamente en lo que trae de serie para principiantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud: &lt;strong&gt;&lt;a href="https://jsbin.com/"&gt;JSBin&lt;/a&gt;&lt;/strong&gt; - Editor online para pruebas, experimentos y compartir ejemplos
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dN1TY8Uz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/jsbin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dN1TY8Uz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/file.axd%3Ffile%3D/2019/2T/editores-html-css-js/jsbin.png" alt="Ejemplo de código en JSBin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la actualidad es casi tan importante escribir código como compartirlo. Por eso, los editores "en la nube" se usan cada vez más. No los usarás para crear proyectos completos (aunque en teoría podrías) sino más bien para usarlos desde cualquier lugar para pruebas rápidas, experimentos y compartir código con otros desarrolladores. Esto último es especialmente útil si estás comenzando.&lt;/p&gt;

&lt;p&gt;Aunque mi favorito en general es &lt;strong&gt;&lt;a href="https://repl.it/"&gt;repl.it&lt;/a&gt;&lt;/strong&gt; porque además soporta muchos lenguajes diferentes, en este caso debo centrarme en alguno especialmente pensado para código Front-End con HTML, CSS y JavaScript. Dentro de esta categoría existen muchos, siendo quizá los más conocidos &lt;strong&gt;&lt;a href="https://jsfiddle.net/"&gt;JSFiddle&lt;/a&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;a href="https://codepen.io/"&gt;Codepen&lt;/a&gt;&lt;/strong&gt;. Sin embargo el que te recomiendo hoy, &lt;strong&gt;&lt;a href="https://jsbin.com/"&gt;JSBin&lt;/a&gt;&lt;/strong&gt;, es uno mucho menos conocido y con un aspecto más espartano. Sin embargo, aunque los tres son buenos, creo que es el que seguramente ofrece las mejores características en conjunto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permite utilizar multitud de preprocesadores, HTML (Markdown, Jade), CSS (Sass, Less, Myth, Stylus), JavaScript (TypeScript, Babel, LiveScript, Cofeescript).&lt;/li&gt;
&lt;li&gt;Puedes añadir simplemente seleccionándolas de una lista decenas bibliotecas JavaScript populares, como jQuery, Bootstrap, QUnit, Angular, React, Vue.js... más que en el caso de los otros (aunque siempre puedes añadir más manualmente).&lt;/li&gt;
&lt;li&gt;Puedes crear plantillas de las que partir en lugar de unos documentos en blanco. También arrastrar archivos directamente desde tu disco.&lt;/li&gt;
&lt;li&gt;Compartir es muy fácil gracias a sus &lt;a href="https://jsbin.com/help/pronounceable-urls/"&gt;URLs "pronunciables"&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tiene la posibilidad de hacer &lt;a href="https://remysharp.com/2013/11/14/what-is-codecasting/"&gt;"Code Casting"&lt;/a&gt;, es decir, empezar a "emitir" todo lo que haces en el editor mientras escribes tu código y que otra gente se suscriba y lo vea en tiempo real para aprender o para ayudarte mientras habláis a través de Skype o similar.&lt;/li&gt;
&lt;li&gt;Lo puedes &lt;a href="https://jsbin.com/help/running-a-local-copy-of-jsbin/"&gt;descargar e instalar localmente&lt;/a&gt; si no quieres usarlo (sólo) online.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tal vez JSFiddle es más conocido y más bonito y tiene algunas características muy chulas, pero JSBin me ha conquistado por su sencillez y porque tiene algunas características que lo hacen único. Cualquiera de los dos que elijas será una gran decisión.&lt;/p&gt;




&lt;p&gt;En esta era de la abundancia, &lt;strong&gt;menos es más&lt;/strong&gt;. Así que esta es mi pequeña lista de preferencias en editores gratuitos de HTML, CSS y JavaScript. Pocos, pero buenos y sobre todo siendo realistas en cuanto a cómo debes desarrollar para la Web hoy. Nada de arrastrar y soltar y mucho de &lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-HTML5-y-CSS3-a-fondo-para-desarrolladores_185.aspx"&gt;entender bien lo que haces&lt;/a&gt;, usar &lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Dise%C3%B1o-Web-Responsive-con-HTML5,-Flexbox,-CSS-Grid-y-Bootstrap_212.aspx"&gt;frameworks o técnicas modernas de maquetación web&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;¿Conoces algún editor que creas que se deba mencionar o que te guste más en alguna de las categorías? Pues dame argumentos (no solo nombres) en los comentarios de debajo 😉&lt;/p&gt;

&lt;p&gt;¡Espero que te resulten útiles!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Guía: Cuándo usar TypeScript en tus desarrollos web</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Tue, 14 May 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/guia-cuando-usar-typescript-en-tus-desarrollos-web-4o13</link>
      <guid>https://dev.to/campusmvp/guia-cuando-usar-typescript-en-tus-desarrollos-web-4o13</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Artículo original publicado en &lt;a href="https://www.campusmvp.es/recursos/post/guia-cuando-usar-typescript-en-tus-desarrollos-web.aspx" rel="noopener noreferrer"&gt;el blog de campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Abróchate el cinturón. En esta guía, comparamos cuándo es absolutamente vital utilizar TypeScript, el lenguaje de programación de tipado estricto, y cuándo tiene sentido atenerse a JavaScript "puro".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F2T%2Ftypescript-time.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F2T%2Ftypescript-time.jpg" alt="Imagen ornamental - Unos edificios, algunos de ellos en remodelación de fachada"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : este artículo es una traducción del artículo &lt;a href="https://khalilstemmler.com/articles/when-to-use-typescript-guide/" rel="noopener noreferrer"&gt;When To Use TypeScript - A Detailed Guide Through Common Scenarios&lt;/a&gt; de &lt;a href="https://twitter.com/stemmlerjs" rel="noopener noreferrer"&gt;Khalil Stemmler&lt;/a&gt; traducido con su permiso expreso. Puedes seguir las discusiones que se generaron sobre el mismo en &lt;a href="https://news.ycombinator.com/item?id=19597359" rel="noopener noreferrer"&gt;Hackernews&lt;/a&gt; y en &lt;a href="https://www.reddit.com/r/javascript/comments/baj49w/when_to_use_typescript_a_detailed_guide_through/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;¿Has oído hablar de ese pequeño &lt;a href="https://www.campusmvp.es/recursos/post/por-que-aprender-typescript.aspx" rel="noopener noreferrer"&gt;lenguaje de programación llamado TypeScript&lt;/a&gt;? Ya sabes, el que hizo Microsoft... ¿El que &lt;a href="https://redmonk.com/sogrady/2019/03/20/language-rankings-1-19/" rel="noopener noreferrer"&gt;está explotando en popularidad&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Tal vez seas como yo, un verdadero purista de JavaScript. Me iba bien con React y Node sin tipos. Los &lt;em&gt;Prop Types&lt;/em&gt; y la validación &lt;em&gt;Joi&lt;/em&gt; me han tratado muy bien, gracias.&lt;/p&gt;

&lt;p&gt;Tal vez cediste ante TypeScript y le diste una oportunidad. Empezaste a trastear con él. Tal vez lo llegaste a odiar porque te recordaba a Java. Tal vez te irritaste por no poder lograr mucha productividad desde el primer momento.&lt;/p&gt;

&lt;p&gt;Estas fueron algunas de mis sensaciones iniciales cuando empecé con TypeScript.&lt;/p&gt;

&lt;p&gt;En realidad no le vi las ventajas... hasta que empecé a sufrir cosas muy molestas. Cosas como que los "builds" no fallaban cuando debían, código con errores y faltas tipográficas que se abrían paso de alguna manera en el código de producción y que empezaron a afectarme. Además, a medida que las exigencias de mi proyecto comenzaban a hacerse más complejas, me resultaba cada vez más difícil plasmar mis diseños de una manera realmente orientada a objetos limpia y clara.&lt;/p&gt;

&lt;p&gt;9 meses después de usar TypeScript, he creado nuevas funcionalidades en aplicaciones Angular para mis clientes, he comenzado a compilar el Front-End React/Redux de &lt;a href="https://univjobs.ca/" rel="noopener noreferrer"&gt;Univjobs&lt;/a&gt; con TypeScript, y he portado todos los servicios de backend de Univjobs a TypeScript desde Node.js con JavaScript "puro", refactorizando de paso enormes cantidades de código durante el proceso.&lt;/p&gt;

&lt;p&gt;En este artículo, echaremos un vistazo a algunos de los &lt;strong&gt;escenarios más comunes&lt;/strong&gt; e identificaremos &lt;strong&gt;cuándo podría ser vital usar TypeScript&lt;/strong&gt; , y cuándo probablemente podríamos prescindir de él y seguir con JavaScript puro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué este debate es hoy más importante que nunca
&lt;/h2&gt;

&lt;p&gt;He llegado a la trascendental conclusión de que, dependiendo de tu situación, contexto, proyecto, nivel de habilidad y otros factores, &lt;strong&gt;resulta extremadamente arriesgado que tu proyecto NO esté programado con TypeScript hoy en día&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;El espacio del Front-End, por mencionar uno de los posibles, se está volviendo cada vez más complejo. Ciertas características que antes se consideraban de vanguardia, ahora los usuarios las esperan como algo estándar.&lt;/p&gt;

&lt;p&gt;Por ejemplo, casi siempre es de esperar que tu aplicación siga funcionando sin conexión en alguna medida; y cuando los usuarios ESTÁN conectados, también suelen tener la expectativa de recibir notificaciones en tiempo real sin tener que actualizar la página.&lt;/p&gt;

&lt;p&gt;Estas son algunas de las exigencias más importantes (y definitivamente no poco realistas) en 2019.&lt;/p&gt;

&lt;p&gt;Antes de sumergirnos en diferentes escenarios, deberíamos hablar de las &lt;strong&gt;tres categorías de problemas de software realmente complejos que debemos resolver&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Categorías de problemas difíciles de resolver en software
&lt;/h2&gt;

&lt;p&gt;En términos generales, hay 3:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;El Problema del Sistema de Alto Rendimiento.&lt;/li&gt;
&lt;li&gt;El Problema del Sistema Embebido.&lt;/li&gt;
&lt;li&gt;El Problema del Dominio Complejo.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. El Problema del Sistema de Alto Rendimiento
&lt;/h3&gt;

&lt;p&gt;Hablemos de Twitter.&lt;/p&gt;

&lt;p&gt;Twitter es en realidad un concepto muy simple.&lt;/p&gt;

&lt;p&gt;Te registras, escribes tuits, te gustan los tuits de otras personas y eso es prácticamente todo.&lt;/p&gt;

&lt;p&gt;Si Twitter es tan sencillito, ¿por qué no podría haberlo hecho otra persona?&lt;/p&gt;

&lt;p&gt;Es evidente que el verdadero reto para Twitter no es tanto "lo que hace", sino "cómo consigue hacer lo que hace".&lt;/p&gt;

&lt;p&gt;Twitter tiene el desafío único de servir las peticiones de aproximadamente 500 millones de usuarios cada día.&lt;/p&gt;

&lt;p&gt;La dificultad que soluciona Twitter es en realidad &lt;strong&gt;un problema de rendimiento&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cuando el reto es el rendimiento, el hecho de que utilicemos o no un lenguaje fuertemente tipado es menos importante.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. El Problema del Sistema Embebido
&lt;/h3&gt;

&lt;p&gt;Un sistema embebido es una combinación de hardware y software informático, con el fin de permitir el control de los aspectos mecánicos o eléctricos de un sistema.&lt;/p&gt;

&lt;p&gt;La mayoría de los sistemas que utilizamos hoy en día están construidos sobre una capa de código muy compleja que, si no está programada inicialmente en C o C++, suele compilar a estos lenguajes.&lt;/p&gt;

&lt;p&gt;La programación en estos lenguajes no es para "flojos".&lt;/p&gt;

&lt;p&gt;En C, no existen los objetos; y a nosotros como humanos nos gustan los objetos porque podemos entenderlos fácilmente. C es procedimental y esto hace que el código que tenemos que desarrollar en este lenguaje sea más difícil de mantener de forma limpia. Estos problemas también exigen tener conocimiento de detalles de bajo nivel.&lt;/p&gt;

&lt;p&gt;C++ hace que la vida sea mucho mejor ya que está orientado a objetos, pero el reto sigue siendo la interacción fundamental con los detalles de hardware de bajo nivel.&lt;/p&gt;

&lt;p&gt;Debido a que realmente no tenemos demasiada elección sobre los lenguajes que usamos para estos problemas, es irrelevante discutir aquí sobre TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. El Problema de Dominio Complejo
&lt;/h3&gt;

&lt;p&gt;En el caso de algunos problemas, el desafío consiste no tanto en escalar en términos de manejar más peticiones, sino en escalar en términos del &lt;strong&gt;tamaño de la base de código&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Las empresas tienen problemas complejos para resolver en la vida real. En estas empresas, los mayores retos de ingeniería del software suelen ser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ser capaz de separar lógicamente (a través de dominios) partes de ese monolito en aplicaciones más pequeñas. Y luego, físicamente (a través de microservicios para contextos vinculados), dividirlos para que se puedan asignar equipos de trabajo para mantenerlos.&lt;/li&gt;
&lt;li&gt;Gestionar la integración y sincronización entre estas aplicaciones&lt;/li&gt;
&lt;li&gt;Modelar los conceptos de dominio y resolver realmente los problemas del dominio&lt;/li&gt;
&lt;li&gt;Creación de un lenguaje ubicuo (que abarque todos los aspectos) para que sea compartido por desarrolladores y los expertos en los dominios.&lt;/li&gt;
&lt;li&gt;No perderse en las cantidades masivas de código escrito y ralentizarse hasta el punto en que se hace imposible añadir nuevas funciones sin romper las existentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He descrito esencialmente los tipos de problemas que resuelve el &lt;a href="https://khalilstemmler.com/articles/domain-driven-design-intro/" rel="noopener noreferrer"&gt;diseño orientado por dominio&lt;/a&gt; (&lt;em&gt;Domain Driven Design&lt;/em&gt;). Para este tipo de proyectos, ni siquiera pensarías en no usar un lenguaje fuertemente tipado como TypeScript.&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript orientado a objetos
&lt;/h4&gt;

&lt;p&gt;En el caso de problemas con &lt;strong&gt;dominios complejos&lt;/strong&gt; , si no se escoge TypeScript y, en su lugar, se escoge JavaScript, se requerirá un esfuerzo adicional para que los resultados sean satisfactorios. No sólo tendrás que estar &lt;strong&gt;más que cómodo&lt;/strong&gt; con tus habilidades de modelado de objetos en JavaScript puro, sino que también tendrás que saber cómo utilizar los 4 principios de la programación orientada a objetos (encapsulación, abstracción, herencia y polimorfismo).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Esto puede ser difícil de hacer. JavaScript no tiene de forma nativa conceptos como interfaces y clases abstractas, y la herencia por prototipos puede resultar complicada a veces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La "segregación de interfaces" de los principios de diseño de SOLID no es fácil de conseguir con JavaScript puro.&lt;/p&gt;

&lt;p&gt;El uso de JavaScript por sí solo también requeriría un cierto nivel de disciplina como desarrollador para mantener el código limpio, y esto es vital una vez que la base de código sea lo suficientemente grande. Y también es importante asegurarse de que todo el equipo de programación comparte la misma disciplina, la misma experiencia y el mismo nivel de conocimientos sobre cómo implementar patrones de diseño comunes en JavaScript. Si no, es necesario orientarlos.&lt;/p&gt;

&lt;p&gt;En proyectos orientados a dominios como este, el gran beneficio de usar un lenguaje fuertemente tipado no consiste tanto en expresar &lt;strong&gt;lo que se puede hacer&lt;/strong&gt; , sino más bien en usar encapsulación y ocultación de información para &lt;strong&gt;reducir la posibilidad de errores limitando lo que los objetos del dominio realmente pueden hacer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Se puede prescindir de esto en la parte Front-End, pero en mi opinión es un &lt;strong&gt;requisito de lenguaje indispensable para el &lt;em&gt;backend&lt;/em&gt;&lt;/strong&gt;. También es la razón por la que cambié mis servicios de backend de Node.js a TypeScript.&lt;/p&gt;

&lt;p&gt;Hay una razón por la que &lt;strong&gt;a TypeScript se le llama "JavaScript que escala"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;De entre las tres categorías de problemas de software difíciles, sólo el problema del dominio complejo es aquel en el que TypeScript es absolutamente imprescindible.&lt;/p&gt;

&lt;p&gt;Además de esto, existen otros factores que pueden determinar cuándo es mejor utilizar TypeScript para los proyectos JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tamaño del código
&lt;/h2&gt;

&lt;p&gt;El tamaño del código generalmente se relaciona con el problema del dominio complejo, donde una base de código grande significa un dominio complejo, pero no siempre es así.&lt;/p&gt;

&lt;p&gt;Cuando la cantidad de código que tiene un proyecto alcanza un cierto tamaño, se hace más difícil llevar un registro de todo lo que existe, y es más fácil terminar reimplementando algo ya programado.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La duplicación es el enemigo de un software bien diseñado y estable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esto se acentúa especialmente cuando los nuevos desarrolladores comienzan a programar sobre una base de código ya de por sí grande.&lt;/p&gt;

&lt;p&gt;El auto-completado de Visual Studio Code e Intellisense ayudan a navegar a través de grandes proyectos. Funciona muy bien con TypeScript, pero es algo más limitado con JavaScript.&lt;/p&gt;

&lt;p&gt;Para &lt;strong&gt;proyectos que permanecerán simples y pequeños&lt;/strong&gt; , o si se sabe que con el tiempo serán desechados, estaría &lt;strong&gt;menos inclinado en recomendar TypeScript como requisito&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software de producción frente a proyectos personales
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;El software que está en producción es el código que importa&lt;/strong&gt; , o el código por el que se puede tener problemas si no funciona. También es un código para el que has hecho pruebas. Por regla general, si a uno le preocupa el código, necesita que le hagan pruebas unitarias.&lt;/p&gt;

&lt;p&gt;Pero si no te importa, no hagas &lt;em&gt;testing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Los proyectos personales&lt;/strong&gt; se explican por sí solos. Se puede hacer lo que se quiera. No hay ningún compromiso profesional para mantener estándares de calidad.&lt;/p&gt;

&lt;p&gt;Es bueno atreverse a hacer cosas. Hacer cosas pequeñas, hacer cosas grandes.&lt;/p&gt;

&lt;p&gt;Tal vez algún día se te haga fastidioso si un proyecto personal se convierte en un proyecto profesional y que algún día se convertirá en software de producción, ya que tendrá errores debido a que no se le hicieron pruebas... 🙃 no es como si me hubiera pasado a mí ni nada de eso....&lt;/p&gt;

&lt;h3&gt;
  
  
  Ausencia de pruebas unitarias
&lt;/h3&gt;

&lt;p&gt;No siempre es posible hacer pruebas para todo, porque, bueno, la vida es así...&lt;/p&gt;

&lt;p&gt;En este caso, diría que, si no se realizan pruebas unitarias, lo mejor que se puede hacer es una &lt;strong&gt;comprobación en tiempo de compilación con TypeScript&lt;/strong&gt;. Después de eso, si se está usando React, lo mejor es usar la comprobación en tiempo de ejecución con &lt;em&gt;Prop Types&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sin embargo, la inspección en tiempo de compilación no es una alternativa a las pruebas unitarias. Lo bueno es que las pruebas unitarias se pueden escribir en cualquier lenguaje, por lo que el argumento para TypeScript aquí es irrelevante. Lo importante es que las pruebas estén programadas y que tengamos confianza en nuestro código.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Startups&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Sin duda, lo mejor es usar lo que ayude a ser más productivo.&lt;/p&gt;

&lt;p&gt;En este momento, el lenguaje que se elija importa mucho menos.&lt;/p&gt;

&lt;p&gt;Lo más importante que se debe hacer es validar el producto.&lt;/p&gt;

&lt;p&gt;Elegir un lenguaje (Java, por ejemplo) o una herramienta (como &lt;a href="https://dev.to/campusmvp/qu-es-kubernetes-y-cmo-funciona-mbd-temp-slug-5971176"&gt;Kubernetes&lt;/a&gt;) que pueda ayudar a escalar en el futuro, sin estar totalmente familiarizado con ella y con la necesidad de pasar tiempo aprendiendo, puede o no ser la mejor opción en el caso de un &lt;em&gt;startup&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Dependiendo de en qué fase se encuentre la empresa, lo más importante que se debe hacer es intentar ser productivo.&lt;/p&gt;

&lt;p&gt;En el famoso artículo de &lt;strong&gt;Paul Graham&lt;/strong&gt; , &lt;a href="http://www.paulgraham.com/pypar.html" rel="noopener noreferrer"&gt;The Python Paradox&lt;/a&gt;, la idea principal es que los programadores novatos sólo deben utilizar una tecnología que maximice su productividad.&lt;/p&gt;

&lt;p&gt;En general, en este caso, se puede usar cualquier cosa con la que uno esté más cómodo: tipado o no tipado. Siempre se puede refactorizar hacia un mejor diseño una vez que se sabe que se ha creado algo que las personas realmente quieren.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trabajo en equipo
&lt;/h2&gt;

&lt;p&gt;Dependiendo del tamaño de los equipos y de los &lt;em&gt;frameworks&lt;/em&gt; que se utilicen, utilizar TypeScript puede salir muy bien o fatal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Equipos grandes
&lt;/h3&gt;

&lt;p&gt;Cuando los equipos son lo suficientemente grandes (porque los problemas son lo suficientemente grandes), es una buena razón para usar un &lt;em&gt;framework&lt;/em&gt; que nos deje poca libertad de opciones, como &lt;strong&gt;Angular para el front-end y TypeScript para el backend&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La razón por la cual el uso de un &lt;em&gt;framework&lt;/em&gt; "con opiniones" es beneficioso es porque se limita el número de formas posibles en que las personas pueden llegar a hacer algo. En Angular, hay casi una manera principal de añadir un &lt;em&gt;Route Guard&lt;/em&gt;, usar inyección de dependencias, conectar rutas, hacer &lt;em&gt;Lazy-Loading&lt;/em&gt; y crear formularios reactivos.&lt;/p&gt;

&lt;p&gt;La gran ventaja es que la API está bien especificada.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con TypeScript, se ahorra mucho tiempo y se hace más eficiente la comunicación&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La capacidad de determinar rápidamente los argumentos necesarios y su tipo de retorno para cualquier método, o la capacidad de describir explícitamente la intención del programa a través de variables públicas, privadas y protegidas es increíblemente útil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sí, algo de todo esto también es posible con JavaScript, pero es un lío.&lt;/p&gt;

&lt;h4&gt;
  
  
  Comunicar patrones e implementar principios de diseño
&lt;/h4&gt;

&lt;p&gt;No sólo eso, sino que los &lt;strong&gt;patrones de diseño&lt;/strong&gt; , las soluciones a los problemas más comunes que ocurren en el software, se comunican más fácilmente a través de lenguajes explícitos fuertemente tipados.&lt;/p&gt;

&lt;p&gt;A continuación se muestra un ejemplo de un patrón común en JavaScript. Fíjate a ver si puedes identificar qué es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AudioDevice {
  constructor () {
    this.isPlaying = false;
    this.currentTrack = null;
  }

  play (track) {
    this.currentTrack = track;
    this.isPlaying = true;
    this.handlePlayCurrentAudioTrack();
  }

  handlePlayCurrentAudioTrack () {
    throw new Error(`Subclasss responsibility error`)
  }
}

class Boombox extends AudioDevice {
  constructor () {
    super()
  }

  handlePlayCurrentAudioTrack () {
    // Play through the boombox speakers
  }
}

class IPod extends AudioDevice {
  constructor () {
    super()
  }

  handlePlayCurrentAudioTrack () {
    // Ensure headphones are plugged in
    // Play through the ipod
  }
}

const AudioDeviceType = {
  Boombox: 'Boombox',
  IPod: 'Ipod'
}

const AudioDeviceFactory = {
  create: (deviceType) =&amp;gt; {
    switch (deviceType) {
      case AudioDeviceType.Boombox:
        return new Boombox();
      case AudioDeviceType.IPod:
        return new IPod();
      default:
        return null;
    }
  }
}

const boombox = AudioDeviceFactory
  .create(AudioDeviceType.Boombox);

const ipod = AudioDeviceFactory
  .create(AudioDeviceType.IPod);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si adivinaste el &lt;strong&gt;Patrón "Factoría Abstracta"&lt;/strong&gt; , estás en lo cierto. Dependiendo de tu familiaridad con el patrón, podría no haber sido tan obvio.&lt;/p&gt;

&lt;p&gt;Veámoslo ahora implementado en TypeScript. Observa cuánta más intención podemos significar sobre &lt;code&gt;AudioDevice&lt;/code&gt; en este lenguaje:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class AudioDevice {
  protected isPlaying: boolean = false;
  protected currentTrack: ITrack = null;

  constructor () {
  }

  play (track: ITrack) : void {
    this.currentTrack = track;
    this.isPlaying = true;
    this.handlePlayCurrentAudioTrack();
  }

  abstract handlePlayCurrentAudioTrack () : void;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Mejoras inmediatas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Sabemos que la clase es abstracta de inmediato. En el ejemplo de JavaScript era necesario investigar un poco.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AudioDevice&lt;/code&gt; puede ser instanciado en el ejemplo de JavaScript. Esto es malo, queríamos que &lt;code&gt;AudioDevice&lt;/code&gt; fuera una clase abstracta. Y las clases abstractas no deberían poder ser instanciadas, sólo están destinadas a ser subclasificadas e implementadas por &lt;a href="https://khalilstemmler.com/articles/when-to-use-typescript-guide/wiki/concrete-class/" rel="noopener noreferrer"&gt;clases concretas&lt;/a&gt;. Esta limitación se establece correctamente en el ejemplo de TypeScript.&lt;/li&gt;
&lt;li&gt;Hemos señalado el ámbito de las variables.&lt;/li&gt;
&lt;li&gt;En este ejemplo, &lt;code&gt;currentTrack&lt;/code&gt; se refiere a una interfaz. Según el principio de diseño de la &lt;a href="https://khalilstemmler.com/wiki/dependency-inversion" rel="noopener noreferrer"&gt;inversión de la dependencia&lt;/a&gt;, siempre debemos depender de las abstracciones, no de las concreciones. Esto no es posible en la implementación con JavaScript.&lt;/li&gt;
&lt;li&gt;También hemos señalado que cualquier subclase de &lt;code&gt;AudioDevice&lt;/code&gt; necesitará implementar el &lt;code&gt;handlePlayCurrentAudioTrack&lt;/code&gt;. En el ejemplo de JavaScript, expusimos la posibilidad de que alguien introdujera errores de ejecución intentando ejecutar el método desde la clase abstracta ilegal o desde la implementación de la clase concreta no completa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt; : si se trabaja en un equipo grande y se necesita minimizar las posibles formas en las que alguien podría hacer un mal uso del código, TypeScript es una buena forma de ayudar a corregirlo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Equipos más pequeños y estilos de programación
&lt;/h3&gt;

&lt;p&gt;Los equipos más pequeños son mucho más fáciles de manejar en lo que respecta a estilos de programación y comunicación. Junto con las herramientas de comprobación de reglas (&lt;em&gt;linting&lt;/em&gt;), las discusiones frecuentes sobre cómo se harán las cosas y &lt;a href="https://www.campusmvp.es/recursos/post/3-trucos-para-automatizar-tus-tareas-de-desarrollo-con-git-hooks.aspx" rel="noopener noreferrer"&gt;los &lt;em&gt;pre-commit hooks&lt;/em&gt;&lt;/a&gt;, creo que los equipos pequeños pueden tener mucho éxito sin TypeScript.&lt;/p&gt;

&lt;p&gt;Creo que el éxito es una ecuación que incluye el tamaño de la base de código y el tamaño del equipo.&lt;/p&gt;

&lt;p&gt;A medida que crece la base de código, el equipo puede encontrar que necesita contar con algo de ayuda del propio lenguaje para recordar dónde están las cosas y cómo deberían estar.&lt;/p&gt;

&lt;p&gt;A medida que el equipo crece, pueden encontrar que necesitan más reglas y restricciones para asegurar la coherencia del estilo y evitar la duplicación de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React y Angular
&lt;/h3&gt;

&lt;p&gt;Mucho de lo que me atrae a mí y a otros desarrolladores de React es la capacidad de escribir código como quieras y de forma elegante/inteligente.&lt;/p&gt;

&lt;p&gt;Es cierto que React te hace mejor programador de JavaScript porque te obliga a enfocar los problemas de forma diferente, te obliga a ser consciente de cómo funciona este vínculo en JavaScript y te permite crear componentes grandes a partir de otros pequeños.&lt;/p&gt;

&lt;p&gt;React también te permite tener un poco de estilo propio. Y debido a la cantidad de formas en que se puede implementar cualquier tarea, lo más frecuente es que se programen aplicaciones en React.js "puro" cuando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La base de código es pequeña&lt;/li&gt;
&lt;li&gt;Sólo lo programa una persona&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pero yo lo compilaría con TypeScript cuando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lo estén programando más de 3 personas, o&lt;/li&gt;
&lt;li&gt;se espera que la base de código llegue a ser muy grande&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También opcionalmente &lt;strong&gt;usaría Angular&lt;/strong&gt; por la misma razón por la que compilaría React con TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;En conclusión, &lt;strong&gt;estas son mis opiniones personales sobre cuándo TypeScript es absolutamente necesario&lt;/strong&gt; y os invito a estar en desacuerdo con cualquiera de ellas.&lt;/p&gt;

&lt;p&gt;Esto es lo que me ha funcionado en el pasado a la hora de decidir si utilizo TypeScript. Sin embargo, hoy en día, como he visto la luz, no es mucho más difícil para mí usar TypeScript que JavaScript puro, ya que me siento igual de cómodo con ambos y preferiría la seguridad del tipado.&lt;/p&gt;

&lt;p&gt;Lo último que quiero decir es lo siguiente:&lt;/p&gt;

&lt;h2&gt;
  
  
  Siempre se puede empezar a utilizar TypeScript gradualmente
&lt;/h2&gt;

&lt;p&gt;Empieza gradualmente añadiendo TypeScript y &lt;a href="https://www.npmjs.com/package/ts-node" rel="noopener noreferrer"&gt;ts-node&lt;/a&gt; a tu &lt;code&gt;package.json&lt;/code&gt; y utilizando la opción &lt;code&gt;allowjs: true&lt;/code&gt;, en tu archivo &lt;code&gt;tsconfig&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Así es cómo, con el paso del tiempo, migré todas mis aplicaciones Node.js a TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los errores de tiempo de compilación son mejores que los de tiempo de ejecución
&lt;/h2&gt;

&lt;p&gt;Eso no admite discusión. Si la detección de errores en el código de producción es especialmente importante para ti, TypeScript te ayudará a minimizar muchos de ellos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si estás en disposición de aprenderlo, apréndelo: hace maravillas con tus habilidades de diseño de software
&lt;/h2&gt;

&lt;p&gt;Dependiendo de dónde estés en tu vida y en tu trayectoria profesional, es posible que no tengas tiempo para aprender y formarte. Si tienes tiempo, te recomiendo que empieces por aprender sobre los principios de diseño SOLID y los patrones de diseño de software. Esta es la manera más rápida de subir de nivel como desarrollador junior, en mi sincera opinión.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>spanish</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Java 12 lanzado: versión descafeinada sin  soporte a largo plazo</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Mon, 25 Mar 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/java-12-lanzado-version-descafeinada-sin-soporte-a-largo-plazo-3k3l</link>
      <guid>https://dev.to/campusmvp/java-12-lanzado-version-descafeinada-sin-soporte-a-largo-plazo-3k3l</guid>
      <description>&lt;p&gt;Dentro de la (en mi opinión bastante absurda) metodología de lanzamiento de versiones "mayores" de la plataforma Java cada 6 meses, el pasado día 19 de marzo apareció la &lt;strong&gt;versión 12 de Java&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Esta versión llega tan solo 6 meses después de &lt;a href="https://www.campusmvp.es/recursos/post/java-11-ya-esta-aqui-te-toca-pagar-a-oracle-o-cambiarte-a-otras-opciones.aspx" rel="noopener noreferrer"&gt;la versión 11&lt;/a&gt;, y no se considera una versión con soporte a largo plazo (LTS) por lo que solo se le dará soporte durante 6 meses por parte de Oracle.&lt;/p&gt;

&lt;p&gt;Entre las cuestiones destacables de esta versión solamente hay dos, y encima se consideran experimentales.&lt;/p&gt;

&lt;p&gt;Veámoslas rápidamente:&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch expressions
&lt;/h2&gt;

&lt;p&gt;Las "Expresiones de conmutación" o &lt;em&gt;Switch Expressions&lt;/em&gt;, son una nueva función de lenguaje que se basa en la instrucción &lt;code&gt;switch&lt;/code&gt; existente en el lenguaje desde siempre. Esta nueva variante nos permite crear una manera más concisa de expresar lo mismo que un condicional que tiene varias ramas. Su aspecto este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int numDias = switch(mes) { 
    case 1, 3, 5, 7, 8, 10, 12 -&amp;gt; 31; 
    case 4, 6, 9, 11 -&amp;gt; 30; 
    case 2 -&amp;gt; esBisiesto(anio) ? 29 : 28; 
    default: throw new IllegalArgumentException("Número de mes no válido");}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso asignamos en una variable el número de días del mes del año que nos interese usando esta nueva sintaxis. Fíjate en que se utiliza un operador flecha (&lt;code&gt;-&amp;gt;&lt;/code&gt;) en lugar de los típicos dos puntos (&lt;code&gt;:&lt;/code&gt;),  y que no hace falta meter instrucciones &lt;code&gt;break&lt;/code&gt; en cada uno de los casos, por lo que la sintaxis es muy compacta. Fíjate también en cómo se puede utilizar cualquier tipo de instrucción en cada rama (como en el caso de los años bisiestos para febrero), y cómo todos los posibles valores que se le pasen al &lt;code&gt;switch&lt;/code&gt; deben tener una rama que los gestione, incluso si generan un error, como es el caso final en el que no se pasa un mes válido.&lt;/p&gt;

&lt;p&gt;La única opción de no tener que poner una rama &lt;code&gt;default&lt;/code&gt; es si usamos una enumeración como argumento para el &lt;code&gt;switch&lt;/code&gt;. Si metemos todos los posibles valores de la enumeración dentro de las ramas, podemos omitir &lt;code&gt;default&lt;/code&gt;, lógicamente.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Es importante señalar que, si bien esto se ha incluido en Java 12, se considera todavía una &lt;strong&gt;característica experimental&lt;/strong&gt; , por lo que no te funcionará por defecto. Para que te funcione y poder usarla en tus programas debes utilizar el modificador &lt;code&gt;--enable-preview&lt;/code&gt; con &lt;code&gt;javac&lt;/code&gt;, el compilador de Java. Así que tenlo en cuenta.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Shenandoah, un nuevo recolector de basura
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava12.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava12.jpg" alt="Imagen ornamental"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La principal novedad de Java 12 es su nuevo sistema de &lt;a href="https://www.campusmvp.es/recursos/post/Modelos-de-gestion-de-memoria-II-Garbage-collector.aspx" rel="noopener noreferrer"&gt;recolección de basura&lt;/a&gt;, que se llama  &lt;strong&gt;Shenandoah&lt;/strong&gt;. Su principal ventaja frente al GC existente es que reduce los tiempos de pausa de las aplicaciones mientras se realiza la limpieza de memoria (evacuación, marcado, compactación...) ya que realiza más trabajo de este tipo en paralelo a la ejecución del propio programa, lo que implica también que las pausas de los programas para limpieza ya no estarán directamente relacionadas con el tamaño de la pila. Todavía quedan trabajos de limpieza que se deben hacer por separado, pero son mucho menores y por lo tanto las pausas son muy pequeñas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shenandoah se considera también una tecnología experimental en Java 12, por lo que para que tu programa la utilice deberás habilitarla explícitamente usando las opciones &lt;code&gt;-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC&lt;/code&gt; al ejecutar el comando java.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En la &lt;a href="https://wiki.openjdk.java.net/display/shenandoah/Main" rel="noopener noreferrer"&gt;página oficial del OpenJDK para este nuevo recolector de basura&lt;/a&gt; puedes encontrar todos los detalles de funcionamiento y una lista con los modificadores de su comportamiento.&lt;/p&gt;

&lt;p&gt;Además de Shenandoah, el recolector de basura convencional, &lt;strong&gt;G1&lt;/strong&gt; , tiene algunas mejoras, en concreto ahora si detecta que falla varias veces seguidas a la hora de determinar el tiempo máximo de pausa necesario para la limpieza, y &lt;a href="https://openjdk.java.net/jeps/344" rel="noopener noreferrer"&gt;ajusta la heurística&lt;/a&gt; para mejorar la predicción y detener el proceso si es necesario. También mejora el uso de memoria devolviendo al sistema operativo durante los periodos de inactividad &lt;a href="https://openjdk.java.net/jeps/346" rel="noopener noreferrer"&gt;la memoria de pila que está sin usar&lt;/a&gt;. Esto último es una gran mejora puesto que hasta ahora no devolvía al sistema la memoria de pila sin usar a no ser que se realizase una "limpieza de basura" completa (y por tanto costosa).&lt;/p&gt;

&lt;h2&gt;
  
  
  Otras cosillas
&lt;/h2&gt;

&lt;p&gt;Aparte de lo anterior, esta versión tiene otras 4 pequeñas mejoras que enlazo a continuación con su nombre oficial, por si tienes interés:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://openjdk.java.net/jeps/230" rel="noopener noreferrer"&gt;JEP 230 – Microbenchmark Suite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://openjdk.java.net/jeps/334" rel="noopener noreferrer"&gt;JEP 334 – JVM Constants API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://openjdk.java.net/jeps/340" rel="noopener noreferrer"&gt;JEP 340 – Un único AArch64 Port, Not Two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://openjdk.java.net/jeps/341" rel="noopener noreferrer"&gt;JEP 341 – Default CDS Archives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ya están disponibles las versiones de &lt;a href="https://jdk.java.net/12/" rel="noopener noreferrer"&gt;&lt;strong&gt;Java 12 para el OpenJDK&lt;/strong&gt;&lt;/a&gt; y para &lt;strong&gt;&lt;a href="https://www.oracle.com/technetwork/java/javase/downloads/index.html" rel="noopener noreferrer"&gt;el build oficial de Oracle&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Post original&lt;/strong&gt;: &lt;a href="https://www.campusmvp.es/recursos/post/java-12-lanzado-version-descafeinada-sin-soporte-a-largo-plazo.aspx" rel="noopener noreferrer"&gt;https://www.campusmvp.es/recursos/post/java-12-lanzado-version-descafeinada-sin-soporte-a-largo-plazo.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Java: cómo listar, filtrar y obtener información de carpetas y archivos</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Thu, 21 Feb 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/java-cmo-listar-filtrar-y-obtener-informacin-de-carpetas-y-archivos-g1i</link>
      <guid>https://dev.to/campusmvp/java-cmo-listar-filtrar-y-obtener-informacin-de-carpetas-y-archivos-g1i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Post original&lt;/strong&gt;: &lt;a href="https://www.campusmvp.es/recursos/post/java-como-listar-filtrar-y-obtener-informacion-de-carpetas-y-archivos.aspx" rel="noopener noreferrer"&gt;https://www.campusmvp.es/recursos/post/java-como-listar-filtrar-y-obtener-informacion-de-carpetas-y-archivos.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una tarea común y básica que necesitamos hacer en cualquier programa es &lt;strong&gt;acceder a la información de los archivos y carpetas&lt;/strong&gt; del sistema de archivos local. Desde algo tan básico como ver el nombre y el tamaño de un archivo hasta listar los contenidos de cualquier carpeta.&lt;/p&gt;

&lt;p&gt;En Java esto es muy fácil de conseguir gracias a &lt;strong&gt;la clase &lt;code&gt;java.io.File&lt;/code&gt;&lt;/strong&gt;. Esta clase nos permite obtener información sobre cualquier elemento del sistema de archivos.&lt;/p&gt;

&lt;p&gt;Para utilizarla solo tenemos que importarla en la cabecera de nuestro programa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.File;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y podremos utilizarla en nuestra aplicación.&lt;/p&gt;

&lt;p&gt;Para obtener información sobre un archivo o carpeta basta con usar su constructor pasándole la ruta de éste. Así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String sCarpAct = System.getProperty("user.dir");File carpeta = new File(sCarpAct);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En la primera línea obtenemos la carpeta actual desde la que se está ejecutando el código, y utilizamos la clase &lt;code&gt;File&lt;/code&gt; para obtener información sobre la misma. A este constructor le podemos pasar una ruta absoluta o relativa en el sistema de archivos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/10/docs/api/java/io/File.html" rel="noopener noreferrer"&gt;La clase &lt;code&gt;File&lt;/code&gt;&lt;/a&gt; sirve para representar a un archivo o carpeta y ofrece propiedades y métodos que nos permiten acceder a sus datos y realizar operaciones sobre ellos, como renombrar, eliminar, crear carpetas, listar sus contenidos, etc... Lo que podamos hacer con ella dependerá de los permisos que tengamos sobre el archivo o carpeta en cuestión. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-file-metodos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-file-metodos.png" alt="Algunos de los métodos de File mostrados por la ayuda contextual de un editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algunos de estos métodos son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;canExecute()&lt;/code&gt;: devuelve un &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;false&lt;/code&gt; en función de si el archivo es ejecutable o no.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;canRead()&lt;/code&gt;: si tienes acceso de lectura o no&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;canWrite()&lt;/code&gt;: si puedes escribir en él o no&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;createNewFile()&lt;/code&gt;&lt;/strong&gt;: crea un nuevo archivo vacío con el nombre que se le indique.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;delete()&lt;/code&gt;&lt;/strong&gt;: borra el archivo o directorio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;exists()&lt;/code&gt;&lt;/strong&gt;: determina si el archivo representado por &lt;code&gt;File&lt;/code&gt; en la ruta que le hayamos pasado existe o no.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getName()&lt;/code&gt;&lt;/strong&gt;: el nombre del archivo o carpeta&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getParent()&lt;/code&gt;&lt;/strong&gt;: devuelve una cadena con la ruta de la carpeta "madre" del archivo o carpeta actuales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;isDirectory()&lt;/code&gt;&lt;/strong&gt;: indica si el objeto actual representa a una carpeta o no&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;isFile()&lt;/code&gt;&lt;/strong&gt;:  indica si el objeto actual representa a un archivo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;isHidden()&lt;/code&gt;&lt;/strong&gt;: si es un elemento oculto en el sistema de archivos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;length()&lt;/code&gt;&lt;/strong&gt;: el tamaño del archivo en bytes. Si no existe o no tienes permiso devuelve un 0. En el caso de carpetas en Linux/Mac con sistema de archivos ext3/ext4 siempre devuelve 4096 ya que este es el tamaño de un bloque en Linux y es el mínimo que puede ocupar cualquier enlace en disco, como una carpeta (4KB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;list()&lt;/code&gt;&lt;/strong&gt;: los nombres de los archivos y carpetas hijos de una carpeta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;listFiles()&lt;/code&gt;&lt;/strong&gt;: como el anterior pero devolviendo objetos File para cada archivo o carpeta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mkdir()&lt;/code&gt;&lt;/strong&gt;: crea una carpeta&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;renameTo()&lt;/code&gt;&lt;/strong&gt;: renombra el archivo o carpeta&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con todo esto se pueden hacer muchas cosas. Consúltalos todos en la documentación con el enlace anterior.&lt;/p&gt;

&lt;p&gt;Vamos a ver un ejemplo de &lt;strong&gt;cómo listar todos los archivos de una carpeta&lt;/strong&gt; usando varios de estos métodos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File carpeta = new File(sCarpAct);String[] listado = carpeta.list();if (listado == null || listado.length == 0) { System.out.println("No hay elementos dentro de la carpeta actual"); return;}else { for (int i=0; i&amp;lt; listado.length; i++) { System.out.println(listado[i]); }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo que se hace en este fragmento es:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Se crea un nuevo objeto &lt;code&gt;File&lt;/code&gt; para representar la carpeta que nos interesa.&lt;/li&gt;
&lt;li&gt;Con el método &lt;code&gt;list()&lt;/code&gt; obtenemos los nombres de todos sus hijos&lt;/li&gt;
&lt;li&gt;Si no devuelve nada o la longitud es 0 mostramos un mensaje de que no hay elementos en la carpeta actual (también podríamos haber comprobado si es una carpeta o no con &lt;code&gt;isDirectory()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;En la otra rama del condicional recorremos en un bucle sencillo todos los nombres de elementos hijo mostrando sus nombres cada uno en una línea en la consola.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Veríamos algo como esto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-listado-simple.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-listado-simple.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Está bien para replicar el comando &lt;code&gt;ls&lt;/code&gt; (Linux, Mac) o &lt;code&gt;dir&lt;/code&gt; (Windows) básico de la línea de comandos, pero si queremos más información no nos va a servir de mucho.&lt;/p&gt;

&lt;p&gt;Podemos mejorarlo utilizando el método &lt;code&gt;listFiles()&lt;/code&gt; que nos devuelve objetos &lt;code&gt;File&lt;/code&gt; y por lo tanto podemos mostrar más información de cada uno sin tener que crearlos explícitamente, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File[] archivos = carpeta.listFiles();if (archivos == null || archivos.length == 0) { System.out.println("No hay elementos dentro de la carpeta actual"); return;}else { SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); for (int i=0; i&amp;lt; archivos.length; i++) { File archivo = archivos[i]; System.out.println(String.format("%s (%s) - %d - %s", archivo.getName(), archivo.isDirectory() ? "Carpeta" : "Archivo", archivo.length(), sdf.format(archivo.lastModified()) )); }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso el código es parecido, pero podemos utilizar los métodos que hemos visto para mostrar más información sobre cada elemento. En este caso mostramos su nombre, si es un directorio o un archivo, su tamaño y la fecha de última modificación. Para mostrar la fecha en un formato adecuado utilizo la clase &lt;code&gt;SimpleDateFormater&lt;/code&gt; del paquete &lt;code&gt;java.text.SimpleDateFormat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bien. Pero, ¿qué pasa si no queremos mostrar todos los archivos, sino sólo los que cumplan con ciertas condiciones?&lt;/p&gt;

&lt;p&gt;Para eso podemos &lt;strong&gt;utilizar un filtro&lt;/strong&gt;. Los filtros son clases que implementan la interfaz &lt;code&gt;FilenameFilter&lt;/code&gt; (si solo queremos filtrar por el nombre) o &lt;code&gt;FileFilter&lt;/code&gt; (si queremos usar objetos File para el filtrado). Esta interfaz lo único que define es un método &lt;code&gt;accept()&lt;/code&gt; que, en su sobrecarga más simple, toma como parámetro el archivo a filtrar y debe devolver &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;false&lt;/code&gt; en función de si el archivo pasa el filtro o no.&lt;/p&gt;

&lt;p&gt;Por ejemplo, vamos a filtrar los elementos de nuestra carpeta para que devuelve únicamente archivos, pero no carpetas. Es una condición sencilla, pero lógicamente podríamos aplicar cualquier regla compleja que nos interesase en función de las propiedades disponibles de cada elemento (su nombre, tamaño, permisos... o una combinación de varios de ellos).&lt;/p&gt;

&lt;p&gt;Veamos cómo hacerlo.&lt;/p&gt;

&lt;p&gt;En primer lugar vamos a definir el filtro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FileFilter filtro = new FileFilter() {
 @Override
 public boolean accept(File arch) {
   return arch.isFile();
 }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, por brevedad, he usado un literal con el constructor para crear el objeto e implementar el método &lt;code&gt;accept()&lt;/code&gt;, pero podría haber creado la clase de la manera más convencional usando &lt;code&gt;implements&lt;/code&gt; para implementar la interfaz, etc.. La forma es lo de menos. Lo único que hace es llamar al método &lt;code&gt;isFIle()&lt;/code&gt; de cada archivo o carpeta para devolver &lt;code&gt;true&lt;/code&gt; solo en caso de que sean archivos. De este modo solamente se obtendrán archivos y ninguna carpeta tras realizar el filtrado.&lt;/p&gt;

&lt;p&gt;Ahora utilizarlo es tan sencillo como pasar el nuevo objeto de filtro al método &lt;code&gt;listFiles()&lt;/code&gt;, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;archivos = carpeta.listFiles(filtro);

if (archivos == null || archivos.length == 0) {
 System.out.println("No hay elementos dentro de la carpeta actual");
 return;
}
else {
 SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
 for (int i=0; i&amp;lt; archivos.length; i++) {
   File archivo = archivos[i];
   System.out.println(String.format("%s (%s) - %d - %s", 
                       archivo.getName(), 
                       archivo.isDirectory() ? "Carpeta" : "Archivo",
                       archivo.length(),
                       sdf.format(archivo.lastModified())
                      ));
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tan solo cambia la primera línea. El resto es como en el ejemplo anterior, solo que en este caso veremos en la consola únicamente los archivos y no los directorios gracias al filtro que hemos aplicado.&lt;/p&gt;

&lt;p&gt;Como ves el uso de esta clase es extremadamente sencillo.&lt;/p&gt;

&lt;p&gt;Te dejo todo el código de ejemplo &lt;a href="https://repl.it/@jmalarcon/Java-File-Basico" rel="noopener noreferrer"&gt;en este repl.it&lt;/a&gt;, embebido a continuación. Pulsa el triángulo de la parte de arriba para ejecutarlo directamente en el navegador y ver sus resultados:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : si te preguntas cómo hago lo de mostrar colores en la consola, lee este otro artículo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Post original&lt;/strong&gt;: &lt;a href="https://www.campusmvp.es/recursos/post/java-como-listar-filtrar-y-obtener-informacion-de-carpetas-y-archivos.aspx" rel="noopener noreferrer"&gt;https://www.campusmvp.es/recursos/post/java-como-listar-filtrar-y-obtener-informacion-de-carpetas-y-archivos.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>spanish</category>
    </item>
    <item>
      <title>TRUCO - Depuración con Chrome: convertir archivos JavaScript en "cajas negras" para evitar depurarlos</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Tue, 19 Feb 2019 18:12:21 +0000</pubDate>
      <link>https://dev.to/jmalarcon/truco---depuracin-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos-59hj</link>
      <guid>https://dev.to/jmalarcon/truco---depuracin-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos-59hj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Publicado originalmente en mi blog técnico: &lt;a href="https://www.jasoft.org/Blog/post/truco-depuracion-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos.aspx"&gt;https://www.jasoft.org/Blog/post/truco-depuracion-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por regla general, cuando estamos depurando una aplicación web hay ciertas cosas en las que podemos confiar. Por ejemplo en el hecho de que si se produce una excepción casi seguro que la culpa es de nuestro código y no de alguna biblioteca JavaScript conocida de las que estamos utilizando. Es decir, la excepción puede saltar en una línea de jQuery o de Angular, pero eso no significa que el error esté ahí, sino que se ha producido por una llamada previa hecha por nuestro código.&lt;/p&gt;

&lt;p&gt;Por ello, cuando estamos depurando paso a paso, poniendo puntos de interrupción en ciertas líneas para luego ir ejecutando el código función a función, introduciéndonos en ellas con &lt;code&gt;F11&lt;/code&gt; o saltándolas con &lt;code&gt;F10&lt;/code&gt;, no tiene mucho sentido que, de repente, se nos abra el código fuente de alguna de estas bibliotecas, pues no vamos a depurarlo. Y mucho menos si lo estamos usando ya minimizado y listo para producción, puesto que encima no veremos gran cosa tampoco:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n5BVHItC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n5BVHItC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-00.png" alt="La imagen muestra el depurador de Chrome parado en una línea ininteligible de jQuery"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¡Estupendo que me pare el depurador en esta línea tan interesante! ¿no?&lt;/p&gt;

&lt;p&gt;Por suerte los desarrolladores de Chrome ya han tenido en cuenta esta situación y nos permiten evitar que ocurra, &lt;strong&gt;permitiéndonos meter en una "caja negra" los &lt;em&gt;scripts&lt;/em&gt; que nos interesen&lt;/strong&gt;. La acción se denomina &lt;strong&gt;"blackboxing"&lt;/strong&gt; y lo que hace es que el &lt;em&gt;script&lt;/em&gt; se ejecuta normalmente pero, en lo que respecta a la depuración, actúa como una caja negra de modo que se saben los parámetros que entran y los que salen, pero jamás se accede a su interior.&lt;/p&gt;

&lt;p&gt;En la práctica esto significa que &lt;strong&gt;el depurador jamás se parará en ningún código de su interior&lt;/strong&gt; , agilizando nuestra depuración.&lt;/p&gt;

&lt;p&gt;Vamos a ver cómo funciona...&lt;/p&gt;

&lt;h2&gt;
  
  
  Activando la capacidad de "blackboxing"
&lt;/h2&gt;

&lt;p&gt;Por defecto esta característica está deshabilitada, por lo que no podremos utilizarla. Para activarla tenemos que ir a los ajustes de las herramientas del desarrollador y acceder al apartado correspondiente que se llama "Blackboxing", activándola desde allí, como se muestra en esta pequeña animación:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mCD4aoUM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-01.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mCD4aoUM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-01.gif" alt="Esta animación muestra cómo activar la característica: F12, F1, Blackboxing y 'Blackbox content scripts'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Añadir scrips a la caja negra
&lt;/h2&gt;

&lt;p&gt;Una vez activada la funcionalidad, tenemos dos opciones para añadir scripts a las caja negra:&lt;/p&gt;

&lt;h4&gt;
  
  
  1.- Añadir rutas y/o nombres genéricos
&lt;/h4&gt;

&lt;p&gt;Por ejemplo, generalmente no querremos que el depurador se pare en ninguna biblioteca minimizada, de producción. Como los archivos de estas bibliotecas suelen terminar con el nombre &lt;code&gt;.min.js&lt;/code&gt;, podemos agregar un patrón como este al nombre de archivo usando el botón que tenemos debajo del &lt;em&gt;check&lt;/em&gt; que acabamos activar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xt6P4VI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-02.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xt6P4VI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-02.gif" alt="La animación muestra cómo agregar un patrón de archivos para convertir en caja negra"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fíjate en un par de cosas importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El patrón es una expresión regular. Por lo tanto puedes usar toda la potencia que te dan éstas (que es mucha) para localizar todo tipo de archivos, Además, como se ve en la animación, en una expresión regular un punto representa cualquier carácter, por lo que si queremos indicar un punto de verdad hay que "escapearlo" poniéndole una barra inclinada delante, como se ve en la animación. Tenlo en cuenta. Gracias a esto podemos añadir muchos archivos de golpe. En la animación todos los que estén minimizados.&lt;/li&gt;
&lt;li&gt;Estos patrones no solo nos permiten convertir archivos en cajas negras, sino lo contrario: deshabilitar la caja negra para ciertos archivos que estuviesen incluidos en alguno de los patrones que hayamos añadido. Así que vale para las dos cosas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.- Convertir individualmente cada archivo en una caja negra
&lt;/h4&gt;

&lt;p&gt;Si además (o en lugar) de usar patrones queremos convertir en cajas negras archivos concretos, al cerrar el diálogo anterior y haber habilitado la funcionalidad, tendremos una nueva opción en los menús contextuales de los archivos en la pestaña de código fuente, &lt;code&gt;Sources&lt;/code&gt;. Basta con que abramos cualquier archivo y pulsemos con el botón derecho en cualquier parte del archivo abierto para ver una nueva opción &lt;code&gt;Blackbox Script&lt;/code&gt; que nos permite hace precisamente eso:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--McBd-tN5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-03.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--McBd-tN5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jasoft.org/Blog/image.axd%3Fpicture%3D/2019/chrome-dev/chrome-dev-blackboxing-03.gif" alt="Animación que muestra el nuevo menú contextual con la opción de caja negra"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir de ese momento el depurador no se detendrá en ese archivo, que es lo que queríamos.&lt;/p&gt;

&lt;p&gt;Fíjate en como en la animación anterior, una vez convertido el archivo en una caja negra, podemos volver a habilitarlo para depuración con el mismo menú contextual, que ahora pone &lt;code&gt;Stop blackboxing&lt;/code&gt;. ¡Súper-fácil!&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;El "blackboxing" de &lt;em&gt;scripts&lt;/em&gt; puede ser muy útil para ir más rápido a la hora de depurar y ser más productivo ya que raramente nos interesa entrar en el detalle del código de una biblioteca de terceros o que esté muy probada (salvo quizá con objetivos didácticos), y haciendo que actúen como cajas negras lo evitaremos. Además es muy fácil de deshabilitar si lo necesitásemos en un momento determinado.&lt;/p&gt;

&lt;p&gt;Mi consejo sería que deshabilitases directamente la depuración de bibliotecas para producción (&lt;code&gt;.min.js&lt;/code&gt;) y quizá las que. aunque no estén minimizadas, estén ampliamente utilizadas y probadas por miles de desarrolladores (frameworks y cosas así). Ahorrarás tiempo y te despistarás menos, fijándote tan solo en la información que trasiega tu programa y las acciones que se gestionan con éste, considerando tan solo los efectos que producen las otras bibliotecas de terceros.&lt;/p&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Post original:&lt;/strong&gt; &lt;a href="https://www.jasoft.org/Blog/post/truco-depuracion-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos.aspx"&gt;https://www.jasoft.org/Blog/post/truco-depuracion-con-chrome-convertir-archivos-javascript-en-cajas-negras-para-evitar-depurarlos.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Java y JavaScript ¿son lo mismo?</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Wed, 13 Feb 2019 10:00:17 +0000</pubDate>
      <link>https://dev.to/campusmvp/java-y-javascript-son-lo-mismo-do6</link>
      <guid>https://dev.to/campusmvp/java-y-javascript-son-lo-mismo-do6</guid>
      <description>&lt;p&gt;Esta pregunta puede parecerle obvia a muchos, pero todavía hay cantidad de gente que no lo tiene claro...&lt;/p&gt;

&lt;p&gt;Dado que comparten una palabra al principio de su nombre, muchas personas piensan que &lt;a href="https://www.campusmvp.es/catalogo/Product-Desarrollo-de-aplicaciones-con-la-plataforma-Java_231.aspx"&gt;Java&lt;/a&gt; y &lt;a href="https://www.campusmvp.es/catalogo/Product-Programaci%C3%B3n-avanzada-con-JavaScript-y-ECMAScript_206.aspx"&gt;JavaScript&lt;/a&gt; están relacionados, o que JavaScript es un subconjunto de Java y cosas parecidas... Nada más lejos de la realidad.&lt;/p&gt;

&lt;p&gt;Java nació en el año 1991 en la empresa Sun Microsystems, de la mano de &lt;a href="https://en.wikipedia.org/wiki/James_Gosling"&gt;James Gosling&lt;/a&gt;. Su objetivo inicial era crear aplicaciones para receptores de televisión y dispositivos embebidos, aunque al final haya terminado funcionando en casi todas partes. Inicialmente iba a llamarse &lt;em&gt;Oak&lt;/em&gt;, y luego &lt;em&gt;Green&lt;/em&gt;, pero finalmente el nombre elegido es el que todos conocemos. La Wikipedia tiene información muy interesante &lt;a href="https://es.wikipedia.org/wiki/Java_(lenguaje_de_programaci%C3%B3n)"&gt;sobre su historia y su nombre&lt;/a&gt; que te recomiendo que te leas.&lt;/p&gt;

&lt;p&gt;JavaScript es un lenguaje de programación posterior, creado a mediados de los años '90 por &lt;a href="https://en.wikipedia.org/wiki/Brendan_Eich"&gt;Brendan Eich&lt;/a&gt;, de la empresa Netscape. Su objetivo era dotar de interactividad a las páginas web visualizadas con su navegador de Internet, Netscape Navigator, el líder del mercado por aquella época. Su nombre en código durante el desarrollo del lenguaje era &lt;em&gt;Mocha&lt;/em&gt;, y pensaban lanzarlo finalmente como &lt;em&gt;LiveScript&lt;/em&gt;, aunque al final se acabó denominando JavaScript por la gran influencia en su sintaxis por parte del lenguaje Java, aunque las similitudes son únicamente estéticas. En la actualidad, además de ser el lenguaje utilizado casi en exclusiva para añadir interactividad a las páginas Web, JavaScript se encuentra integrado en otras muchas aplicaciones además de los navegadores: servidores, lenguajes de programación de propósito específico como Node.js o sistemas operativos como Windows.&lt;/p&gt;

&lt;p&gt;Bien es cierto que la gente de Netscape intentó aprovechar el tirón de marketing que ofrecía Java en aquel momento, y usando la palabra "Java" en el nombre del nuevo lenguaje pretendían darle un halo de seriedad. Me imagino que, dada la confusión que generaron, se arrepintieron pronto de su decisión y de no haberle dejado el nombre de LiveScript.&lt;/p&gt;

&lt;p&gt;Aparte de esa raíz común en el nombre, Java y JavaScript son lenguajes totalmente diferentes. He aquí algunos ejemplos importantes de sus muchas diferencias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  JavaScript es un lenguaje interpretado, y Java es compilado. Para entendernos, y dicho muy básicamente, los programas JavaScript son archivos de texto que pueden leer tanto los ordenadores como las personas, mientras que los de Java se compilan a un archivo especial optimizado para que lo lea un ordenador y lo ejecute. Podríamos entrar en detalles de que Java se compila a un lenguaje intermedio llamado &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Bytecode"&gt;bytecode&lt;/a&gt;&lt;/em&gt; que es interpretado por un ejecutar JIT que facilita que sea multiplataforma, pero no es el objeto de este artículo y quiero mantenerlo intencionadamente simple.&lt;/li&gt;
&lt;li&gt;  Java se depura en dos fases y JavaScript en una. Como con todos los lenguajes interpretados, en JavaScript solamente sabes si has cometido inadvertidamente un error de sintaxis cuando vas a ejecutar el programa (salvo que uses herramientas especializadas como Visual Studio o WebStorm, que interpretan el código en segundo plano). En Java sin embargo, primero se realiza la fase de compilación, en la que el compilador ya indica los posibles errores de sintaxis que existan. Luego al ejecutar podrían surgir errores de lógica o de otra índole. En JavaScript todos ellos se depuran al mismo tiempo, haciéndolo más complicado.&lt;/li&gt;
&lt;li&gt;  Java es un lenguaje orientado a objetos puro, pero JavaScript está basado en prototipos. En realidad JavaScript debe simular muchas de las características de orientación a objetos que se dan en la mayoría de los lenguajes. A cambio proporciona diversos paradigmas de programación (funcional, imperativo, dinámico y orientado a objetos) lo que lo convierte en un lenguaje tremendamente versátil. De hecho en JavaScript es posible cambiar la "base" de la que hereda una clase en cualquier momento, afectando a todas, cosa imposible en la mayoría de los lenguajes orientados a objetos.&lt;/li&gt;
&lt;li&gt;  Java es fuertemente tipado, y JavaScript es débilmente tipado. En Java todas las variables tienen un tipo determinado y una vez definidas no se pueden cambiar. En JavaScript una misma variable puede contener primero un texto, luego un número, luego una fecha o un objeto, etc... Esto es un arma de doble filo pues permite una gran flexibilidad a cambio de muchos posibles errores si no tenemos cuidado.&lt;/li&gt;
&lt;li&gt;  Java tiene ámbito por bloque y JavaScript lo tiene por función: el acceso a las variables depende de dónde las hayamos definido. JavaScript tiene algunas reglas que pueden despistar bastante a los programadores de otros lenguajes.&lt;/li&gt;
&lt;li&gt;  JavaScript tiene clausuras, Java las acaba de incorporar. Uno de los conceptos más importantes en la programación con JavaScript (y en otros lenguajes) son las clausuras. Java no las tuvo hasta la versión 8 aparecida hace muy poco tiempo, que añadió también las &lt;a href="http://www.drdobbs.com/jvm/lambda-expressions-in-java-8/240166764"&gt;funciones lambda&lt;/a&gt;, para dar soporte al paradigma de &lt;a href="https://es.wikipedia.org/wiki/Programaci%C3%B3n_funcional"&gt;programación funcional&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Las funciones en JavaScript son multi-argumento siempre. En Java es necesario indicarlo.&lt;/li&gt;
&lt;li&gt;  JavaScript es estándar, Java no. El control del lenguaje JavaScript lo lleva la organización sin ánimo de lucro &lt;em&gt;European Computer Manufacturers Association&lt;/em&gt; (ECMA). De hecho su nombre oficial es ECMAScript, y &lt;a href="https://www.ecma-international.org/publications/standards/Ecma-262.htm"&gt;está estandarizado&lt;/a&gt;. Por el contrario el control sobre Java lo tiene Oracle, una empresa privada que decide a su antojo lo que se hace con él.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En resumen, y para dejar bien clara la diferencia sin palabras técnicas, desmiento a continuación algunos falsos mitos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; JavaScript NO es lo mismo que Java.&lt;/li&gt;
&lt;li&gt; JavaScript NO es un subconjunto de Java.&lt;/li&gt;
&lt;li&gt; JavaScript NO es una versión de Java para programar páginas web.&lt;/li&gt;
&lt;li&gt; JavaScript NO comparte prácticamente nada con Java. Si acaso la misma sintaxis que comparte con otros lenguajes como C, C++ o C#, y algún detalle más como algunos nombres de clases (&lt;em&gt;Math&lt;/em&gt; o &lt;em&gt;Date&lt;/em&gt;, por ejemplo), pero nada más.&lt;/li&gt;
&lt;li&gt; JavaScript NO es más fácil que Java. De hecho en algunas áreas concretas es más difícil de dominar.&lt;/li&gt;
&lt;li&gt; Si sabes programar en Java NO sabes programar en JavaScript. Y viceversa.&lt;/li&gt;
&lt;li&gt; JavaScript NO es solo un lenguaje para páginas web, al igual que Java no es un lenguaje solo para servidor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Espero que esto sirva para aclararlo de una vez por todas :-)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ABLiQ4SO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0ql7yohspute1wdy8efm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ABLiQ4SO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0ql7yohspute1wdy8efm.gif" alt="Meme: Java vs JavaScript"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original: &lt;a href="https://www.campusmvp.es/recursos/post/Comparando-valores-y-referencias-en-varios-lenguajes-de-programacion.aspx"&gt;https://www.campusmvp.es/recursos/post/Comparando-valores-y-referencias-en-varios-lenguajes-de-programacion.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>javascript</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Cómo cambiar los colores de la consola con Java y System.out.println</title>
      <dc:creator>José M. Alarcón 🌐</dc:creator>
      <pubDate>Wed, 13 Feb 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/cmo-cambiar-los-colores-de-la-consola-con-java-y-systemoutprintln-23l2</link>
      <guid>https://dev.to/campusmvp/cmo-cambiar-los-colores-de-la-consola-con-java-y-systemoutprintln-23l2</guid>
      <description>&lt;p&gt;Hoy toca un truco sencillo pero útil.&lt;/p&gt;

&lt;p&gt;Cuando programamos en &lt;strong&gt;Java&lt;/strong&gt; estamos acostumbrados a &lt;strong&gt;enviar mensajes por la consola&lt;/strong&gt; para informar a los usuarios de lo que va a ocurriendo. Para ello la manera por defecto de conseguirlo es mediante el &lt;strong&gt;uso del método &lt;code&gt;System.out.println&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Este método, en principio, no permite cambiar el color de lo que se emite por pantalla. Todo se ve con el color predeterminado que tengamos, generalmente blanco (o gris claro) sobre fondo negro, algo así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-x-defecto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-x-defecto.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sin embargo, cuando estamos creando una herramienta de línea de comandos nos puede resultar muy útil &lt;strong&gt;emplear otros colores para destacar cosas&lt;/strong&gt;. Por ejemplo, usar el color rojo cuando se produzca una excepción y queramos avisar de ello tras haberla controlado, o el verde para cuando se lleve a cabo una tarea con éxito.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : este tipo de usos del color para marcar significados &lt;strong&gt;no es accesible&lt;/strong&gt; y por tanto no son apropiados si queremos que los puedan usar usuarios con problemas de visión, como por ejemplo los daltónicos que no distinguen entre rojo y verde. Asegúrate de que además de los colores &lt;strong&gt;utilizas algo más en el propio texto&lt;/strong&gt; (mayúsculas, símbolos...) para indicar que se trata de un evento especial.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La buena noticia es que existen una serie de &lt;a href="https://es.wikipedia.org/wiki/C%C3%B3digo_escape_ANSI" rel="noopener noreferrer"&gt;códigos de escape ANSI&lt;/a&gt; que nos permiten controlar ciertos aspectos de la consola, entre ellos los colores utilizados.&lt;/p&gt;

&lt;p&gt;Si definimos las siguientes constantes en nuestro código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static final String ANSI\_BLACK = "\u001B[30m";
public static final String ANSI\_RED = "\u001B[31m";
public static final String ANSI\_GREEN = "\u001B[32m";
public static final String ANSI\_YELLOW = "\u001B[33m";
public static final String ANSI\_BLUE = "\u001B[34m";
public static final String ANSI\_PURPLE = "\u001B[35m";
public static final String ANSI\_CYAN = "\u001B[36m";
public static final String ANSI\_WHITE = "\u001B[37m";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podremos utilizarlas para controlar el color que queremos mostrar con &lt;code&gt;System.out.println&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Además podemos definir esta constante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static final String ANSI_RESET = "\u001B[0m";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;que nos permitirá dejarlo todo como estaba y volver a los colores por defecto.&lt;/p&gt;

&lt;p&gt;Así, podemos escribir lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.out.println(ANSI_RED + "Texto de color rojo" + ANSI_RESET);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y veremos el color rojo como esperábamos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-rojo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-rojo.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;dejando además la consola en su estado predeterminado, justo a continuación.&lt;/p&gt;

&lt;p&gt;Del mismo modo podemos definir una serie de constantes para establecer el color de fondo que queremos usar con el texto, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static final String ANSI_BLACK_BACKGROUND = "\u001B[40m";public static final String ANSI_RED_BACKGROUND = "\u001B[41m";public static final String ANSI_GREEN_BACKGROUND = "\u001B[42m";public static final String ANSI_YELLOW_BACKGROUND = "\u001B[43m";public static final String ANSI_BLUE_BACKGROUND = "\u001B[44m";public static final String ANSI_PURPLE_BACKGROUND = "\u001B[45m";public static final String ANSI_CYAN_BACKGROUND = "\u001B[46m";public static final String ANSI_WHITE_BACKGROUND = "\u001B[47m"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con ellas podemos establecer también el color de fondo y combinarlas con las anteriores para el color del texto, así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.out.println(ANSI_GREEN_BACKGROUND + ANSI_BLUE + "Texto de color azul sobre fondo verde");System.out.println("Como no lo he resetado sigue igual.");System.out.println("¡Reseteo ahora!" + ANSI_RESET);System.out.println("FIN");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;obteniendo esto por pantalla:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-fondo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.campusmvp.es%2Frecursos%2Fimage.axd%3Fpicture%3D%2F2019%2F1T%2Fjava-consola-color-fondo.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si te fijas, mientras no le mandes el código de control de "reset" no se vuelve a establecer el color por defecto, por lo que podrías ir enviando comandos no visibles para cambio de color sin necesidad de escribir nada, y usarlos simplemente para ir controlando el cambio de colores.&lt;/p&gt;

&lt;p&gt;Te dejo estos ejemplos (con las constantes, que es lo que te interesa) funcionando &lt;a href="https://repl.it/@jmalarcon/Colores-por-consola" rel="noopener noreferrer"&gt;dentro de este repl.it&lt;/a&gt;.  Pulsa sobre el botón verde del triángulo para ejecutarlo y ver los resultados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Una pega: no funciona en Windows... Por defecto.
&lt;/h2&gt;

&lt;p&gt;Esto que te acabo de enseñar funciona perfectamente en Mac y en Linux. Pero si lo intentas usar con Java en una consola de Windows verás que no te funciona.&lt;/p&gt;

&lt;p&gt;Por suerte existe una biblioteca Open Source llamada &lt;a href="https://github.com/fusesource/jansi" rel="noopener noreferrer"&gt;JANSI&lt;/a&gt; que utiliza la &lt;a href="https://es.wikipedia.org/wiki/Java_Native_Interface" rel="noopener noreferrer"&gt;Java Native Interface (JNI)&lt;/a&gt; para obtener los mismos resultados de manera coherente en todos los sistemas operativos, incluido Windows.&lt;/p&gt;

&lt;p&gt;Solo tienes que descargarla, agregarla a tu proyecto y usar sus métodos específicos en vez de las constantes anteriores. Te funcionará también en el sistema de las ventanas. Mira la documentación en Github y verás que es muy sencillo.&lt;/p&gt;

&lt;p&gt;¡Espero que te resulte útil!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Post original:&lt;/strong&gt; &lt;a href="https://www.campusmvp.es/recursos/post/como-cambiar-los-colores-de-la-consola-con-java-y-system-out-println.aspx" rel="noopener noreferrer"&gt;https://www.campusmvp.es/recursos/post/como-cambiar-los-colores-de-la-consola-con-java-y-system-out-println.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>trucos</category>
      <category>spanish</category>
    </item>
  </channel>
</rss>
