https://a.storyblok.com/f/270183/1368x665/d80f2b5c9f/kotlin_sdk-updates.png

Annonce du SDK Kotlin Server de Vonage

Publié le October 25, 2024

Temps de lecture : 17 minutes

Introduction

Lorsque Kotlin est apparu pour la première fois au début des années 2010, peu de gens auraient pu imaginer qu'il deviendrait un des 20 premiers langages de programmation qu'il est aujourd'hui, dépassant d'autres langages JVM bien établis tels que Groovy et Scala. Depuis qu'il est devenu le langage de facto pour le développement d'applications Android, l'écosystème n'a fait que s'étendre avec de riches fonctionnalités et une conférence annuelle dédiée.

Malgré la mise à jour de la cadence de publication et l'afflux de fonctionnalités du langage pour rester pertinent, Kotlin reste un langage populaire au-delà des applications mobiles. Pour le développement côté serveur, Kotlin est un excellent choix pour plusieurs raisons : un riche écosystème de bibliothèques existantes (ce dont bénéficient tous les langages basés sur la JVM), même la dernière version 2.0 est toujours compatible avec le bytecode Java 8 vieux d'une décennie, il est élégamment conçu dès le départ sans caractéristiques héritées et, de manière générale, il fait de la programmation un plaisir grâce à un minimum de "boilerplate" et à un sucre syntaxique et sémantique à la fois puissant et intuitif.

J'ai le plaisir d'annoncer que, après avoir travaillé à temps plein pendant un trimestre, le SDK Kotlin de Vonage de Vonage est maintenant officiellement disponible et pris en charge à partir de la v1.0.0! Il est publié sur Maven Centraloù vous trouverez également des instructions pour l'utiliser dans votre système de construction. Avec ce SDK, vous pouvez utiliser toutes les API de Voice en Kotlin pour passer des appels vocaux, envoyer et recevoir des SMS, et créer des applications Video. Dans cet article de blog, je vais expliquer comment et pourquoi ce SDK a vu le jour.

Contexte

Conscients de la prévalence croissante de Kotlin côté serveur, et du fait que de nombreux développeurs Kotlin ont les yeux qui se froncent lorsqu'ils doivent travailler avec Java, nous avons envisagé de fournir des extraits de code Kotlin pour le Java Server SDK. Après tout, l'un des avantages de Kotlin est sa compatibilité transparente avec Java. Cependant, nous avons décidé d'aller plus loin. Nous voulions offrir une expérience de premier ordre aux développeurs Kotlin, mais sans le coût et la charge de maintenance qu'implique le développement d'un SDK à partir de zéro. Notre objectif était de créer une preuve de concept dans un délai relativement court, qui aboutirait à terme à un SDK à part entière, tout en continuant à utiliser le SDK Java pour sa mise en œuvre et son modèle de données. Le reste est... eh bien, dans l'historique des modifications. historique du commit!

Motivation

La question qui vient naturellement à l'esprit est la suivante : "Qu'est-ce qui ne va pas avec le SDK Java ? qu'est-ce qui ne va pas avec le SDK Java ? Après tout, je le maintiens plus ou moins à plein temps depuis le deuxième trimestre 2022, et Kotlin lui-même fait beaucoup d'efforts pour assurer la compatibilité. La réponse réside dans l'écart entre Kotlin et les caractéristiques du langage Java. La réputation de verbosité de Java, combinée à la réticence des entreprises à migrer vers Java 8 (ou du moins à le faire à un rythme glacial), et le fait que la compatibilité entre les deux langages se situe au niveau du bytecode, signifient que ce qui peut être idiomatique en Java ne se traduit pas nécessairement bien en Kotlin. De plus, l'arsenal impressionnant de fonctionnalités puissantes du langage Kotlin ne peut être exploité que par du code écrit en Kotlin.

Nullité

