c'est à proprement parler illisible! Et j'ai du mal à voir l'intérêt par rapport à un assert (ben oui, y a pas qu'en c que assert existe)
c'est à proprement parler illisible! Et j'ai du mal à voir l'intérêt par rapport à un assert (ben oui, y a pas qu'en c que assert existe)
intéressant que ça arrive enfin en java
JML est présente depuis 2-3 ans déjà...
Oui et non... L'imprévu comme tu dis ne doit pas arriver! s'il arrive est que ton système ne peut revenir à un état stable celà dénote un gros problème de conception.
Le zéro bug n'existe pas... Donc après, tout dépend du contexte: tu peux, bien évidemment, rebooter un téléphone sans trop de conséquence... mais, sur un gros serveur les conséquences risquent d'être tout autre!
Perso, j'espère bien que les ordinateurs de bord des avions sur lesquels j'embarque ne vont pas rebooter sur le moindre imprévu
IMHO: les assert en prod sont à réserver aux applis non critiques.
Effectivement le code devient vite illisible... mais, sous contrôle! Et puis, tu ne vas pas t'amuser à contrôler toutes les méthodes de ton appli... à toi, d'analyser, en amont, les points critiques de ton code qui nécessitent une telle attention!
Et si en étendant la notion de typage fort, on passait carrément au typage sélectif : une première analyse est effecutée sur les paramètres de la méthode, permettant d'invoquer la fonction, enfin l'implémentation, qui convient.
Une fonction a plusieurs implémentations, avec la même signature, mais chacune d'elles seront invoqués-ou refusées- sélectivement après l'analyse des paramètres.
Exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 interface MonExemple{ MaMethode( int i); } class MaClass implements MonExemple{ @Choix( i=0) MaMethode( int i){...} @Choix( i>0) MaMethode( int i){ ...} @Choix( i<0) MaMethode( int i){ ...} }
Data Scientist, Architecte de Système d'information, Développeur d'applications web Java/Php sur http://www.onjanirina.pro/
Hacker sur TopCoder, CodeChef, CodeForces, Kaggle, HackerRank (Pseudo : Onjanirina)
Un assert est une situation interdite de par conception. Vous préférez quoi? Que l'application critique lance une asseritonError dans son thread, remonte éventuellement à un niveau où l'on peut réinitialiser le module concerné, annuler l'opération concernée ou prendre toute mesure face à "une situation imprévue et inacceptable" ou que votre truc critique continue a fonctionner avec des valeur erronée.
Pour reprendre l'exemple de votre avions, je préfère le module qui crashe, histoire que le module redondant prenne en charge les opérations, qu'un module qui fait descendre l'avion en piqué en disant "tout va bien"
Les assertion sont d'autant plus importantes à garder en appplication critiques que
-> Elle permettent la prise en charge par les système de secours en cas de besoin
-> En l'absence de système de secours, (application critique sur serveur), elle permettent une intervention immédiate d'un administrateur.
Et n'oubliez pas que, pour les situations où vous estimez pouvoir récupérer, il reste la possibilié de lancer un IllegalStateException et de le traiter.
IMHO, une assertion qui foire, c'est une situation critique, je préfère la voir immédiatement plutot que d'avoir un système qui continue à fonctionner en se cachant les yeux sur sa situation, c'est comme ça qu'on corrompt des bases de données entières.
En l'occurence ici puisque l'on parle de contrat:
- le maximum d'exceptions doivent être levées en pre-condition pour être sûr de pouvoir executer du code (des IllegalStateException, des IllegalArgumentException, ou tout autre exception!).
- puis en post-condition lever d'autres exceptions ou éventuellement des AssertionError pour vérifier que le code a bien été exécuté ou vérifier que les invariants de ton système soient bien préservés. Bref, ici, l'Assert est délégué au second plan. Et non pas l'inverse...
En résumé les assertions ne peuvent en aucun cas se substituer aux exceptions ! Et sont réservées au debug en phase d'intégration et validation.
Tout a fait d'accord, les assertions s'utilisent à bas niveau, quand il est trop tard ou trop bas pour avoir la moindre idée sur la méthode de récupération appropriée. D'ailleurs elles étendent error et, en général, c'est une mauvaise pratique de catcher les erreurs. Mais elle forment un outils important pour améliorer la robustesse du code, c'est le dernier garde fou avant la catastrophe. Raison de plus pour ne pas les désactiver en production.
C'est là où l'on diverge...
La cause de l'Assertion est ce qui doit être corrigé rien de plus (que la cause et les effets soient critique ou pas)!
L'exception est ce qui peut déstabiliser un système et qui doit être traitée par l'administrateur avant d'être eventuellement remontée au développeur ! Imagines que du jour au lendemain l'option ea soit supprimée par erreur ou par directive...
Le garde fou doit, IMHO, être assuré par l'Exception et non pas par l'Error (le AssertionError en l'occurence). Et doit être traitée au plus prêt !
Par ailleurs pourquoi devraient-ils avoir un traitement différent des exceptions qui passent outre tes gardes fous (des pointeurs null, des divisions par 0 non traitées par exemples) ?
L'Assertion ne devrait être qu'un outil de développeur; et, non pas un outil d'admin ! L'assertionError n'est pas nécessairement à traiter au plus prêt de l'erreur.
Vu l'exemple posté, les "contrats" sont mis sur les méthodes et pas sur les interfaces. C'est pourquoi je suis plutôt de l'avis de tchize_ en considérant que ces "contrats" sont des assert améliorés. Ou, pour être exact, des aspects de type "pré-conditon" et "post-condition".
Dans l'idéal, le contrat devrait être placé sur l'interface en entier, car l'interface modélise le comportement.
D'ailleurs si on se place au niveau du comportement, le @Requires sur la méthode setHour() n'est pas nécessaire, car le @Ensures fait référence à la méthode getHour() qui nous assure que 0<=h<=23.
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.
en fait, plus besoin d'implémenter l'interface.
Quand je lit ça
l'interface est déjà, de facto, implémentée. Le compilateur pourrait etre capable de partir de là et dire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 @Ensures({ "result >= 0", "result <= 23" }) int getHour(); @Requires({ "h >= 0", "h <= 23" }) @Ensures("getHour() == h") void setHour(int h);
si je fait un setHour, le getHour me retourne la même valeur.
=>
ensuite: le require est traduit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 public int getHour() {return _hour;} public void setHour(int h) {_hour = ;}
puis aussi le ensure sur le retour.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 public void setHour(int h) { assert(h>=0); assert(h<=23); _hour = ;}
Je sais pas si ça se passe comme ça actuellement, mais tant qu'à faire
Par «*interface », je voulais dire « spécification », « interface » par opposition à « implémentation ». Les assert tels qu'on les a en Java font partie de l'implémentation de la méthode : si une classe fille surcharge la méthode, elle fournit sa propre implémentation et les assert disparaissent avec l'ancienne (sauf si la classe fille les répète). Un contrat, en revanche, fait partie de la spécification de la méthode : si une classe fille hérite et surcharge la méthode, elle devra respecter la même interface, et le framework lui appliquera les mêmes contrats (éventuellement étendus selon les règles d'héritage).
La sémantique standard des pré/postconditions est : si Précondition est satisfaite en entrée, alors je garantie Postcondition en sortie. Si on enlève la précondition, cela reviendrait à dire que peu importe l'entrée, on garantie qu'en sortie h == getHour(), ce qui n'est pas possible, car on garantie d'un autre côté que getHour() renvoie quelque chose entre 0 et 23. D'un point de vue sémantique, la différence fondamentale est que la précondition est à la charge de l'appelant tandis que la postcondition est une garantie que je garantie sur ma méthode. Autrement dit, si le framework lève une erreur de postcondition, c'est que j'ai un bug dans mon code ; s'il lève une précondition, c'est que l'utilisateur de mon code est fautif.D'ailleurs si on se place au niveau du comportement, le @Requires sur la méthode setHour() n'est pas nécessaire, car le @Ensures fait référence à la méthode getHour() qui nous assure que 0<=h<=23.
@lenhat : oui, j'ai bien compris ce que faisait ce framework et ce qu'était dans ce cas la définition du contrat. Je dis simplement que pour moi c'est un assert codé dans une annotation, déclenché lors de l'entrée/sortie d'un appel de méthode. C'est bien un contrat de codage (niveau implémentation) et pas un contrat de comportement (niveau conception).
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.
J'ai commencé en java avec un livre sur le C prenant java pour une extension dudit langage et introduisait la notion de contrat dans le langage Java. J'ai passé des mois à écrire les @require, ... dans mon code sans savoir que le JDK n'avait rien à f**tre.
je vais enfin pouvoir réellement utiliser la notion de contrat en java.
Merci google
Cela dit, ce n'est pas le premier framework de programmation par contrats pour Java. Il y a aussi JContractor, mais on dirait bien qu'il n'est plus maintenu :
http://jcontractor.sourceforge.net/
Les contrats au sein même des interfaces, c'est supremement sympa pour être certain que toutes les implémentations de ces interfaces respecteront une certaine norme.
Par contre, j'aimerai bien que Java embarque directement les contrats, sans passer par des extensions tierces qui du coup ne disposeront jamais d'aucune aide des environnement de développement au niveau de la complétion ou autre. Le C# a embrassé les contrats dans sa version 4 (encore qu'il faille un plugin additionnel pour les activer dans l'IDE, et non utilisable dans Visual express), à quand Java ? :-)
eclipse et netbeans intégrent automatiquement toutes les annotations qu'il trouvent dans votre classpath de projet. donc vous avez d'office l'autocompletion, la doc etc. Quand au supprot pour la vérification, je suppose que ce genre de règle viens avec soit des test unitaires ad-hoc pour maven ou autre (que les ide peuvent intégrer sans soucis), soit avec des règle de weaving pour les injecter dans le code généré (encore une fois, ceci est géré par les ide). Bref, je ne m'inquiéterait pas donc de ce coté là. Certes vous n'aurez probablement pas de la part de l'IDE quelque chose du style
souligné en rouge avec le commentaire "le contrat dit que ca doit retourner entre 0 et 23, valeur -1 non autorisé dans instruction return"
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 public int getHour(){ return -1; // not implemented }
mais bon
Je connais cette lib inspirée d'Eiffel qui existe depuis 6 ans au moins.
http://jcontractor.sourceforge.net/
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager