


Modifier le code d’une base de données hautes performances sans perdre en vitesse ni en compatibilité
À utiliser quand une IA modifie une base de données rapide qui couvre Java, SQL, Rust, le code natif et la CI. Fixe des règles de style, de NULL, de libération mémoire, de tests de requêtes, d’échecs, de pull requests et de build, puis vérifie tout avant de déclarer le travail terminé.
Pour utiliser ces règles d'IA
## Garder les modules de la base de données séparés et protéger les chemins de données sans allocation
- Préservez des frontières explicites entre les modules du moteur de stockage, du moteur SQL, des protocoles réseau, des utilitaires, des files de workers, de la journalisation, des tâches en arrière-plan, des benchmarks, des tests de compatibilité et des exemples.
- Séparez le code de production des benchmarks, des utilitaires de build, des exemples et des wrappers de plateforme.
- Traitez tout dépôt client imbriqué ou sous-module comme un dépôt indépendant, avec ses propres commits et sa propre cible de compatibilité.
- Identifiez le bon point d’entrée avant de modifier le comportement : démarrage du serveur, moteur de stockage, compilateur SQL, lecteur de table ou rédacteur de table.
- Protégez les chemins de données sans allocation pendant l’exécution des requêtes et l’ingestion.
- Privilégiez les pools d’objets, les tampons réutilisables, le stockage en colonnes, l’exécution vectorisée et l’accélération native lorsque l’architecture les exige.
- N’introduisez pas de dépendances d’exécution tierces lorsque le projet implémente délibérément en interne les algorithmes critiques pour les performances.
- Limitez le code natif aux opérations qui justifient les risques qu’il présente pour la mémoire, les plateformes et les défaillances.
## Ordonner les membres des classes Java et rester compatible avec les anciens clients Java
- Regroupez les membres de classe selon qu’ils sont statiques ou d’instance et selon leur visibilité, puis classez-les par ordre alphabétique dans chaque groupe.
- Insérez les nouveaux champs et méthodes à la position correspondant à leur ordre de tri, au lieu de créer des groupes de sections décoratifs.
- N’ajoutez jamais de commentaires en bannière servant de titres de section Java artificiels.
- Utilisez les fonctionnalités modernes du langage prises en charge par le module principal, notamment les `switch` améliorés, les chaînes multilignes et les variables de motif.
- Respectez les anciennes versions du langage ciblées par les modules de compatibilité ; ne laissez pas la syntaxe du module principal passer dans un client ciblant une version antérieure de Java.
- Préfixez les variables, champs et méthodes booléens par `is` ou `has`, selon le cas.
- Limitez strictement les messages de journalisation à l’ASCII lorsque le pipeline de journalisation ne peut pas restituer de façon fiable la ponctuation ou les symboles Unicode.
- Utilisez les types de collections du projet qui tiennent compte des ressources, plutôt que des tableaux d’objets génériques, lorsqu’ils s’intègrent aux utilitaires de nettoyage établis.
- Respectez les conventions existantes de nommage, de propriété et d’allocation avant d’introduire une nouvelle abstraction.
## Décider du traitement des NULL et libérer la mémoire sur chaque chemin d’erreur
- Définissez explicitement le comportement de NULL pour les données de colonnes, les résultats d’expressions, les instructions SQL et les états intermédiaires.
- Distinguez une sentinelle NULL signifiant « pas encore initialisé » d’une véritable valeur NULL dans les données.
- Suivez chaque allocation et chaque ressource fermable sur les chemins de réussite, d’erreur, d’annulation et de retour anticipé.
- Utilisez systématiquement les utilitaires de nettoyage du dépôt pour les listes et les éléments fermables.
- Traitez la prévention des fuites comme une exigence de conception, et non comme une préoccupation réservée aux tests.
- Ajoutez des assertions de fuite de mémoire aux tests qui allouent de la mémoire native.
- Les tests unitaires ciblés qui n’allouent manifestement aucune mémoire native peuvent omettre le dispositif de détection des fuites.
- Vérifiez le nettoyage sur chaque chemin d’erreur pertinent, et pas seulement sur le chemin de réussite.
- Ne dissimulez jamais une ambiguïté de propriété derrière un conteneur ou un utilitaire pratique.
## Tester les requêtes avec des assertions strictes qui relisent les résultats
- Préférez le framework canonique d’assertion fluide des requêtes aux anciens utilitaires qui impriment et comparent en un seul passage.
- Pour les requêtes déterministes, imposez un second passage du curseur, des recoupements de taille, des contrôles des colonnes variables et les assertions pertinentes sur les propriétés de la factory.
- N’utilisez une assertion à passage unique que lorsque la projection est réellement instable d’une relecture à l’autre, et indiquez-en la raison.
- Les fonctions aléatoires sans graine définie et les fonctions variant dans le temps sont des exemples valides d’instabilité.
- Exécutez le DDL et les autres instructions qui ne sont pas des requêtes par le chemin d’exécution prévu pour ces instructions.
- Vérifiez les plans d’exécution avec les utilitaires de plan du framework lorsque le comportement de l’optimiseur fait partie du contrat.
- Utilisez une seule instruction `INSERT` pour plusieurs lignes de test lorsque le dialecte le permet.
- Utilisez des chaînes multilignes pour le SQL long et les résultats attendus sur plusieurs lignes.
- Écrivez les mots-clés SQL de manière cohérente, de préférence en majuscules.
- Séparez les milliers par des traits de soulignement dans les littéraux de cinq chiffres ou plus lorsque cette syntaxe est prise en charge.
## Respecter le dialecte SQL et pointer l’erreur sur le caractère exact
- Traitez les types de tableaux multidimensionnels comme des types distincts lorsque le nombre de dimensions est encodé dans le type de colonne.
- Employez systématiquement la syntaxe de conversion de type privilégiée par le dialecte, au lieu de mélanger des formes équivalentes.
- Maintenez la prise en charge des séparateurs numériques alignée entre l’analyseur, le code d’implémentation et les tests.
- Ne supposez pas que les fonctionnalités du SQL standard existent ; documentez et testez les opérations non prises en charge.
- Lorsque la suppression de lignes n’est pas prise en charge, modélisez explicitement la suppression logique dans la logique applicative.
- Distinguez les opérations de suppression au niveau d’une partition de la suppression au niveau d’une ligne, car leur périmètre et leur sécurité diffèrent.
- Faites pointer la position d’une erreur SQL signalée vers le caractère fautif exact, et pas seulement vers le début de l’expression.
- Testez les erreurs de l’analyseur à la fois pour leur message et leur position précise.
- Préservez la distinction entre les erreurs de syntaxe, de sémantique, de type et d’exécution.
## Traiter chaque test en échec comme un vrai défaut jusqu’à preuve du contraire
- Traitez chaque test en échec, chaque tâche de CI échouée et chaque entrée de journal surprenante comme un défaut actif jusqu’à ce que des preuves démontrent le contraire.
- « Préexistant », « intermittent », « sans rapport » et « problème connu » sont des hypothèses, pas des conclusions.
- Reproduisez le problème sur la référence pertinente, examinez l’historique des versions, mesurez les contraintes temporelles et consultez les rapports officiels du projet amont.
- N’écartez une défaillance que lorsque les preuves imposent cette conclusion.
- Présentez les preuves qui ont justifié la classification afin qu’une autre personne chargée de la revue puisse les vérifier.
- Ne considérez pas une nouvelle exécution réussie comme l’unique preuve qu’une défaillance était sans conséquence.
- Recherchez les défaillances d’interaction lorsque plusieurs modifications partagent la même lignée de CI.
- Conservez les journaux, les entrées en échec et la plus petite reproduction fiable nécessaire au diagnostic.
- Limitez la correction à la cause démontrée et ajoutez un test de régression qui échoue sans elle.
## Adapter les branches et les pull requests au mode de merge et au coût de la CI
- Adaptez la stratégie de branches et de pull requests au modèle de fusion du dépôt et au coût de la CI.
- Dans un processus de squash merge, ne consacrez pas d’efforts à polir l’historique d’une branche vouée à disparaître.
- Ajoutez un commit correctif clair au lieu de réécrire les commits précédents ou d’effectuer un push forcé uniquement pour embellir l’historique.
- Regroupez les corrections liées lorsqu’une séparation multiplierait les longs passages de CI, l’exposition aux tests intermittents et la coordination des fusions.
- Ne scindez les modifications que si l’utilisateur le demande ou si elles doivent pouvoir être fusionnées ou annulées indépendamment.
- Lorsque vous mettez à jour une pull request existante, synchronisez-vous avec sa tête distante, ajoutez les modifications à cette branche et actualisez ses métadonnées.
- N’ouvrez pas une seconde pull request uniquement pour relancer la validation de la même lignée de modifications.
- Ne créez pas de worktrees de revue et ne changez pas de branche lorsque la politique du dépôt définit une autre branche comme état canonique de revue.
- Récupérez le diff d’une pull request sans changer de branche lorsque seul le diff est nécessaire.
- Créez d’abord le commit dans le dépôt imbriqué avant d’enregistrer le pointeur de son sous-module dans le dépôt parent.
## Écrire des pull requests et des commits qui présentent autant les avantages que les inconvénients
- Respectez la convention de titre des pull requests imposée par le dépôt et rédigez une description utile aux utilisateurs finaux.
- Décrivez les effets positifs, les effets négatifs, les régressions et les compromis avec la même importance.
- Évitez le langage commercial, les superlatifs, les métriques sélectives et les mises en valeur décoratives.
- Référencez un ticket corrigé dans le format de clôture requis au début du corps de la pull request.
- Gardez les titres de commits courts, descriptifs et conformes au style exigé par le dépôt.
- Ajoutez un corps de commit substantiel qui explique la modification au lieu de répéter le titre.
- Utilisez des puces simples dans les plans de test lorsque les cases à cocher ou les coches sont interdites.
- Appliquez des étiquettes correspondant au domaine et au titre de la modification.
- Employez la voix active dans les commits, les pull requests et les commentaires de code.
- Nommez la classe, la méthode, l’appelant ou le composant qui agit au lieu de le dissimuler dans des constructions passives.
## Vérifier l’environnement, puis lancer le build et les tests sur le plus petit périmètre
- Vérifiez avant le build le runtime du langage, l’outil de build, l’architecture et les variables d’environnement requis.
- Choisissez le plus petit profil de build qui démontre la modification actuelle, puis utilisez des profils plus complets lorsque des artefacts web ou natifs sont concernés.
- Recompilez les modules dépendants lorsqu’un cache local d’artefacts peut contenir un client ou une bibliothèque obsolète.
- Exécutez séquentiellement les appels de tests coûteux lorsque les builds parallèles interfèrent entre eux.
- Commencez par la classe ou la méthode de test pertinente la plus ciblée, puis élargissez selon le risque et la politique du dépôt.
- Ne considérez pas la compilation seule comme une preuve du comportement à l’exécution.
- Validez le serveur par le chemin de démarrage pris en charge et examinez le point d’accès ou l’interface directement concernés.
- Conservez les artefacts de build dans les emplacements désignés qui appartiennent à leurs modules.
- Consignez la commande exacte qui a échoué et la première erreur exploitable lorsqu’un build s’arrête.
## Éliminer les avertissements Rust et empêcher un panic de faire planter la JVM via JNI
- Avant de terminer un travail en Rust, exécutez le formatage, la compilation de toutes les cibles, le linting et les tests de bibliothèque depuis la racine du crate.
- Exigez zéro erreur et zéro avertissement dans tous les contrôles obligatoires.
- Mesurez la couverture après avoir ajouté ou modifié des tests.
- Pour chaque ligne non couverte, ajoutez un test ou prouvez qu’elle est inaccessible et indiquez explicitement cet invariant.
- N’appelez jamais `unwrap()` ou `expect()` sur des données provenant de fichiers ou fournies de l’extérieur.
- Propagez les défaillances récupérables avec `Result`, `Option` et le mécanisme standard de propagation des erreurs du langage.
- N’oubliez pas qu’une panique Rust qui traverse JNI peut interrompre l’ensemble de la JVM sans possibilité de récupération.
- Compilez les bibliothèques C et C++ natives avec la configuration de publication du dépôt et vérifiez les artefacts attendus.
- Traitez la propriété, la durée de vie, l’alignement et la conversion des erreurs à la frontière FFI comme des contrats explicites.
- Testez les défaillances aux limites sur chaque plateforme prise en charge et concernée par la modification.
## Éviter les allocations sur le tas et mesurer les gains de vitesse avec des benchmarks
- Évitez les allocations sur le tas dans les chemins de données où l’absence de ramasse-miettes est une exigence architecturale.
- Réutilisez les tampons et les objets mis en pool, et explicitez le transfert de propriété.
- Stockez les données analytiques par colonne lorsque la compression et les opérations vectorisées dépendent de cette disposition.
- Maintenez SIMD, la gestion de la mémoire et les optimisations propres aux plateformes derrière des frontières natives étroites.
- Séparez le stockage, l’analyse, la planification, la génération de code, l’exécution, le traitement des protocoles et le travail en arrière-plan.
- N’utilisez des collections personnalisées que lorsque leur comportement d’allocation et de nettoyage est compris et testé.
- Mesurez les changements de performances au moyen de benchmarks représentatifs plutôt qu’à l’intuition.
- Accompagnez toute optimisation de tests d’exactitude, de contrôles des ressources et d’un compromis documenté.
- N’affaiblissez ni la compatibilité ni la précision des erreurs pour obtenir une accélération non mesurée.
## Relire le diff final et rendre compte des résultats avant de déclarer le travail terminé
- Examinez le diff final pour vérifier l’ordre des membres, les frontières de compatibilité, le comportement de NULL, la propriété des ressources et la présence accidentelle d’Unicode dans les journaux.
- Exécutez les contrôles ciblés Java, SQL, Rust, natifs et d’intégration concernés par la modification.
- Confirmez que les requêtes déterministes utilisent le chemin d’assertion rigoureux avec relecture.
- Confirmez qu’une entrée externe ne peut pas déclencher une panique native irrécupérable.
- Vérifiez que toute défaillance examinée possède une classification étayée par des preuves et une reproduction consignée.
- Assurez-vous que les métadonnées, les étiquettes, le plan de test, le texte du commit et les références aux tickets de la pull request respectent la politique du dépôt.
- Vérifiez que les dépôts imbriqués et les pointeurs parents sont enregistrés dans le bon ordre.
- Ne déclarez pas l’achèvement tant que les contrôles obligatoires comportent des erreurs ou des avertissements.
- Signalez les commandes exécutées, les résultats observés, les risques restants et le périmètre délibérément non testé.
