Header Ads Widget

Ticker

6/recent/ticker-posts

Creación de API en la JVM con Kotlin y Spark - Parte 1

 

Creación-de-API-JVM-kotlin-spark-java-nordic-apis-pt-1

Cuando inicia un nuevo proyecto de API, una de las primeras preguntas que debe responder es qué lenguaje de programación usar. Elegir el correcto puede marcar la diferencia. Algunos idiomas ayudan a resolver ciertos problemas, mientras que otros inhiben las soluciones. Incluso después de que se elige un idioma y se han escrito decenas de miles de líneas de código, existe la posibilidad de reducir la complejidad mediante el uso de nuevos lenguajes en el mismo tiempo de ejecución .

En esta serie de blogs de dos partes, explicaremos por qué la JVM proporciona una base sólida sobre la cual ejecutar sus API y cómo simplificar su construcción utilizando un marco llamado Spark y un nuevo lenguaje de programación llamado Kotlin . En esta primera parte, le presentaremos la JVM y cómo puede ejecutar código escrito en muchos lenguajes de programación, incluido Kotlin. Discutiremos una serie de características de Kotlin y las mostraremos en el contexto de las API.

En nuestra segunda publicación , exploramos el marco de Spark en detalle y cómo complementar este kit de herramientas con componentes adicionales como Inversión de control (IoC). Durante la serie, desarrollaremos un modelo estándar que puede usar para crear API robustas con Kotlin y Spark . El código se puede encontrar en Github , así que consúltelo allí mientras lee los fragmentos a continuación.

Vea a Travis Spencer presentando este tema en el encuentro de Java de Estocolmo

Presentando la JVM

La máquina virtual Java (JVM) es un tiempo de ejecución que ofrece una variedad de opciones de idioma. La adopción de Clojure, Groovy, Scala, Jython y otros lenguajes basados ​​en JVM está muy extendida. Aparte de la amplia gama de opciones de idioma, otro aspecto poco común de la JVM es su apertura. Puede obtener una implementación de la JVM no solo de Oracle, sino también de una lista expansiva de otros proveedores . Muchas distribuciones de Linux vienen precargadas con OpenJDK , que es la implementación de referencia de Java, lo que permite a los desarrolladores de API alojar su servicio con muy poco costo y molestias.

Uno de los inquilinos principales de Java es que cada nueva versión es compatible con versiones anteriores. Esto ha provocado que el lenguaje de programación Java evolucione más lentamente que otros como C #, donde los cambios importantes en el lenguaje vienen con esfuerzos de actualización masivos. 
Esto ha mejorado mucho a lo largo de los años, y Java 8 ha eliminado muchos errores del lenguaje con la introducción de lambdas . Independientemente del ritmo de evolución de Java, este compromiso con la compatibilidad con versiones anteriores ha dado como resultado una base muy estable .

La apertura y compatibilidad continua de la JVM ofrece una serie de razones muy convincentes para crear API en esta plataforma:

  • Retorno de la inversión (ROI) : el código que continúa ejecutándose puede seguir produciendo un retorno de la inversión realizada para escribirlo.
  • El conocimiento sigue siendo relevante : dado que el código antiguo continúa ejecutándose, todo el conocimiento adquirido para escribir ese código sigue siendo útil. Con las nuevas versiones de la JVM, puede seguir escribiendo código de estilo antiguo. No tiene que volver a capacitarse cuando el proveedor del tiempo de ejecución actualiza la plataforma.
  • Ecosistema : estos factores han provocado que un ecosistema muy grande florezca alrededor de la JVM. Este sistema incluye corporaciones masivas y algunas de las comunidades de código abierto más grandes que trabajarán arduamente para garantizar su longevidad.

Probablemente uno de los mayores inconvenientes de seleccionar Java para codificar su API es que es muy detallado. ¡¿Quién lo usaría si no tuvieran que hacerlo ?! El ROI es a menudo una razón suficiente para que las empresas lo seleccionen incluso para trabajos totalmente nuevos, lo que pone a los programadores en el dolor de su verbosidad incluso con la llegada de alternativas como Node.js y Golang .

