<?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: campusMVP</title>
    <description>The latest articles on DEV Community by campusMVP (@campusmvp).</description>
    <link>https://dev.to/campusmvp</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%2Forganization%2Fprofile_image%2F328%2F7ddf1f46-4630-42df-86dd-62f34db68311.png</url>
      <title>DEV Community: campusMVP</title>
      <link>https://dev.to/campusmvp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/campusmvp"/>
    <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: Los 5 mejores frameworks para desarrollo Web</title>
      <dc:creator>campusMVP</dc:creator>
      <pubDate>Mon, 23 Dec 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/java-los-5-mejores-frameworks-para-desarrollo-web-45fa</link>
      <guid>https://dev.to/campusmvp/java-los-5-mejores-frameworks-para-desarrollo-web-45fa</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post original en &lt;a href="https://www.campusmvp.es/recursos/post/java-los-5-mejores-frameworks-para-desarrollo-web.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt; es sin duda el lenguaje más demandado en el mercado laboral. Sirve para crear &lt;strong&gt;todo tipo de aplicaciones&lt;/strong&gt; : desde el móvil hasta el servidor, pasando por el escritorio o la Web. Y es esto último precisamente lo que nos ocupa hoy: el &lt;strong&gt;desarrollo Web&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Aunque Java ofrece de serie todo lo necesario para crear aplicaciones para Internet, no sería muy inteligente ceñirse tan solo a eso, al igual que no lo haríamos así con ninguna otra plataforma. Simplemente sería demasiado complejo. Así que para abstraernos de la necesidad de bajar mucho de nivel, existe &lt;strong&gt;una amplia oferta de &lt;em&gt;frameworks&lt;/em&gt; Java que nos ayudan con el desarrollo Web&lt;/strong&gt; , ofreciéndonos ya hechas muchas de las funcionalidades que necesitamos: desde acceso a bases de datos, gestión de sesiones, creación de servicios, servir contenidos estáticos, crear vistas.... y por supuesto reutilizar código, probarlo, etc...&lt;/p&gt;

&lt;p&gt;Para orientarte en el camino sobre qué aprender para desarrollar aplicaciones Web con Java hemos creado esta lista con &lt;strong&gt;los 5 frameworks más importantes&lt;/strong&gt; , los cuales son todos &lt;strong&gt;gratuitos y &lt;em&gt;Open Source&lt;/em&gt;&lt;/strong&gt; :&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://spring.io/"&gt;1.- Spring MVC&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B-7mLPNF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-spring.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B-7mLPNF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-spring.png" alt="Imagen ornamnetal - Logo de Sping"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El conocido &lt;em&gt;framework&lt;/em&gt; Spring es seguramente el más popular y utilizado del mundo. Se trata de un &lt;em&gt;framework&lt;/em&gt; de desarrollo de aplicaciones ligero para Java EE que en realidad se puede utilizar para todo tipo de aplicaciones, no sólo para la Web, pero que es especialmente útil para éstas. &lt;/p&gt;

&lt;p&gt;Nos ayuda a crear cualquiera de las capas de la aplicación, cosa en la que otros &lt;em&gt;frameworks&lt;/em&gt; son más limitados. Dispone de varios &lt;em&gt;sub-frameworks&lt;/em&gt; como:  &lt;strong&gt;Spring Core&lt;/strong&gt; , que dota de funcionalidad a todo lo demás;  &lt;strong&gt;SpringMVC&lt;/strong&gt; , para la parte que UI que se devuelve al navegador; &lt;strong&gt;Spring ORM&lt;/strong&gt; , para el acceso a datos; &lt;strong&gt;Spring Security&lt;/strong&gt; , para autenticación y autorización de las aplicaciones; etc...&lt;/p&gt;

&lt;p&gt;Aumenta la productividad, reduce los errores y hace que las aplicaciones sean más fáciles de mantener. Soporta la configuración de su comportamiento a partir de XML o mediante anotaciones en el código. Permite usar JDBC para el acceso a datos si lo preferimos. También facilita el &lt;em&gt;testing&lt;/em&gt; del código web. Ofrece una documentación muy buena.&lt;/p&gt;

&lt;p&gt;Lo utiliza... prácticamente todo el mundo, pero hay muchas empresas conocidas que desarrollan con Spring: &lt;strong&gt;Netflix&lt;/strong&gt; , &lt;strong&gt;Amazon&lt;/strong&gt; o &lt;strong&gt;eBay&lt;/strong&gt; por poner algunos ejemplos.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://hibernate.org/"&gt;2.- Hibernate&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OeUwyTmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-hibernate.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OeUwyTmp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-hibernate.png" alt="Imagen ornamental - Logo de Hibernate"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vale, esto no es específico para desarrollo Web, sino para cualquier desarrollo con Java que utilice acceso a datos. Pero es el &lt;em&gt;framework&lt;/em&gt; de datos más utilizado del mundo y en cualquier desarrollo web lo vas a acabar utilizando.&lt;/p&gt;

&lt;p&gt;Hibernate es &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/post/que-es-un-orm.aspx"&gt;un ORM&lt;/a&gt;&lt;/strong&gt; que nos permite crear la capa de acceso a datos de nuestra aplicación utilizando objetos en lugar de consultas, disminuyendo la fricción entre el mundo de las bases de datos relacionales y la Programación Orientada a Objetos. Vamos, como cualquier ORM. La diferencia con otros es que Hibernate es con diferencia el más utilizado y ello significa que hay mucho más soporte y comunidad que para cualquier otro y te resultará más fácil resolver cualquier problema y obtener nuevas funcionalidades.&lt;/p&gt;

&lt;p&gt;Su mayor desventaja es seguramente su tamaño y que puede resultar complejo a veces. Pero es algo que, si programas en Java hay que conocer sí o sí.&lt;/p&gt;

&lt;p&gt;Al igual que en el caso de Spring, Hibernate lo usa casi todo el mundo para desarrollar en Java: la propia &lt;strong&gt;Oracle&lt;/strong&gt; , &lt;strong&gt;IBM&lt;/strong&gt; , &lt;strong&gt;Accenture&lt;/strong&gt;...&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://struts.apache.org/"&gt;3.- Struts&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oItaVxgD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-struts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oItaVxgD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-struts.png" alt="Imagen ornamental, logo de Struts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Otro &lt;em&gt;framework&lt;/em&gt; de desarrollo para Java lleno de características, mantenido en este caso por la &lt;strong&gt;Fundación Apache&lt;/strong&gt;. Es bastante antiguo pero por el mismo motivo está muy probado y lo utiliza mucha gente, y sacan versiones constantemente. Es comparable en muchos sentidos con Spring, que mencionamos antes. Está basado en &lt;a href="https://dev.to/campusmvp_es/que-es-el-patron-mvc-en-programacion-y-por-que-es-util-2c2e-temp-slug-4666309"&gt;el patrón MVC&lt;/a&gt; y su enfoque es en crear aplicaciones de nivel empresarial de manera rápida y que sean fáciles de mantener.&lt;/p&gt;

&lt;p&gt;Dispone de una arquitectura basada en &lt;em&gt;plugins&lt;/em&gt; que permiten extenderlo fácilmente con cualquier funcionalidad que requieras y no tenga de serie. Trae muchos plugins de serie para hacer de todo (procesar JSON, crear servicios REST...) y existen muchos más creados por la comunidad.&lt;/p&gt;

&lt;p&gt;Lo puedes combinar con otros &lt;em&gt;frameworks&lt;/em&gt; para conseguir funcionalidad que no tenga. Por ejemplo, puedes usar inyección de dependencias a través de Spring, o Hibernate para el acceso a datos.&lt;/p&gt;