L'une des caractéristiques de Kotlin par rapport à Java est sa distinction entre les valeurs nullables et non nullables. Cette distinction n'est pas réalisée au moyen d'une structure monadique telle que java.util.Optional; elle est propre au langage et à sa syntaxe. Par conséquent, Toute (l'équivalent de Objet) et Any ? sont deux types bien distincts : le premier est non annulable et le second est annulable. Comme Java ne fait pas cette distinction (sauf pour les types primitifs), Kotlin a la notion de "types de plate-forme"qui sont désignés par un point d'exclamation (par ex. Tout !). Cela permet de contourner la caractéristique de nullité de Kotlin pour des raisons de compatibilité. La création d'un SDK Kotlin permet d'être explicite sur ce qui est ou n'est pas nullable, à la fois dans les paramètres des fonctions et dans les types de retour.

Paramètres nommés, par défaut et optionnels

Le principal avantage de la nullité explicite est peut-être mieux compris dans les arguments de fonction. L'utilisation de Optional en Java n'est pas vraiment élégante, mais en Kotlin, les paramètres optionnels peuvent être rendus explicites dans le code en les déclarant comme nullables et en leur attribuant la valeur null par défaut. Cela permet aux utilisateurs de ne spécifier que ce qu'ils veulent et ce dont ils ont vraiment besoin. En outre, Kotlin dispose de paramètres de fonction nommés, ce qui signifie que les arguments ne doivent pas être fournis en fonction de leur position ; ils peuvent être déclarés explicitement, ce qui permet à l'utilisateur d'ignorer certains paramètres facultatifs et de rendre explicite le paramètre qu'il fournit sans avoir à s'appuyer sur les incrustations de code d'un IDE - particulièrement utile lorsqu'il y a plusieurs paramètres du même type. En outre, la possibilité de définir des valeurs par défaut, même pour les paramètres non annulables, présente l'avantage de documenter explicitement la valeur par défaut et signifie qu'une seule méthode doit être déclarée pour chaque fonction, plutôt que des surcharges avec un nombre variable d'arguments pour chaque combinaison, comme c'est le cas en Java.

Par exemple, une opération courante sur la plupart de nos API consiste à dresser la liste des ressources - il s'agit généralement de la ressource centrale d'une API - Utilisateurs, Appels, Applications, Diffusions, etc. La signature de la méthode listRender dans l'API Video illustre ce point : les valeurs par défaut des paramètres count et offset sont fournies. Comme ces deux paramètres sont du même type, il serait impossible de fournir 4 variantes différentes de cette méthode en Java. En Kotlin, une seule méthode est nécessaire pour couvrir les quatre cas : aucun paramètre, décalage uniquement, count uniquement et les deux paramètres. Ces méthodes seraient invoquées comme suit :

video.listRenders()            // Default params
video.listRenders(count = 25)  // Count only
video.listRenders(offset = 10) // Offset only
video.listRenders(25, 10)      // Both params

Lambdas pour les constructeurs

Un autre inconvénient du SDK Java est sa forte dépendance à l'égard des constructeurs. J'ai déjà précédemment écrit sur le modèle Builderet sur le fait qu'il n'existe que parce que le langage n'a pas de paramètres de constructeur nommés et par défaut (optionnels). Dans certains cas, Kotlin nous permet d'éliminer complètement l'utilisation des constructeurs, en se basant uniquement sur les paramètres nommés / optionnels. Un bon exemple est l'implémentation de l'API Number Insight API. Remarquez que sous les couvertures, le constructeur du SDK Java est utilisé, mais que l'expressivité de Kotlin nous permet de délimiter les paramètres obligatoires et facultatifs en utilisant uniquement la signature de la méthode.