Pero, ¿y si tuvieras la sintaxis más dulce con la que puedas soñar sin tener que cambiar nada más? ¿Qué pasaría si pudiera conservar su sistema de compilación, empaquetado, dependencias, código existente y rendimiento, y obtener el lenguaje que ha estado anhelando?

Entra Kotlin

Kotlin es un nuevo lenguaje de programación de Jetbrains, los creadores de algunas de las mejores herramientas de programación en el negocio, incluido Intellij IDEA , un IDE para Java y otros lenguajes. Como líder en la comunidad de Java, Jetbrains comprende los problemas de Java y los muchos beneficios de la JVM. No queriendo tirar al bebé con el agua de la bañera, Jetbrains diseñó a Kotlin para que se ejecutara en la JVM para obtener lo mejor de esa plataforma.

Ellos no la restringen a este tiempo de ejecución, sin embargo - los desarrolladores también pueden compilar su código Kotlin en JavaScript , lo que le permite ser utilizado en ambientes como Node.js . Para trabajar con entornos no tipificados y tipificados como estos, Kotlin está tipificado estáticamente de forma predeterminada, pero permite a los desarrolladores definir tipos dinámicos también. Este equilibrio proporciona un gran poder y muchas oportunidades.

¿Por qué Kotlin?

Mike Hearn hace un trabajo espectacular al explicar por qué debería considerar el uso de Kotlin . En su artículo, enumera las siguientes razones:

  • Kotlin compila en código de bytes JVM y JavaScript
  • Kotlin proviene de la industria, no de la academia
  • Kotlin es de código abierto y no cuesta nada adoptar
  • Los programas de Kotlin pueden usar marcos Java o JavaScript existentes
  • La curva de aprendizaje es muy baja
  • Kotlin no requiere ningún estilo particular de programación (OO o funcional)
  • Kotlin se puede utilizar en el desarrollo de Android además de otros en los que funcionan Java y JavaScript
  • Ya existe un excelente soporte IDE (Intellij y Eclipse)
  • Kotlin es muy adecuado para tiendas Java empresariales.
  • Tiene el fuerte apoyo comercial de una empresa de software establecida.

Lea el artículo de Mike para obtener más información sobre la justificación del uso de Kotlin. Sin embargo, con suerte, esta lista es suficiente para convencerlo de que considere seriamente Kotlin para su próxima API. Para ver lo fácil que puede ser esto, explicaremos cómo usar Kotlin con un marco de microservicios llamado Spark . Profundizaremos en Spark en la siguiente parte de esta serie, pero ahora explicaremos algunas de las excelentes características del lenguaje Kotlin con un código de muestra .

Ejemplos de sintaxis de Kotlin

Para ver cómo se puede usar Kotlin para crear excelentes API , veremos una muestra que demuestra muchas de las características del lenguaje en el contexto de las API. Puede encontrar el código completo en Github , y todo es de código abierto.

Para empezar, aquí está el punto de entrada de la API:

fun main(args: Array) = api(composer = ContainerComposer())
{
	route(
        	path("/login", to = LoginController::class, renderWith = "login.vm"),
        	path("/authorize", to = AuthorizeController::class, renderWith = "authorize.vm"),
        	path("/token", to = TokenController::class))
}

Tenga en cuenta que lo que tenemos es muy legible incluso sin conocimiento de Kotlin. Este fragmento inicia una API que expone varias rutas que se enrutan a los controladores, algunas de las cuales son representadas por una plantilla y otras no. Fácil. Kotlin se presta a crear API fluidas como esta, lo que lo convierte en un código muy legible y marcos accesibles.

Funciones y constructores