&lt;p&gt;Su mayor pega quizá sea que es más complejo que otros y que te fuerza a seguir un determinado estilo de programación y ciertas reglas (lo cual, en muchas empresas es una ventaja).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="http://www.javaserverfaces.org/"&gt;4.- JavaServer Faces (JSF)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r1W3d-HS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-jsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r1W3d-HS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-jsf.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaServer Faces es en realidad &lt;a href="https://javaee.github.io/javaserverfaces-spec/"&gt;una especificación&lt;/a&gt; "estándar" para la creación de interfaces de usuario para aplicaciones Web, aunque se puede usar también para crear aplicaciones nativas. La creó la propia Oracle y su primera versión data del año 2004, así que es algo muy estable y probado también. Al igual que otros, utiliza el patrón MVC, y está basado en componentes. El objetivo es que puedas construir componentes de interfaz de usuario que sean reutilizables, pudiendo gestionar su estado, conectarlos a orígenes de datos y atarlos a eventos para realizar acciones.&lt;/p&gt;

&lt;p&gt;Tiene un sistema de plantillas para crear los componentes que se llama Facelets y que utilizan XML en lugar de Java para definirlas, aunque puedes usar otros métodos para lo mismo sin salirte de JSF (usando Java directamente si quieres).&lt;/p&gt;

&lt;p&gt;Es bastante complejo y no es el más rápido, pero tiene dos ventajas fundamentales: está &lt;strong&gt;incluido con Java EE&lt;/strong&gt; (y &lt;a href="https://www.campusmvp.es/recursos/post/Los-mejores-entornos-de-desarrollo-para-Java.aspx"&gt;los principales IDEs&lt;/a&gt; dan soporte de serie para usarlo) y la &lt;strong&gt;documentación es muy buena&lt;/strong&gt;  ya que está creada y mantenida por Oracle.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://grails.org/"&gt;5.- Grails&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uk-GrJSF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-grails.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uk-GrJSF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/4T/java-frameworks-grails.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grails&lt;/strong&gt; es un &lt;em&gt;framework&lt;/em&gt; de desarrollo Web que utiliza &lt;strong&gt;&lt;a href="http://groovy-lang.org/"&gt;el lenguaje Groovy&lt;/a&gt;&lt;/strong&gt; para la plataforma Java. Groovy es un lenguaje orientado a objetos que compila a Bytecode y que está enfocado a fondo en la productividad del desarrollador. Por ese motivo, Grails lo que te da es una productividad altísima y te permite estar produciendo código para tu aplicación de manera casi inmediata (en 1 hora puedes tener tu primera aplicación probada y en marcha).&lt;/p&gt;

&lt;p&gt;Aunque programas con Groovy y no con Java directamente, la sintaxis es compatible con Java y además funciona de maravilla con otras tecnologías Java como Hibernate o incluso Spring. De hecho está basado en Spring Boot, por lo que incluye características como la inyección de dependencias. Sigue buenas prácticas y principios de desarrollo modernos como convención sobre configuración.&lt;/p&gt;

&lt;p&gt;Escala bien y te servirá tanto para proyectos pequeños como muy grandes. El soporte de los diferentes IDEs es muy bueno. Tiene centenares de &lt;em&gt;plugins&lt;/em&gt; para hacer casi cualquier cosa que se te ocurra.&lt;/p&gt;

&lt;p&gt;La &lt;a href="http://grails.org/documentation.html"&gt;documentación de Grails&lt;/a&gt; es muy buena, y tiene también unas &lt;a href="https://guides.grails.org/index.html"&gt;guías paso a paso de Grails&lt;/a&gt; muy buenas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original en &lt;a href="https://www.campusmvp.es/recursos/post/java-los-5-mejores-frameworks-para-desarrollo-web.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</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>Paquetes en Java: qué son, para qué se utilizan, y cómo se usan (con vídeo)</title>
      <dc:creator>campusMVP</dc:creator>
      <pubDate>Wed, 14 Aug 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/paquetes-en-java-que-son-para-que-se-utilizan-y-como-se-usan-con-video-11e5</link>
      <guid>https://dev.to/campusmvp/paquetes-en-java-que-son-para-que-se-utilizan-y-como-se-usan-con-video-11e5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post original escrito por Franciso Charte en &lt;a href="https://www.campusmvp.es/recursos/post/paquetes-en-java-que-son-para-que-se-utilizan-y-como-se-usan.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Los paquetes son el mecanismo que usa Java &lt;strong&gt;para facilitar la modularidad del código&lt;/strong&gt;. Un paquete puede contener una o más definiciones de interfaces y clases, distribuyéndose habitualmente como un archivo. Para utilizar los elementos de un paquete es necesario importar este en el módulo de código en curso, usando para ello la sentencia &lt;code&gt;import&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La funcionalidad de una aplicación Java se implementa habitualmente en múltiples clases, entre las que suelen existir distintas relaciones. &lt;strong&gt;Las clases se agrupan en unidades de un nivel superior, los paquetes&lt;/strong&gt; , que actúan como &lt;strong&gt;ámbitos de contención de tipos&lt;/strong&gt;. Cada módulo de código establece, mediante la palabra clave &lt;code&gt;package&lt;/code&gt; al inicio, a qué paquete pertenece. Como ya sabrás, con la &lt;strong&gt;cláusula &lt;code&gt;import&lt;/code&gt;&lt;/strong&gt; cualquier módulo de código puede hacer referencia a tipos definidos en otros paquetes.&lt;/p&gt;

&lt;p&gt;Vamos a familiarizarnos con los procedimientos para construir paquetes, para referenciarlos desde otros puntos y también veremos la &lt;strong&gt;relación existente entre paquetes, clases y el sistema de archivos&lt;/strong&gt; donde se almacena el proyecto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creación de paquetes
&lt;/h2&gt;

&lt;p&gt;Un paquete Java se genera sencillamente incluyendo la palabra clave &lt;code&gt;package&lt;/code&gt; al inicio de los módulos de código en los que se definen las clases que formarán parte del mismo. Trabajando en un proyecto con &lt;a href="https://www.campusmvp.es/recursos/post/Los-mejores-entornos-de-desarrollo-para-Java.aspx"&gt;NetBeans&lt;/a&gt;, comprobaremos que en la ventana &lt;code&gt;Projects&lt;/code&gt; los paquetes se representan con un icono específico y actúan como nodos contenedores, alojando los módulos &lt;code&gt;.java&lt;/code&gt; con el código fuente. El menú contextual del proyecto nos ofrece la opción &lt;code&gt;New&amp;gt;Java Package&lt;/code&gt;, que será el que usemos habitualmente para crear un nuevo paquete:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Juqagt_o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/NewPackage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Juqagt_o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/NewPackage.png" alt="Creación de un nuevo paquete en Netbeans"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : cada vez que se crea un nuevo proyecto con NetBeans se propone la definición de un nuevo paquete, cuyo nombre sería el mismo del proyecto, donde se alojarían los módulos de código. En proyectos complejos, no obstante, puede ser necesaria la &lt;strong&gt;creación de paquetes adicionales&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Un paquete puede contener, además de definiciones de tipos como las clases e interfaces, otros paquetes, &lt;strong&gt;dando lugar a estructuras jerárquicas de contenedores&lt;/strong&gt;. La denominación de los &lt;strong&gt;subpaquetes, paquetes contenidos en otros&lt;/strong&gt; , se compondrán del identificador del contenedor seguido de un punto y el nombre del subpaquete. De existir niveles adicionales se agregarían los distintos identificadores separados por puntos, formando así el nombre completo del paquete.&lt;/p&gt;

