Translate

miércoles, 27 de julio de 2022

Filosofía de Kotlin


Cuando hablamos de Kotlin, es un lenguaje pragmático, conciso y seguro con un enfoque en la interoperabilidad. ¿Qué significan exactamente con cada una de esas palabras? 

Pragmático: Kotlin es un lenguaje práctico diseñado para resolver problemas del mundo real. Su diseño se basa en muchos años de experiencia en la industria creando sistemas a gran escala, y sus funciones se eligen para abordar los casos de uso que encuentran muchos desarrolladores de software. Además, los desarrolladores tanto dentro de JetBrains como en la comunidad han estado usando las primeras versiones de Kotlin durante varios años y sus comentarios han dado forma a la versión lanzada del lenguaje. Kotlin puede ayudar a resolver problemas en proyectos reales.

Kotlin tampoco es un lenguaje de investigación. No estamos tratando de avanzar en el estado del arte en el diseño de lenguajes de programación y explorar ideas innovadoras en informática. En su lugar, siempre que sea posible, confiamos en funciones y soluciones que ya han aparecido en otros lenguajes de programación y han demostrado ser exitosas. Esto reduce la complejidad del lenguaje y hace que sea más fácil de aprender al permitirle confiar en conceptos familiares.

 Además, Kotlin no impone el uso de ningún estilo o paradigma de programación en particular. A medida que comienza a estudiar el lenguaje, puede usar el estilo y las técnicas que le resultan familiares de su experiencia con Java. Más adelante, descubrirá gradualmente las funciones más potentes de Kotlin y aprenderá a aplicarlas en su propio código, para hacerlo más conciso e idiomático.

Otro aspecto del pragmatismo de Kotlin es su enfoque en las herramientas. Un entorno de desarrollo inteligente es tan esencial para la productividad de un desarrollador como un buen lenguaje; y debido a eso, tratar el soporte IDE como una ocurrencia tardía no es una opción. En el caso de Kotlin, el complemento IntelliJ IDEA se desarrolló al unísono con el compilador, y las características del lenguaje siempre se diseñaron teniendo en cuenta las herramientas.

La compatibilidad con IDE también juega un papel importante a la hora de ayudarte a descubrir las características de Kotlin. En muchos casos, las herramientas detectarán automáticamente patrones de código comunes que se pueden reemplazar por construcciones más concisas y se ofrecerán a corregir el código por usted. Al estudiar las características del lenguaje utilizadas por las correcciones automáticas, también puede aprender a aplicar esas características en su propio código.

Conciso: Es bien sabido que los desarrolladores dedican más tiempo a leer código existente que a escribir código nuevo. Imagina que eres parte de un equipo que está desarrollando un gran proyecto y necesitas agregar una nueva función o corregir un error. ¿Cuáles son tus primeros pasos? Busca la sección exacta del código que necesita cambiar y solo entonces implementa una corrección. Lees mucho código para saber lo que tienes que hacer. Este código puede haber sido escrito recientemente por sus colegas, por alguien que ya no trabaja en el proyecto, o por usted, pero hace mucho tiempo. Solo después de comprender el código que lo rodea, puede realizar las modificaciones necesarias.

Cuanto más simple y conciso sea el código, más rápido entenderá lo que está pasando. Por supuesto, el buen diseño y los nombres expresivos juegan un papel importante aquí. Pero la elección del lenguaje y su concisión también son importantes. El lenguaje es conciso si su sintaxis expresa claramente la intención del código que lee y no lo oscurece con el texto estándar requerido para especificar cómo se logra la intención.

 En Kotlin, todo el código que escribe tiene un significado y no esta ahí solo para satisfacer los requisitos de la estructura del código. Gran parte del código estándar de Java, como getters, setters y la lógica para asignar parámetros de constructor a los campos, está implícito en Kotlin y no abarrota el código fuente.

Otra razón por la que el código puede ser innecesariamente largo es tener que escribir código explícito para realizar tareas comunes, como ubicar un elemento en una colección. Al igual que muchos otros lenguajes modernos, Kotlin tiene una rica biblioteca estándar que le permite reemplazar estas secciones largas y repetitivas de código con llamadas a métodos de biblioteca. La compatibilidad de Kotlin con lambdas facilita el paso de pequeños bloques de código a funciones de biblioteca. Esto le permite encapsular todas las partes comunes en la biblioteca y mantener solo la porción única y específica de la tarea en el código de usuario.

Al mismo tiempo, Kotlin no intenta reducir el código fuente al menor número de caracteres posible. Por ejemplo, aunque Kotlin admite la sobrecarga de operadores, los usuarios no pueden definir sus propios operadores. Por lo tanto, los desarrolladores de bibliotecas no pueden reemplazar los nombres de los métodos con secuencias de puntuación crípticas. Las palabras suelen ser más fáciles de leer que la puntuación y es más fácil encontrar documentación.

Un código más conciso requiere menos tiempo para escribir y, lo que es más importante, menos tiempo para leer. Esto mejora la productividad y permite hacer las cosas más rápido.