Para crear nuestro lenguaje específico de dominio ( DSL ) para alojar API, estamos utilizando varias de las novedades sintácticas y características de lenguaje de Kotlin. En primer lugar:

  • Constructores : en Kotlin, no utiliza la newpalabra clave para crear instancias de objetos; en su lugar, usa el nombre de la clase junto con paréntesis, como si estuviera invocando la clase como una función (a la Python). En el fragmento anterior, ContainerComposerse está creando un nuevo objeto invocando su constructor predeterminado .
  • Funciones : Las funciones , que comienzan con la funpalabra clave, se pueden definir en una clase o fuera de una (como hicimos anteriormente). Esta sintaxis significa que podemos escribir código orientado a objetos (OO) o no. Esto le dará más opciones y potencialmente eliminará muchas clases repetitivas.
  • Funciones de expresión única : la API fluida nos permite conectar todas nuestras rutas en una sola expresión. Cuando una función consta de una sola expresión como esta, podemos quitar las llaves y especificar el cuerpo de nuestra función después de un símbolo igual.
  • Omitir el tipo de retorno : cuando una función no devuelve un valor (es decir, cuando es "nula"), el tipo de retorno es UnitEn Kotlin, no tiene que especificar esto ; está implícito.

Si no usáramos estas dos últimas funciones, la versión un poco más detallada de nuestra función principal sería la siguiente:

fun main(args: Array) : Unit {
    // ...
}

La diferencia es solo unos pocos caracteres, pero el resultado es menos ruidoso.

Argumentos con nombre y literales de función de paso

La siguiente parte de este método principal es la llamada a la apifunción. Esta función utiliza algunas otras características interesantes:

  • Argumentos con nombre : cuando pathllamamos a la función, especificamos ciertos argumentos por nombre (por ejemplo, torenderWith). Hacerlo hace que el código sea más fluido.
  • Pasar literales de función fuera de la lista de argumentos : cuando una función, como nuestra apifunción, espera un argumento que es en sí mismo una función, puede pasarlo después de cerrar la lista de argumentos. Esto limpia mucho el código. Para ver lo que queremos decir con esto, observe la apidefinición de función:
fun api(composer: Composable, routes: () -> ListControllable<>) {
    // ...
}

Esta función toma dos argumentos:

  1. El compositor (más sobre eso en la próxima parte de esta serie)
  2. Las rutas como una función que no toma argumentos y produce una lista.

El segundo argumento es el interesante. Es una expresión lambda . En Kotlin, las lambdas se escriben () -> Tdonde los paréntesis contienen la lista de argumentos posiblemente vacía y sus tipos, un símbolo de flecha (es decir, ->o "produce") y el tipo de retorno. Nuestra apifunción usa esta sintaxis para definir su último argumento. En Kotlin, cuando el último argumento de una función también es una función, podemos pasar la expresión lambda fuera de la llamada. Sin esta capacidad, llamar al apimétodo se vería así:

api(ContainerComposer(), {
	// ...
})

¿Ver la diferencia? Si es un programador de jQuery, probablemente no lo entienda. Eche un vistazo a este ejemplo artificial que muestra la diferencia más claramente:

a({
b({ c({ }) }) })

¿Vealo Ahora? Cuando un método toma una función literal como argumento, termina con un grotesco intercambio de paréntesis y llaves. En cambio, Kotlin nos permite pasar el cuerpo de la función literal después de la llamada al método. ¡Los programadores de JQuery se unen! ¡Esta es su manera de salir de la trampa de los delimitadores en la que se ha encontrado! En cambio, Kotlin le permite escribir este tipo de oscilación como esta:

a()
{ b() { c() } }

Tan claro. Tan fácil de entender. Esta convención es lo que estamos usando en la llamada a la apifunción. Nuestras rutas se definen en una lambda que devuelve una lista de objetos de datos (que explicaremos en breve). El resultado es media docena de líneas de código que inician un servidor web que aloja nuestra API, configura tres rutas, las asigna a controladores y asocia plantillas a ciertos puntos finales. Esa es la poderosa tríada que mencionamos anteriormente ( lenguaje, tiempo de ejecución y marcos basados ​​en JVM ) que nos permiten comenzar a ofrecer API rápidamente.