&lt;p&gt;El diagrama siguiente representa el contenido de un paquete llamado &lt;code&gt;campusmvp&lt;/code&gt;, teóricamente correspondiente a un proyecto de aplicación de contabilidad. En ese paquete de primer nivel tenemos un subpaquete con utilidades, llamado &lt;code&gt;campusmvp.util&lt;/code&gt;, no directamente vinculadas con la aplicación de contabilidad. El subpaquete &lt;code&gt;campusmvp.conta&lt;/code&gt; contendría todos los elementos asociados a dicha aplicación, distribuidos a su vez en un tercer nivel de paquetes que contienen las clases correspondientes al modelo, la vista, etc., siguiendo al &lt;strong&gt;&lt;a href="https://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador"&gt;patrón arquitectónico MVC&lt;/a&gt;&lt;/strong&gt;. Cada uno de los módulos de definición de clase, denominados &lt;code&gt;Cuenta.java&lt;/code&gt;, &lt;code&gt;Movimiento.java&lt;/code&gt;, &lt;code&gt;Vista.java&lt;/code&gt;, etc., comenzarían con una cláusula &lt;code&gt;package&lt;/code&gt; indicando &lt;strong&gt;el nombre completo del paquete al que pertenecen&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cz2GQl05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/NestedPackages.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cz2GQl05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/NestedPackages.png" alt="Estructura jerárquica de paquetes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : todas las clases que pertenecen a un mismo paquete comparten un ámbito común, al que pertenecerán aquellos miembros que no especifiquen explícitamente otro tipo de visibilidad.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Importación de paquetes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Los paquetes Java son como cajas de herramientas&lt;/strong&gt; , cada una de ellas con una colección distinta de instrumentos útiles para nuestro trabajo, a las que podemos necesitar acceder cada vez que abordamos el desarrollo de un nuevo proyecto. Es en este contexto donde recurriremos a la cláusula &lt;strong&gt;&lt;code&gt;import&lt;/code&gt;&lt;/strong&gt; , a fin de &lt;strong&gt;importar en el ámbito actual las definiciones de otro paquete y poder usarlas&lt;/strong&gt; según el procedimiento habitual, creando objetos, accediendo a los servicios de las clases, etc.&lt;/p&gt;

&lt;p&gt;La cláusula &lt;code&gt;import&lt;/code&gt; puede utilizarse para importar un elemento concreto de un paquete, facilitando el nombre de este seguido de un punto y el identificador de dicho elemento. Por ejemplo, para importar la clase &lt;code&gt;Math&lt;/code&gt; del paquete &lt;code&gt;java.lang&lt;/code&gt;, pudiendo así acceder a la constante &lt;code&gt;PI&lt;/code&gt; y las funciones matemáticas que aporta, bastaría con la siguiente línea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.lang.Math;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Es habitual que al importar un paquete nos interesen muchas de las clases definidas en el mismo. En este caso podríamos importarlas individualmente, usando la sintaxis anterior, o bien podríamos recurrir a la siguiente alternativa. Esto nos permitiría usar la clase &lt;code&gt;Math&lt;/code&gt;, así como la clase &lt;code&gt;System&lt;/code&gt;, la clase &lt;code&gt;Thread&lt;/code&gt; y muchas otras definidas en el paquete &lt;code&gt;java.lang&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.lang.\*;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;En ocasiones, como ocurre con la clase &lt;code&gt;Math&lt;/code&gt;, &lt;strong&gt;importamos una clase para acceder directamente a sus miembros estáticos, constantes y métodos&lt;/strong&gt; , no para crear objetos a partir de ellas, lo que nos fuerza a utilizar constantemente la sintaxis &lt;code&gt;Clase.miembro&lt;/code&gt;, por ejemplo &lt;code&gt;Math.PI&lt;/code&gt; o &lt;code&gt;Math.sin()&lt;/code&gt;. Si tras importar la clase &lt;code&gt;Math&lt;/code&gt; intentamos referirnos a estos miembros simplemente por su nombre, como se hace en la mitad superior de la siguiente imagen, obtendremos un error. En estos casos podemos recurrir a la sintaxis &lt;strong&gt;&lt;code&gt;import static paquete.clase.*&lt;/code&gt;&lt;/strong&gt; , cuya finalidad es &lt;strong&gt;incluir en el ámbito actual los miembros estáticos de la clase indicada&lt;/strong&gt;. Es lo que se hace en la mitad inferior de la siguiente imagen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4wsBeVSr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/ImportStatic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4wsBeVSr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/ImportStatic.png" alt="Importación de paquetes" title="Distintas alternativas para hacer referencia al contenido de paquetes Java"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Relación entre clases, paquetes y el sistema de archivos
&lt;/h2&gt;

&lt;p&gt;En Java existe una estrecha relación entre &lt;strong&gt;las definiciones de paquetes y clases y el sistema de archivos local&lt;/strong&gt; , en el que se almacenan los módulos conteniendo el código. Es un hecho que puede pasarnos totalmente inadvertido al trabajar con un IDE como el de NetBeans, ya que sus opciones se encargan de ocultar estos detalles. No obstante, &lt;strong&gt;es interesante que conozcamos dicha relación&lt;/strong&gt; ya que esto nos permitirá, en caso de necesidad, trabajar directamente con el JDK.&lt;/p&gt;

&lt;p&gt;Cada módulo de código de un proyecto Java únicamente puede contener una clase pública, cuyo nombre, respetando mayúsculas y minúsculas, debe coincidir con el del módulo. Es decir, existe una &lt;strong&gt;correspondencia directa entre los identificadores de clase y archivos en los que se alojan&lt;/strong&gt;. Esto no afecta a las clases anidadas y otras clases no públicas que pudiesen definirse en el mismo módulo.&lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;nombre del paquete establece además el nombre de la carpeta donde se alojan los módulos de código&lt;/strong&gt; contenidos en el paquete. Los nombres de paquete pueden ser compuestos, usándose el punto como separador de las diferentes porciones del identificador. Cada parte identificaría a un subdirectorio, según se muestra en el siguiente esquema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KEQJ8pDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/FilesystemScheme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KEQJ8pDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/FilesystemScheme.png" alt="Esquema sistema de archivos" title="Esquema de la correspondencia entre el sistema de archivos y la definición de paquetes y clases"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al trabajar desde la línea de comandos, usando directamente el JDK, hemos de tener en cuenta que tanto la compilación como la ejecución verificarán que se &lt;strong&gt;satisface la correspondencia entre el nombre de paquete y clase y la estructura de directorios y nombre de archivo&lt;/strong&gt;. Si esta no se cumple en algún punto, como ocurre en la parte inferior de la siguiente imagen, se obtiene un error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7TgwSxcJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/PackageFilesystem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7TgwSxcJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/3T/PackageFilesystem.png" alt="Relación entre paquete y sistema de archivos" title="La clase Cuenta pertenece al paquete com.campusmvp.contabilidad, denominación que condiciona la jerarquía de carpetas en el sistema de archivos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : la estructura de directorios de un paquete puede almacenarse completa, una vez se compila el proyecto, en un archivo JAR. Este contendría asimismo los archivos de clase de cada módulo de código.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A continuación puedes ver un &lt;strong&gt;vídeo práctico explicativo&lt;/strong&gt; de todo lo anterior, que está extraído directamente del &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Desarrollo-de-aplicaciones-con-la-plataforma-Java_231.aspx"&gt;curso de programación con Java&lt;/a&gt;&lt;/strong&gt; de campusMVP:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/x4BDc-VGeZY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original escrito por Franciso Charte en &lt;a href="https://www.campusmvp.es/recursos/post/paquetes-en-java-que-son-para-que-se-utilizan-y-como-se-usan.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</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>5 motivos por los que utilizar Java para desarrollar tus aplicaciones</title>
      <dc:creator>campusMVP</dc:creator>
      <pubDate>Wed, 10 Apr 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones-2k32</link>
      <guid>https://dev.to/campusmvp/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones-2k32</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post original: &lt;a href="https://www.campusmvp.es/recursos/post/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones.aspx"&gt;https://www.campusmvp.es/recursos/post/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Java es una &lt;a href="https://www.campusmvp.es/recursos/post/Descifrando-Java-lenguaje-plataforma-ediciones-implementaciones.aspx"&gt;plataforma de desarrollo&lt;/a&gt; de propósito general cuya principal oferta de valor siempre ha sido "Escribe una vez, ejecuta en todas partes". En la actualidad es prácticamente ubicua: puedes encontrar aplicaciones Java desde pequeños dispositivos conectados del "Internet de las Cosas" (IoT), hasta servidores, pasando por aplicaciones de gestión en escritorio, desarrollos para móviles, videojuegos...&lt;/p&gt;

