Blog Arolla

Quand kotlin …

J'adore kotlin. En particulier parce qu'il me permet de limiter le bruit du langage, et de focaliser sur le fonctionnel et les intentions.

Pour illustrer ça, jouons au Jeu de la vie. C'est une manière simplifiée de simuler les comportements émergents de la vie. En particulier, au cœur de ce simulateur, on trouve les règles suivantes :

  • une cellule morte possédant exactement trois cellules voisines vivantes devient vivante (elle naît), sinon elle reste morte.
  • une cellule vivante possédant deux ou trois cellules voisines vivantes le reste, sinon elle meurt.

En java, j'aurais probablement écrit ce genre de code pour implémenter ces règles :

public Boolean willLive(Boolean didLive, int numberOfLiveNeighbours) {
    if (didLive) {
        if (numberOfLiveNeighbours == 2 || numberOfLiveNeighbours == 3)
            return true;
        else
            return false;
    }
    else if (numberOfLiveNeighbours == 3)
        return true;
    else return false;
}

En kotlin, je suis arrivé à du code comme ça, qui me semble plus clair :

fun willLive(didLive: Boolean, numberOfLiveNeighbours: Int): Boolean =
     when (didLive surroundedBy numberOfLiveNeighbours) {
        true surroundedBy 2, true surroundedBy 3 -> true
        false surroundedBy 3 -> true
        else -> false
    }

private infix fun Boolean.surroundedBy(numberOfLiveNeighbours: Int) = 
    Pair(this, numberOfLiveNeighbours)

J'y suis notamment arrivé grâce à la méthode d'extension infix surroundedBy, qui crée une instance de Pair. Elle m'a permis de mettre un petit peu plus en évidence le domaine, et surtout de limiter les niveaux d'imbrication.

Et pourtant, j'aurais aimé écrire un autre code :

fun willLive(didLive: Boolean, numberOfLiveNeighbours: Int): Boolean =
    when (didLive, numberOfLiveNeighbours) {
        (true, 2), (_, 3) -> true
        else -> false
    }

C'est le genre de code que j'aurais pu écrire en python, rust, scala, ou elm, et probablement beaucoup d'autres langages. Il met en œuvre deux fonctionnalités :

  • La possibilité de passer plusieurs arguments à when, voire d'y déconstruire un tuple ou un objet.
  • Le pattern matching sur plusieurs arguments. Ici, par ex, j'ai dit que je voulais qu'une paire de n'importe quel état et de 3 voisines vivantes donne une cellule vivante.

Kotlin n'offre ni l'une ni l'autre, et c'est une de ses grosses limites, qui frustre les devs qui viennent de langages plus complets de ce point de vue. Ça oblige à passer par des circonvolutions comme la méthode surroundedBy ci-dessus.

Et ça limite grandement les possibilités de refactoring progressif. En effet, le code auquel je suis naturellement arrivé par TDD en kotlin ressemble finalement au code java qu'on a vu plus haut :

fun willLive(didLive: Boolean, numberOfLiveNeighbours: Int): Boolean =
    if (didLive) when (numberOfLiveNeighbours) {
        2, 3 -> true
        else -> false
    } else when (numberOfLiveNeighbours) {
        3 -> true
        else -> false
    }

Si kotlin avait proposé ces possibilités, il aurait été facile pour intellij de détecter les if/when imbriqués sur les mêmes variables, et de proposer de les fusionner directement en un seul when. Puis de fusionner (true, 3) et (false, 3) en (_, 3). Sans ces fonctionnalités, il ne peut pas. C'est d'autant plus dommage que kotlin a été créé pour maximiser le refactoring automatique dans un IDE.

Pour arriver au premier morceau de code que je vous ai montré, j'ai dû abandonner les baby-steps automatiques, et monter une trop grosse marche à mon goût. J'obtiens une branche de trop dans le when. Et j'ai cette méthode surroundedBy qui sert de vitrine à des fonctionnalités intéressantes de kotlin, mais qui amène une complexité artificielle dont je me serais bien passé.

Dommage. Je pense que kotlin va devoir rapidement apporter ces fonctionnalités, surtout maintenant que java a décidé de s'y atteler. Même si ça va probablement prendre plusieurs années pour java.

Plus de publications

2 comments for “Quand kotlin …

  1. 20 janvier 2023 at 21 h 20 min

    Je suis aussi passé de Java à Kotlin.
    Impossible de retourner en arrière !

  2. Antoine Alberti
    27 janvier 2023 at 11 h 26 min

    Merci pour le commentaire

    J’ai aussi l’impression de revenir en arrière quand je repasse au java. La bonne nouvelle, c’est que, comme après chaque voyage, on a vu des paradigmes un peu différents en kotlin qui nous font mieux coder en java. Et ça nous permet d’être directement à l’aise avec les nouveautés de java.

    Et qui sait, peut-être qu’un jour java nous sortira une feature qu’on aimerait avoir en kotlin. Le when pattern matché en est un bon exemple.