Genéricos

Como vio en la definición de la apifunción, Kotlin tiene soporte para genéricos (es decir, plantillas de funciones). En Kotlin, los genéricos no son tan confusos como en Java. Lo que hace que los genéricos de Java sean tan complicados son los tipos parametrizados con comodines . Estos eran necesarios para garantizar la compatibilidad con versiones anteriores del código Java anterior. Kotlin no tiene comodines, lo que facilita mucho el uso de genéricos en este nuevo lenguaje. De hecho, los genéricos son tan fáciles para los desarrolladores de Java y C # que hay muy poco que decir.

Un aspecto de los genéricos de Kotlin que puede no estar claro al principio es el uso de la outanotación en algunos parámetros de la plantilla. Esto se ve en la definición de la RouteDataclase incluida en el código de muestra :

data class RouteData(
    val path: String,
    val controllerClass: Class,
    val template: String? = null)

Esta clase se parametriza junto con el argumento del constructor; controllerClassSin Tembargo, ambos tienen este modificador adicional ¿Qué significa esto? Significa que el tipo de salida Tno se pasará como entrada; en cambio, la RouteDataclase solo producirá objetos de tipo Tcomo salida. Esto es lo que se conoce como variación del sitio de declaración . Debido a que la RouteDataclase no consume ningún valor de tipo, Tsolo los produce como valores de retorno, el compilador sabe que es seguro que cualquier clase que se extienda Controllablese use como un valor de parámetro, ya que siempre se pueden convertir de manera segura en tiempo de ejecución a la Controllableinterfaz .

Si Tno fuera un tipo de solo salida, se requeriría un abatimiento potencialmente inseguro en tiempo de ejecución. Al proporcionar esta información adicional al compilador, podemos evitar los comodines (es decir, algo como RouteData<? extends Controllable>en Java) y terminar con genéricos más seguros y fáciles de usar.

Clases de datos

La dataanotación es otra característica interesante de Kotlin que estamos usando en la RouteDataclase. Este modificador le dice al compilador que los objetos de este tipo solo contendrán datos. Esto le permite sintetizar un montón de código estándar para nosotros. Específicamente, el compilador implementará los siguientes métodos para nosotros:

  • equals
  • hashCode
  • toString
  • copyy
  • Getters y setters para cada parámetro de constructor marcado con val(es decir, variables de solo lectura).

Después de definir una clase de datos, también podemos usarla para declarar y establecer los valores de múltiples variables simultáneamente de esta manera:

val (path, controllerClass, template) = routeData

Dado un objeto de datos de tipo RouteData, podemos separarlo en partes constituyentes, donde cada propiedad de la clase se asigna a las variables respectivas. Esto puede ayudarlo a escribir código autodocumentado y también se puede usar para devolver más de un valor de una función.

Múltiples valores de retorno de funciones

Una característica atractiva del lenguaje de Golang es su sintaxis que permite a los desarrolladores definir múltiples valores de retorno para una función. En Go, puede escribir un código muy descriptivo como este:

func (file *File) Write(b []byte) (n int, err error) {
    // ...
}

Esto dice que la función Writedevuelve dos valores: un número entero llamado nerrun errorobjeto. Esta construcción de lenguaje única evita la necesidad de pasar referencias a objetos que la función modificará cuando también se necesite un valor de retorno adicional. Esto es lo que uno tiene que hacer en Java, que puede ver en una versión basadaControllable en Java de nuestro tipo :

interface Controllable {
	default boolean get(Request request, Response response,
   	 final Map model) { return true; }

	default boolean post(Request request, Response response,
   	 final Map model) { return true; }

	default boolean put(Request request, Response response,
   	 final Map model) { return true; }

	// ...
}

