Interdire les appels à des fonctions / classes arbitraires dans du code externe

12

J'ai connu des cas où il serait utile de restreindre l'accès à l'API des bibliothèques et des cadres externes pour éviter des conséquences négatives dans le système.

Par exemple, dans une application SharePoint, il peut sembler naturel d'appeler spList.Items.GetItemByIdpour obtenir un élément de liste, même peut-être en boucle, sans se rendre compte que cela peut entraîner d'énormes problèmes de performances.

Il se peut également que nous devions interdire l'utilisation de SmtpClient afin de forcer tout le monde à utiliser notre propre classe pour envoyer des e-mails, afin de garantir que nous pouvons correctement proxy et se moquer de tous les e-mails dans l'environnement de test.

Existe-t-il des moyens fiables et raisonnablement simples de respecter ces contraintes sur le code externe, sauf à partir de certains endroits spécifiques de notre propre code? Il n'est pas nécessaire d'empêcher absolument en toutes circonstances l'accès à ces méthodes / classes, par exemple par réflexion ou simplement par une sorte de désactivation, il devrait plutôt être un avertissement strict de ne pas les utiliser. Forcer de préférence le programmeur à prendre activement des mesures pour contourner ces contraintes si possible / nécessaire.

Alex
la source
11
Cela ressemble à une application d'une forme extrême de style de codage (interdit d'utiliser un appel de bibliothèque particulier). Donc, pour moi, cela soulève la question préalable de faire des révisions de code ou des vérifications de style en premier lieu?
Peter M
3
Espérez-vous intercepter et bloquer ces appels à l' exécution ou à la compilation ?
MetaFight
1
Depuis que vous utilisez C #, avez-vous déjà entendu parler de StyleCop ? Vous savez que vous pouvez créer des règles personnalisées à votre guise, non?
Machado
10
" Existe-t-il des moyens fiables et raisonnablement simples de respecter ces contraintes sur le code externe, sauf à partir de certains endroits spécifiques de notre propre code? ". Oui: écrivez votre propre analyseur Roslyn pour signaler l'accès à certaines API comme une erreur de compilation.
David Arno
3
@Machado, StyleCop est effectivement un produit mort. Il est remplacé par StyleCopAnalyzers, qui est construit au-dessus de Roslyn. Ce ne serait certainement pas une bonne idée d'investir du temps dans la rédaction de règles StyleCop personnalisées de nos jours.
David Arno

Réponses:

8

Existe-t-il des moyens fiables et raisonnablement simples de respecter ces contraintes sur le code externe, sauf à partir de certains endroits spécifiques de notre propre code?

Comme la question concerne spécifiquement C #, il existe une solution basée sur un compilateur qui peut être utilisée ici pour appliquer ces règles: Roslyn Analyzers . Vous pouvez écrire votre propre analyseur qui signale l'accès à certaines API comme une erreur de compilation ou un avertissement.

Les analyseurs StyleCop , qui remplacent l'ancienne fonction StyleCop pour C #, constituent un exemple d'analyseurs, qui fournissent de nombreux exemples de code lors de l'écriture de la vôtre .

Cela dit, ces contrôles automatisés peuvent toujours être contournés par des gens déterminés à "enfreindre les règles". Par conséquent, cette approche ne se substitue pas aux revues de code comme discuté dans la réponse de Karl Bielefeldt. Il peut aider à de tels examens, mais ne doit pas les remplacer.

David Arno
la source
Il n'a jamais été question de remplacer quoi que ce soit d'autre, je cherchais simplement un outil spécialisé pour ma boîte à outils.
Alex
25

Vous pouvez faire des choses qui prennent du temps, comme écrire un wrapper autour de l'API externe qui laisse de côté vos opérations indésirables, mais rien ne vaut la formation et les révisions de code, car quelles que soient les normes ou les mesures techniques que vous mettez en place, les gens trouveront des moyens créatifs de les contourner. .

Par exemple, nous avons plusieurs services écrits en Scala, et l'une des choses que nous demandons au moment de la révision du code est pour l'immuabilité, mais nous communiquons souvent cela comme se débarrassant du vars. Quelqu'un l'autre jour a utilisé un val x: ListBuffer [booléen] pour contenir une seule variable mutable comme seul élément de la liste. Vous ne pouvez pas en affecter un autre ListBufferà x, mais vous pouvez remplacer les éléments de la liste en place autant que vous le souhaitez. Aussi mauvais que d'utiliser un var, mais plus sournois.

En d'autres termes, vous devez vérifier si les gens contournent vos solutions techniques. Si ces solutions techniques sont coûteuses et ajoutent de la complexité, vous pouvez tout aussi bien vérifier qu'elles les codent correctement.

Karl Bielefeldt
la source
putain c'est sournois!
2017
@snb C'est équivalent à ce que Java fait comme hack pour contourner le fait de ne pouvoir renvoyer qu'un objet / valeur et de ne pas avoir d'arguments de référence appropriés; en passant à la place un tableau dont le contenu sera mis à jour. (Quelques exemples: AtomicMarkableReference.getet AtomicStampedReference.get).
JAB
Merci pour votre réponse, mais je ne suis absolument pas intéressé à faire des choses complexes qui prennent du temps, comme écrire des wrappers autour du code externe. Cela ne serait probablement même pas utile car ils peuvent simplement aller à la source. Cette réponse semble supposer qu'une solution sera coûteuse et ajoutera de la complexité. Et une solution pure et simple?
Alex
1
@Alex, la solution la plus simple est là: "rien ne vaut la formation et les revues de code".
Mr.Mindor
2
"rien ne vaut le faire manuellement" est juste jusqu'à ce que quelqu'un l'automatise.
Ewan
0