&lt;p&gt;Existen diversos motivos, técnicos y no técnicos, para la popularidad de Java, pero &lt;strong&gt;¿cuáles son las principales propuestas de valor TÉCNICAS para desarrollar con Java?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seguro que hay muchas más, y desde luego las siguientes no son exclusivas de Java en su mayor parte, pero la combinación de todas ellas, por lo que nos cuentan &lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Desarrollo-de-aplicaciones-con-la-plataforma-Java_231.aspx"&gt;nuestros alumnos de Java&lt;/a&gt;, es lo que suelen valorar las empresas:&lt;/p&gt;

&lt;h2&gt;
  
  
  1.- Es multiplataforma
&lt;/h2&gt;

&lt;p&gt;Aunque en la actualidad no es una ventaja tan grande como lo era cuando nació y hay muchas otras plataformas que ofrecen multiplataforma, lo cierto es que el hecho de que Java funcione en prácticamente cualquier dispositivo, servidor o sistema operativo, sigue siendo uno de sus principales atractivos para mucha gente.&lt;/p&gt;

&lt;p&gt;Existe una implementación de la &lt;a href="https://www.campusmvp.es/recursos/post/que-es-la-maquina-virtual-de-java-o-java-virtual-machine.aspx"&gt;máquina virtual de Java&lt;/a&gt; para casi cualquier sistema que se nos ocurra.&lt;/p&gt;

&lt;p&gt;Además no debemos olvidar que Java se diseñó inicialmente para ejecutarse en dispositivos embebidos, con muchas limitaciones de memoria y potencia, por lo que, dependiendo de dónde lo ejecutemos, puede resultar de gran ayuda apoyarse en el lenguaje.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.- El código Java es robusto
&lt;/h2&gt;

&lt;p&gt;Hay otros lenguajes como C++ que ofrecen más rendimiento y mayor control, pero que son mucho más difíciles de manejar sin meter la pata. Java es un lenguaje que ofrece manejo automático de la memoria y cuyos objetos no hacen referencia a datos fuera de sí mismos o de otros objetos de Java. Esto hace imposible que una instrucción de Java pueda corromper la memoria, ni "pisar" o comprometer los datos de otras aplicaciones o del propio sistema operativo. La máquina virtual realiza todo tipo de comprobaciones para asegurar la integridad que impiden que pueda romper el sistema operativo u otros programas.&lt;/p&gt;

&lt;p&gt;También &lt;a href="https://www.campusmvp.es/recursos/post/Modelos-de-gestion-de-memoria-II-Garbage-collector.aspx"&gt;gestiona la liberación de memoria&lt;/a&gt; de manera automática, por lo que la usa eficientemente sin que el programador tenga que preocuparse de nada.&lt;/p&gt;

&lt;p&gt;Nuevamente, esto no es exclusivo de Java, ya que otras plataformas, como .NET, disponen de las mismas protecciones, pero es una ventaja frente a plataformas más tradicionales.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.- Es orientada a objetos
&lt;/h2&gt;

&lt;p&gt;Otra cuestión que no llama la atención por especial en la actualidad, pero a mediados de los años 90, cuando se lanzó Java, no era algo tan frecuente como lo es ahora. Gracias a su orientación a objetos es más fácil crear aplicaciones modulares y reutilizar partes de las mismas, además de que permite implementar mejores patrones de diseño probados que contribuyen a la robustez que se comentaba en el apartado anterior.&lt;/p&gt;

&lt;p&gt;También es uno de los motivos de que la propia plataforma sea tan extensible y disponga de tantas funcionalidades nativas o añadidas.&lt;/p&gt;

&lt;p&gt;Lo cual nos lleva a...&lt;/p&gt;

&lt;h2&gt;
  
  
  4.- Funcionalidad de base y mucho código Open Source
&lt;/h2&gt;

&lt;p&gt;Aparte de la enorme cantidad de funcionalidad base que ya incluye la propia plataforma listo para ser utilizado, con Java dispones de muchísimo código de terceros listo para ser utilizado.&lt;/p&gt;

&lt;p&gt;Entre que lleva bastante más de dos décadas entre nosotros y que la comunidad es enorme, existen infinidad de bibliotecas y utilidades creadas para extender la funcionalidad y mejorar la plataforma Java.&lt;/p&gt;

&lt;p&gt;Casi cualquier cosa que puedas necesitar seguro que la encuentras ya creada en algún proyecto de código abierto. No solo eso: mucha de las bibliotecas más conocidas y utilizadas las han creado y las mantienen grandes organizaciones como Google, Facebook o la fundación Apache, lo cual siempre es una garantía adicional.&lt;/p&gt;

&lt;p&gt;Esto facilita mucho la vida de los programadores y no existen muchas otras plataformas que puedan aportar la misma exuberante variedad de código utilizable.&lt;/p&gt;

&lt;h2&gt;
  
  
  5.- Java es relativamente fácil de aprender
&lt;/h2&gt;

&lt;p&gt;Comparado con lenguajes clásicos como C o C++, desde luego. En general se puede decir que Java no es un lenguaje más difícil de aprender que cualquier otro, especialmente otros modernos como C# o Swift, pero sí que es más fácil de aprender que muchos otros.&lt;/p&gt;

&lt;p&gt;Gracias a &lt;a href="https://www.campusmvp.es/recursos/post/Los-mejores-entornos-de-desarrollo-para-Java.aspx"&gt;herramientas especializadas&lt;/a&gt; (¡y gratuitas!) como NetBeans y otros editores o entornos de desarrollo, la compilación, depuración y despliegue es muy sencillo y comenzar con él muy fácil.&lt;/p&gt;

&lt;p&gt;Como cualquier plataforma compleja y de propósito general como esta, tienes dos retos al aprenderla:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hay tanta funcionalidad que es difícil saber por dónde empezar y cuáles de las, literalmente, miles de clases disponibles debes aprender.&lt;/li&gt;
&lt;li&gt;A medida que aprendes y profundizas la cosa se vuelve más compleja y necesitas dominar mejor los fundamentos para poder salir adelante.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3iHwZk4g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/1T/java-ventajas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3iHwZk4g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.campusmvp.es/recursos/image.axd%3Fpicture%3D/2019/1T/java-ventajas.png" alt="Imagen ornamental"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ninguna de estas ventajas es exclusiva de Java y se puede aplicar a otras plataformas, especialmente a .NET y el lenguaje C#. Sin embargo, la combinación de lo que hemos dicho con el hecho de llevar tanto tiempo en el mercado, la enorme comunidad de desarrolladores que hay por todo el mundo y la gran demanda existente en empresas e instituciones, crea un "círculo virtuoso" que hace que Java sea desde hace muchos años la plataforma de desarrollo más importante.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original: &lt;a href="https://www.campusmvp.es/recursos/post/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones.aspx"&gt;https://www.campusmvp.es/recursos/post/5-motivos-por-los-que-utilizar-java-para-desarrollar-tus-aplicaciones.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>spanish</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>Contenedores: cómo es el ciclo de vida de una aplicación en Kubernetes</title>
      <dc:creator>campusMVP</dc:creator>
      <pubDate>Thu, 21 Mar 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/contenedores-como-es-el-ciclo-de-vida-de-una-aplicacion-en-kubernetes-1ief</link>
      <guid>https://dev.to/campusmvp/contenedores-como-es-el-ciclo-de-vida-de-una-aplicacion-en-kubernetes-1ief</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post original escrito por &lt;strong&gt;Eduard Tomás&lt;/strong&gt; en &lt;a href="https://www.campusmvp.es/recursos/post/contenedores-como-es-el-ciclo-de-vida-de-una-aplicacion-en-kubernetes.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hace poco os explicaba en un artículo &lt;strong&gt;&lt;a href="https://dev.to/campusmvp/qu-es-kubernetes-y-cmo-funciona-mbd-temp-slug-5971176"&gt;qué es Kubernetes, cuál es su arquitectura y su funcionamiento básico&lt;/a&gt;&lt;/strong&gt;. Léelo antes de continuar si no tienes claros estos conceptos.&lt;/p&gt;