Cependant, tout réimplémenter en utilisant ce modèle nécessiterait plus de travail (et de duplication) que ce qui était prévu dans le cadre de ce projet et augmenterait le fardeau de la maintenance. Au lieu de cela, le modèle de construction établi dans le SDK Java peut être réutilisé dans Kotlin de manière très élégante en utilisant des "lambdas de suivi" ; une fonctionnalité qui est couramment utilisée dans la création de langages spécifiques à un domaine (DSL). Pour illustrer cela, commençons par quelques exemples de base. Dans l'implémentation de l'API mise en œuvre de l'API Messagesil existe des méthodes utilitaires pour chaque combinaison valide de type de message et de canal. Chaque fonction prend en entrée une expression lambda avec la classe Builder appropriée comme récepteur. Cela signifie que, du point de vue de l'utilisateur, l'envoi d'un SMS ressemblerait à ceci :

vonage.messages.send(smsText {
  from("Kotlin SDK")
  to(System.getenv("TO_NUMBER"))
  text("Hello, World!")
})

Les méthodes de, à et texte proviennent tous de l'outil SmsTextRequest.Builder du SmsTextRequest.Builder du SDK Java et de sa superclasse MessageRequest.Buildery compris la documentation et les paramètres. Cependant, du point de vue d'un développeur Kotlin, l'ensemble du processus d'obtention du constructeur et d'appel de la fonction build() est caché. Combiné aux paramètres par défaut, cela signifie que si tous les paramètres d'un constructeur sont optionnels, il peut être entièrement omis. Par exemple, voici l'implémentation de la méthode createSession dans l'API Video :

fun createSession(properties: CreateSessionRequest.Builder.() -> Unit = {}): CreateSessionResponse =
  client.createSession(CreateSessionRequest.builder().apply(properties).build())

Pour les paramètres par défaut, il peut être appelé comme suit :

val session = vonage.video.createSession()

Pour fournir des paramètres facultatifs, il est possible d'utiliser la syntaxe lambda, comme suit :

val session = vonage.video.createSession {
  mediaMode(MediaMode.RELAYED)
  archiveMode(ArchiveMode.MANUAL)
}

Il est également possible d'utiliser des lambdas de fin pour fournir des valeurs optionnelles. Les exemples les plus complexes se trouvent peut-être dans la mise en œuvre de l'API Voice, où la complexité de la définition des NCCO dans le SDK Java bénéficie le plus de cette approche. Pour illustrer, voici un exemple de création d'un appel vocal vers un numéro de téléphone avec deux actions - Parler et Connecter - dans le SDK Java, ainsi que d'autres configurations, écrites en Kotlin :

val callEvent = javaClient.voiceClient.createCall(Call.builder()
  .to(PhoneEndpoint("448001234567", "1p2#5"))
  .fromRandomNumber(true)
  .advancedMachineDetection(AdvancedMachineDetection.builder().build())
  .ncco(
    TalkAction.builder("Hello, this is a text-to-speech call.")
      .language(TextToSpeechLanguage.UNITED_KINGDOM_ENGLISH)
      .premium(true)
      .build(),
    ConnectAction.builder()
      .endpoint(SipEndpoint.builder("sip:me@example.org").build())
      .ringbackTone("http://example.com/ringback.mp3")
      .build()
  )
  .ringingTimer(30)
  .eventUrl("https://example.com/webhooks/events")
  .build()
)

Bien qu'il soit assez lisible avec une indentation appropriée, il n'est pas aussi élégant qu'une approche plus idiomatique. Voici la même chose écrite avec le SDK Kotlin :

val callEvent = vonage.voice.createCall {
  toPstn("448001234567", "1p2#5")
  fromRandomNumber(true)
  advancedMachineDetection()
  ncco(
    talkAction("Hello, this is a text-to-speech call.") {
      language(TextToSpeechLanguage.UNITED_KINGDOM_ENGLISH)
      premium(true)
    },
    connectToSip("sip:me@example.org") {
      ringbackTone("http://example.com/ringback.mp3")
    }
  )
  ringingTimer(30)
  eventUrl("https://example.com/webhooks/events")
}

