Fatigué des tests non-sémantique pour compenser le typage dynamique - suggestions?
-
09-10-2019 - |
Question
Je l'habitude de faire beaucoup de programmation web dans Rails (PHP avant que) avant de commencer à étudier le génie informatique.
Depuis, je l'ai fait beaucoup de travail scolaire en C, et des trucs personnels Objective-C (substance Mac). J'ai appris à l'amour typage statique.
Mais maintenant, je vais avoir à faire un peu de développement web professionnel (freelance) et ont repris une nouvelle fois Rails. Je trouve qu'il est vraiment gênant pour écrire des tests de vérification de type non-sémantiques. Je recevais les gratuitement de compilateurs C et Objective-C. J'aimais frapper Construire et avoir le système vérifie tout mon code pour voir que A peut appeler B, B peut appeler une bibliothèque obscure C, etc. Tout ce que je devais faire était test de la sémantique. Mais avec Rails, je suis le compilateur. :(
Quelqu'un at-il foulé ce même chemin? Mes seules options pour le développement web ASP.NET MVC avec C # et Java + x cadre? Vous cherchez des suggestions, ou même une certaine sympathie ...: P
Par ailleurs, je fais une référence spécifique à Rails plutôt que Ruby parce que je ne me dérange pas de nature dynamique de Ruby pour des trucs simples comme les scripts ou que non. Mais puisque Rails dépend de tant de pierres précieuses et puisque l'on ajoute généralement un certain nombre d'autres pierres précieuses, le typage dynamique devient un problème.
Merci!
modifier
J'ai suivi sur la suggestion de pst et regardé dans Scala. En lisant la programmation du livre à Scala, écrit par le créateur de la langue, Martin Odersky, je suis tombé sur ce morceau de texte qui à bien des égards exprime mes préoccupations et un peu plus. lecture très intéressante.
Tiré de la page 52 de la programmation de Martin Odersky à Scala:
Scala est statiquement typé
classifie système de type statique des variables et des expressions en fonction de les types de valeurs qu'ils détiennent et calculer. Scala se distingue comme langue avec un statique très avancé système de type. A partir d'un système de les types de classes imbriquées beaucoup comme Java, de il vous permet de types de Paramétrer avec les génériques, de combiner les types en utilisant intersections, et pour masquer les détails de types utilisant des types abstraits. Ceux-ci donnent une base solide pour la construction et composer vos propres types, de sorte que vous peut concevoir des interfaces qui sont au même temps et en toute sécurité de souplesse d'utilisation.
Si vous aimez les langages dynamiques tels que Perl, Python, Ruby, ou Groovy, vous pourrait trouver un peu étrange Le système de type statique de Scala est répertorié comme l'un de ses points forts. Après tout, l'absence d'un type statique système a été cité par certains comme avantage majeur des langues dynamiques. Les arguments de la plupart des communes contre types statiques sont qu'ils font programmes trop verbeux, empêchent programmeurs de s'exprimer comme ils le souhaitent, et rendre impossible certains modèles de dynamique modifications des systèmes logiciels.
Cependant, souvent ces arguments ne font pas aller à l'encontre de l'idée des types statiques général, mais contre le type spécifique systèmes, qui sont jugés trop bavard ou trop rigide. Pour par exemple, Alan Kay, l'inventeur Smalltalk, a dit un jour: « Je ne suis pas contre les types, mais je ne suis pas connaître de tout type systemsthat sont pas douleur complète, donc je aime toujours dynamique taper. »
Nous espérons vous convaincre dans ce livre que le système de type de Scala est loin d'être étant une « douleur complète ». En fait, adresses bien deux de l'habituel préoccupations au sujet de typage statique: verbosité est évité par le type inférence et la flexibilité est acquise grâce à l'appariement de motif et plusieurs de nouvelles façons d'écrire et de types Compose. Avec ces obstacles sur le chemin, les avantages classiques de type statique Les systèmes peuvent être mieux appréciés. Parmi les plus importants de ces avantages sont des propriétés vérifiables de abstractions du programme, coffre-fort refactoring, et mieux documentation.
propriétés Vérifiables
type statique sytiges peuvent prouver la absence de certaines erreurs d'exécution. Par exemple, ils peuvent prouver propriétés comme: booléens ne sont jamais ajouté à des nombres entiers; variables privées ne sont pas accessibles depuis l'extérieur de leur classe; les fonctions sont appliquées à la nombre d'arguments; seulement les chaînes sont toujours ajoutées à un ensemble de cordes.
D'autres types d'erreurs ne sont pas détectées par des systèmes de type statique d'aujourd'hui. Pour par exemple, ils seront généralement pas détecter les fonctions non-terminaison, tableau bounds violations, ou divisions par zéro. Ils détecteront pas non plus que votre programme ne se conforme pas à sa spécification (en supposant qu'il existe un spec, c'est!). systèmes de type statique ont donc été rejeté par certains ne pas être très utile. L'argument raconte que depuis ces systèmes de type peuvent seulement détecter les erreurs simples, alors que tests unitaires fournissent plus étendue couverture, pourquoi embêter avec les types statiques du tout?
Nous croyons que ces arguments manquent le point. Bien qu'un type statique système remplacer ne peut certainement pas l'unité les tests, il peut réduire le nombre de tests unitaires nécessaires en prenant soin de certaines propriétés qui autrement doivent être testées. De même, l'unité test ne peut pas remplacer le typage statique. Après tout, comme l'a dit Edsger Dijkstra, le test ne peut prouver la présence de erreurs, jamais leur absence. Alors le garantit que le typage statique donne peuvent être simples, mais ils sont réels garanties d'une forme aucun montant de les tests peuvent fournir.
refactorisations Safe
Un système de type statique fournit une filet de sécurité qui vous permet d'effectuer des modifications à une base de code avec un degré élevé de confiance. Considérons par exemple un refactorisation qui ajoute un montant supplémentaire paramètre d'une méthode. Dans un statiquement langue dactylographiée que vous pouvez faire le changement, re-compiler votre système et simplement fix toutes les lignes qui provoquent une erreur de type. Une fois que vous avez fini avec cela, vous ne manqueront pas d'avoir trouvé tous les lieux que besoin d'être changé. De même pour beaucoup d'autres refactorisations de simples comme la modification d'un nom de méthode, ou le déplacement les méthodes d'une classe à une autre. Dans tous les cas, une vérification de type statique fournir une assurance suffisante que la nouvelle système fonctionne exactement comme l'ancienne.
Documentation
types statiques sont la documentation du programme qui est vérifié par le compilateur pour exactitude. Contrairement à un commentaire normale, une annotation de type ne peut jamais être hors de la date (au moins pas si le fichier source qui le contient a récemment adopté une compilateur). De plus, les compilateurs et environnements de développement intégrés peuvent utiliser des annotations de type à fournir une meilleure aide contextuelle. Pour par exemple, un développement intégré environnement peut afficher toutes les membres disponibles pour une sélection par la détermination du type statique de la expression sur laquelle la sélection est fait et regardant tous les membres de ce type.
La solution
Ceci est l'un de mes « saisines » sur les langages dynamiques. Je veux tester la sémantique, pas erreurs de type ;-) Cela dit, un bon test cadre / configuration est vraiment un must dans toutes les situations non triviales et bonne couverture de code et les exigences testées est / sont importants.
Si vous voulez aller sur le chemin-typage statique sur la machine virtuelle Java (je), je recommande vivement regarder Scala . En venant de Ruby, il est beaucoup moins douloureux (et en fait beaucoup de plaisir de différentes manières) que d'aller à Java. Vous obtenez de « garder » les choses que vous prenez pour acquis - une syntaxe basée sur l'expression, la fermeture, la capacité de types de Omettre dans de nombreux endroits (pas aussi ouvert que Ruby, mais vous ne recevez pas la vérification du type de compilation ;-), tout (*) - est-objet OO, unifié accesseur méthodes, la capacité de construire DSLs facilement, et le sucre - et obtenir les avantages d'un langage typé statiquement avec inférence de type local, pattern matching, un cadre de collecte relativement riche, et intégration décente avec Java (y compris les nombreux cadres web, il y a des cadres spécifiques Scala, ainsi que l'effet de levier le langage Scala).
C # 3.0 / 4.0 (et .NET3.5 +) ne sont pas trop mal soit (mais évitez C # 2.0, qui est maintenant, espérons une relique), avec l'introduction de LINQ / fermetures, inférence de type de base et d'autres belle langue, il propose que je trouve « acceptable » pour la plupart des tâches (faire une supposition que je dirais Java comme langage ;-). Cependant, C # est un langage cible CLR (il est / était un port Scala .NET, mais je ne suis pas sûr de l'état - il n'est pas la principale plate-forme cible bien).
Depuis que je l'ai mentionné Scala, je dois aussi mentionner F # (maintenant un langage .NET « officiel ») qui prend la « fonctionnelle avec OO » approche étant similaire à OCaml - Scala est plus l'inverse et je décrirais comme « OO avec fonctionnelle ». Je l'ai entendu des arguments pour / contre F # par rapport à C # w.r.t le système de type, mais sans expérience pratique avec F #. Vous pouvez ou peut ne pas aimer le changement de paradigme.
Happy codage.
Autres conseils
Comme vous le mentionnez Rails, et étant donné que vous êtes devenu intéressé par Scala, vous devriez certainement vérifier Ascenseur. Voici un interview 2008 avec son créateur, et 2009 présentation (vidéo), que je créer un lien parce que, si vieux, ils se comparent avec Ascenseur alternatives dans d'autres langues.
Si Lift est pas votre truc, mais, rassurez-vous qu'il ya autres web Scala cadres .
Ce type de test est généralement pas fait dans Rails. Au lieu d'être ennuyé d'avoir à le faire, pensez à ne pas se soucier à ce sujet. Ou peut-être faire un meilleur travail d'expliquer pourquoi vous pensez que c'est un problème, car la plupart des programmeurs Rails ne le font pas.
Mise à jour
La personne qui a écrit test_include_with_order_works
fait en sorte que Rails interprétera un symbole même comme une chaîne dans ce cas particulier. Cela ne semble pas comme quelque chose que vous auriez à tester, puisque Rails a déjà fourni et testé cette fonctionnalité pour vous. Franchement, je suis un peu surpris que quelqu'un puisse même se soucier de savoir si oui ou non un symbole fonctionnera comme une chaîne. Nous savons tous qu'il peut et souvent.
En général, je pense que le cadre Rails doit veiller à ce que vous faites pas que sa mise en œuvre sera conforme à sa conception. Je crois que ce code est client de la philosophie de travail dans les langues dynamiquement tapées ne passera pas dans les paramètres qui brisera les méthodes qu'ils appellent. Si elles le font, ils ne reçoivent aucune utilisation de l'appel des méthodes. Vous ne devez pas perdre votre temps en vous assurant que vos méthodes jetteront exceptions lorsqu'elles sont fournies trop de paramètres, lorsque votre méthode peut aussi facilement (et devrait) ignorer les paramètres supplémentaires.
Alors, je ne sais pas si les exemples que vous avez donnés démontrent vraiment la nécessité d'essais non sémantique dans Rails.