&lt;p&gt;En esta ocasión voy a continuar con aquella explicación analizando cómo es el ciclo de vida de una aplicación que está desplegada con Kubernetes.&lt;/p&gt;

&lt;p&gt;Lo primero que debemos tener claro es que &lt;strong&gt;en Kubernetes nunca se ejecutan contenedores de forma directa&lt;/strong&gt;. Es decir, no se puede desplegar un contenedor o parar un contenedor. En su lugar se opera con lo que se llaman &lt;strong&gt;&lt;em&gt;pods&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Un &lt;em&gt;pod&lt;/em&gt; es la unidad mínima de despliegue y operación en Kubernetes&lt;/strong&gt;. Es decir, desplegamos &lt;em&gt;pods&lt;/em&gt;, escalamos &lt;em&gt;pods&lt;/em&gt; y son los &lt;em&gt;pods&lt;/em&gt; los que se ejecutan en los distintos nodos.&lt;/p&gt;

&lt;p&gt;La relación entre &lt;em&gt;pod&lt;/em&gt; y contenedor no tiene por qué ser de uno a uno: es decir,  &lt;strong&gt;en un único &lt;em&gt;pod&lt;/em&gt; se pueden ejecutar varios contenedores&lt;/strong&gt;. Solo recuerda que en este caso se escalarán y desplegarán de forma conjunta (ya que se escala o despliega todo el &lt;em&gt;pod&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Aunque es posible, teóricamente, desplegar en un &lt;em&gt;pod&lt;/em&gt; una web y su API en dos contenedores, eso no es lo que suele hacer. En la gran mayoría de casos las relaciones entre &lt;em&gt;pod&lt;/em&gt; y contenedor son, efectivamente, de uno a uno. Pero que un &lt;em&gt;pod&lt;/em&gt; pueda ejecutar varios contenedores habilita ciertos escenarios avanzados como p. ej. tener un contenedor que ofrezca servicios a otro contenedor (como podría ser hacer de &lt;em&gt;proxy&lt;/em&gt;, de &lt;em&gt;logger&lt;/em&gt; o similar).&lt;/p&gt;

&lt;p&gt;Es importante tener presente que &lt;strong&gt;todos los contenedores que se ejecutan en un mismo &lt;em&gt;pod&lt;/em&gt; comparten espacio de red&lt;/strong&gt;. Es decir, se comunican entre ellos usando &lt;em&gt;localhost&lt;/em&gt; y no pueden abrir los mismos puertos. También comparten el espacio &lt;a href="https://es.wikipedia.org/wiki/Comunicaci%C3%B3n_entre_procesos"&gt;IPC&lt;/a&gt; por lo que pueden usar cualquier técnica de IPC (como semáforos) para comunicarse entre ellos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los distintos estados de un &lt;em&gt;pod&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Un &lt;em&gt;pod&lt;/em&gt; pasa por varias fases a lo largo de su ciclo de vida:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Pending&lt;/em&gt;&lt;/strong&gt; : el &lt;em&gt;pod&lt;/em&gt; ha sido creado, pero aún no se han creado sus contenedores ni se ha decidido qué nodo lo va a ejecutar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Running&lt;/em&gt;&lt;/strong&gt; : los contenedores del &lt;em&gt;pod&lt;/em&gt; han sido creados y el &lt;em&gt;pod&lt;/em&gt; ya se está ejecutando en un nodo. Al menos un contenedor del &lt;em&gt;pod&lt;/em&gt; se está ejecutando o está en proceso de creación.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Esto es importante&lt;/strong&gt; : que un &lt;em&gt;pod&lt;/em&gt; esté en estado &lt;em&gt;running&lt;/em&gt; no significa que sus contenedores estén ejecutándose. P. ej. se pueden estar iniciando o reiniciando.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Succeeded&lt;/em&gt;&lt;/strong&gt; : los contenedores del &lt;em&gt;pod&lt;/em&gt; han finalizado (todos) su ejecución de forma satisfactoria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Failed&lt;/em&gt;&lt;/strong&gt; : los contenedores del &lt;em&gt;pod&lt;/em&gt; han finalizado (todos) su ejecución y al menos uno de ellos lo ha hecho con error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Unknown&lt;/em&gt;&lt;/strong&gt; : el estado del &lt;em&gt;pod&lt;/em&gt; no se puede saber. Esto suele indicar un error de comunicación con el nodo &lt;em&gt;minion&lt;/em&gt; que está ejecutando el &lt;em&gt;pod&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;CrashLoopBackOff&lt;/em&gt;&lt;/strong&gt; : el &lt;em&gt;pod&lt;/em&gt; está corriendo, pero uno de sus contenedores se está reiniciando debido a que ha terminado (generalmente de forma errónea).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es importante &lt;strong&gt;separar el ciclo de vida del &lt;em&gt;pod&lt;/em&gt; del ciclo de vida de sus contenedores&lt;/strong&gt;. Un &lt;em&gt;pod&lt;/em&gt; puede estar en la fase de &lt;em&gt;running&lt;/em&gt; pero uno de sus contenedores puede no estar ejecutándose. Cuando un &lt;em&gt;pod _está en fase de _CrashLoopBackOff&lt;/em&gt; eso significa que uno de los contenedores está en proceso de reinicio, pero otros contenedores del &lt;em&gt;pod&lt;/em&gt; pueden estar ejecutándose.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Muchas veces se dice que Kubernetes reinicia un &lt;em&gt;pod&lt;/em&gt; pero esa expresión no es estrictamente cierta: Kubernetes reinicia contenedores de un &lt;em&gt;pod&lt;/em&gt;, pero el &lt;em&gt;pod&lt;/em&gt; en sí mismo sigue ejecutándose durante todo este tiempo. Que Kubernetes decida reiniciar o no los contenedores de un &lt;em&gt;pod&lt;/em&gt; (y en qué casos) depende de la configuración del &lt;em&gt;pod&lt;/em&gt;. Es decir, para ciertos &lt;em&gt;pods&lt;/em&gt; no hay posibilidad de que entren nunca en fase de &lt;em&gt;Succeeded&lt;/em&gt; ya que su misión es estar ejecutándose permanentemente (p. ej. una API), por lo que si un contenedor termina será reiniciado por Kubernetes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Los &lt;em&gt;pods&lt;/em&gt; se consideran "objetos transitorios", en el sentido de que hay determinados eventos del clúster a los cuales no sobreviven. P. ej. si el nodo &lt;em&gt;minion&lt;/em&gt; se cae, todos los &lt;em&gt;pods&lt;/em&gt; que se estén ejecutándose en él se caen también. &lt;strong&gt;Los &lt;em&gt;pods&lt;/em&gt; no se mueven de nodo ni se reinician&lt;/strong&gt; (sí se reinician sus contenedores como se ha comentado antes).&lt;/p&gt;

&lt;p&gt;En general &lt;strong&gt;no se suele crear nunca &lt;em&gt;pods&lt;/em&gt; de forma directa&lt;/strong&gt; , en su lugar usamos lo que llamamos un &lt;strong&gt;controlador&lt;/strong&gt;. Un controlador es el responsable de garantizar que en todo momento se cumple una cierta condición al respecto de los &lt;em&gt;pods&lt;/em&gt; que controla, como que en todo momento haya N instancias de este &lt;em&gt;pod&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hago aquí un inciso de nomenclatura: cuando digo "N instancias de un &lt;em&gt;pod&lt;/em&gt;" me refiero a N &lt;em&gt;pods _idénticos (ejecutando los mismos contenedores y con la misma configuración) pero son N _pods&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si estamos usando un controlador y deseamos tener en todo momento 2 instancias de un determinado &lt;em&gt;pod&lt;/em&gt; y uno de los dos &lt;em&gt;pods&lt;/em&gt; se muere (porque se muere su nodo p. ej.), el controlador creará otro &lt;em&gt;pod&lt;/em&gt; para asegurar de que siga habiendo dos instancias.&lt;/p&gt;

&lt;p&gt;Cuando tenemos N instancias, los N &lt;em&gt;pods&lt;/em&gt; se consideran todos "idénticos". Si por algún motivo (p. ej. debe desescalarse) debe eliminarse algún &lt;em&gt;pod&lt;/em&gt;, el controlador eliminará uno cualquiera, sin preferencias. Eso encaja con el modelo &lt;em&gt;stateless&lt;/em&gt; de aplicación en el que los contenedores encajan perfectamente. Es decir, como desarrollador debes asegurar que tus contenedores sean &lt;em&gt;stateless&lt;/em&gt;, ya que en cualquier momento Kubernetes puede decidir eliminar el &lt;em&gt;pod&lt;/em&gt; (y por lo tanto el contenedor) y recrearlo en otra parte.&lt;/p&gt;

&lt;p&gt;Este modelo &lt;em&gt;stateless&lt;/em&gt; no siempre aplica: a veces, si tenemos N instancias de un &lt;em&gt;pod&lt;/em&gt; hay alguno que juega un rol especial y por lo tanto se requiere que estos tengan identidad. Un ejemplo es una configuración de base de datos en modo maestro/esclavo. Si uno de los &lt;em&gt;pods&lt;/em&gt; se cae, el nuevo que se cree debe ser del mismo tipo, y no solo eso, sino que debe recibir el estado que tenía el &lt;em&gt;pod&lt;/em&gt; caído. Kubernetes es capaz de gestionar estos casos mediante un controlador específico (llamado &lt;code&gt;StatefulSet&lt;/code&gt;), pero lo ideal es que nuestras aplicaciones sean &lt;em&gt;stateless&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original escrito por &lt;strong&gt;Eduard Tomás&lt;/strong&gt; en &lt;a href="https://www.campusmvp.es/recursos/post/contenedores-como-es-el-ciclo-de-vida-de-una-aplicacion-en-kubernetes.aspx"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>tools</category>
      <category>spanish</category>
    </item>
    <item>
      <title>10 Diferencias entre .NET Core y .NET Framework</title>
      <dc:creator>campusMVP</dc:creator>
      <pubDate>Tue, 19 Mar 2019 08:00:00 +0000</pubDate>
      <link>https://dev.to/campusmvp/10-diferencias-entre-net-core-y-net-framework-3e5o</link>
      <guid>https://dev.to/campusmvp/10-diferencias-entre-net-core-y-net-framework-3e5o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Post original escrito por &lt;strong&gt;José María Aguilar&lt;/strong&gt; en &lt;a href="https://www.campusmvp.es/recursos/post/10-diferencias-entre-net-core-y-net-framework.aspx" rel="noopener noreferrer"&gt;campusMVP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seguro que todos los desarrolladores que trabajáis normalmente usando herramientas Microsoft habéis oído hablar bastante de .NET Core en los últimos tiempos. Incluso quizás muchos de vosotros habéis tenido oportunidad de trabajar con este nuevo &lt;em&gt;framework&lt;/em&gt; y ya conocéis sus principales características y las bondades (e incluso algún que otro inconveniente) que ofrece sobre el ya clásico .NET Framework.&lt;/p&gt;

&lt;p&gt;Pero probablemente sois muchos también los que sólo lo conocéis de oídas, pues vuestro día a día está más enfocado al mantenimiento de sistemas existentes, o quizás trabajáis sobre tecnologías que están ancladas a versiones determinadas del &lt;em&gt;framework&lt;/em&gt; .NET, o simplemente el fragor de la batalla diaria no os deja tiempo para explorar nuevos horizontes.&lt;/p&gt;

&lt;p&gt;Si este último es tu caso, lo mínimo que debes saber es que &lt;strong&gt;.NET Core es una implementación del estándar .NET que&lt;/strong&gt; , al igual que otras implementaciones como .NET Framework o Mono, &lt;strong&gt;incluye todo lo necesario para crear y ejecutar aplicaciones&lt;/strong&gt; : como los &lt;a href="https://github.com/dotnet/roslyn" rel="noopener noreferrer"&gt;compiladores&lt;/a&gt;, las &lt;a href="https://github.com/dotnet/corefx" rel="noopener noreferrer"&gt;bibliotecas de clases básicas&lt;/a&gt; o la &lt;a href="https://github.com/dotnet/coreclr" rel="noopener noreferrer"&gt;máquina virtual o &lt;em&gt;runtime&lt;/em&gt;&lt;/a&gt; que proporciona el entorno donde se ejecutan las aplicaciones.&lt;/p&gt;

&lt;p&gt;En otras palabras, con .NET Core puedes crear una aplicación con lenguajes como C# o VB.NET, utilizar en ella clases básicas como las habituales &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; o &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;, compilarla a &lt;a href="https://es.wikipedia.org/wiki/Common_Intermediate_Language" rel="noopener noreferrer"&gt;&lt;em&gt;bytecode&lt;/em&gt; CIL&lt;/a&gt; y ejecutarla en tu ordenador.&lt;/p&gt;

&lt;p&gt;Entonces, &lt;strong&gt;¿qué diferencia a .NET Core de .NET Framework?&lt;/strong&gt; Pues precisamente eso es lo que vamos a ver en este artículo 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  1. NET Core es nuevo, y escrito prácticamente desde cero
&lt;/h2&gt;

&lt;p&gt;.NET Core es, en muchos sentidos, &lt;strong&gt;un &lt;em&gt;reboot&lt;/em&gt; de .NET Framework&lt;/strong&gt; y ha tenido que ser reescrito desde cero. Obviamente se han aprovechado las APIs, ya estandarizadas y conocidas por todos los desarrolladores, pero internamente se han vuelto a implementar muchos componentes para poder lograr los ambiciosos objetivos que se plantearon en su diseño y que veremos en algunos puntos siguientes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. .NET Core es &lt;em&gt;open source&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Aunque determinados componentes del &lt;em&gt;stack&lt;/em&gt; clásico, como ASP.NET MVC o Entity Framework, habían sido &lt;a href="https://en.wikipedia.org/wiki/.NET_Framework#Licensing" rel="noopener noreferrer"&gt;publicados bajo licencias &lt;em&gt;open source&lt;/em&gt;&lt;/a&gt;, .NET Framework no era un marco de trabajo abierto en su totalidad y aún tiene piezas distribuidas bajo licencias propietarias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.NET Core es un proyecto completamente &lt;em&gt;open source&lt;/em&gt; desde sus orígenes&lt;/strong&gt;. De hecho, aunque dirigido y soportado oficialmente por Microsoft, el proyecto pertenece a la &lt;a href="https://dotnetfoundation.org/" rel="noopener noreferrer"&gt;.NET Foundation&lt;/a&gt; y en su desarrollo están involucrados activamente cientos de desarrolladores de todo el mundo, que pueden participar en su diseño y realizar contribuciones de cualquier tipo al &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. .NET Core es multiplataforma
&lt;/h2&gt;

&lt;p&gt;Sin duda, una de las características .NET Core que más lo diferencian respecto a sus predecesores es su &lt;strong&gt;capacidad real de funcionar en múltiples plataformas&lt;/strong&gt; , incluyendo algunas impensables hace sólo algunos años, como Linux o macOS.&lt;/p&gt;

&lt;p&gt;Los SDK y &lt;em&gt;runtimes&lt;/em&gt; &lt;a href="https://dotnet.microsoft.com/download" rel="noopener noreferrer"&gt;están disponibles para una gran variedad de sistemas operativos y distribuciones&lt;/a&gt; (Windows, macOS, Ubuntu, RHEL, Debian, Fedora, CentOS...), lo que hace que sea posible desarrollar aplicaciones sobre cualquiera de las plataformas soportadas y ejecutarlas también sobre cualquiera ellas. De esta forma, ahora sería totalmente posible, por ejemplo, programar una aplicación en Windows y ejecutarla en un Mac, o desarrollarla en Mac y ejecutarla en una distribución Debian de Linux.&lt;/p&gt;

&lt;p&gt;De la misma forma, es &lt;strong&gt;compatible con distintas arquitecturas de procesador&lt;/strong&gt; , como x64, x86 o ARM, lo que posibilita su uso en diversos tipos de dispositivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. .NET Core es modular
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;.NET Framework es un bloque monolítico&lt;/strong&gt; que ha ido creciendo con el tiempo hasta convertirse en algo difícil de manejar. Por ejemplo, las distintas versiones o revisiones actualizan el &lt;em&gt;framework&lt;/em&gt; completo, muchas veces sobrescribiendo las versiones anteriormente instaladas (con los problemas que esto podría provocar). También, suelen estar bastante distanciadas en el tiempo, porque se trata de actualizaciones completas del marco de trabajo.&lt;/p&gt;

&lt;p&gt;En cambio, &lt;strong&gt;.NET Core está formado por distintas piezas distribuidas a través de paquetes NuGet&lt;/strong&gt;. De esta forma, las correcciones a bugs o mejoras en componentes concretos pueden distribuirse y actualizarse de forma independiente al resto, sólo actualizando el paquete correspondiente. Sin duda, un modelo mucho más ágil y eficiente que el anterior, y que permite un ritmo de evolución mucho más rápido.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Las operaciones principales de .NET Core se realizan desde línea de comandos
&lt;/h2&gt;

&lt;p&gt;Para conseguir ser &lt;em&gt;cross platform&lt;/em&gt; real, era absolutamente imprescindible que las herramientas de .NET Core estuviesen disponibles en Windows, Linux y Mac. ¿Y cómo conseguirlo de la forma más sencilla? Pues acudiendo al denominador común: la línea de comandos.&lt;/p&gt;

&lt;p&gt;A diferencia de .NET Framework, donde a veces nos encontrábamos casi obligados a utilizar Visual Studio, &lt;strong&gt;para compilar, ejecutar, testear o publicar aplicaciones .NET Core basta con tener a mano la línea de comandos&lt;/strong&gt; de cada sistema operativo y utilizar las órdenes de la CLI (&lt;em&gt;Command Line Interface&lt;/em&gt;) proporcionada por el &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Aquí tienes algunos ejemplos de comandos en acción:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\Test&amp;gt;dotnet new console
Preparándose...
La plantilla "Console Application" se creó correctamente.

Procesando acciones posteriores...
Ejecutando "dotnet restore" en C:\Test\Test.csproj...
  Restaurando paquetes para C:\Test\Test.csproj...
  Generación de archivo MSBuild C:\Test\obj\Test.csproj.nuget.g.props.
  Generación de archivo MSBuild C:\Test\obj\Test.csproj.nuget.g.targets.
  Restauración realizada en 147,78 ms para C:\Test\Test.csproj.

Restauración correcta.

C:\Test&amp;gt;dotnet build
Microsoft (R) Build Engine versión 15.9.20+g88f5fadfbe para .NET Core
Copyright (C) Microsoft Corporation. Todos los derechos reservados.

  Restauración realizada en 23,44 ms para C:\Test\Test.csproj.
  Test -&amp;gt; C:\Test\bin\Debug\netcoreapp2.2\Test.dll

Compilación correcta.
    0 Advertencia(s)
    0 Errores

Tiempo transcurrido 00:00:00.52

C:\Test&amp;gt;dotnet run
Hello World!

C:\Test&amp;gt;_

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. .NET Core puede distribuirse de varias formas
&lt;/h2&gt;

&lt;p&gt;Como seguramente sabes ya, .NET Framework se distribuye a través paquetes descargables que se instalan en el equipo de forma única, es decir, &lt;strong&gt;sólo puede existir una copia a nivel de equipo&lt;/strong&gt;. Además, determinadas versiones (principalmente actualizaciones) sobrescriben la versión instalada anteriormente, por lo que puede dar lugar a problemas si tenemos aplicaciones que dependen de versiones específicas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.NET Core es mucho más flexible en este sentido&lt;/strong&gt; : el &lt;em&gt;framework&lt;/em&gt; puede estar instalado a nivel de equipo, como .NET Framework, pero también podemos hacerlo a nivel de usuario o incluso a nivel de aplicación (es decir, que cada aplicación incluya su propia copia de .NET Core).&lt;/p&gt;

&lt;p&gt;Además, &lt;strong&gt;distintas versiones y revisiones pueden convivir sin problemas&lt;/strong&gt; en el mismo equipo. Por ejemplo, la siguiente traza de consola muestra el resultado de invocar el comando &lt;code&gt;dotnet --info&lt;/code&gt;, donde aparecen las distintas versiones del SDK y &lt;em&gt;runtimes&lt;/em&gt; instalados en mi equipo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\&amp;gt;dotnet --info
SDK de .NET Core (reflejando cualquier global.json):
 Version: 2.2.102
 Commit: 96ff75a873

Entorno de tiempo de ejecución:
 OS Name: Windows
 OS Version: 10.0.17763
 OS Platform: Windows
 RID: win10-x64
 Base Path: C:\Program Files\dotnet\sdk\2.2.102\

Host (useful for support):
  Version: 2.2.1
  Commit: 878dd11e62

.NET Core SDKs installed:
  1.1.11 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.503 [C:\Program Files\dotnet\sdk]
  2.2.102 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

C:\&amp;gt;_

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. .NET Core no soporta todos los modelos de aplicación ni todos los &lt;em&gt;frameworks&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Lo más habitual es que a la hora de construir aplicaciones lo hagamos &lt;em&gt;subidos a hombros de gigantes&lt;/em&gt;, es decir, utilizamos &lt;em&gt;frameworks&lt;/em&gt; que nos ayudan a desarrollar más rápidamente y con menos errores. Por ejemplo, si vamos a crear una aplicación web, lo habitual es usar ASP.NET, si nuestra aplicación es de escritorio podríamos usar WinForms o WPF, o si vamos a acceder a datos, una opción razonable es Entity Framework.&lt;/p&gt;

&lt;p&gt;Pues bien, muchos de estos &lt;em&gt;frameworks&lt;/em&gt; sólo funcionan sobre las plataformas para las que han sido creados. Por ejemplo, SignalR, ASP.NET MVC o Entity Framework 6 sólo funcionarán sobre .NET Framework porque es el &lt;em&gt;framework&lt;/em&gt; para el que han sido construidos.&lt;/p&gt;

&lt;p&gt;Como consecuencia, a día de hoy, &lt;strong&gt;con .NET Core 2.x sólo podemos crear determinados tipos de aplicaciones&lt;/strong&gt; : consola, web (ASP.NET Core) y Xamarin. Esto limita algo las posibilidades de uso de este &lt;em&gt;framework&lt;/em&gt;, pero, afortunadamente, esto va a cambiar en un futuro próximo: previsto para 2019, &lt;strong&gt;.NET Core 3.0 incluirá soporte para WPF y Windows Forms&lt;/strong&gt; , que se beneficiarán de algunas de las ventajas que aportan este nuevo marco de trabajo.&lt;/p&gt;

&lt;p&gt;En definitiva, &lt;strong&gt;a la hora de desarrollar con .NET Core debemos utilizar marcos de trabajo específicos para esta plataforma&lt;/strong&gt; , como ASP.NET Core, Entity Framework Core o SignalR Core.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. En .NET Core el rendimiento es algo prioritario
&lt;/h2&gt;

&lt;p&gt;Desde sus orígenes, &lt;strong&gt;en .NET Core el rendimiento ha sido siempre una prioridad&lt;/strong&gt; , y esto se pone de manifiesto en los &lt;em&gt;benchmarks&lt;/em&gt; que demuestran que este &lt;em&gt;framework&lt;/em&gt; supera a su predecesor con creces en este aspecto.&lt;/p&gt;

&lt;p&gt;Por dar algunas cifras, algo tan simple y recurrente como utilizar los métodos &lt;code&gt;IndexOf()&lt;/code&gt; o &lt;code&gt;StartsWith()&lt;/code&gt; sobre una cadena son &lt;strong&gt;un 200% más rápidos en .NET Core que en .NET Framework&lt;/strong&gt;. Un &lt;code&gt;ToString()&lt;/code&gt; sobre el elemento de un &lt;em&gt;enum&lt;/em&gt; &lt;strong&gt;gana un 600% de rendimiento&lt;/strong&gt;. &lt;strong&gt;LINQ es hasta un 300% más eficiente&lt;/strong&gt; en determinados puntos. &lt;code&gt;Lazy&amp;lt;T&amp;gt;&lt;/code&gt; es &lt;strong&gt;un 500% más rápido&lt;/strong&gt;...&lt;/p&gt;

&lt;p&gt;Beneficiarios directos de estas mejoras son los &lt;em&gt;frameworks&lt;/em&gt; específicos como ASP.NET Core o Entity Framework Core. Por ejemplo, el primero de ellos se ha situado ya sólidamente en los &lt;em&gt;top ten&lt;/em&gt; de los marcos de trabajo más rápidos para la web según las &lt;a href="https://www.techempower.com/benchmarks/#section=test&amp;amp;runid=8ca46892-e46c-4088-9443-05722ad6f7fb&amp;amp;hw=ph&amp;amp;test=plaintext" rel="noopener noreferrer"&gt;pruebas TechEmpower&lt;/a&gt; soportando &lt;strong&gt;más de 7 millones de peticiones por segundo&lt;/strong&gt; , algo impensable en ASP.NET 4.x.&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%2F2019-02-05-16-57-44.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%2F2019-02-05-16-57-44.png" alt="Benchmarks de ASP.NET Core"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. .NET Core ha sido creado pensando en los &lt;em&gt;tiempos modernos&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Cuando se creó .NET Framework, hace más de quince años, una nube era simplemente un agregado visible de minúsculas gotitas de agua, de cristales de hielo o de ambos, suspendido en la atmósfera y producido por la condensación de vapor de agua (&lt;a href="https://dle.rae.es/?id=QgpwJRv" rel="noopener noreferrer"&gt;RAE dixit&lt;/a&gt;), los contenedores se usaban exclusivamente para almacenar cosas diversas, como mercancías o residuos, y probablemente al hablar de microservicios sólo podíamos pensar en cuartos de baño pequeñitos 😆&lt;/p&gt;

&lt;p&gt;Hoy en día, el &lt;em&gt;cloud&lt;/em&gt; está presente en casi cualquier aspecto del desarrollo, sobre todo en aplicaciones que, de alguna u otra forma, hacen uso de Internet. Los contenedores se han consolidado como una forma simple, ágil y escalable para desplegar aplicaciones, y los microservicios se han demostrado como arquitecturas apropiadas en múltiples escenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.NET Core y los &lt;em&gt;frameworks&lt;/em&gt; construidos sobre él han sido creados teniendo en cuenta todos estos aspectos&lt;/strong&gt;. Sus componentes están diseñados con el enfoque &lt;em&gt;cloud-first&lt;/em&gt; en mente, por lo que se integran a la perfección en infraestructuras de nube. Se trata además de una tecnología especialmente recomendada para la construcción de microservicios, entre otros aspectos, por la facilidad con que pueden ser creados y distribuidos en contenedores.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Se pueden desarrollar aplicaciones .NET Core con cualquier editor o IDE
&lt;/h2&gt;

&lt;p&gt;Ni a nuestros más acérrimos enemigos le desearíamos algo tan terrible como crear aplicaciones para .NET Framework sin Visual Studio. De hecho, aunque técnicamente era evitable, en muchos modelos de aplicación (por ejemplo, WinForms, WPF o ASP.NET) era prácticamente obligatorio utilizar el IDE de Microsoft.&lt;/p&gt;

&lt;p&gt;Por el contrario, &lt;strong&gt;con .NET Core tenemos libertad completa a la hora de elegir el editor&lt;/strong&gt; que utilizaremos en el desarrollo de nuestros proyectos. Si trabajamos sobre Windows, muchos preferimos seguir utilizando Visual Studio en el día a día (al fin y al cabo, es el mejor IDE 😜, pero hay quien prefiere trabajar con Visual Studio Code, o con editores alternativos como Atom, Brackets o Sublime Text. Y si trabajamos desde Linux o Mac, podemos utilizar cualquier editor disponible en dichos entornos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Corolario: .NET Core es tu próximo &lt;em&gt;framework&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Lo queramos o no, &lt;strong&gt;.NET Core se convertirá en algún momento en la herramienta que usaremos en nuestro día a día&lt;/strong&gt;. Aunque en principio .NET Framework seguirá existiendo y Microsoft continuará dándole soporte, la tendencia actual indica que &lt;strong&gt;todo está confluyendo en .NET Core&lt;/strong&gt; : Xamarin, WPF, WinForms, Entity Framework, SignalR o MVC son sólo algunos ejemplos de &lt;em&gt;frameworks&lt;/em&gt; que ya están o van a estar pronto basados en la nueva infraestructura.&lt;/p&gt;

&lt;p&gt;Además, es lógico pensar que estos marcos de trabajo continuarán evolucionando exclusivamente sobre .NET Core. Sólo hay que mirar un poco hacia atrás y ver que en los últimos dos años han aparecido ya varias versiones completas de &lt;em&gt;frameworks&lt;/em&gt; como Entity Framework Core o ASP.NET Core, mientras que EF o ASP.NET MVC "clásicos" apenas han lanzado pequeñas actualizaciones.&lt;/p&gt;

&lt;p&gt;En nuestro &lt;strong&gt;&lt;a href="https://www.campusmvp.es/recursos/catalogo/Product-Desarrollo-Web-con-ASP.NET-Core-2-MVC_227.aspx" rel="noopener noreferrer"&gt;curso de ASP.NET Core MVC&lt;/a&gt;&lt;/strong&gt; se estudia a fondo la creación de aplicaciones Web con el nuevo &lt;em&gt;framework&lt;/em&gt; de Microsoft. ¿A qué esperas para dar el salto?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Post original escrito por &lt;strong&gt;José María Aguilar&lt;/strong&gt; en campusMVP: &lt;a href="https://www.campusmvp.es/recursos/post/10-diferencias-entre-net-core-y-net-framework.aspx" rel="noopener noreferrer"&gt;https://www.campusmvp.es/recursos/post/10-diferencias-entre-net-core-y-net-framework.aspx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>csharp</category>
      <category>netcore</category>
      <category>spanish</category>
    </item>
  </channel>
</rss>