Remarquez que la syntaxe du DSL est plus naturelle. En particulier, l'élément toPstn libère l'utilisateur de l'obligation d'appeler la fonction to et remarquez qu'en l'absence de toute configuration pour la détection avancée des machines, aucun constructeur ou lambda n'est nécessaire. Cependant, pour l'action talkActionle paramètre obligatoire - le texte à prononcer - fait partie du constructeur, tandis que les paramètres facultatifs se trouvent dans la lambda. De même, pour l'action connectToSip l'URI est obligatoire, avec un lambda optionnel pour une configuration supplémentaire. Dans les deux cas, la lambda peut être omise, comme suit :

val callEvent = vonage.voice.createCall {
  toPstn("448001234567", "1p2#5")
  fromRandomNumber(true)
  advancedMachineDetection()
  ncco(
    talkAction("Hello, this is a text-to-speech call.")
    connectToSip("sip:me@example.org")
  )
  ringingTimer(30)
  eventUrl("https://example.com/webhooks/events")
}

Vous pouvez voir comment cela est mis en œuvre dans les fonctions connectTo* de la Voice APIqui combinent deux constructeurs en un seul appel de fonction. Les paramètres des fonctions correspondent au point d'extrémité auquel on se connecte, et le lambda de fin sert à configurer la fonction connecter elle-même.

Critères d'évaluation basés sur les ressources

En plus de capitaliser sur les fonctionnalités soignées de Kotlin pour réduire la " boilerplate ", une autre distinction entre le SDK Kotlin et Java est que le SDK Kotlin a une approche basée sur les ressources pour faire des appels d'API. Dans la plupart des API de Vonage, il existe au moins une ressource qui peut être interrogée, créée, mise à jour et supprimée. Pour chacune de ces ressources, il existe une classe correspondant à cette ressource qui permet d'accéder à ces points d'extrémité. Ce que ces ressources ont en commun, c'est un identifiant unique. Plutôt que d'avoir à le mettre en cache ailleurs pour effectuer des appels répétés à l'API sur une ressource particulière, le SDK s'en charge, de sorte que l'identifiant n'a pas besoin d'être fourni à chaque fois. Ces ressources peuvent même être imbriquées, comme le montre l'exemple suivant la mise en œuvre de l'API Video. En voici un exemple :

val existingSession = vonage.video.session(sessionId)
val streams = existingSession.listStreams()
existingSession.connection(connectionId).sendDtmf("1234")

Cela aura beaucoup plus de sens si vous utilisez un IDE avec auto-complétion. À cet égard, les appels d'API sont regroupés par type de ressource. En particulier dans les API complexes telles que Video, où il existe des ressources et des ID imbriqués, la tâche consistant à fournir un ID est moins sujette à erreur, puisque le paramètre requis est fourni par construction. Cela permet d'alléger les signatures de méthodes pour les ressources imbriquées, de sorte que vous puissiez vous concentrer sur la fourniture de paramètres significatifs séparément de l'adressage de la ressource. En revanche, le SDK Java est "plat/sans contexte" en ce sens qu'il existe généralement une correspondance univoque entre les points finaux de la spécification de l'API et les points finaux du SDK. Cette approche améliore encore la séparation des paramètres obligatoires et facultatifs et signifie qu'une demande est plus susceptible d'être correcte par construction.

Jetez un coup d'œil à la spécification de l'API pour la mise en sourdine d'un flux vidéo. spécification de l'API pour la mise en sourdine d'un flux vidéo à titre d'exemple. Il est clair que les coordonnées du point de terminaison nécessitent l'ID de la session et l'ID du flux. Dans l'implémentation du l'implémentation du SDK Javail est possible de confondre l'ID de session et l'ID de flux en les transmettant dans le mauvais ordre. En revanche, l'implémentation du SDK Kotlin l'implémentation du SDK Kotlin ne nécessite aucun paramètre, puisqu'aucune donnée n'est envoyée. De la même manière, pour ajouter un flux à une archivel'implémentation du Kotlin SDK comporte une seule méthode dans laquelle il est clair que l'identifiant du flux est le paramètre qui doit être transmis, compte tenu du contexte. En revanche, l'implémentation du SDK Java comporte deux méthodes (en raison des paramètres facultatifs) et s'appuie sur le nom et la documentation de la méthode pour décrire son fonctionnement et son action.

