Migration Assistée par LLM
Le cas Sicas
La migration de Sicas comporte 3 défis majeurs
Sécurité
Qualité
Déploiement
La version Java 1.6 est obsolète et comporte de nombreuses failles de sécurité
Le code de Sicas n’est testé qu’à 1,8%.
Plus personne ne maîtrise le fonctionnel
Des adaptations sont nécessaires :
- Spring ⟶ Spring Boot
- Corriger les issues Sonar
- Dépendances obsolètes
- Couverture de test
Choix des outils
Pour la migration nous avons sélectionné
Amazon Q Transform solution clé en main de migration de codebase d’une version obsolète (6) de Java vers une version LTS moderne (17 ou 21). Il est disponible sous la forme d’un plugin JetBrains.
La solution utilise :
-
OpenRewrite
Outil de migration déterministe
-
Claude 3.7

Choix des outils
Pour la migration nous avons sélectionné
Cline est une solution de GenAI agentique avec choix du modèle.
Le modèle Claude 4 Opus est un des plus performants pour la génération de code grâce à son attention à l’architecture générale du produit.
Nous l’utilisons dans VSCode.
https://binaryverseai.com/best-llm-for-code-in-2025-claude-4-leads/#2-comprehensive-comparison-of-leading-code-ll-ms
https://writingmate.ai/blog/best-llm-ai-coding

Le plan
1
2
3
Java 6 ⟶ Java 21
Spring ⟶ Spring Boot
Mise au standard de qualité
Everybody has a plan until they get punched in the mouth
Première étape
migration avec Amazon Q Transform
Durée de l'étape : Une heure

Amazon Q Transform
Durée de l'étape : Une heure

Amazon Q Transform
Amazon Q Transform
Transformation Hub
Il permet de suivre la progression du job.

Amazon Q Transform
Summary
Rapport détaillé de la transformation effectuée
et de ce que le LLM n’a pas pu faire.
Limitation : pour vérifier son travail il builde dans son datacenter.
⇒ il n’a pas accès aux libs propriétaires.

Amazon Q Transform
Summary
✅ Done
Java 6 ⟶ Java 21
Spring 3 ⟶ Spring 6 (quasi)
Code métier intact (un peu trop)
⏳ Reste à faire
Des librairies propriétaires obsolètes à remplacer
Des librairies OSS obsolètes n’ont pas pu être migrées
car plus maintenues (unitils.org)
Utiliser les structure modernes de Java 21
(records, enhanced for-loops, try-with-resources, Streams, etc.)
Durée de l'étape :
Une heure
1 bis, terminer la migration
Correction des tests
Méthodo

Correction des tests
Après plusieurs itérations nous sommes arrivés à un ensemble efficace de règles
# Convert test to Junit4-compatible version
## Goal
Change this Java test file to be compatible with JUnit4 leveraging the vintage library.
## Rules
<rule>In the imports, replace import org.junit.jupiter.api.Assertions; with import org.junit.Assert;</rule>
<rule>In the code, find the Assertions and replace them with Assert</rule>
<rule>In the imports, replace import org.junit.jupiter.api.Disabled; with import org.junit.Ignore;</rule>
<rule>In the code, find the Disable and replace them with Ignore</rule>
<rule>In the imports, replace import org.junit.jupiter.api.Test; with import org.junit.Test;</rule>
<rule>Don't change the "import static org.junit.jupiter.api.Assertions.assertThrows;"</rule>
<rule>Don't change assertThrows in the code</rule>
Correction des CVE
Le LLM en a corrigé la moitié en une heure en mettant à jour la codebase.
L’autre moitié a été corrigée au cas par cas “à la main” pendant le reste de la journée en mettant à jour les versions des dépendances.
Nous avons corrigé la totalité des 60 CVEs
Durée de l'étape :
le reste de la journée (6h)
Deuxième étape
Spring ⟶ Spring Boot
Obstacle : JNDI
JNDI nécessite un serveur d'appli
Spring Boot = pas de serveur d'appli
Je ne savais pas comment résoudre le problème.
Claude me l’a expliqué et donné des pistes de résolution.
🐤
Canard en caoutchouc qui parle
📚
Et qui sait beaucoup de choses

Configuration XML ⟶ Java
Claude est super fort pour ça !