La réponse de Karl est 100% correcte. Il n'y a aucun moyen de garantir la conformité. Cependant, en plus de la formation et des révisions de code, envisagez l'utilisation d'outils d'analyse statique pour garantir la conformité. (Remarque: j'ai dit "en plus de", car on peut également les contourner exactement de la même manière que Karl l'a déclaré).

L'avantage d'utiliser des outils d'analyse statique est de supprimer une analyse de code humain fastidieuse à la recherche d'instances d '«utilisation multiple d'IEnumerable» ou de tout problème de performance de la semaine que vous regardez (ou, du moins, que j'ai toujours l'impression d'être regarder). Cela permettra aux revues de code et à la formation de se concentrer sur des problèmes plus "intéressants".

Pour C #, en particulier, j'ai inclus quelques suggestions ci-dessous. Branchez-les dans votre environnement de construction et vous êtes prêt à partir. Mais, généralement, quelle que soit la langue que vous utilisez, il existe un outil d'analyse statique quelque part.

Copiez / collez directement à partir de la page Wikipedia, utilisez la page wiki pour les informations et les liens les plus récents: https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#.NET

  • .NET Compiler Platform (Codename Roslyn) - Framework de compilateur open source pour C # et Visual Basic .NET développé par Microsoft .NET. Fournit une API pour analyser et manipuler la syntaxe.
  • CodeIt.Right - Combine l'analyse de code statique et le refactoring automatique aux meilleures pratiques qui permettent la correction automatique des erreurs et violations de code; prend en charge C # et VB.NET.
  • CodeRush - Un plugin pour Visual Studio qui avertit les utilisateurs des violations des meilleures pratiques.
  • FxCop - Analyse statique gratuite pour les programmes Microsoft .NET qui se compile en CIL. Autonome et intégré dans certaines éditions de Microsoft Visual Studio; par Microsoft.
  • NDepend - Simplifie la gestion d'une base de code .NET complexe en analysant et en visualisant les dépendances du code, en définissant des règles de conception, en effectuant une analyse d'impact et en comparant différentes versions du code. S'intègre dans Visual Studio.
  • Parasoft dotTEST - Un plug-in d'analyse statique, de tests unitaires et de révision de code pour Visual Studio; fonctionne avec les langages pour Microsoft .NET Framework et .NET Compact Framework, notamment C #, VB.NET, ASP.NET et Managed C ++.
  • Sonargraph - Prend en charge C #, Java et C / C ++ en mettant l'accent sur l'analyse des dépendances, la vérification automatisée de l'architecture, les métriques et la possibilité d'ajouter des métriques personnalisées et des vérificateurs de code.
  • StyleCop - Analyse le code source C # pour appliquer un ensemble de règles de style et de cohérence. Il peut être exécuté à partir de Microsoft Visual Studio ou intégré dans un projet MSBuild.
Bleu Reginald
la source
-1

Pour développer la suggestion "formation et révision de code" soulevée dans une autre réponse: comme le code que vous souhaitez interdire est du code légal, vous ne pouvez pas compter sur le compilateur pour l'empêcher, et vous devrez vous fier à un processus ultérieur, l'article.

Cela peut (et devrait) inclure des étapes de révision manuelle et automatique:

  • Préparez une liste de contrôle des problèmes connus et passez en revue ceux-ci dans vos revues de code manuelles, un par un. Organisez une réunion récurrente pour examiner et mettre à jour la liste de contrôle. Chaque fois qu'un bug méchant est détecté et analysé, ajoutez-le à la liste de contrôle.

  • Ajoutez des règles d'archivage pour rechercher des modèles connus. Cela peut être compliqué à écrire, mais pour un grand projet, au fil du temps, cela peut être utile. TFS vous permet d'écrire des règles en C #, et d'autres systèmes de build ont leurs propres hooks. Pensez à utiliser des générations fermées pour rejeter les enregistrements qui correspondent au modèle. Oui, cela ralentit le développement, mais après une certaine taille et complexité du projet, ralentir les développeurs peut être une bonne chose.

Avner Shahar-Kashtan
la source
-1

Peut-être que le compilateur peut vous aider à intercepter les appels indésirables.

Renommez les classes / méthodes de code dans votre propre bibliothèque qui ne doivent pas être utilisées par les clients de bibliothèque externes. Alternativement, rendre les classes / méthodes internes et ajouter des internes visibles aux classes autorisées à les utiliser.

Les utilisateurs de bibliothèques externes obtiendront une méthode / classe d'erreur de compilation introuvable.

Classes / méthodes interdites des bibliothèques publiques: créez le même espace de noms / classe / méthode dans votre bibliothèque

Les utilisateurs de bibliothèques externes obtiendront une erreur de compilation en raison de la classe en double trouvée

[mise à jour]

Il n'est pas nécessaire d'empêcher absolument en toutes circonstances l'accès à ces méthodes / classes, par exemple par réflexion ou simplement par une sorte de désactivation, ....

forçant le programmeur (... client de la lib ...) à prendre activement des mesures pour contourner ces contraintes si possible / nécessaire.

k3b
la source
Voter cela, non seulement parce que c'est un hack désagréable, mais il est facile à contourner avec C # (avec lequel l'OP a marqué la question) en utilisant des alias externes .
David Arno