Il s'agit peut-être d'une question de préférence personnelle ; aucune des deux approches ne peut être considérée comme objectivement meilleure. Toutefois, la cohérence avec laquelle le SDK Kotlin suit cette approche dans toutes les API lorsque cela est possible est un aspect distinctif important, en particulier si l'on considère la forte dépendance du SDK Java à l'égard des constructeurs, même pour les paramètres obligatoires.

Extensions

Une autre fonctionnalité intéressante de Kotlin est les fonctions d'extensionla possibilité de définir des méthodes sur des classes existantes sans les étendre. Ceci est particulièrement utile pour améliorer les constructeurs définis dans le SDK Java afin de les rendre plus idiomatiques en Kotlin. Prenons, par exemple, l API d'application. Chaque Applications Vonage peut avoir plusieurs capacités, une de chaque type. Chaque capacité a un ou plusieurs Webhooks, et chaque Webhook a un type, tel que answer_url, status_url, event_url etc. Toutefois, en fonction du type de capacité, seuls certains Webhooks sont applicables. Par exemple, pour la capacité Verify, seuls les Webhooks suivants sont applicables status_urltandis que la capacité Voice a un answer_url, fallback_answer_url et event_url. Au moment de la rédaction du présent document, l'implémentation du SDK Java est assez maladroite. Voici un exemple de mise à jour du nom d'une application existante, de suppression de la capacité Messages et de mise à jour des webhooks pour Verify et Voice. Notez que pour mettre à jour une application, il faut d'abord la récupérer, car quelle que soit la configuration fournie, elle écrasera l'application existante. Ici, l'application est écrite à l'aide du SDK Java :

val ac = javaClient.applicationClient
val existing = ac.getApplication(appId)
val updated = ac.updateApplication(Application.builder(existing)
  .name("My Updated Application")
  .addCapability(Verify.builder()
    .addWebhook(Webhook.Type.STATUS, Webhook.builder()
      .address("https://example.org/webhooks/verify/status")
      .method(HttpMethod.POST)
      .build()
    )
    .build()
  )
  .addCapability(Voice.builder()
    .addWebhook(Webhook.Type.ANSWER, Webhook.builder()
      .address("https://example.org/webhooks/voice/answer")
      .method(HttpMethod.POST)
      .build()
    )
    .addWebhook(Webhook.Type.EVENT, Webhook.builder()
      .address("https://example.org/webhooks/voice/event")
      .method(HttpMethod.GET)
      .build()
    )
    .build()
  )
  .removeCapability(Capability.Type.MESSAGES)
  .build()
)

Cela fait beaucoup de constructeurs ! Il est facile de se perdre, et rien dans la conception ne vous empêche de spécifier le mauvais type de webhook pour une capacité. Comparez cela au SDK Kotlin :

val ac = vonage.application
val application = ac.application(appId)
application.update {
  name("My Updated Application")
  verify {
    status {
      url("https://example.org/webhooks/verify/status")
      method(HttpMethod.POST)
    }
  }
  voice {
    answer {
      url("https://example.org/webhooks/voice/answer")
      method(HttpMethod.GET)
    }
    event {
      url("https://example.org/webhooks/voice/event")
      method(HttpMethod.POST)
    }
  }
  removeCapability(Capability.Type.MESSAGES)
}