Queremos volver dos cosas de getpostput, etc. - un indicador booleano que será utilizado para abortar si el enrutamiento false, y el modelo que contiene los valores de la plantilla (si se utiliza de plantillas por la vista). Aquí, el lenguaje Java realmente está trabajando en nuestra contra, obligándonos a escribir código poco claro. Google Go nos ayudaría a escribir esto con mayor claridad, al igual que Kotlin.

En Kotlin, nuestro Controllabletipo se define así:

abstract class Controllable {
	public open fun get(request: Request, response: Response):
   	 ControllerResult = ControllerResult()

	public open fun post(request: Request, response: Response):
   	 ControllerResult = ControllerResult()

	public open fun put(request: Request, response: Response):
   	 ControllerResult = ControllerResult()

	// ...
}

Kotlin nos permite decir que los métodos de nuestro controlador devuelven un ControllerResulttipo. Como se RouteDatadescribió anteriormente, ControllerResultes una clase de datos:

data class ControllerResult(
val continueProcessing: Boolean = true, val model: Map = emptyMap())

Con esta línea, podemos definir fácilmente un tipo de resultado que podemos usar Routerpara controlar el flujo de solicitudes de procesamiento y proporcionar vistas con datos de modelo.

Gran cosa, puedes decir. Crea una clase en Java y haz lo mismo. Por supuesto. Con aunque Java, nuestra ControllerResultclase se convierte en 50 líneas molestos de código después de que aplicamos equalstoStringhashCode, un constructor de copia, captadores y definidores. Como describimos anteriormente, las clases de datos incluyen todo esto en una línea de código . ¡Tómelo como una bebida refrescante después de un largo día de trabajo bajo el caluroso sol de verano!

Usando clases de datos, nuestros controladores pueden anular métodos en la Controllableclase de esta manera:

public override fun get(request: Request, response: Response): ControllerResult =
    ControllerResult(model = mapOf(
    	"user" to request.session(false).attribute("username"),
    	"data" to mapOf(
            	"e1" to "e1 value",
            	"e2" to "e2 value",
            	"e3" to "e3 value")))

Usando la topalabra clave y un mapa de solo lectura producido por la mapOffunción de la biblioteca Kotlin estándar , terminamos con una implementación muy sucinta pero legible de este método. Consulte los documentos de Kotlin para obtener más información sobre cómo crear mapas con la topalabra clave , la mapOffunción y los métodos de reemplazo definidos en una clase base . Sin embargo, por ahora, veamos cómo podemos usar los ControllerResultobjetos de una manera segura e intuitiva usando una de las mejores características del lenguaje de Kotlin.

Casts inteligentes

Como discutiremos más en la siguiente parte de esta serie de blogs, los métodos de nuestros controladores se invocan dinámicamente dependiendo del método HTTP utilizado por el cliente. Esto se hace en la Routerclase así:

val httpMethod = request.requestMethod().toLowerCase()
val method = controllerClass.getMethod(httpMethod, javaClass(), javaClass())
val result = method.invoke(controller, request, response)

if (result is ControllerResult && result.continueProcessing)
{
   controller.after(request, response)

   model = result.model
}

En las primeras tres líneas, usamos la reflexión para invocar un método en el controlador que tiene el mismo nombre que el método HTTP especificado por nuestro consumidor de API. Invokese define en el tiempo de ejecución de Java para devolver un Objectarchivo que Kotlin representa como AnyEsto es útil porque dos de nuestros Controllablemétodos, beforeafter, no devuelven ControllerResultobjetos mientras que la mayoría de ellos lo hacen. Usando la función de lenguaje de transmisión inteligente de Kotlin , podemos escribir un código muy claro y seguro para manejar esta discrepancia.