Configuration XML ⟶ Java
Il analyse l’intention du la configuration

Configuration XML ⟶ Java
Et la restitue
dans un fichier
en Java

Durée de l'étape
8 jours (JH)
Troisième étape
Mise au standard
de qualité
Augmentation de la couverture
Méthodo

Augmentation de la couverture
Claude comprends bien les contextes imbriqués dans des balises XML
# Objective
Test JPA Entity in order to maximize test coverage with a Spring Data Jpa Test.
<rule>
When an entity is fetch from the database its setters are implicitly invoked.
Make sure they are invoked with various values so edge-cases are tested.
<example>
```java
var entity = new Entity();
entity.setId(ID);
entity.setValue("value with strange characters: %$?");
...
// Then
assertTrue(found.isPresent());
assertEquals("value with strange characters: %$?", found.get().getValue());
```
</example>
</rule>
Augmentation de la couverture
Kaizen
Carefully read the following instructions.
Then ask what class these instruction should be applied to.
# Objective
<rule>
Create test classes that can run in isolation of any external system.
Example of external system:
- Databases. Use in-memory HSQLDB
- Web Services. Use MockServer library to stub the behavior of Web Services
</rule>
<rule>
Test all public methods of the class.
</rule>
<rule>
Tests must maximize test coverage.
All reachable branches of execution must be covered by a test method
</rule>
<rule>
Edge-cases must be tested.
For each parameter of a tested method, test the behavior of the tested method when
- if the parameter is a reference, test when the argument is null
- if the parameter is a String, test when the argument is the empty String `""`
- is the parameter is a number, test when the argument is negative, zero, positive
The nominal case must also be tested
- When the arguments are all valid
</rule>
<rule>
All test methods that test the same testes class method must be grouped in a nester class.
The nested class in annotated with @Nested
</rule>
<rule>
Test must use JUnit5
</rule>
<rule>
The test is an integration test and the test class must be annotated with @SpringBootTest
</rule>
<rule>
Do not mock simple java beans.
Juste instantiate them and set their test values with their mutators or their constructor arguments accordingly
<example>
Don't do this:
```java
Entity entityMock = mock(Entity.class);
when(entityMock.getValue()).thenReturn("A Value");
```
Do this instead:
```java
Entity testEntity = new EntityImpl();
testEntity.setValue("A value");
```
</example>
</rule>
<rule>
For operations on the file system, use the JimFS library and select Linux as the file system type.
</rule>
<rule>
Start by creating test setup in each test methods.
Then factorized setup in @BeforeEach methods at the nested class level when the setup is used by all test methods of the nested class
Then factorize setup in @BeforeEach at the test root class when it is used in all nested classes
</rule>
<rule>
Use modern Java syntax like text blocks, SequencedCollections.
</rule>
Augmentation de la couverture
Courbe Sonar

Augmentation de la couverture
Apprentissages
Le LLM interprète l'intention du code
(vs: lit l'implémentaiton)
⚠️ Prendre soin du nommage !
✅ Permet de découvrir les écarts entre intention et implémentation
(A.K.A. les bugs)
❌ Ne sait pas faire "copier-coller"
Next steps
On a un fichier par stratégie de test
Pour l’instant c’est l’humain qui sélectionne les instructions
à appliquer.
Car ce choix est instinctif ➡ on est C3.
En définissant clairement les critères de sélection
on passerait C4 ➡ on pourrait automatiser aussi cette partie.

Durée de l'étape
14 jours (JH)
Bilan

Capitalisation du savoir
Standing on the shoulders of giants
Cette expérience est une opportunité pour écrire un nouveau standard.
Pour l'ajouter à la collection de nos standards sur l'IA
https://www.notion.so/m33/Partnering-with-AI-395ef37df344425aaaadf61266768bf1

Réflexions
Prompt engineering
Prompt crafting
Des règles qu’on assemble pour en faire des instructions
pour une machine 🤔
Est-ce que ce ne serait pas un langage de programmation de plus ?
Prompt engineering
Prompt crafting
En fait cette idée n’est pas originale
On appelle ça un langage de 5è génération

problem-solving using constraints given to the program, rather than using an algorithm written by a programmer – Wikipedia
Merci !
Votre avis compte !

Migration Assistée par LLM
By Loïc Broquet
Migration Assistée par LLM
- 33