Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Les DSLs en Kotlin

Les DSLs en Kotlin

La conception d’un code expressif, élégant et robuste.

Avatar for Corentin LEFFY

Corentin LEFFY

April 13, 2021
Tweet

Other Decks in Technology

Transcript

  1. Définition Domain Specific Language ou Langage dédié à un domaine

    : ◦ Fournit une notation orientée à un domaine d’application ◦ Se base sur les concepts et fonctionnalités du domaine en question ◦ Est un moyen efficace et élégant pour décrire et générer des programmes dans un domaine spécifique Source : Wikipédia 4
  2. DSL externe ◦ Possède sa propre syntaxe ◦ Nécessite un

    outil pour analyser le code, l’interpréter et le traduire en un autre code Exemples : HTML, CSS, Sass, PlantUML, SQL, Gherkin, ... 5 @startuml actor MyUser actor CustomerCare database database MyUser /> CustomerCare : Ask a refund CustomerCare /> database : Verify the data CustomerCare /> MyUser : Issue a refund @enduml
  3. DSL interne (ou embarqué) ◦ Utilise un langage hôte (Java,

    C#, Kotlin, …) ◦ Donne la sensation d’un langage particulier ◦ Est également appelé Fluent Interface 6 private void makeFluent(Customer customer) { customer.newOrder() .with(6, “TAL”) .with(5, “HPK”).skippable() .with(3, “LGV”) .priorityRush(); }
  4. Exemples de DSLs internes ◦ Les bibliothèques de test double

    (Mockito, Moq, Mockk, ...) : when(mockedList.get(0)).thenReturn(“first”); ◦ Les bibliothèques de tests (xUnit, Jest, Kotest, …) : assertEquals(“Hello, World !”, actualGreeting); ◦ Et plein d’autres encore : Jetpack Compose, Gradle, Spring integration DSL, Apache Camel DSL, ... 7
  5. Kotlin, c’est ... ◦ Un langage de programmation : ▫

    Multi-paradigmes (objet + fonctionnel) ▫ Statiquement typé ▫ Compilé vers la JVM, Javascript et plateformes natives (grâce à LLVM) ▫ Développé par JetBrains ▫ Open-source Source : Wikipédia 9
  6. Infix fetch.balance(12345678); 11 object fetch { infix fun balance(number: Int)

    = … } fetch balance 12345678 fetch.balance(12345678); Définit un Singleton Permet de supprimer les parenthèses et le point
  7. Infix 12 enum class Message { StatementReady, LowBalanceAlert } object

    send { fun message(messageId: Message, number: Int) = … } send.message(StatementReady, 12345678) ⚠ Le mot clef infix ne peut être utilisé que pour les fonctions avec un récepteur et un seul argument.
  8. Infix 13 enum class Message { StatementReady, LowBalanceAlert; infix fun

    to(number: Int) = … } object send { infix fun message(messageId: Message) = messageId } send message StatementReady to 12345678
  9. Fonctions d’extension 2 days ago 5 days after 14 enum

    class TimeAdverbs { ago, after } infix fun Int.days(duration: TimeAdverbs) = when(duration) { ago /> println("That's $this days ago") after /> println("That's $this days from now") } 2.days(ago) 5.days(after) Correspond à l’instance de la classe Int (2 et 5 dans notre cas)
  10. Opérateurs May in begin/.end e 15 Opérateurs contains et rangeTo

    val begin = LocalDate.of(2020, 2, 15) val end = LocalDate.of(2020, 9, 30) val May = Month.MAY val June = Month.JUNE ////. operator fun ClosedRange<LocalDate>.contains(month: Month) = month.value /= start.month.value /& month.value /= endInclusive.month.value
  11. Opérateurs ◦ +a ◦ -a ◦ !a ◦ a/+ ◦

    a/- ◦ a + b ◦ a - b ◦ a * b ◦ a / b ◦ a % b ◦ a += b ◦ a -= b ◦ a *= b ◦ a /= b ◦ a %= b ◦ a > b ◦ a < b ◦ a /= b ◦ a /= b ◦ a() 17 Liste des opérateurs disponibles : ◦ a/.b ◦ a in b ◦ a !in b ◦ a[i] ◦ a[i] = b ◦ a(i) Source : Kotlin - Operator Overloading
  12. Fournir un contexte build { version = "1.2" src =

    "/src" test = "/test" dependency("some.library") dependency("another.library") task("test") { jvmArgs = "-p somepath" } } 18 build { version = "1.2" src = "/src" test = "/test" dependency("some.library") dependency("another.library") task("test") { jvmArgs = "-p somepath" } } Code exécuté dans un contexte build { version = "1.2" src = "/src" test = "/test" dependency("some.library") dependency("another.library") task("test") { jvmArgs = "-p somepath" } } Code exécuté dans un autre contexte
  13. Fournir un contexte fun build(block: Config.() /> Unit): Config 19

    fun build(block: Config.() /> Unit): Config { val configuration = Config() configuration.block() return configuration } Définit la lambda comme une fonction d’extension de la classe Config fun build(block: Config.() /> Unit) = Config().apply(block) build({//.}) build({//.}) build {//.}
  14. Classe interne schedule meeting { starts at 14.30 ends at

    15/.30 } 20 object schedule { infix fun meeting(block: Meeting.() /> Unit) = Meeting().apply(block) }
  15. Classe interne 21 class Meeting { var startTime = IntRange.EMPTY

    var endTime = IntRange.EMPTY } val starts = Starts() inner class Starts { infix fun at(time: IntRange) { startTime = time } } // Même chose pour endTime La classe Starts connaît l’ état interne de la classe Meeting
  16. Pour résumer Infix Le mot clef infix permet de supprimer

    le superflux Fonctions d’extension Ajouter de nouveaux comportements à des classes Fournir un contexte Exécuter des méthodes dans un context précis Classe interne Pour partager l’état d’un objet entre différents contextes 22 Opérateurs Surcharger les différents opérateurs pour simplifier la lecture
  17. OK, mais dans la vraie vie, mais à quel moment

    ? 23 une visite { prevu le "30-01-2021" demarrant le "15-03-2021" tarifs { +"M1" +"M2" +"M3" } } • Code de tests = Bac à sable = Droits à l’erreur • Test Data Builder pour créer des visites (objets complexes) au sein des scénarios de tests • Facilite la lecture des tests pour des experts métiers ou testeurs (non-développeurs)
  18. RÉFÉRENCES ◦ Programming DSLs in Kotlin : Design Expressive and

    Robust Special Purpose Code - Venkat Subramaniam ◦ Dessine moi ... un DSL en Kotlin - Benoît Prioux ◦ Create DSL with Kotlin - s1m0nw1 ◦ Kotest - Bibliothèque de tests ◦ Jetpack Compose - Bibliothèque pour créer des composants Android 24
  19. CRÉDITS Merci à toutes les personnes qui ont créé et

    publié ces ressources géniales gratuitement : ◦ Modèle de présentation de SlidesCarnival 26