En el fragmento anterior, verificamos en tiempo de ejecución para ver si el Anyobjeto es de tipo ControllerResultEsto se hace usando el operador is de Kotlin en la instrucción if. Si es así, también verificamos si la continueProcessingpropiedad del objeto de datos regresa trueHacemos esto sin lanzarlo. En el lado derecho del &&operador lógico , Kotlin trata el resultobjeto no como un tipo Anysino como un tipo ControllerResultSin tener que escribir código para realizar la conversión, podemos acceder a la ContinueProcessingpropiedad del objeto Sin conversión inteligente y sin propiedades, tendríamos que escribir esta declaración condicional detalladamente en Java de esta manera:

if (result instanceof ControllerResult) {
    ControllerResult controllerResult = (ControllerResult)result;

    if (controllerResult.getContinueProcessing()) {
        // ...
    }
}

Incluso con el asoperador de C # , terminamos con un código que no es tan claro como el de Kotlin. En C #, tendríamos que escribir esto:

ControllerResult controllerResult = result as ControllerResult
if (controllerResult != null && controllerResult.continueProcessing) {
// ...
}

Kotlin nos permite evitar todo este código confuso y detallado. Esto garantizará que nuestra intención sea más clara y nos ayudará a encontrar y corregir errores en nuestras API más rápidamente.

Java Meetup Medium CTA-01

Usando Kotlin

Debido a su interoperabilidad con otras herramientas en el ecosistema de Java, es muy fácil comenzar a usar Kotlin. Puede aprovechar todas las mismas herramientas y conocimientos que está utilizando hoy en su desarrollo de Java. ¿Construyendo con Ant o Maven? Esos trabajan con Kotlin. ¿Escribiendo código en Intellij IDEA, Eclipse o Sublime? ¡Sigue usándolos!

Para comenzar a usar sus herramientas favoritas con Kotlin, aquí hay algunos enlaces útiles:

  • Intellij IDEA
  • Paquete Kotlin Sublime Text 2
  • Eclipse
  • Guía de uso de Maven
  • Usando Gradle con Kotlin
  • Integración de hormigas

Conversión de código existente

Cuando comience a usar Kotlin, puede ayudar a convertir un proyecto Java existente a este nuevo lenguaje. Luego, puede ver cómo se ve el código familiar con Kotlin. Para convertir el código existente, debe usar Intellij , Eclipse o (si solo tiene un fragmento) la consola en línea de Kotlin . Al final, probablemente reescribirá gran parte del código convertido para usar más modismos y estilos de Kotlinic, pero convertir el código existente es un excelente punto de partida.

Compilando Kotlin

Ya sea que convierta su código o lo escriba desde cero, necesitará compilarlo. Los complementos IDE facilitan esto mientras trabaja. Sin embargo, para usar este lenguaje en proyectos más grandes, necesitará automatizar esas compilaciones. Esto requerirá integración con Maven, Ant o Gradle. Jetbrains y la comunidad de Kotlin los proporcionan listos para usar, y el uso es el que cabría esperar. Para un proyecto existente basado en Java que usa uno de estos, se puede cambiar a Kotlin reemplazando solo unas pocas líneas en su script de compilación. Por ejemplo, el proyecto de muestra que acompaña a esta serie se convirtió para compilar código Kotlin en lugar de Java con solo unas pocas docenas de líneas .

Depuración

Compilar código no es necesariamente código de trabajo. Para que su software sea funcional, puede usar uno de los muchos marcos de registro basados ​​en JVM para imprimir declaraciones de depuración. Puede ver esto en el proyecto de muestra que usa SLF4J y Log4j para imprimir declaraciones sobre solicitudes y respuestas de API. Aquí hay una muestra indicativa de AuthorizationController:

public class AuthorizeController : Controllable()
{
private val _logger = LoggerFactory.getLogger(javaClass())

public override fun before(request: Request, response: Response): Boolean
{
_logger.trace("before on Authorize controller invoked")

if (request.session(false) == null)
{
_logger.debug("No session exists. Redirecting to login")

response.redirect("/login")

// Return false to abort any further processing
return false
}

_logger.debug("Session exists")

return true
}

// ...
}

