.NET Core es la nueva generación de tecnologías basadas en .NET y orientadas a la nube. No se trata de una nueva versión llamada a sustituir a la anterior, sino que es una nueva tecnología que se mantendrá en paralelo a la tecnología actual. Tiene unos objetivos diferentes: sobre todo que sea multi-plataforma (Windows, Linux y Mac), que ofrezca más rendimiento y menos consumo de recursos para su uso en la nube, y que sea totalmente modular. Hace un tiempo te explicamos en un artículo en qué consiste .NET Core, qué contendrá y qué esperar de esta tecnología en el corto plazo.
Hace poco el equipo de .NET Core sacó un artículo en el que explicaban a vista de pájaro qué opciones existen para poder migrar tus aplicaciones desde la versión completa de .NET a la más liviana y multi-plataforma nueva versión, que por otro lado no ha sido lanzada todavía, pero está cerca. Queremos ofrecerte un resumen aquí.
¿Qué aplicaciones se pueden portar?
En primer lugar hay que tener claro que .NET Core no permite crear cualquier tipo de desarrollo. Por el momento se centra en tres tipos fundamentales de aplicaciones:
- Aplicaciones y servicios Web: ésta es de lejos la aplicación principal y la más popular.
- Aplicaciones universales para la plataforma Windows: aquí pierde un poco de sentido lo de que sea multi-plataforma, aunque nos imaginamos que, tras la reciente compra de Xamarin, la intención es ampliarlo para que cubra desarrollos multi-plataforma también. En ese caso sí que será algo muy a tener en cuenta.
- Aplicaciones de consola: ideales para crear herramientas de administración del sistema que se ejecuten en Windows, Mac y Linux.
Veamos qué ventajas sacaríamos de portar aplicaciones de cada tipo a .NET Core.
¿Por qué deberíamos (o no) portarlas?
En el caso de las aplicaciones web las principales ventajas de migrarlas serían que se podrían ejecutar en Mac o Linux además de Windows, que podrías usar de manera más eficiente los recursos del servidor al desplegar exactamente la funcionalidad del framework que vayas a usar, y que se ejecutarán más ágiles en general por estar .NET Core pensado para un entorno Cloud, donde la eficiencia prima. Si es un servicio Web API la migración es sencilla. No tanto con ASP.NET MVC (aunque es relativamente sencillo). Imposible si usas Web Forms.
En el caso de aplicaciones pensadas para Windows 8/10, si ya usas la plataforma universal no tienes nada que migrar: funcionarán sin problemas en .NET Core. En el caso de que sean aplicaciones basadas en Silverlight la migración es muy simple pues solo hay que cambiar algunos espacios de nombres y poco más (hasta hay una herramienta para pseudo-automatizar esto). Si son aplicaciones de escritorio basadas en WPF (y ya no digamos en Windows Forms), entonces la migración es complicada porque no está soportado en Core. Ahora bien, WPF se parece mucho al lenguaje de la interfaz de WinRT, por lo que en este caso el aprendizaje al menos será mucho menor.
Finalmente si tienes una aplicación de consola, el atractivo principal de la migración sería el poder usarlas en los tres principales sistemas operativos del mercado. Si tu aplicación hace cosas poco ligadas al funcionamiento de bajo nivel del sistema operativo (por ejemplo, si procesa archivos y cosas similares), entonces la migración será más o menos sencilla en función de las bibliotecas de las que dependa. En caso de que uses cosas como automatización COM o APIs del sistema, vete olvidándote de ello.
¿Qué APIs y funcionalidades de .NET no están soportadas en .NET Core y nunca lo estarán?
Existen una serie de tecnologías que no están soportadas en .NET Core y nunca lo van a estar ya que Microsoft ha decidido considerarlas "problemáticas" (sic). Otras no lo están todavía pero puede que lo estén en el futuro, aunque en muchos casos ni siquiera han pensado en cómo harían esa migración, y solamente se considerarán llegado el caso.
Veamos las más importantes:
Reflection
.NET está íntimamente ligado al concepto de "Reflexión", es decir, el poder examinar en tiempo de ejecución las diferentes clases y objetos, al contrario que otros lenguajes más estrictos que requieren compiladores y runtimes que usen solo información estática. Tan ligado está .NET a este concepto que la clase Object, base de todas las demás clases del framework, depende directamente de Reflection y dispone de un método llamado GetType que devuelve un objeto con toda la información sobre el tipo del objeto actual, para poder enumerar sus propiedades, métodos y muchos otros detalles.
En .NET Core esto ha cambiado puesto que para poder hacer totalmente modular la plataforma es necesario tener información estática sobre la funcionalidad a utilizar, pudiendo desplegar así solo lo que sea necesario en cada momento. Así que el equipo decidió romper la compatibilidad y que System.Type ya no represente toda la información de un tipo, sino solamente su nombre :-S
Si necesitas acceder a las capacidades de reflexión tendrás que utilizar un nuevo método extensor específico de System.Type llamado GetTypeInfo() e incluir el módulo System.Reflection.
Aquí tienes un artículo sobre todos estos cambios. A mayores, y dado que se han desdicho de alguno de ellos (es una constante últimamente: que nada es constante), aquí tienes otro documento oficial en GitHub que explica que algunas cosas que habían desaparecido han decidido incluirlas de nuevo.
Seriación binaria
Relacionado con lo anterior en cierto modo. La serialización (o seriación) binaria es "increíblemente compleja" (sic) y requiere un conocimiento íntimo de los tipos a seriar ya que incluye el estado de objetos internos y privados. En .NET Core no está soportada. Se recomienda usar tipos estándar de seriación como JSON, que no llegan a un nivel tan interno pero son suficientes para la mayor parte de las aplicaciones.
Dominios de aplicación
Los dominios de aplicación (o App Domain) en .NET siempre han sido un concepto importante. Son equivalentes dentro del CLI a un proceso en el sistema operativo. Es decir, son una forma de proporcionar un aislamiento entre distintos procesos de ejecución de una aplicación para conseguir mayor seguridad (no se puede acceder de unos a otros), estabilidad (un error que eche abajo uno no afecta a los demás) e independencia de versiones (cada uno puede ejecutar código en una versión de .NET diferente).
Aunque, casi por definición, la nueva .NET Core implementa dominios de aplicación para aislar sus procesos, estos no son accesibles en modo alguno para el programador, y específicamente el compilador a código nativo de .NET Core (.NET Native) no les da soporte ni se lo dará en el futuro debido a que es muy costoso en términos de rendimiento y recursos hacerlo (y .NET Core es todo acerca de esto, como ya hemos comentado).
Para aislar procesos dentro de nuestra propia aplicación deberemos usar la API de System.Diagnostics.Process. Si lo que quieres es cargar dinámicamente ensamblados, entonces hay una nueva clase para eso llamada AssemblyLoadContext.
Sandboxing
Tradicionalmente otra de las funcionalidades que se delegaban a .NET era el aislamiento y control de acceso a recursos. Es decir, es .NET el que controla si tenemos acceso a ciertos recursos como archivos en red, otras máquinas, el registro, etc...
En .NET Core esto se delega directamente al sistema operativo, que antes era una capa de control a mayores.
Remoting
Bueno, estaba claro que esta tecnología llevaba muchos años muerta. A pesar del bombo que se le dio en los inicios de .NET hace 15 años, la propia Microsoft reconoce que es una tecnología "problemática" (sic).
Para comunicaciones entre procesos de la misma máquina es mejor usar técnicas tradicionales como archivos mapeados en memoria o "pipes". Para comunicación entre máquinas, la Web API es tu amiga.
¿Qué APIs y funcionalidades de .NET no están soportadas en .NET Core pero quizá, algún día, en el futuro lo estén?
Del mismo modo que hay funcionalidad para la que no existen planes de migración o soporte, hay otras que si bien todavía no hay planes tampoco, no descartan que en el futuro quizá sí que estén soportadas. Según ellos mismos, "simplemente no hemos tenido tiempo de investigar si tendría sentido portarlo o no pensamos que sean relevantes para los modelos de aplicaciones que se ofrecen actualmente en .NET Core".
De todo lo que hay (que son muchas cosas) el equipo de .NET Core dice que son conscientes de que la gente les reclama todas estas cosas en GitHub:
- System.Data: o sea, todo lo que es ADO.NET Clásico, que a pesar de Entity Framework sigue siendo muy popular por su sencillez de uso, potencia y universalidad para acceso a todo tipo de datos.
- System.Transactions: no hay tampoco soporte para transacciones distribuidas. Muy relacionado con lo anterior.
- System.DirectoryServices: para comunicación con Directorio Activo y directorios basados en LDAP en general. Una omisión importante en aplicaciones empresariales, en mi opinión.
- System.Drawing: aunque esto ha estado tradicionalmente ligado a Windows Forms e interfaces de usuario de lado cliente, el poder manipular y pintar imágenes en memoria se usa mucho para generar al vuelo imágenes en el servidor y devolverlas. Tendrás que usar otra cosa para ello.
- System.Net.Mail: para envío de correo. Tendrás que usar un servicio externo estilo SendGrid o Mandrill.
- System.IO.Ports: nada de comunicación a través de puertos de serie, así que nada de conectarte a ciertos dispositivos de hardware.
- System.Xaml: ya comentábamos antes que debes usar WinRT XAML, no el XAML tradicional de WPF.
- System.Workflow: ah, pero ¿es que alguien usa Windows Workflow Foundation todavía?. Una tecnología prometedora en su día (y una virguería, la verdad) que se lanzó con .NET 3.5 como gran estrella junto a WCF y WPF, pero que se quedó en nada al igual que sus "hermanas". No creo que sea un gran problema para la mayoría, pero como dependas de ella que sepas que no podrás usar .NET Core.
- Soporte de XSL y esquemas XML: pues eso: que sí hay soporte para XML (solo fastidiaría) y para XPath, pero nada de transformaciones XSL ni esquemas. Tampoco firmas digitales basadas en Xml. Vicisitudes de otra tecnología que en 2001 se vendía como el futuro pero que se han quedado en casi nada.
En GitHub tienes una lista de todas estas cosas y muchas más que la gente les reclama y que quizá algún día consideren portar. También dicen que, a lo mejor, alguna gente de la comunidad se anima a crear reemplazos de algunas de estas tecnologías que funcionen bajo .NET Core. Buena suerte con eso, aunque ahora es más fácil que nunca gracias a que el código completo de .NET (del actual también) es Open Source.
También hay otras que no se mencionan en ningún lado pero que no podrás hacer, como por ejemplo crear servicios o "demonios" del sistema.
Si hay alguna cosa que echas en falta en .NET puedes probar suerte y pedírsela también desde aquí.
¿Cómo puedo comprobar lo factible que es la migración de mi aplicación?
Bueno, antes de nada deberías hacer un análisis automatizado de tus ejecutables y DLLs. No hace falta el código fuente, solo los binarios.
Microsoft tiene una herramienta específica para esto: .NET Compatibility Diagnostic Tools.
Existe una versión de consola y un plugin para Visual Studio. Asegúrate de usar siempre la última versión pues .NET Core cambia de un día para otro.
La herramienta devuelve dos informes:
- Resumen de alto nivel: te dice en cada uno de los ensamblados el % que creen que es portable directamente a .NET Core. Muchas veces las cosas simplemente se pueden cambiar un poco para que funcionen (como en Reflection). En otros casos no hay forma posible de arreglarlo.
- Lista de APIs no-portables: de todo lo que usas te dice qué APIs no están soportadas por .NET Core.
Por cierto, la app que genera los informes también le pasa información anónima al equipo para saber qué aplicaciones hay por ahí que pueden no estar soportadas. Así que si te interesa especialmente que porten un API y la usas en alguna de tus apps, pásale la aplicación de análisis para que se den por informados también por esa vía.
Estrategias de migración
Al final del artículo oficial referenciado al principio hablan de diversas estrategias para portar tu aplicación a .NET Core, que básicamente son las obvias:
- Co-evolución: básicamente que te quedes con tu aplicación actual en .NET tradicional y que vayas portando cosas concretas (o lo nuevo que hagas) a .NET Core.
- Migración: usar todo lo anterior que hemos visto para migrar completamente la aplicación a .NET Core (sobre todo las que son apps Web, que deberían ser las más fáciles).
- Empezar de cero: si no puedes migrarla y realmente tienes interés, empieza desde cero con .NET Core. Más te vale que la aplicación no sea muy grande en este caso, digo yo.
A mí, siendo malo, se me ocurre una cuarta opción: cambiarte de plataforma y empezar con NodeJS o Python. Y de hecho me consta que lamentablemente hay alguna gente que es la vía que ha tomado. Una verdadera pena por todos los años invertidos en .NET.
Para finalizar el artículo te ofrecen algunas indicaciones concretas más para la segunda y la tercera opción, pero nada que no se te ocurra a uno solo.
Existen unos cuantos enlaces al final del artículo que pueden resultar útiles.
¿Y tú qué opinas de .NET Core? ¿Vas a migrar alguna aplicación? ¿Te quedas para siempre con .NET clásico? ¿Te quieres cambiar de plataforma? Cuéntanoslo en los comentarios.