Kotlin progresse encore pour atteindre 1,18% de part de marché.
J'ai mis à jour ce post afin de montrer l'évolution. 14 places en 1 an c'est beaucoup. Je pense que Kotlin est en train de manger les parts de Java et le phénomène s'accélère.
Par contre qu'arrivera-t-il à la JVM lorsque Java ne sera plus utilisé et que Kotlin l'aura remplacé ?
Pour moi, la JVM devrait se transformer en moteur d'exécution et plusieurs langages tourneront dessus.
D'ailleurs c'est le projet d'Oracle avec GraalVM qui est déjà polyglotte et marche très bien.
— Liens directs
Je travaille en ce moment sur deux projets, un en Java/Kotlin pour des clients, un second en Rust pour des besoins internes, et j'ai réalisé la chose suivante :
C'est incroyable à quel point le borrow checker vous pousse à écrire du code procédurale et mécaniquement intestable. Dès l'instant où l'on souhaite passer par des traits tout devient ultra compliqué. Dernièrement je me suis faite avoir en utilisant des Rc
et des RcCell
sur un code qui allait devenir multi-thread #Horreur
Pour moi, casser le couplage entre deux composants via une interface/trait est IN-DIS-PEN-SABLE mais Rust pousse à définir des structures comme contrat d'interfaçage principal entre deux pans de code.
Forcément, le langage se transforme en enfer dès l'instant où l'on souhaite dépendre d'un trait et non d'une structure (c'est pourtant le 'I' de SOLID, dépendre des Interfaces mais pas des Implémentations).
En même temps je l'avais déjà dit par le passé, le paradigme fonctionnel pur est un cancer métastasé car l'expressivité de la syntaxe donne le sentiment que des tests ne sont pas nécessaires or c'est toujours faux.
Et j'ai suffisamment souffert de Java dans ma vie pour haïr le fait de devoir mocker/instancier/déclarer quarante-douze-mille trucs avant de pouvoir tester une simple fonction.
Bref, deux ans sur Rust à temps partiel et je me vois retourner dans le RustBook tous les 4 mois pour y chercher un truc #Pénible alors qu'en Kotlin ça ne m'arrive jamais.
— Liens directs
Un article qui montre comment invoquer du JS depuis du code Kotlin qui sera transpilé en JS ensuite.
Je cherche à supprimer TypeScript du code de mes SPA pour n'avoir que du Kotlin côté back, du Kotlin transpilé/compilé vers du JS ou vers WASM côté front et du DSL en Kotlin via Ktorm pour le SQL.
Bref un langage pour les contrôler tous.
— Liens directs
@Kalvn pour exécuter du JS sur Node quand tu veux avoir un maximum de contrôles appliqués par le compilateur tu peux aussi tout coder en Kotlin et transpiler tes sources en JS. Tu as un plugin Gradle et un plugin Maven qui gèrent ça pour toi.
On a du mal à se rendre compte à quel point Kotiln change la vie avant de l'avoir adopté. Je pense que le gain du passage de Java/C#/TS vers Kotlin est même plus important que le gain du passage de C/C++/ASM vers Rust, c'est dire !
Et avec le REPL des JRE 17+, on peut écrire des scripts en Kotlin (au sens Bash du terme), et ça c'est trop cool ! <3
]]>L'évolution de la demande de développeurs Kotlin est en plein boom en France 😁 :
Rust ne suit pas encore mais c'est un résultat attendu puisque l'emploi est pour l'instant situé en Chine, en Corée et aux USA et l'étude se focalise sur la France. Au fil des mois, il devrait phagocyter tout doucement ses parts à C et surtout C++ 🤩 :
La bonne surprise c'est de voir que Kotlin se positionne très bien sur la grille des salaires bruts 🤑 :
Pour l'instant j'ai eu le nez creux avec Kotlin, il faut dire que le compilateur fait des choses époustouflantes, notament la preuve d'absence de de référencement de pointeurs (NullPointer) lors de la compilation, et que son API est merveilleuse comparée à Java (même si elle s'appuie dessus).
Il en va de même pour Rust, qui apporte tellement de choses qui manquent à C et C++, notamment la preuve d'absence de fuites memoire et de race-conditions dès la compilation ou encore un gestionnaire de paquets digne de ce nom.
Bref, attendons encore un peu avant de crier victoire mais pour l'instant, tout se profile comme il le faut pour moi et cela valait bien de s'investir autant 🥳.
— Liens directs
Une introduction à ce qu'il est possible de mesurer à l'aide de l'utilitaire jcmd
embarqué dans les JDK.
— Liens directs
Tout est dans le titre. Je suis en train de comparer plusieurs choses actuellement :
Le surcoût que représente la JRE 17 sur une application Kotlin.
Le gain qu'apporte une JRE 17 custom produite à l'aide de l'utilitaire JLink.
Les performances de (1) et (2) face à la même application codée en Rust, en termes de consommation mémoire et d'opérations par seconde.
Les nouvelles options que la JRE prends en paramètre et leurs effets sur le CPU, la mémoire et le débit.
Le tuning de JRE a toujours été compliqué, mais pour obtenir une JRE de 30 Mo optimisée comme il faut, il y a encore plus de choses à connaître et comprendre qu'avant. Damned !
— Liens directs
Alors la situation est un poil plus compliquée que ce qui est dit.
Sur les vieilles versions de Java, Oracle fait effectivement la chasse aux licences. Mais il s'agit d'un modèle privateur donc normal.
Sur les versions 8 à 19 de Java, le modèle est basé sur trois composantes. Une JVM (machine virtuelle Java) avec les dernières features, une JVM avec les derniers correctifs de stabilité ou de sécurité, une JVM gratuite.
Quelle est l'astuce ? Simple, on ne peut pas avoir ces trois composantes simultanément.
C'est-à-dire que soit on veut avoir les dernières features et être stable/securisé et alors on paie.
Soit on ne paie pas mais dans ce cas on a :
Enfin, rappellons que Java est libre (GPLv2) et que les projets Eclipse Temurin, Apache et OpenJDK ont fusionné pour donner naissance à une JVM 100% libre Adoptium. Donc bye bye Oracle.
Remarque : si vous codez en Kotlin, puisque le compilateur peut cibler la version de la JVM que vous utilisez et vous fournir les dernières features sans que la JVM ne soit a jour, alors autant partir sur la dernière LTS gratuite de Java et être tranquille côté sécurité / stabilité.
Sinon Kotlin se compile très bien en WASM et en natif aussi <3
— Liens directs
L'utilitaire JavaDoc ne fonctionne pas avec du code Kotlin (normal me direz-vous). Heureusement, Jetbrains fourni Dokka sous la forme de plugin Maven et Gradle permettant de faire la même chose.
Les annotations et syntaxes Dokka diffèrent un peu de la JavaDoc, voici un résumé :
@param Identique à JavaDoc
@property Pour documenter un attribut
@constructor Pour documenter un constructeur primaire
@return Identique à JavaDoc
Pour faire un lien vers une _classe/method/autre_ simplement écrire ceci
/** Je veux faire un lien vers [MaClass] **/
et Dokka fera le job
]]>Attention, Java 6 n'étant plus supportée les dépendances kotlin-stdlib-jdk7 et kotlin-stdlib-jdk8 n'existent plus (puisque c'est Java 8 la version minimale requise pour Kotlin à présent).
Il faut donc les remplacer par kotlin-stdlib. Une migration simple qui va poser de nombreux problèmes à certains, sans aucun doute.
— Liens directs
Je cite :
« À mesure qu'Android passe de C/C++ à Java/Kotlin/Rust, nous nous attendons à ce que le nombre de vulnérabilités liées à la sécurité de la mémoire continue de diminuer. Vivement un avenir où les bogues de corruption de la mémoire sur Android seront rares », a conclu Google.
Rust et Kotlin sont deux superbes langages (avec une petite préférence pour Kotlin). J'ai pourtant quelques reproches à faire à l'un et à l'autre mais quand je vois que le marché avance vers eux à grands pas, autant vous dire que j'en suis toute chose <3
Que du beau sous le soleil.
— Liens directs
En un exemple court et simple :
package com.memorynotfound;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
public class GetUpTime {
public static void main(String... args) throws InterruptedException {
RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
System.out.println("Up time: " + rb.getUptime() + " ms");
}
}
]]>Edit
En complément il y a ce projet sur lequel jcefmaven est basé.
Problème
Solution
Cette dépendance Maven qui intègre un moteur de rendu WebKit :
<dependency>
<groupId>me.friwi</groupId>
<artifactId>jcefmaven</artifactId>
<version>105.3.36</version>
</dependency>
Avec le tuto pour Java
//Create a new CefAppBuilder instance
CefAppBuilder builder = new CefAppBuilder();
//Configure the builder instance
builder.setInstallDir(new File("jcef-bundle")); //Default
builder.setProgressHandler(new ConsoleProgressHandler()); //Default
builder.addJcefArgs("--disable-gpu"); //Just an example
builder.getCefSettings().windowless_rendering_enabled = true; //Default - select OSR mode
//Set an app handler. Do not use CefApp.addAppHandler(...), it will break your code on MacOSX!
builder.setAppHandler(new MavenCefAppHandlerAdapter(){...});
//Build a CefApp instance using the configuration above
CefApp app = builder.build();
]]>Ceci se fait en deux étapes :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>LAST_SUREFIRE_VERSION</version>
<configuration>
<systemProperties>
<property>
<name>name-the-property-will-have-in-test</name>
<value>${my-property}</value>
</property>
</systemProperties>
</configuration>
</plugin>
val property = System.getProperty("name-the-property-will-have-in-test")
]]>Kotiln, Rust et Python progressent et de plus en plus de développeurs les adoptent (et c'est très bien).
J'ai été une grande utilisatrice de Python il y a un peu plus d'une quinzaine d'années lorsque je travaillais en labo sur du Data-Mining (l'ancêtre du Machine Learning). J'avais laissé de côté Python pour trois raisons à l'époque :
Aujourd'hui, si je devais produire un système temps-réel et très peu énergivore, je partirais sur Rust.
Dans tous les autres cas de figure, je prendrais Kotlin sur OpenJDK ou Kotlin native (via le compilateur Kotlin-native ou GraalVM).
Par contre Python n'est plus du tout dans ma liste car pour moi à présent, si l'exécution d'un langage n'est pas prouvée à la compilation, c'est un stop immédiat. La majorité des développeurs n'écrivant pas de tests et maîtrisant mal le code (en tout cas en industrie) c'est indispensable.
— Liens directs
Kotlin 1.7 se profile à l'horizon. Je vais rester sur Koltin 1.6 cette année, mais si les évolutions sur Kotlin-JS et Kotlin-Native débarquent, je vais vite changer d'avis :P
— Liens directs
Ahhh Java... Je me souviens de mon tout premier code en Java. J'étais encore au lycée, je voulais apprendre à faire des sites web pour notre club d'anglais et j'avais entendu parlé de JavaScript. Alors j'ai demandé un bouquin à mes parents mais vu le prix des livres à l'époque j'avais fait une croix dessus... Puis à Noël...
J'ai reçu un libre qui s'appelait Total Java ! Et mes parents tout fiers à l'époque : "Le libraire nous a dit que tu pourrais faire des sites avec ça"... Oui avec des Applets Maman #Facepalm.
En réalité, j'ai très vite adoré Java et puis j'ai appris à le détester en migrant vers Kotlin. Le langage en lui-même n'est trop pas mal :
A présent je me rends compte de la lourdeur de sa syntaxe, que sa capacité à gérer autant de paradigmes différents font de lui un langage dont la syntaxe devient au final incohérente, que la rétro-compatibilité ascendante garantie n'a jamais permis à Java de trier le bon grain de l'ivraie pour ne se focaliser que sur le nouveau ; rétro-compatibilité depuis 1995 quand même !
@Warrior Du Dimanche si tu as des questions en Java demande, je tâcherai d'y répondre :-*. Mais quitte à bosser sur JVM, je te recommande Kotlin, bien plus élégant, bien plus expressif, bien mieux !
— Liens directs
Excellente idée ! Merci à @Philou pour le lien.
— Liens directs
Retour d'expérience d'une équipe d'Amazon Prime sur l'utilisation de Kotlin à la place de Java.
Overall : 75% de devs satisfaits de la transition.
— Liens directs
Excellent, je cherchais un moteur Kotlin 2D sympa pour un kata un peu gros. C'est top !
Merci @Riduidel
— Liens directs
La polygot maven extension permet de produit des pom en Yaml (j'avais fait un tuto ici en son temps) et maintenant en Kotlin. Vous savez que j'adore Kotlin et pourtant je vois dans cette opportunité une immondice sans nom pour ne pas dire la plus grande des saloperies !
Pourquoi ?
Parce que le DSL Kotlin permet de coder dans le pom dont le but est qu'il soit pourtant 100 % déclaratif. Car du code dans un pom n'aura jamais de TU, a un probabilité très haute de ne pas être portable et surtout, chaque évolution du code ne profitera ni à la communauté (car pas de plugin) et deviendra un risque pour l'entreprise qui va accentuer l'effet "copier-coller".
Non vraiment, si c'était pour faire de Maven la même horreur de maintenance que l'est Gradle, mais les performances en moins, je pense qu'il valait mieux s'abstenir.
Voici l'exemple qui m'a fait vomir deux fois (vous saurez apprécier le code à copier-coller dans chaque projet d'entreprise en début de pom n'est-ce pas ?) :
import java.io.File
// define a comparable data class to simplify handling versions
data class Version(val major: Int, val minor: Int, val patch: Int) : Comparable<Version> {
override fun compareTo(other: Version): Int =
compareValuesBy(this, other, Version::major, Version::minor, Version::patch)
override fun toString(): String = "$major.$minor.$patch"
}
// define a function to execute the git command and return its standard output
fun git(vararg args: String): String {
// use the basedir of the project as the command's working dir if it contains a '.git' subdir
// otherwise use the current working directory of this script if it contains a '.git' subdir
// if both conditions are false the result will be null; the git command will probably fail
val workingDir = basedir.takeIf { it.resolve(".git").exists() }
?: File(".").takeIf { it.resolve(".git").exists() }
// run the git command with the provided arguments
val process = ProcessBuilder()
.directory(workingDir)
.redirectErrorStream(true)
.command(listOf("git") + args)
.start()
// read the standard output completely as a String
val output = process.inputStream.bufferedReader().readText().trim()
// return the output if the exit value is 0 or throw an exception otherwise
if (process.waitFor() == 0) return output
else throw IllegalStateException(output)
}
val gitVersions by lazy {
// run the `git tag` command
git("tag")
// the returned list of tags is separated by newlines
.split("\n")
// filter out only tags that are versions (such as 1.231.15)
.filter { it.matches(Regex("[0-9]+\\.[0-9]+\\.[0-9]")) }
// the separate parts of each version are separated by dots,
// also parse each part as an int
.map { it.split('.').map { it.toInt() } }
// map each triple of numbers to an instance of the `Version` class
.map { (major, minor, patch) -> Version(major, minor, patch) }
// sort the list of versions
.sorted()
}
// the last release is always the tag with the highest version number
val lastRelease by lazy {
gitVersions.max()
}
// the next version is determined based on the git commit log
val nextVersion by lazy {
// use the lsat released version as the base
val baseVersion = lastRelease
// if there are no releases yet, we use the version 0.0.1
if (baseVersion == null) Version(0, 0, 1)
else {
// split the base version in each separate part using destructuring
val (major, minor, patch) = baseVersion
// create a separator to split each log message on (log messages are multiline)
val separator = "-".repeat(5) + "commit" + "-".repeat(5)
// get all log messages from the last release tag until the current HEAD
// for each commit the separator is printed + the full commit message
val logMessages = git("log", "--pretty=format:$separator%n%B", "$baseVersion..HEAD")
// split the output on each separator generated earlier
.split(separator)
// trim each message, removing excess newlines
.map { it.trim() }
// only keep non-empty messages
.filter { it.isNotEmpty() }
when {
// increment the major and reset the minor + patch if any
// message contains the words 'BREAKING CHANGE'
logMessages.any { it.contains("BREAKING CHANGE") } -> Version(major + 1, 0, 0)
// increment the minor and reset the patch if any message starts with 'feat'
logMessages.any { it.startsWith("feat") } -> Version(major, minor + 1, 0)
// increment the patch in all other cases
else -> Version(major, minor, patch + 1)
}
}
}
project {
// use the next version calculated above when defining our project id
id("nl.craftsmen.blog.kotlin:kotlin-rest-service:${nextVersion}")
dependencies {
compile("org.glassfish.jersey.inject:jersey-hk2:2.29")
compile("org.glassfish.jersey.containers:jersey-container-netty-http:2.29")
compile("org.glassfish.jersey.media:jersey-media-json-jackson:2.29")
runtime("ch.qos.logback:logback-classic:1.2.3")
}
properties {
"project.build.sourceEncoding" to "UTF-8"
"maven.compiler.source" to "11"
"maven.compiler.target" to "11"
}
distributionManagement {
repository("local") {
url(basedir.resolve("repo").toURI().toASCIIString())
}
}
build {
execute(id = "release", phase = "deploy") {
// create a new tag using the next version calculated above
git("tag", "-am", "Release $nextVersion", "$nextVersion")
// print some output
println("Tagged current HEAD as $nextVersion")
}
}
}
]]>Une lib Java rikiki de 153 Ko permet d'écrire des logs plus rapidement qu'avec LogBack ou Log4J2 et qui implémente les interfaces de SLF4J. #Nice
— Liens directs
De mon côté Kotlin est constaté dans deux banques et un géant de l'énergie (secteur Parisien) et nous sommes en train de le pousser comme langage par défaut sur le développements d'API qui doivent être utilisées sur des infrastructures ultra legacy (Weblogic + Java 7 #Pleure) pour les remplacer, car Kotlin permet justement de coder avec les features de 2021 et de transcompiler le bytecode vers de vielles JVM 6/7/8.
Rappelons que Java a mis 10 ans pour devenir Java et que quelques années plus tard il est à 1/8ème de son paroxysme, cf. cette Google Trend du 1er janvier 2004 au 7 mars 2021 montrant l'évolution de Java sur ces 17 dernières années.
En comparaison, Kotlin va seulement fêter sa 6ème année... Laissons-lui encore 4 ou 5 ans histoire de voir.
— Liens directs
Un framework de test de mutation pour JRE, donc qui marche avec Kotlin et Java.
— Liens directs
Encore une très bonne nouvelle pour Kotlin ! Le fait d'avoir une fondation à part, disposant d'un modèle économique clair et qui assure au langage sa survit et mieux encore son évolution est ce qu'il fallait faire.
Le parfait contre-exemple que je pourrais donner est ce qu'a fait la fondation Apache avec Maven dans le sens où Apache étant "anti-argent", la fondation a toujours refusé que des contributeurs majeurs de Maven mettent en place un modèle économique de financement de leurs contributions. 15 ans plus tard, le projet n'a qu'une mise à jour tous les 18 mois... Heureusement, des forks sont apparus comme Maven Daemon mais cela fragmente le marché.
Bref, je suis très contente pour Kotlin.
— Liens directs
Très simple :
gu install native-image
.sudo apt install gcc build-essential
Enjoy :D
— Liens directs
Parser des fichiers CSV avec la lib OpenCSV en Java et en Kotlin.
Extrait du petit code qui va bien pour une lecture de trèèèès gros fichiers :
try (CSVReader reader = new CSVReader(new FileReader("file.csv"))) {
String[] lineInArray;
while ((lineInArray = reader.readNext()) != null) {
System.out.println(lineInArray[0] + lineInArray[1] + "etc...");
}
}
]]>Cela fait pas mal d'années que je cherche un serveur web à embarquer dans mes applications à destination d'une JRE (Java Runtime Environment) et qui soit :
Jooby répond à toutes ces conditions. Donc après avoir utilisé Glassfish (outch), Tomcat, Websphere (hur), Jonas (damned), Weblogic (hur again), Jetty, Sparkjava, Undertow, Javalin, Rapidoid et dernièrement Netty, je pense que je vais migrer vers Jooby qui en plus a de meilleures performances que les autres (d'un facteur 2 par rapport à son meilleur challenger, il est même au niveau des serveurs à destination du C++).
— Liens directs
Je découvre le mot-clef expect
de Kotlin. Son objectif est de dire que pour une même classe, il va y avoir différentes implémentations en fonction de la plateforme.
Par exemple pour la classe (vide) :
expect class KMPDate(formatString: String) {
fun asString(): String
}
Nous aurons cette première implémentation pour Android :
actual class KMPDate actual constructor(formatString: String) { // 1
private val dateFormat = SimpleDateFormat(formatString) // 2
actual fun asString(): String {
return dateFormat.format(Date()) // 3
}
}
et cette seconde pour iOS :
actual class KMPDate actual constructor(formatString: String) { // 1
private val dateFormatter = NSDateFormatter().apply { // 2
this.dateFormat = formatString
}
actual fun asString(): String {
return formatter.stringFromDate(NSDate()) // 3
}
}
KPMDate n'est pas une interface mais bien une classe concrète avec plusieurs implémentions dites "platform-dependent" dans le même fichier.
Mieux encore, c'est compatible avec GraalVM et Kotlin native pour produire des binaires natifs (AMD64 et ARM64 principalement) compilés et linkés statiquement (+ compilation AOT + tree shaking pour les optims) sans avoir besoin d'une JRE d'installée sur l'environnement cible, donc parfait dans des conteneurs très légers par exemple :D
]]>Dans la même veine que mon poste précédente et avec les mêmes remarques concernant la sécurité.
— Liens directs
Tout est dans le titre.
Attention à l'extraction de fichiers dont le chemin dans l'archive sont des chemins absolus ! Si c'est root qui décompresse, il est alors possible d'écraser le /etc/profile
par exemple, voir modifier des démons gérés par systemctl
et compromettre le système.
Bref, toujours concaténer le répertoire de décompression en début de chemin du fichier.
— Liens directs
Outch, la dernière version stable est touchée (1.3.72). Il est recommandé de migrer vers la 1.4.0 aussitôt qu'elle sera publiée.
La criticité est de 8.8/10, avec une faille permettant une élévation de privilèges, ça fait mal.
Edit : je n'avais pas vu mais Kotlin 1.4.0 était déjà sortie. Il semble que le NIST et l'OWASP aient publié l'info qu'une fois la nouvelle version de Kotlin fût corrigée et publiée par JetBrains. C'est très pro !
— Liens directs
Cela faisait quelques temps que je me demandais quel ORM choisir pour remplacer ActiveJDBC car ce dernier est très bien mais je souhaitais un framework qui accentue d'avantage l'OOP.
D'ailleurs ActiveJDBC avait remplacé depuis bientôt 5 ans maintenant Hibernate & OpenJPA chez moi, car eux-mêmes étaient beaucoup trop orientés procédurale (@Sweet clin d’œil à ce sujet) au point de rendre impossible de respecter le principe d'encapsulation et aussi parce que l'usage intensif de l'API réflexion par Hibernate ne permet pas la compilation en natif via GraalVM.
Bref, j'hésitais entre trois frameworks et je pense que je vais partir du Ktorm qui a une super doc, de bonnes performances et une façon très simple de requêter la base :
J'ai sorti Kuery car il n'est plus maintenu depuis trois ans et qu'il lui manque certaines fonctionnalités et j'ai aussi mis de côté Exposed car trop orienté fonctionnel et donc incitant à violer l'encapsulation à l'image d'Hibernate.
Bref Ktorm est dans le pipe.
]]>Sans blague... Utiliser un des compilateurs les plus difficiles du marché (ici Kotlin) prévient une grande partie des bugs et réduit leur nombre de 33%, le cas présent sur l'application Google Home depuis Que Goole a remplacé le code en Java par Kotlin.
C'est un peu comme si les langages interprétés et sans contrôles ultra-stricts à la compilation étaient moins efficaces... La surprise est totale ! (Ô__Ô) #Kotlin #Rust
Tiens j'entends comme un écho qui dénigrerait Python... Et quelqu'un d'autre qui tousse très fort JS/NodeJS... Vraiment bizarre, allez savoir pourquoi #TrollInsideOuPas
]]>@Animal attention ce que tu écris ne fonctionne QUE parce que ton fichier se trouve dans le classpath de test (car intégré au jar de test).
Dès que le fichier est en dehors du classpath, ça ne marchera pas.
— Liens directs
Je développe une lib en Kotlin (jusque là normal) et disposant de deux PC, il m'arrive de démarrer le travail sur l'un et de le finir sur l'autre (encore une fois normal). Sauf que... Sur mon PC portable, que nous appellerons le PC-P, impossible de compiler la même lib au même numéro de commit (une erreur obscure émane du JDK lui-même) alors que sur mon PC fixe, que nous appellerons PC-F, aucun problème.
1) Mes outils ne sont pas à jour sur l'un des deux postes
Le PC-P ayant les dernières versions mais pas le PC-F, j'aligne le tout (OpenJDK, Intellij, OS, Maven, etc) dans les dernières versions disponibles et non, même résultat. PC-F ça marche, PC-P ça plante !
2) J'accuse le répo local de Maven.
Je drop l'intégralité du répo sur les deux machines, je rebuild avec les mêmes lignes de commande, rien n'y fait.
3) J'accuse le compilateur Kotlin.
Ayant fait une montée de version vers la 1.3.72 je me dis que cette toute dernière version est peut-être instable. Du coup je décrémente sa version à la 1.3.41. Toujours ce fichu problème (il s'agit un JVM access FileNotFound au passage - erreur que je n'avais jamais vu de ma vie).
4) J'accuse mon code
Aparté : oui seulement au bout de 4 étapes mais les trois premières ne me demandaient pas beauoup d'effort.
Je reviens en arrière surun commit, deux commits, cinq commits, 17 commits plus loin et ça marche enfin sur les deux... Sachant que tous mes commits ont été stashés et squashés vous n’imaginez pas le nombre de lignes modifiées... #Pleur
Après investigation, j'arrive au point où j'identifie une classe de test mais plante-t-elle à la compile ou au run ? Je commence à lancer un mvn test-compile
et ça marche. Je lance un mvn test
et ça pète mais toujours pas d'indice.
#FastForward Il se passe une nuit et j'en parle à @Lenny le lendemain. Il teste sur son poste et lui-aussi sa plante. Sauf qu'ayant une version plus ancienne de Mint mais aussi du JDK il voit un message différent du mien : un FileNotFound qui indique une classe, précisément classDeTest$NomDeMethod.class (ce sont les classes virtuelles que créé Java).
Je lui demande de prendre tout le chemin de fichier et d'effectuer un touch (car le chemin à l'air assez long) et le touch pète ! #PremièreVictoire
=> Conclusion rapide : le chemin de fichier est trop long. Mais alors pourquoi est-ce que ça marche sur mon PC-F et pas sur mon PC-P !!? #WTF
... Petit moment de suspense... Ur ur ur (^__^)
Réponse :
Le PC-P de @Lenny tout comme le mien ont une partition Ext4 chiffrée ! Or mon PC Fixe a une partition en clair et il faut savoir qu'une partoche Ext4 en claire permet des chemins de fichiers de 255 caractères tandis qu'une Ext4 chiffrée est limitée à 143 caractères ! Le voilà notre coupable...
Vous n'avez pas idée des heures que j'ai perdues à cause de ce comportement mais je suis tellement contente d'avoir trouvé !
]]>Pour @Chlouchloutte, un tuto simple montrant comment mocker l'objet Context
des routes de JavaLin avec MockK. Mais normalement Mockito en direct devrait aussi faire le café.
Concept :
main()
vide (enfin qui contient juste le point suivant).Je vais me coder une petite lib qui va se charger de charger l'application à la place de la main()
et permettre les démarrages à chaud. #Luv
— Liens directs
Objectifs :
Ma sélection :
]]>Oh my my, la citation du jour sur Scala et Kotlin :
Kotlin is much like Scala, just without the shitty parts... Whiiiich I guess makes Kotlin nothing like Scala.
Quand vous avez fait du Scala et du Kotlin, vous ne pouvez pas vous empêcher de rire tellement c'est vrai.
— Liens directs
Kotlin progresse magistralement sur l'indice de popularité des langages de programmation : PyPL. Soit 4 places de gagnées et 12ième position sur le podium !
]]>Vous avez lu le titre ?
Je veux dire
I'm sooooooo happy ! Déjà parce que j'avais misé sur Kotlin il y bientôt 4 ans maintenant mais ce n'est pas tout ! Kotlin dispose de l'un des compilateurs les plus restrictifs du marché (avec celui de Rust) et cela signifie que plus ces langages se développeront et moins il sera possible à des non-dev de se faire passer pour des développeurs car il ne leur sera plus possible de passer la barrière du compilateur sans comprendre tous les mécanismes qui se passent derrière (et donc devenir de "vrais devs").
Pourquoi cet élitisme me direz-vous ?
Tout simplement parce que je suis à mon compte et que voir des sous-traitants qui mentent sur un CV et conséquemment tirent mes tarifs vers le bas alors que nous ne proposons pas du tout le même niveau de prestation, bah ça m'agace. Et je ne travaille pas pour être gentille avec le reste du monde, je suis en concurrence directe et brutale avec ceux qui ne m'aident pas à augmenter mon bénéfice. C'est ça, le "libre-marché", ce n'est pas quelque chose j'approuve dans le fond (ceux qui me lisent connaissent mon point de vue sur l'ignominie capitaliste), mais je ne vais pas nier la réalité du terrain et me priver des outils que les règles du jeu fabriquent et permettent.
Bref, non seulement Kotlin est un outil formidable du point de vue de l'ingénierie mais en plus Kotlin sera un outil formidable du point de vue du recrutement et de la sélection. Et ce n'est qu'un début, vous verrez :D
— Liens directs
Un bel exemple d'exécution parallèle et de résultat synchrone en Kotlin.
@Animal je te recommande cet article pour mieux comprendre le travail que tu feras avec @Milk et @Sigmund.
— Liens directs
Remarque :
// Usage :
object Main {
fun regularUseCase() {
// Given
val christmas = LocalDate(2019, 12, 25)
val calendar:HolidaysCalendar = HolidaysCalendarForYear(Year(2019))
// When
val daysOff:DateSet = calendar.daysOff()
// Then
println(daysOffs.contains(christmas)) // print true
}
fun cachedUseCase() {
// Given
val christmas = LocalDate(2019, 12, 25)
val cache:Cache = HolidaysCalendarCache()
// When
val daysOff2:HolidaysCalendar = cache.value(Year(2019))
val daysOff3:HolidaysCalendar = cache.value(Year(2019))
// Then
println(daysOff2.contains(christmas)) // print true
println(daysOff2 === daysOff3) // print true (same instance)
}
@JvmStatic
fun main() {
val main = Main()
main.regularUseCase()
main.cachedUseCase()
}
}
// Interfaces
interface DateSet {
/**
* Determine whether or not the specified date is in this set.
*
* @param date
* The date to research.
*
* @return true if the date exists in this set, false otherwise.
*/
fun contains(date:LocalDate):Boolean
/**
* Determine whether or not the specified date is in this set.
*
* @param date
* The date to research.
*
* @return true if the date exists in this set, false otherwise.
*/
fun contains(date:Calendar):Boolean
/**
* Return the current set of date as an iterable collection.
*
* @return A collection having all the date stored in this set.
*/
fun asCollection():Collection<LocalDate>
}
interface HolidaysCalendar {
/**
* Return a set of holiday dates.
*
* @return All holidays for a period (see implementation for more detail).
*/
fun daysOff():DateSet
/**
* The period covered by this calendar.
*
* @return Something in the CalenadrPeriod enumeration.
*/
fun range():CalenadrPeriod
}
class Cache<K, V> {
/**
* Determine whether or not the specified value exists in this cache.
*
* @param value
* The value to search.
*
* @return true if the value has been found, false otherwise.
*/
fun contains(value:V):Boolean
/**
* Determine whether or not a key exists in this cache.
*
* @param key
* The key to search.
*
* @return true if the key exists, false otherwise (reminder: a key cannot exists if linked to nothing).
*/
fun containsKey(key:K):Boolean
/**
* Retrieve the value related to the specified key.
*
* @param key
* The key related to the researched value.
*
* @return The value related to the given key.
*
* @throw UnexistingEntryException
* When the subsystem cached by this object is not able to restitute a value using the specified key.
*/
fun value(key:K):V
/**
* The list of keys used by this cache.
*
* @return The list of keys used by this cache.
*/
fun keys():List<K>
/**
* Remove the specified key in order to force an update.
*
* @param key
* The key of the cache entry to remove.
*/
fun remove(key:K)
/**
* Clear all entry is the current cache.
*/
fun reset()
}
// Implementation of HolidaysCalendar
class HolidaysCalendarForYear(private val year:Year):HolidaysCalendar
class HolidaysCalendarForMonth(private val year:Year, private val month:Month):HolidaysCalendar
// Implementation of Cache
class HolidaysCalendarCache:Cache<Year, HolidaysCalendar>
]]>J'abonde dans le sens de l'article. Le design pattern Builder est totalement obsolète en Kotlin puisque ce langage intègre les "defaulted method parameters" ce qui fait que si un paramètre venait à manquer, alors il prendrait automatiquement la valeur par défaut, par exemple :
class SocketJavaX(
private val port:Int = 0,
private val host:String? = null,
private val ssl:Boolean = false
)
Quand je vous disais que Kotlin a une multitude de petites choses qui rendent le dev facile et magique.
— Liens directs
Quand j'évoque Kotlin, je sais que comme beaucoup je mets en avant un langage en donnant une impression de fanatisme... Mais faut bien comprendre que je suis une grande fan !
Un exemple, la différence entre la @Deprecated
de Java et la @Deprecated
de Kotlin.
// En java nous déclarons une méthode dépréciée soit sans commentaire
@Deprecated
public void vieuxProut() {
// ...
}
// Soit avec
@Deprecated("Cette implémentation sera abandonnée dans la future 1.2. Utilisez Toto.petDansLaSoie() à la place")
public void vieuxProut() {
// ...
}
Mais en Kotlin nous avons bien plus !
@Deprecated(
"Cette implémentation sera abandonnée dans la future 1.2. Utilisez Toto.petDansLaSoie() à la place",
replaceWith = ReplaceWith(
"petDansLaSoie(x)",
"com.maboite.monprojet.Toto.petDansLaSoie"
)
)
fun vieuxProut() {
// ...
}
Et à cet instant IntelliJ va automatiquement proposer d'utiliser la nouvelle implémentation, par exemple :
Et ce langage est BARDÉ de petits détails comme ça qui vous facilitent la vie.
]]>Bon ça fait deux années maintenant et je sais où j'en suis niveau langage de programmation : de toutes les syntaxes, ma préférée est sans aucun doute et de trèèès loin celle de Kotlin (sauf pour les get / set).
Par contre, le meilleur compilateur du marché est celui de Rust, il n'y a pas photo. J'ai vraiment hâte que Kotlin Native décolle 😉 !
Via Riduidel.
— Liens directs
Spoiler de l'article : Kotlin gagne quasiment partout.
Par contre Kotlin n'est pas que pour Android mais aussi pour tout ce qui cible la JVM ou la compilation du byte-code de JVM en natif. Chez nous il est côté serveur depuis plus de deux ans maintenant et a TOTALEMENT REMPLACÉ JAVA !
]]>Nouvelle version mineure de Kotlin apportant une pléthore de correctifs ! La release note générale est très bien faite (les animations aident vraiment comprendre) ! Bref un modèle à suivre.
En plus de tout ceci je vous mets :
J'étais complètement passée à côté de cela ! L'API time a été repensée en Kotlin pour éviter la confusion de passer une durée en Long et de ne pas savoir s'il s'agit de secondes, de millisecondes, de nanosecondes, etc.
L'idée est d'utiliser les inline-classes (ie. l'enrichissement d'un type existant par un sous-type) et c'est très astucieux regardez :
import kotlinx.coroutines.delay
import kotlin.time.*
@ExperimentalTime
suspend fun greetAfterTimeout(duration: Duration) {
delay(duration.toLongMilliseconds())
println("Hi!")
}
@UseExperimental(ExperimentalTime::class)
suspend fun main() {
greetAfterTimeout(100.milliseconds)
greetAfterTimeout(1.seconds)
}
Les Integer contiennent des classes internes qui vont retourner un objet de type Duration
et contenant la valeur de l'Integer. De cette manière nous avons la valeur et son type en une seule fois.
Ce langage est tellement réfléchi c'est incroyable.
— Liens directs