Remarquez que nous n'avons même pas eu besoin d'obtenir l'application à l'aide du point de terminaison - le SDK s'en charge. le SDK s'en charge pour vous. En outre, les fonctions d'extension définies sur chaque capacité limitent les webhooks qui peuvent être définis, de sorte qu'ils sont corrects par construction. Cela aura plus de sens si vous utilisez un IDE avec auto-complétion, mais en fait, lorsque vous êtes à l'intérieur, par exemple, de l'application Voice les seules options qui apparaissent sont réponse, réponse de repli et événementcar ce sont les seuls définies sur le constructeur en tant qu'extension. Il n'y a aucune mention de "build" nulle part, et il n'est même pas nécessaire de spécifier directement le type de webhook : il suffit de déclarer l'élément approprié.

Ce sont de petites choses comme celles-ci qui peuvent améliorer l'expérience et la productivité des développeurs. Bien sûr, comme nous ne générons pas automatiquement nos SDK chez Vonage, cela pourrait également s'appliquer à Java. En fait, dans le cadre du développement du SDK Kotlin, j'ai dressé une liste des éléments à modifier dans le SDK Java, qu'ils soient petits ou grands. Au moment où j'écris ces lignes, cette liste pourrait être convertie en 55 tickets JIRA ! Cependant, il est agréable de constater que des gains faciles peuvent être obtenus grâce à des fonctions d'extension. Bien sûr, toutes les améliorations du SDK Kotlin ne peuvent ni ne doivent être reportées sur le SDK Java.

Documentation

Le SDK Kotlin est documenté à l'aide de KDocs. Chaque fonction et classe dispose d'une documentation écrite à la main sur les paramètres, le type de retour, les exceptions et une description de ce qu'elle fait. En outre, ces documents sont publiés au format moderne Dokka HTML, dans le style de la documentation de l'API Kotlin, par opposition au format Javadocs, d'apparence relativement désuète. Vous pouvez parcourir la documentation en utilisant n'importe quel service capable de restituer des documents à partir de fichiers JAR, comme Javadoc.io. Bien entendu, la documentation est également disponible directement dans votre IDE.

Échantillons de code

Vous trouverez des extraits de code pour toutes les API prises en charge sur notre portail des développeurs. Il vous suffit de naviguer jusqu'au produit qui vous intéresse et, sous "Build Your Solution", vous trouverez les extraits de code pour lesquels Kotlin est l'un des langages. Vous pouvez également les consulter directement et les exécuter à l'aide de la fonction Vonage Kotlin Code Snippets sur GitHub. Par exemple, voici un texte "Hello World", voici un extrait de synthèse vocale "Hello World" utilisant l'API Voice dans le SDK Kotlin. Chaque extrait de code, tel qu'il est présenté sur la page de documentation, comporte également un lien vers le code source de soutien sur GitHub. Pour exécuter les exemples, il suffit de consulter le dépôt et de définir les variables d'environnement, puis de les exécuter via Gradle ou votre IDE. Les instructions pour cela peuvent être trouvées dans le fichier README.

Essais

Le SDK a 99 % de couverture du code au moment de la rédaction du présent document. Chaque fonction est testée, avec les paramètres obligatoires et facultatifs. Même les éléments qui résident dans le SDK Java sont testés pour être complets. L'approche adoptée est un test de bout en bout / d'intégration puisque le SDK Java teste déjà le modèle de données et la validation des paramètres. J'ai décidé d'utiliser WireMock pour cela ; un cadre pour les tests d'API.

