Recherche/Ajouter des fonctions à une bibliothèque multilingue d’infrastructure en tant que code sans casser les utilisateurs actuels

Ajouter des fonctions à une bibliothèque multilingue d’infrastructure en tant que code sans casser les utilisateurs actuels

Pour modifier une bibliothèque IaC typée qui génère des liaisons vers d’autres langages. Place chaque fonction dans la bonne couche, évite la syntaxe non prise en charge, protège les changements par des indicateurs de fonctionnalité, limite les permissions et ajoute doc et tests.

Pour utiliser ces règles d'IA
## Garder le code des utilisateurs fonctionnel et exposer toute la plateforme Travaillez dans l’intérêt des utilisateurs de la bibliothèque, de ses mainteneurs et de l’écosystème au sens large, et pas uniquement pour la personne qui demande la modification. - Préservez la rétrocompatibilité : le code utilisateur existant et l’infrastructure synthétisée doivent continuer à fonctionner par défaut. - Respectez le principe de moindre surprise : les API doivent correspondre au modèle mental de l’utilisateur. - Exposez l’ensemble des fonctionnalités de la plateforme tout en fournissant des valeurs par défaut pertinentes et modifiables. - Maintenez une voie de repli vers la ressource de bas niveau générée afin que l’absence de fonctionnalités de haut niveau ne bloque jamais les utilisateurs. - Lorsque les règles sont ambiguës, consignez la décision et son raisonnement dans la description de la modification au lieu de faire une supposition silencieuse. Si le travail demandé sort du cadre de la création ou de la revue de code pour ce type de bibliothèque, arrêtez-vous et signalez cette divergence de périmètre. N’appliquez pas ces règles spécialisées à un travail sans rapport. ## Placer la plupart des fonctions dans l’API écrite à la main du niveau 2 Conservez trois niveaux d’abstraction distincts : - Le niveau 1 regroupe les enveloppes générées autour du schéma de ressources du fournisseur. Ne les modifiez jamais manuellement. - Le niveau 2 regroupe des API écrites manuellement, fondées sur l’intention et dotées de valeurs par défaut utiles. La plupart des travaux fonctionnels relèvent de ce niveau. - Le niveau 3 regroupe les modèles faisant intervenir plusieurs ressources. N’ajoutez de nouveaux modèles que si le dépôt accepte explicitement ce niveau d’abstraction. Concevez le niveau 2 en fonction de l’intention de l’utilisateur plutôt que du schéma brut du fournisseur. Masquez aux appelants ordinaires les détails du schéma généré, le câblage interne, les actions d’autorisation et les identifiants physiques, tout en continuant d’exposer l’ensemble des fonctionnalités du fournisseur. Représentez les contrats de ressources sous forme d’interfaces afin que les implémentations tierces puissent se comporter comme les implémentations natives. Préférez la plus petite interface qui satisfait un paramètre : d’abord une référence contenant uniquement un identifiant, puis une interface comportementale complète seulement lorsque des opérations pratiques sont nécessaires, et des classes concrètes uniquement dans des cas exceptionnels. ## Choisir entre mixin, façade et trait pour chaque nouvelle fonction Placez chaque fonctionnalité selon ce qu’elle affecte : 1. La transmission directe d’une propriété de bas niveau, sans logique, relève d’un mixin de propriétés léger. 2. La logique qui modifie les propriétés ou le cycle de vie de la ressource elle-même relève d’un mixin autonome. 3. Un comportement destiné à des consommateurs externes, tel que les autorisations, les métriques ou les événements, relève d’une façade. 4. Une capacité transversale interrogée par d’autres constructs relève d’un trait. 5. Dans les autres cas, utilisez une méthode sur le construct de niveau 2. Ne confondez pas ces rôles. Les mixins sont tournés vers l’intérieur, les façades vers l’extérieur, et les traits signalent des capacités indépendantes des services. Utilisez des gardes de type statiques fondés sur des marqueurs d’exécution stables plutôt que `instanceof`, car les objets peuvent franchir les limites des paquets ou des langages. Gardez les bases abstraites disponibles pour l’implémentation, mais ne les acceptez pas comme paramètres publics. ## Nommer l’API publique de façon cohérente et éviter les types que d’autres langages ne gèrent pas Utilisez des noms publics cohérents : PascalCase pour les classes et les énumérations, camelCase pour les propriétés et les méthodes, le préfixe `I` pour les interfaces comportementales, aucun préfixe pour les structures de données et des majuscules séparées par des traits de soulignement pour les membres d’énumération. Conservez la terminologie officielle de la plateforme et indiquez les unités lorsqu’aucun type fort n’est disponible. Les objets de propriétés doivent être en lecture seule, plats et nommés d’après le construct. Chaque propriété facultative doit avoir une valeur par défaut documentée qui en explique le comportement, plutôt que d’indiquer simplement qu’elle n’est pas définie. Préférez des types forts pour la durée, la taille et les références aux ressources aux nombres bruts ou aux chaînes d’identifiants. N’exposez pas les types de bas niveau générés dans les propriétés de haut niveau. Évitez les types union et les autres constructions non prises en charge par le générateur de liaisons ; utilisez plutôt des classes semblables à des énumérations, des objets de propriétés distincts ou des méthodes de fabrique. L’emplacement des fichiers de types publics fait partie du contrat externe. Ne les déplacez pas à la légère. Évitez les types mappés ou conditionnels, les fonctions surchargées, les espaces de noms propres à un langage et les constantes d’objet exportées lorsqu’ils ne peuvent pas être représentés de manière cohérente dans les langages cibles. N’utilisez pas de méthodes fluides qui renvoient `this` ; elles se traduisent mal d’un langage à l’autre et masquent les mutations derrière le chaînage. ## Écrire des erreurs de validation claires et vérifier d’abord les valeurs non résolues Utilisez des erreurs de validation délimitées lorsqu’un contexte de construct existe, et des erreurs de validation non délimitées dans les autres cas. Les codes d’erreur doivent être des littéraux connus à la compilation, réutilisables lorsque la cause et la résolution sont identiques, et les messages doivent indiquer la valeur erronée, les valeurs attendues et la correction requise. Préférez corriger automatiquement une configuration sûre plutôt que lever une erreur. Échouez rapidement en cas de mauvaise utilisation de l’API, ajoutez une validation postérieure à la construction pour l’état accumulé et émettez des diagnostics de synthèse pour les problèmes d’environnement. N’interceptez pas les erreurs de construction irrécupérables ; représentez les résultats réellement récupérables dans les valeurs de retour. Les valeurs non résolues peuvent représenter des chaînes, des nombres, des listes ou des attributs de ressources. Vérifiez si une valeur n’est pas résolue avant de valider sa longueur, sa plage, son itération ou sa valeur logique. Les listes tokenisées peuvent exposer des longueurs de marqueur, et les valeurs scalaires tokenisées peuvent apparaître comme fausses. Utilisez des vérifications explicites de valeur indéfinie pour les valeurs facultatives, une conversion numérique tenant compte des jetons, et n’incluez jamais d’attributs de ressources non résolus dans les hachages servant à créer les noms physiques. Pour l’état accumulé après la construction, utilisez une boîte de valeur différée qui capture les sites d’appel des mutations. Utilisez des boîtes de liste, de valeur, de table ou d’ensemble ; transmettez-les aux propriétés de bas niveau par l’intermédiaire d’adaptateurs de jetons ; modifiez-les au moyen des opérations de la boîte ; et ne modifiez jamais l’arbre des constructs dans un rappel paresseux ou un rappel de boîte. ## Limiter les permissions et protéger les changements de comportement par des indicateurs de fonctionnalité Préférez des actions d’autorisation précises aux caractères génériques couvrant tout un service, limitez les identifiants de ressources au préfixe le plus étroit possible et regroupez les actions liées selon la portée des ressources. Utilisez les fonctions d’octroi de la bibliothèque au lieu d’assembler manuellement les déclarations de stratégie. Les stratégies de confiance doivent inclure des conditions sur le compte source et la ressource source lorsqu’il existe un risque de confused deputy. Les autorisations de chiffrement doivent limiter l’utilisation au service prévu. Émettez un avertissement au moment de la synthèse dès qu’une configuration crée un accès public. Lorsque le comportement observable d’une API existante change, protégez la compatibilité à l’aide d’un indicateur de fonctionnalité : - Utilisez un indicateur de correction de bogue lorsque l’ancien comportement était incorrect. - Utilisez un indicateur de valeur par défaut de l’API lorsque l’ancien comportement reste valable, mais n’est plus recommandé, et documentez la compatibilité avec cet ancien comportement. - Les applications non configurées doivent conserver leur comportement antérieur. - Les indicateurs de sécurité peuvent réduire la confiance ou les autorisations, mais ne doivent pas les élargir silencieusement ; un accès plus large nécessite une option d’API explicite. N’utilisez pas un indicateur simplement parce qu’un construct de remplacement existe. Rendez plutôt l’ancien construct obsolète et signalez les changements de comportement par le mécanisme d’annotation standard. ## Compiler d’abord le paquet concerné et mettre à jour les instantanés d’intégration Compilez le paquet concerné avant d’exécuter les tests, l’analyse de style, les instantanés d’intégration ou les vérifications des exemples de documentation. Pendant les itérations, utilisez le module ou la cible de test pertinente la plus restreinte ; avant la remise, revenez aux contrôles de paquet et de compatibilité exigés par le dépôt. Sachez quels fichiers sont générés, où se trouvent les tests d’intégration stables et expérimentaux, et où les références de conception destinées aux agents prévalent sur les guides plus longs destinés aux humains. Ne modifiez jamais directement les sources générées de niveau 1. Utilisez les commandes de paquet et les répertoires de travail locaux au dépôt plutôt que d’inventer d’autres chemins de compilation. N’exécutez les corrections automatiques de style que si les modifications qui en résultent restent dans le périmètre demandé. Lorsque vous modifiez des identifiants logiques, mettez à jour tous les instantanés d’intégration concernés, y compris ceux qui couvrent plusieurs paquets. La réussite d’un test unitaire local ne prouve pas que les liaisons générées, les exemples de documentation ou les modèles d’intégration se compilent encore. ## Documenter chaque nouvelle API publique et garder les exemples compilables Documentez chaque nouvelle classe, méthode, propriété et interface publique. Commencez par un résumé concis, puis ajoutez une ligne vide et un corps explicatif. Incluez, le cas échéant, les balises de paramètre, de retour, de valeur par défaut, de référence associée, d’exemple et d’attribut généré. Les noms d’attributs doivent commencer par le type de ressource plutôt que d’employer des noms ambigus. Reprenez les descriptions officielles de la plateforme lorsqu’elles sont disponibles, mais ne dupliquez pas la documentation dans les redéfinitions qui en héritent d’une interface de base. Chaque guide de module doit indiquer son niveau de maturité, placer un exemple simple près du début et inclure des exemples pour les principaux cas d’usage. Tous les exemples typés ordinaires doivent être compilables ; n’utilisez le marqueur explicite d’exclusion du dépôt que lorsqu’un dispositif de test ne peut réellement pas s’appliquer. Chaque modification fonctionnelle doit mettre à jour le guide du module concerné. Un texte uniquement documentaire ne remplace pas les tests d’API, et l’implémentation de l’API ne justifie pas des exemples obsolètes. ## Vérifier des propriétés précises dans les tests unitaires et ajouter des tests d’intégration Dans les tests unitaires, vérifiez les propriétés générées précises qui comptent au lieu de comparer des modèles entiers ou d’accepter des valeurs arbitraires. Utilisez à bon escient les comparateurs d’objet partiel, d’objet exact, de tableau, d’expression régulière et d’absence. Couvrez les valeurs limites avec des tests pilotés par les données. Les tests d’erreur doivent vérifier le diagnostic exact et indiquer le comportement d’échec dans le nom du test. Testez les fonctions utilitaires séparément des constructs et conservez les tests des API obsolètes. Les nouvelles propriétés facultatives nécessitent des tests de rétrocompatibilité prouvant que le comportement par défaut n’a pas changé. Les fonctions d’octroi doivent être testées avec des rôles, des utilisateurs et des principaux de service créés et importés. Les tests d’intégration doivent utiliser le construct de test d’intégration du dépôt sans appel de synthèse supplémentaire. Les assertions sont recommandées pour tous les nouveaux tests et obligatoires pour les ressources personnalisées. Évitez les pairs réseau ouverts, sauf si l’accès ouvert est précisément le comportement testé. Ajoutez une couverture d’intégration pour les nouveaux types ou propriétés de ressources générées, les comportements interservices, les nouvelles versions et les ressources personnalisées. Séparez les tests par domaine fonctionnel et conservez des extensions et des emplacements d’instantanés cohérents. ## Lier les titres de changement à une issue et ne jamais changer les identifiants stables Utilisez des titres de modification conventionnels avec le module concerné, le cas échéant. Les fonctionnalités et les corrections doivent faire référence à un ticket. Les modifications fonctionnelles nécessitent des tests unitaires, des instantanés d’intégration et une mise à jour de la documentation du module. Les modifications incompatibles ne sont autorisées que dans des paquets explicitement expérimentaux et doivent être annoncées clairement dans la description de la modification. Limitez chaque modification à un seul sujet ; soumettez les changements purement esthétiques séparément. N’ajoutez jamais d’abstractions spéculatives, ne modifiez pas les identifiants stables des constructs, ne laissez pas de code commenté ou mort et ne désactivez pas les règles de style pour masquer des infractions. La modification d’identifiants peut remplacer des ressources déployées et entraîner une perte de données. Avant d’ajouter une validation à une API existante, déterminez si une entrée précédemment acceptée pouvait être déployée avec succès. Si c’était le cas, protégez le nouveau rejet derrière un indicateur de compatibilité. Si elle échouait toujours au déploiement, préférez un échec précoce lors de la synthèse et expliquez pourquoi cette validation plus stricte est justifiée. Avant la remise, examinez les modifications à la recherche d’éditions de fichiers générés, de déplacements de types publics, de syntaxe incompatible avec les liaisons, d’instantanés obsolètes, de documentation manquante, de régressions de compatibilité et de changements sans rapport.