Algunas cosas a tener en cuenta sobre ese fragmento antes de continuar:

  • Es algo normal de SLF4J, por lo que no hay una curva de aprendizaje para los desarrolladores de Java.
  • El SLF4J LoggerFactoryrequiere una clase estática para inicializarlo. Esta es una clase de Java, por lo que usamos la ::classsintaxis de Kotlin para obtener un KClassobjeto y luego llamar a su javapropiedad de extensión. ¡Voila! Interoperabilidad de Java :)

La instrumentación básica solo te llevará hasta cierto punto; Sin embargo, a veces es necesario arremangarse y sumergirse en el código de ejecución. Puede hacer esto fácilmente en Intellij y Eclipse usando los depuradores de esas herramientas tal como lo haría con su código Java. En estos entornos, tiene las mismas herramientas en las que confía al depurar otro código basado en JVM. Por ejemplo, la pila de llamadas , la lista de subprocesos en ejecución , la evaluación de expresiones y, por supuesto , los puntos de interrupción , ¡están disponibles para usted! Aquí hay una captura de pantalla del código anterior que se ejecuta en Intellij con el depurador adjunto:

depuración

Encontrar errores será fácil más fácil con eso. Este es un ejemplo muy convincente de por qué Kotlin es una mejor opción para crear API a gran escala que otros lenguajes (por ejemplo, Go). Golang se puede depurar usando GDB , pero esa herramienta no es tan fácil de usar como los depuradores de Intellij y Eclipse).

Conclusión

A diferencia de otros entornos de programación, la JVM le ofrece opciones tanto de idiomas como de proveedores que pueden ayudarlo a crear una API increíble. En la JVM puede elegir entre lenguajes dinámicos como Groovy, funcionales como Scala y Clojure, y ahora otro rival: Kotlin . Hablamos sobre varias razones para usar este lenguaje y mostramos algunas de las características que ofrece esta nueva JVM advenediza.

Todo esto es genial, puedes estar diciendo, pero ¿cuál es el truco? Hay algunos inconvenientes , pero son menores. El argumento más fuerte en contra de Kotlin es su inmadurez: aún no está en la v1. Este es un problema que inevitablemente se solucionará con un poco más de tiempo. Incluso ahora, en el hito 12, el compilador le advierte sobre el uso de funciones de lenguaje obsoletas que no se incluirán en la versión inicial. Esto facilita el pivote y la preparación.

batalla

En la parte 2 de esta serie, profundizamos en Spark y lo explicamos más usando el código de muestra de Kotlin que comenzamos a desarrollar en esta publicación. Mientras tanto, asegúrese de registrarse para nuestro próximo evento en Estocolmo, donde discutiremos Kotlin, Clojure, Groovy y la creación de API en la JVM. Aprender más sobre Kotlin también podría brindarle la ventaja que necesitará si planea participar en el próximo hackathon de PayPal, BattleHack , que se llevará a cabo el 14 y 15 de noviembre en Estocolmo.

Continúe con la Parte 2: Creación de API en la JVM con Kotlin y Spark - Parte 2

Recursos de Kotlin

Si no vas a estar en Estocolmo este mes para la reunión, también puedes aprender más sobre este nuevo idioma en estos recursos:

  • Referencia del lenguaje Kotlin (comience aquí)
  • Hoja de referencia del lenguaje de programación Kotlin
  • Diseño de DSL en Kotlin
  • RE: Por qué Kotlin es mi próximo lenguaje de programación - Discusión de SubReddit
  • Ejemplo de proyecto de API web con Kotlin y Spark
  • Aprovechar al máximo la JVM con Java, Clojure, Kotlin y Groovy Meetup en Estocolmo
  • Creación de API en la JVM con Kotlin y Spark - Parte 2

[Divulgación: PayPal es patrocinador de la reunión de Java Estocolmo producida por las API nórdicas]

Publicar un comentario

0 Comentarios