J'ai construit une petite bibliothèque de fonctions de haut niveau pour faciliter l'affirmation des corps et en-têtes des requêtes et des réponses. Le résultat est que chaque test se lit comme une spécification, comme tous les bons tests devraient le faire. L'anatomie d'un test consiste à simuler l'URL d'extrémité attendue, la méthode HTTP, le corps de la requête (JSON ou paramètres de requête), les en-têtes (authentification, type de contenu, agent utilisateur), les paramètres de réponse attendus (s'il y en a, au format JSON) et le code d'état HTTP. Cela reflète essentiellement la spécification de l'API dans le code. Pour rendre l'écriture des tests moins verbeuse et moins sujette aux erreurs, les corps de la requête et de la réponse ne sont pas écrits directement au format JSON, mais sous la forme d'une Map<String, Any>. Celle-ci peut être sérialisée à l'aide de Jackson, de sorte qu'il suffit de fournir les noms de propriété corrects et les valeurs attendues.

Voici un exemple qui teste l'envoi d'une nouvelle demande à un utilisateur dans l'API l'API Verify. Vous pouvez voir tous les éléments en jeu ici, l'approche déclarative de la définition de la spécification et la façon dont elle capture tous les éléments de la spécification OpenAPI. Dans la pratique, la plupart des tests du SDK utilisent des méthodes de niveau supérieur déclarées dans le même fichier afin de réduire davantage la duplication et la complexité. En outre, chaque paramètre est testé, de sorte que chaque point final dispose souvent de deux méthodes de test : l'une pour tous les paramètres et l'autre pour les paramètres requis uniquement. Les tests les plus complexes concernent l Voice APImême si l'approche déclarative les rend beaucoup plus lisibles et faciles à maintenir que les tests relativement verbeux qui utilisent JSON directement dans le SDK Java. Par exemple, comparez les tests de Video API dans le SDK Java et Kotlin SDKJe suis sûr que vous serez d'accord !

L'avantage d'avoir des tests qui sont écrits à la base indépendamment de l'implémentation sous-jacente est qu'à l'avenir, n'importe qui pourrait réécrire le SDK en Kotlin pur sans utiliser le SDK Java. Les tests décrivent la spécification, de sorte que seules les utilisations réelles du SDK devraient être modifiées, et non les mocks. La seule chose que le SDK Kotlin ne teste pas est la validation des paramètres, c'est-à-dire si certaines combinaisons de paramètres sont valides, ou les paramètres requis dans les constructeurs. La validation du modèle de données est testée dans le SDK Java et n'est volontairement pas reproduite dans le SDK Kotlin. Certains pourraient même affirmer que c'est le backend de l'API qui devrait effectuer la validation et renvoyer une réponse d'erreur, et non le SDK. Pour éviter de dupliquer la logique de validation et d'alourdir encore les tests et le temps de développement, cet aspect a été intentionnellement laissé en dehors du champ d'application, car il s'agit d'une préoccupation orthogonale.

Prochaines étapes

Bien que le SDK soit maintenant officiellement pris en charge avec des implémentations de toutes les API de Vonage en état de disponibilité générale, ce n'est que le début. En plus de suivre les nouvelles fonctionnalités et API en tandem avec le SDK Java, il y a des tutoriels à écrire, des intégrations à construire et des améliorations diverses à apporter en fonction des commentaires des utilisateurs. À ce propos, les commentaires et suggestions de la communauté sont les bienvenus, même s'ils impliquent des changements radicaux. Essayez le SDK et dites-nous ce que vous en pensez !

Clôture de la session

C'est tout pour l'instant. Si vous rencontrez des problèmes ou si vous avez des suggestions d'amélioration, n'hésitez pas à soulever un problème sur GitHubou de nous contacter sur X (anciennement Twitter) ou de passer par notre Communauté Slack. J'espère que vous aurez une expérience agréable avec le SDK Kotlin, et je suis impatient de recevoir vos commentaires.

Partager:

https://a.storyblok.com/f/270183/400x400/46a3751f47/sina-madani.png
Sina MadaniVonage Ancien membre de l'équipe

Sina est développeur Java chez Vonage. Il est issu d'une formation universitaire et est généralement curieux de tout ce qui touche aux voitures, aux ordinateurs, à la programmation, à la technologie et à la nature humaine. Pendant son temps libre, on peut le trouver en train de marcher ou de jouer à des jeux vidéo compétitifs.