Seguro: En general, cuando hablamos de un lenguaje de programación como seguro, nos referimos a que su diseño previene ciertos tipos de errores en un programa. Por supuesto, esto no es un absoluto igualdad; ningún lenguaje previene todos los posibles errores. Además, la prevención de errores generalmente tiene un costo. Debe proporcionar al compilador más información sobre la operación prevista del programa, de modo que el compilador pueda verificar que la información coincida con lo que hace el programa. Por eso, siempre hay una compensación entre el nivel de seguridad que se obtiene y la pérdida de productividad necesaria para realizar anotaciones más detalladas.

Con Kotlin, se logra un mayor nivel de seguridad que en Java, con un costo total menor. La ejecución en la JVM ya proporciona muchas garantías de seguridad: por ejemplo, seguridad de la memoria, prevención de desbordamientos de búfer y otros problemas causados ​​por el uso incorrecto de la memoria asignada dinámicamente. Como lenguaje tipificado estáticamente en JVM, Kotlin también garantiza la seguridad de tipos de sus aplicaciones. Esto tiene un costo menor que con Java: no tiene que especificar todas las declaraciones de tipos, porque en muchos casos el compilador infiere los tipos automáticamente.

Kotlin también va más allá, lo que significa que se pueden evitar más errores mediante comprobaciones en tiempo de compilación en lugar de fallar en tiempo de ejecución. Lo más importante es que Kotlin se esfuerza por eliminar NullPointerException de su programa. El sistema de tipos de Kotlin realiza un seguimiento de los valores que pueden y no pueden ser nulos y prohíbe las operaciones que pueden conducir a una excepción NullPointer en tiempo de ejecución. El costo adicional requerido para esto es mínimo: marcar un tipo como anulable requiere solo un carácter, un signo de interrogación al final:

val s: String? = null

val s2: String = ""

Además, Kotlin proporciona muchas formas convenientes de manejar datos anulables. Esto es de gran ayuda para eliminar los bloqueos de aplicaciones.

Otro tipo de excepción que Kotlin ayuda a evitar es ClassCastException. Ocurre cuando conviertes un objeto en un tipo sin verificar primero que tenga el tipo correcto. En Java, los desarrolladores a menudo omiten la verificación, porque el nombre del tipo debe repetirse en la verificación y en el siguiente lanzamiento. En Kotlin, por otro lado, la verificación y el elenco se combinan en una sola operación: una vez que hayas verificado el tipo, puedes referirte a los miembros de ese tipo sin ningún casteo adicional. Por lo tanto, no hay motivo para omitir la verificación y no hay posibilidad de cometer un error. Así es como funciona esto:

if (value is String) println(value.toUpperCase())

Interoperable: Con respecto a la interoperabilidad, su primera preocupación probablemente sea: "¿Puedo usar mis bibliotecas existentes?" Con Kotlin, la respuesta es: "Sí, absolutamente". Independientemente del tipo de API que la biblioteca requiera que uses, puedes trabajar con ellas desde Kotlin. Puede llamar a métodos de Java, extender clases de Java e implementar interfaces, aplicar anotaciones de Java a sus clases de Kotlin, etc.

 A diferencia de otros lenguajes JVM, Kotlin va aún más allá con la interoperabilidad, lo que hace que llamar al código Kotlin desde Java también sea sencillo. No se requieren trucos: las clases y los métodos de Kotlin se pueden llamar exactamente como las clases y los métodos de Java normales. Esto le brinda la máxima flexibilidad para combinar código Java y Kotlin en cualquier parte de su proyecto. Cuando comience a adoptar Kotlin en su proyecto de Java, puede ejecutar el convertidor de Java a Kotlin en cualquier clase de su base de código, y el resto del código seguirá compilando y funcionando sin modificaciones. Esto funciona independientemente del rol de la clase que haya convertido.

Otra área en la que Kotlin se centra en la interoperabilidad es el uso de las bibliotecas Java existentes en la mayor medida posible. Por ejemplo, Kotlin no tiene su propia biblioteca de colecciones. Se basa completamente en las clases de la biblioteca estándar de Java y las amplía con funciones adicionales para un uso más conveniente en Kotlin. (Veremos el mecanismo para esto con más detalle en la sección 3.3). Esto significa que nunca necesitará envolver o convertir objetos cuando llame a las API de Java desde Kotlin, o viceversa. Toda la riqueza de API proporcionada por Kotlin viene sin costo en tiempo de ejecución.

 Las herramientas de Kotlin también brindan soporte completo para proyectos en varios lenguajes. Puede compilar una combinación arbitraria de archivos fuente de Java y Kotlin, independientemente de cómo dependan entre sí. Las funciones del IDE también funcionan en todos los lenguajes, lo que le permite:

  • Navegar libremente entre los archivos fuente de Java y Kotlin
  • Depurar proyectos de lenguaje mixto y pasar entre código escrito en diferentes lenguajes
  • Refactorizar sus métodos Java y actualice correctamente su uso en el código Kotlin, y viceversa.