VOID-SAFE  En Eiffel
Copyright 2012, Group SBenoît Marchal, Paul-Georges Crismer  @declencheur          @pgcrismerCette présentation est distri...
AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique  Nouveaux projets  Conversion d’un projet
Montrez-moi Void !
Heu… sérieusement :-)durant l’exécution d’une application, une référence est  soit attachée à un objet    create a_domain....
Banalsynonymes dans tous les langages  SQL, JavaScript, Java, C# : null  Lisp, Pascal : nil  VB : nothing  C/C++ : Ø ou null
Parce que c’est utile
Maisl’appel sur une référence non attachée/void  erreur d’exécutionplus fréquent dans un langage orienté-objet  les objets...
Difficile à trouverévidemment, on n’écrit pas  Void.do_somethingcreate a_domain.make -- a_domain attachéea_range := Void --...
Similaire à ÷Øen calcul sur des entiers  on a besoin du zéro  on a besoin de diviser des entiersmais il ne faut jamais div...
De même, VoidVoid  indispensable  source d’erreur difficile à détecterréférences fréquentes dans un système orienté-objet
A propos…appel sur Void déclenche une exception  qu’on pourrait intercepter  mais il est plus simple de tester la référenc...
Avoid a void“That case occurs in system-oriented parts ofprograms, typically in libraries that implementfundamental data s...
Concrètement               ownerACCOUNT: 123           PERSON: Jack               ownerACCOUNT: 345           PERSON: John...
Et pourtant               ownerACCOUNT: 123             PERSON: Jack                          is_nogood: False            ...
Ou encore               ownerACCOUNT: 123              REAL_PERSON: Jack               ownerACCOUNT: 345             REAL_...
Voire même                             owner   ACCOUNT: 123                           PERSON: Jack                        ...
A propos du SQL Nullnorme ISO : information manquante ou non applicable  complexe (logique à 3 valeurs, join,…)  mais il n...
Donc, Voidindispensablesource d’erreur difficile à détecter  appel sur une référence à Void  fréquent dans un système orient...
EIFFEL VOID-SAFE
Void safetyrenforcer le contrôle des types de référence  attached  detachable    cas particulier, pour les aspects techniq...
CAPtransforme un référence détachable en attachéeCAP de base  x.f(…) est void-safe si    x est un paramètre ou une variabl...
Exemple de CAPlocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend
Erreur VEVIVariable is not properly set.  local  * text: attached STRING  do  * text.append (" or something")  end
Une solution possiblelocal* text: attached STRINGdo* text := "John"* text.append (" or something")end
Erreur VUTATarget of the Object_call is not attached.  local  * name: detachable STRING  do  * -- …  * name.append (" or s...
Une solution possiblelocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append (" or something")* endend
Erreur VUARNon-compatible actual parameter in feature call.  local  * name: detachable STRING  * text: attached STRING  do...
Une solution possiblelocal* name: detachable STRING* text: attached STRINGdo* text := "nothing"* -- …* if name /= Void the...
MICRO-EXERCICE
Créer un projet “Exo_VS”
Sans le compiler
Configurer le projet            1                    2   3                4
Configurer le projet (bis)                    5
Configurer le projet (ter)                    6
Compiler
créer un projet “exo_vs”, sans le compiler  full-class checking? true  void safety: Complete void-safe  syntax: standard s...
Enoncépar clarté, on indique explicitement attached/detachable  normalement, on n’indique que detachablecomplétez deux rou...
Attachédo_attached* local* * queen: attached STRING* do* * queen.mirror* * print (queen)* end
Détachédo_detachable (language: detachable STRING)* do* * language.append (" is void-safe")* * print (language)* end
Proposition de solutiondo_attached* local* * queen: attached STRING* do* * queen := "etihW wonS"* * queen.mirror* * print ...
Proposition de solutiondo_detachable (language: detachable STRING)* do* * if language /= Void then* * * language.append ("...
LANGAGENouvelles constructions
AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique  Nouveaux projets  Conversion d’un projet
VOID CLARITY
Un faux problème ?pré-conditions de type /= Void assure déjà la sécurité  oui, pour du code existant  mais pour du nouveau...
En tous petits caractères    update_flag (a_document, a_file : STRING ;                 a_secretary : SELECT_CLASS)    * req...
Contrats logicielsdans le contrat, on trouve  assertions métier, sémantiquement riches    a_file_in_list : has_file (a_file) ...
Redonner de la lisibilitéupdate_flag (a_document, a_file : STRING ;            a_secretary : SELECT_CLASS)* require* * a_file...
Bénéficesdélègue au compilateur les considérations techniques  moins de code à écrire, déboguer, etc.  sécurité accrue, par...
LANGAGE
4 objectifsstatique : vérifiable à la compilationgénéral : applicable à tous les typessimple : à comprendre et raisonnable ...
Types attachésqualifie l’attachement d’un type : attached/detachableVoid n’est permis que pour les références détachables  ...
Un choix logiquelocal* name: detachable STRING* text: attached STRINGdo* text := "nothing"       mais inverse* -- …       ...
Assignationl’assignation préserve le caractère attachéassigner un type attaché ou un paramètre attaché  uniquement depuis ...
Initialisationpar défaut, une référence est initialisée à Void  il faut donner une valeur acceptable (erreur VEVI)une vari...
CAPcertified attachment pattern  assurer la compatibilité  en intégrant des pratiques courantes    si elles sont sûres  en ...
Exemple de CAPlocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend
Autre exemple de CAPlocal* current: detachable LIST_ITEM* -- …from* current := first_elementuntil* current = Void or else c...
CAP et pré-conditiondo_detachable (name: detachable STRING)* require* * name_attached: name /= Void* do* * name.append (" ...
CAP et attributsif x /= Void then* do_something* x.do_something_elseendn’est pas void-safe si x est un attribut  multithre...
Stableimpossible d’assigner Void à un attribut stable  donc une fois attaché, il le restestable x: detachable TYPEpermet d...
Test d’objetif attached {TYPE} expression as a_local then* -- …* a_local.do_somethingendteste le type de l’expression et l...
Versions simplifiéesif attached expression as local then* -- …* local.do_somethingendif attached local then* -- …* local.do...
Et si on le “sait” ?e.g., en combinant diverses pré-conditionsinvariant : error implies attached messagereport_error* requ...
Check… then… plus lisibleif attached message as a_message then* a_message.do_somethingelse* -- que mettre ici ? une erreur...
Génériqueun paramètre générique est-il attaché ou non ?si nécessaire, on le précise lors de la déclaration  une déclaratio...
Tableauxles éléments d’un tableau sont initialisés à… Void  acceptable pour un type détachable  inacceptable pour un type ...
OPTIONS DU PROJET
Options par clustercascade
Full class checking        PERSON                     make_with_names (a_first, a_last: STRING)                            ...
Obligatoire en Void-safemais automatique en Eiffel 7.xre-vérifie les features héritées dans le descendantdans l’exemple, err...
Void-safetyNo void safety  compilation à l’ancienne, pas de contrôleOn demand void safety  vérifie l’initialisation des réf...
Void controlVoid safety  le compilateur garantit l’absence d’appel sur VoidVoid confidence  le programmeur a confiance dans ...
Etat des lieux, Group S2012  EiffelBase : Void-safe  EWF : Void-safe  ECLI/EPOM : Void-confident  Gobo : pas encore Void-saf...
Donc, en pratiqueon peut viser la void confidence  au moins jusqu’à la migration de Gobo  remplacer EPOSIX par EiffelBase, s...
SyntaxObsolete/transitional/standard syntax  note remplace indexing comme mot-cléProvisional syntax  éléments en cours de ...
Type attachmentattached ➡ detachableAre types attached by default?  True, pour tout nouveau projet    conseillé pour un no...
EN PRATIQUE Nouveaux projets
AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique  Nouveaux projets  Conversion d’un projet
BOITE À OUTILS
De nouvelles habitudesle void-safe est un outil  comme le système de type  comme les contrats logiciels  comme l’encapsula...
Dans le code applicatifminimiser les références détachables  pas un but de les éradiquer mais un moyenmais il faut… se déf...
Pattern du zéro pointé          1          tookCAMERA           ARRAY[PHOTO]                    count = 54                ...
Référence détachable                          à éviter                                 took           CAMERAVoid ici signi...
si la référence est détachable  if attached took as a_took then  * accross a_took as i loop i.item.something end  endsi la...
Quand l’appliquer ?relation dont la cardinalité Ø-n  structure (tableau, liste,…), vide pour Øattention aux “faux null”  p...
Pattern de la fourmi               2inherit ANY redefine default_create endcreate default_createfeature {NONE} -- Construct...
Référence attachéelazy initialisation  on accepte l’initialisation par défaut (Void)     donc la référence doit être détac...
Un compromis…Calcul (et donc bogues)   Mémoire
Et, bien entendu…make (a_text: STRING)* do* * default_create* * text.copy (a_text)* endmake_as_mirror (a_text: STRING)* do...
Choisir le défautchaîne videmessage informatif  “Nom inconnu”données de test  “4200 0000 0000 0000”voir aussi le pattern I...
Et pour les invariants…confus, on n’est pas tenté de l’écrire ou de le lire  invariant  * valid: card /= Void implies is_v...
Quand l’appliquer ?dès qu’une valeur par défaut raisonnable existeattention aux “faux nulls”  par exemple, dans la BD, la ...
Pattern de la roue libre        3feature -- Access* message: STRING* * attribute* * * create Result.make_empty* * endiniti...
Attributsi on l’initialise directement  message := "Hello world!"  le code de l’attribut ne sera pas exécutélazy initialis...
feature -- Access* message: STRING assign set_message* * attribute* * * create Result.make_empty* * endfeature -- Element ...
Quand l’appliquer ?similaire à la fourmidès qu’une valeur par défaut raisonnable existe  meilleur quand le coût de créatio...
Pattern Iznogoud                                4pourquoi avoir une référence à Void  bogue : erreur d’initialisation ☞ Vo...
Vive la logique booléenne               ownerACCOUNT: 123             PERSON: Jack                          is_nogood: Fal...
Inversons la chargesoit la valeur est utilisable, soit elle est inconnueor la plupart des routines appliquent un défaut  i...
la plupart des routines se contentent du défaut  name: STRING attribute Result := "Unknown" end  print (owner.name)quelque...
deferred class IZNOGOUD* feature {NONE} -- Constructor* * make_iznogoud* * * do* * * * is_nogood := True* * * ensure* * * ...
Quand l’appliquer ?extension des patterns précédentsdès qu’une valeur par défaut raisonnable existe    mais quelques routi...
Pattern de l’héritier maudit                 5               ownerACCOUNT: 123              REAL_PERSON: Jack             ...
Quand l’appliquer ?relation Ø-1pour l’objet lié  des valeurs/traitements par défaut existent     variante plus intelligent...
Pattern singleton orphelin                                6                            owner    ACCOUNT: 123              ...
Quand l’appliquer ?relation Ø-1pour l’objet lié  des valeurs par défaut raisonnables existent  ou des traitements par défa...
Pattern de l’objet relation           7ACCOUNT: 123            PERSON: Jack               OWNINGACCOUNT: 345            PE...
Quand l’appliquer ?relation Ø-1on souhaite enrichir la relationil n’y a pas de valeurs par défaut raisonnablesinconvénient...
Pattern detachable                           8quand on ne peut pas travailler avec une valeur  inconnu ou inapplicablede f...
if touch.is_nogood then* touch.do_specialelse* touch.do_regularendif touch /= Void then* touch.do_specialelse* touch.do_re...
Quand l’appliquer ?selon la fréquence de ces tests  si > 85% des algorithmesavantage  le compilateur garantit qu’on oublie...
EXERCICE
Table des matièresAPPLICATION la racine du systèmeIDEA un concept dans une arborescence/Mind Map nom, description tableau ...
Tout est détachable !malheureusement  développeur n’a pas perçu le bénéfice du Void-safe  donc le code est difficile à lire, ...
APPLICATIONnote                                                                                     *     *   *      toolb...
IDEAnote                                                                                       *           *              ...
EN PRATIQUE  Conversion
AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique  Nouveaux projets  Conversion d’un projet
Pré-conditionsparameter_not_void: parameter /= Voiddevenues inutiles pour les paramètres attachéslaissez-les, au moins dan...
if … /= Voidle plus gros effort  indiquent que Void a un signification  ils sont toujours vrais…    donc on doit adapter un ...
Ajuster les testsen utilisant nos patterns  ré-écrire le test    if stuff.is_nogood then  utiliser une valeur par défaut ou...
Compromis de contratpréserver autant que possible le contrat  mais le défaut à changer entre attaché/détachable  à évaluer...
Prochain SlideShare
Chargement dans…5
×

Void-safe en Eiffel

753 vues

Publié le

Void-safe augmente la stabilité et la fiabilité du logiciel tout en diminuant le travail pour le développeur ! Une opération totalement gagnante.
Le langage de programmation Eiffel offre une excellente mise en œuvre du Void-safe mais certains des principes présentés ici s'appliquent à tous les langages.

Publié dans : Technologie
0 commentaire
1 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
753
Sur SlideShare
0
Issues des intégrations
0
Intégrations
2
Actions
Partages
0
Téléchargements
2
Commentaires
0
J’aime
1
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Void-safe en Eiffel

  1. 1. VOID-SAFE En Eiffel
  2. 2. Copyright 2012, Group SBenoît Marchal, Paul-Georges Crismer @declencheur @pgcrismerCette présentation est distribuée sous licence CC-BYPour les conditions d’utilisation, consulterhttp://creativecommons.org/licenses/by/2.0/be/
  3. 3. AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique Nouveaux projets Conversion d’un projet
  4. 4. Montrez-moi Void !
  5. 5. Heu… sérieusement :-)durant l’exécution d’une application, une référence est soit attachée à un objet create a_domain.make soit Void a_domain := Void
  6. 6. Banalsynonymes dans tous les langages SQL, JavaScript, Java, C# : null Lisp, Pascal : nil VB : nothing C/C++ : Ø ou null
  7. 7. Parce que c’est utile
  8. 8. Maisl’appel sur une référence non attachée/void erreur d’exécutionplus fréquent dans un langage orienté-objet les objets sont accessibles via des référencesque dans un langage procédural où (hormis C) les pointeurs étaient moins utilisés
  9. 9. Difficile à trouverévidemment, on n’écrit pas Void.do_somethingcreate a_domain.make -- a_domain attachéea_range := Void -- a_range détachéea_space.lots_of_complex_stuff a_space… heu… joker !
  10. 10. Similaire à ÷Øen calcul sur des entiers on a besoin du zéro on a besoin de diviser des entiersmais il ne faut jamais diviser par zéro c’est une erreur à l’exécutionmais… plus d’appels sur références que de divisions
  11. 11. De même, VoidVoid indispensable source d’erreur difficile à détecterréférences fréquentes dans un système orienté-objet
  12. 12. A propos…appel sur Void déclenche une exception qu’on pourrait intercepter mais il est plus simple de tester la référence d’où les innombrables assertions a_param /= Voidet le bogue courant c’est d’oublier un test
  13. 13. Avoid a void“That case occurs in system-oriented parts ofprograms, typically in libraries that implementfundamental data structures in the more application-oriented parts of a program, void references aregenerally unnecessary.[…] confine void references to specific parts of asystem, largely preserving the application-orientedlayers from having to worry about the issues [of voidreferences]”
  14. 14. Concrètement ownerACCOUNT: 123 PERSON: Jack ownerACCOUNT: 345 PERSON: John ownerACCOUNT: 567 Void ici signifie “je ne le connais pas.”
  15. 15. Et pourtant ownerACCOUNT: 123 PERSON: Jack is_nogood: False ownerACCOUNT: 345 PERSON: John is_nogood: False ownerACCOUNT: 567 PERSON: Unknown is_nogood: True
  16. 16. Ou encore ownerACCOUNT: 123 REAL_PERSON: Jack ownerACCOUNT: 345 REAL_PERSON: John ownerACCOUNT: 567 UNKNOWN_PERSON <<deferred>> PERSON REAL_PERSON UNKNOWN_PERSON
  17. 17. Voire même owner ACCOUNT: 123 PERSON: Jack owner ACCOUNT: 345 PERSON: John owner ACCOUNT: 567 PERSON: Unknown {NONE} unknown_personSHARED_UNKNOWN_PERSON Shared_unknown: PERSON is_unknown(person: PERSON): boolean
  18. 18. A propos du SQL Nullnorme ISO : information manquante ou non applicable complexe (logique à 3 valeurs, join,…) mais il ne s’agit pas d’une référence, pas d’appelsouvent traduit par une référence détachable en Eiffel sans doute pas la meilleure représentation nous verrons quelques patterns alternatifs
  19. 19. Donc, Voidindispensablesource d’erreur difficile à détecter appel sur une référence à Void fréquent dans un système orienté-objetà limiter aux parties techniques de l’application
  20. 20. EIFFEL VOID-SAFE
  21. 21. Void safetyrenforcer le contrôle des types de référence attached detachable cas particulier, pour les aspects techniques certified attachment patternsgarantie du compilateur : plus d’appels sur Void
  22. 22. CAPtransforme un référence détachable en attachéeCAP de base x.f(…) est void-safe si x est un paramètre ou une variable locale dans la portée d’un test d’attachement de x n’est pas précédé par une assignation à x
  23. 23. Exemple de CAPlocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend
  24. 24. Erreur VEVIVariable is not properly set. local * text: attached STRING do * text.append (" or something") end
  25. 25. Une solution possiblelocal* text: attached STRINGdo* text := "John"* text.append (" or something")end
  26. 26. Erreur VUTATarget of the Object_call is not attached. local * name: detachable STRING do * -- … * name.append (" or something") end
  27. 27. Une solution possiblelocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append (" or something")* endend
  28. 28. Erreur VUARNon-compatible actual parameter in feature call. local * name: detachable STRING * text: attached STRING do * text := "nothing" * -- … * text.append (name) end
  29. 29. Une solution possiblelocal* name: detachable STRING* text: attached STRINGdo* text := "nothing"* -- …* if name /= Void then* * text.append (name)* endend
  30. 30. MICRO-EXERCICE
  31. 31. Créer un projet “Exo_VS”
  32. 32. Sans le compiler
  33. 33. Configurer le projet 1 2 3 4
  34. 34. Configurer le projet (bis) 5
  35. 35. Configurer le projet (ter) 6
  36. 36. Compiler
  37. 37. créer un projet “exo_vs”, sans le compiler full-class checking? true void safety: Complete void-safe syntax: standard syntax are types attached by default? true base library: …base-safe.ecf precompiled base: …base-safe.ecf
  38. 38. Enoncépar clarté, on indique explicitement attached/detachable normalement, on n’indique que detachablecomplétez deux routines pour les rendre void-safe et compiler :-)notez que ce n’est pas la même erreur bonus : pourquoi ?
  39. 39. Attachédo_attached* local* * queen: attached STRING* do* * queen.mirror* * print (queen)* end
  40. 40. Détachédo_detachable (language: detachable STRING)* do* * language.append (" is void-safe")* * print (language)* end
  41. 41. Proposition de solutiondo_attached* local* * queen: attached STRING* do* * queen := "etihW wonS"* * queen.mirror* * print (queen)* end
  42. 42. Proposition de solutiondo_detachable (language: detachable STRING)* do* * if language /= Void then* * * language.append (" is void-safe")* * * print (language)* * end* end
  43. 43. LANGAGENouvelles constructions
  44. 44. AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique Nouveaux projets Conversion d’un projet
  45. 45. VOID CLARITY
  46. 46. Un faux problème ?pré-conditions de type /= Void assure déjà la sécurité oui, pour du code existant mais pour du nouveau code, réduit l’effort moins à écrire moins de bogues augmente la lisibilité
  47. 47. En tous petits caractères update_flag (a_document, a_file : STRING ; a_secretary : SELECT_CLASS) * requirelisible *? a_document_not_void : a_document /= Void * * * a_file_not_void : a_file /= Void * * a_file_in_list : has_file (a_file) * * a_secretary_not_void : a_secretary /= Void * do * * -- … * end
  48. 48. Contrats logicielsdans le contrat, on trouve assertions métier, sémantiquement riches a_file_in_list : has_file (a_file) noyées dans… de la technique, un faux void-safe a_file_not_void : a_file /= Void
  49. 49. Redonner de la lisibilitéupdate_flag (a_document, a_file : STRING ; a_secretary : SELECT_CLASS)* require* * a_file_in_list : has_file (a_file)* do* * -- …* end
  50. 50. Bénéficesdélègue au compilateur les considérations techniques moins de code à écrire, déboguer, etc. sécurité accrue, par rapport aux préconditionsune vraie documentation lisible et riche maintenance, reprise du code simplifiée
  51. 51. LANGAGE
  52. 52. 4 objectifsstatique : vérifiable à la compilationgénéral : applicable à tous les typessimple : à comprendre et raisonnable à implémentercompatible : avec le langage et les applications en pratique, ce n’est que partiel, il faut porter
  53. 53. Types attachésqualifie l’attachement d’un type : attached/detachableVoid n’est permis que pour les références détachables right: detachable LINKABLE[G]attached est la valeur par défaut, on ne l’écrit pas vérifier les paramètres du projet ! attention à l’ancien code, c’est un changement…
  54. 54. Un choix logiquelocal* name: detachable STRING* text: attached STRINGdo* text := "nothing" mais inverse* -- … d ’aujourd’hui* if name /= Void then* * text.append (name)* endend
  55. 55. Assignationl’assignation préserve le caractère attachéassigner un type attaché ou un paramètre attaché uniquement depuis une référence attachée text := "nothing" if a_detachable /= Void then * text := a_detachable end
  56. 56. Initialisationpar défaut, une référence est initialisée à Void il faut donner une valeur acceptable (erreur VEVI)une variable doit avoir une valeur acceptable variable locale, dans le corps de la routine attribut, via le constructeur
  57. 57. CAPcertified attachment pattern assurer la compatibilité en intégrant des pratiques courantes si elles sont sûres en particulier, le test d’une variable locale /= Void
  58. 58. Exemple de CAPlocal* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend
  59. 59. Autre exemple de CAPlocal* current: detachable LIST_ITEM* -- …from* current := first_elementuntil* current = Void or else current.item.is_equal (sought)loop* current := l.rightend
  60. 60. CAP et pré-conditiondo_detachable (name: detachable STRING)* require* * name_attached: name /= Void* do* * name.append (" is famous")* * print (text)* end
  61. 61. CAP et attributsif x /= Void then* do_something* x.do_something_elseendn’est pas void-safe si x est un attribut multithreading : modification entre test et appel monothread: do_something modifie l’attribut
  62. 62. Stableimpossible d’assigner Void à un attribut stable donc une fois attaché, il le restestable x: detachable TYPEpermet d’utiliser le CAP avec des attributs puisqu’il ne peut être détaché après le test… sucre syntaxique pour une conversion
  63. 63. Test d’objetif attached {TYPE} expression as a_local then* -- …* a_local.do_somethingendteste le type de l’expression et l’assigne à local remplace la tentative d’assignation ?= restreint la portée de la variable locale au test
  64. 64. Versions simplifiéesif attached expression as local then* -- …* local.do_somethingendif attached local then* -- …* local.do_somethingend
  65. 65. Et si on le “sait” ?e.g., en combinant diverses pré-conditionsinvariant : error implies attached messagereport_error* require* * error_set: error* do* * -- message est attaché… pas pour le compilateur* end
  66. 66. Check… then… plus lisibleif attached message as a_message then* a_message.do_somethingelse* -- que mettre ici ? une erreur ?endcheck attached message as a_message then* a_message.do_somethingend
  67. 67. Génériqueun paramètre générique est-il attaché ou non ?si nécessaire, on le précise lors de la déclaration une déclaration de contrainte habituelleclass GENERIC_CLASS[T -> attached ANY]
  68. 68. Tableauxles éléments d’un tableau sont initialisés à… Void acceptable pour un type détachable inacceptable pour un type attachémake_filled (low, high: INTEGER; value: G)make_empty et on fait grossir le tableau si les indices progressent 1 par 1
  69. 69. OPTIONS DU PROJET
  70. 70. Options par clustercascade
  71. 71. Full class checking PERSON make_with_names (a_first, a_last: STRING) * domake_with_names (a_first, a_last) * * first_name := a_first first_name: STRING * * last_name := a_last last_name: STRING * end make TAXI_DRIVER * -- first_name & last_name ne sont pas attachés ! * do make * * create taxi.make taxi: CAR " end
  72. 72. Obligatoire en Void-safemais automatique en Eiffel 7.xre-vérifie les features héritées dans le descendantdans l’exemple, erreur VEVI make_with_names (a_first, a_last: STRING) * do * * Precursor (a_first, a_last) * * create taxi.make * end
  73. 73. Void-safetyNo void safety compilation à l’ancienne, pas de contrôleOn demand void safety vérifie l’initialisation des références attachéesComplete void safety applique tous les contrôles
  74. 74. Void controlVoid safety le compilateur garantit l’absence d’appel sur VoidVoid confidence le programmeur a confiance dans son code par contrat et/ou “On demand void safe” choix réaliste et suffisant ?
  75. 75. Etat des lieux, Group S2012 EiffelBase : Void-safe EWF : Void-safe ECLI/EPOM : Void-confident Gobo : pas encore Void-safe (en cours) EPOSIX : pas Void-safe
  76. 76. Donc, en pratiqueon peut viser la void confidence au moins jusqu’à la migration de Gobo remplacer EPOSIX par EiffelBase, si possiblele projet doit être “On demand Void-safe” et utiliser les nouveaux ECF
  77. 77. SyntaxObsolete/transitional/standard syntax note remplace indexing comme mot-cléProvisional syntax éléments en cours de normalisationrecommendation : Standard syntax ISO 25436/ECMA 367
  78. 78. Type attachmentattached ➡ detachableAre types attached by default? True, pour tout nouveau projet conseillé pour un nouveau projet False préserve l’ancien comportement réservé aux conversions complexes
  79. 79. EN PRATIQUE Nouveaux projets
  80. 80. AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique Nouveaux projets Conversion d’un projet
  81. 81. BOITE À OUTILS
  82. 82. De nouvelles habitudesle void-safe est un outil comme le système de type comme les contrats logiciels comme l’encapsulationpour construire des systèmes plus robustesVoid-safe n’est pas un but en soi
  83. 83. Dans le code applicatifminimiser les références détachables pas un but de les éradiquer mais un moyenmais il faut… se défaire de mauvaises habitudes Void veut-il dire quelque chose : quoi ? peut-on l’exprimer de façon plus claire ? quelques patterns pour nous aider
  84. 84. Pattern du zéro pointé 1 tookCAMERA ARRAY[PHOTO] count = 54 1 54 PHOTO tookCAMERA ARRAY[PHOTO] count = 0
  85. 85. Référence détachable à éviter took CAMERAVoid ici signifie pas de photo donc zéro photo soyons plus explicite encore
  86. 86. si la référence est détachable if attached took as a_took then * accross a_took as i loop i.item.something end endsi la référence est attachée accross took as i loop i.item.something end toujours aussi correct mais plus lisible zéro passage dans la boucle…
  87. 87. Quand l’appliquer ?relation dont la cardinalité Ø-n structure (tableau, liste,…), vide pour Øattention aux “faux null” par exemple, dans la BD, la foreign key est nulle
  88. 88. Pattern de la fourmi 2inherit ANY redefine default_create endcreate default_createfeature {NONE} -- Constructor* default_create* * do* * * Precursor* * * create text.make_empty* * end
  89. 89. Référence attachéelazy initialisation on accepte l’initialisation par défaut (Void) donc la référence doit être détachable if attached text as a_text then à éviter * a_text.append (something) end habituellement c’est une optimisation à priori
  90. 90. Un compromis…Calcul (et donc bogues) Mémoire
  91. 91. Et, bien entendu…make (a_text: STRING)* do* * default_create* * text.copy (a_text)* endmake_as_mirror (a_text: STRING)* do* * default_create* * text.copy (a_text.mirrored)* end
  92. 92. Choisir le défautchaîne videmessage informatif “Nom inconnu”données de test “4200 0000 0000 0000”voir aussi le pattern Iznogoud
  93. 93. Et pour les invariants…confus, on n’est pas tenté de l’écrire ou de le lire invariant * valid: card /= Void implies is_valid (card)facile à écrire, lisible le défaut est une carte de test, donc valide invariant * valid: is_valid (card)
  94. 94. Quand l’appliquer ?dès qu’une valeur par défaut raisonnable existeattention aux “faux nulls” par exemple, dans la BD, la colonne est nullecoût légère surconsommation mémoire
  95. 95. Pattern de la roue libre 3feature -- Access* message: STRING* * attribute* * * create Result.make_empty* * endinitialise à une valeur par défaut
  96. 96. Attributsi on l’initialise directement message := "Hello world!" le code de l’attribut ne sera pas exécutélazy initialisation automatique… derrière le compilateur doit insérer des tests donc c’est parfois plus coûteux que la fourmi
  97. 97. feature -- Access* message: STRING assign set_message* * attribute* * * create Result.make_empty* * endfeature -- Element change* set_message (a_message: STRING)* * do* * * message := a_message* * ensure* * * message_set: message = a_message* * end
  98. 98. Quand l’appliquer ?similaire à la fourmidès qu’une valeur par défaut raisonnable existe meilleur quand le coût de création est plus élevé par exemple, une requête BD…attention aux “faux nulls” par exemple, dans la BD, la colonne est nulle
  99. 99. Pattern Iznogoud 4pourquoi avoir une référence à Void bogue : erreur d’initialisation ☞ Void-safe lazy initialisation ☞ zéro pointé, fourmi, roue libre valeur inconnue : Void a une sémantique métierla plupart des routines ne font pas de différence valeur par défaut et valeur inconnue
  100. 100. Vive la logique booléenne ownerACCOUNT: 123 PERSON: Jack is_nogood: False ownerACCOUNT: 345 PERSON: John is_nogood: False ownerACCOUNT: 567 PERSON: Unknown is_nogood: True
  101. 101. Inversons la chargesoit la valeur est utilisable, soit elle est inconnueor la plupart des routines appliquent un défaut if owner = Void then * print ("Unknown") else * print (owner.name) end mais on doit répéter le test partout
  102. 102. la plupart des routines se contentent du défaut name: STRING attribute Result := "Unknown" end print (owner.name)quelques routines traitent différemment le cas inconnu if (owner.is_nogood) then * database.store_name_as_null else * database.store_name (owner.name) end
  103. 103. deferred class IZNOGOUD* feature {NONE} -- Constructor* * make_iznogoud* * * do* * * * is_nogood := True* * * ensure* * * * iznogoud: is_nogood* * * end* feature {ANY} -- Access* * -- default initialization is False* * is_nogood: BOOLEANend
  104. 104. Quand l’appliquer ?extension des patterns précédentsdès qu’une valeur par défaut raisonnable existe mais quelques routines ont un traitement spécial erreur, avertissement, BD, etc.peu d’algorithmes n’acceptent pas la valeur par défaut mais il y en a dans la classe
  105. 105. Pattern de l’héritier maudit 5 ownerACCOUNT: 123 REAL_PERSON: Jack ownerACCOUNT: 345 REAL_PERSON: John ownerACCOUNT: 567 UNKNOWN_PERSON <<deferred>> PERSON REAL_PERSON UNKNOWN_PERSON
  106. 106. Quand l’appliquer ?relation Ø-1pour l’objet lié des valeurs/traitements par défaut existent variante plus intelligente du “Null object pattern”inconvénient : deux classes supplémentairesavantage : isole les créations par défaut
  107. 107. Pattern singleton orphelin 6 owner ACCOUNT: 123 STRING: John owner ACCOUNT: 345 STRING: John owner ACCOUNT: 567 STRING: Unknown owner ACCOUNT: 789 {NONE} unknown_personSHARED_UNKNOWN_PERSON shared_unknown: STRING is_unknown(person: STRING): BOOLEAN
  108. 108. Quand l’appliquer ?relation Ø-1pour l’objet lié des valeurs par défaut raisonnables existent ou des traitements par défaut difficile de modifier le graphe d’héritage librairie ou lisibilité
  109. 109. Pattern de l’objet relation 7ACCOUNT: 123 PERSON: Jack OWNINGACCOUNT: 345 PERSON: John OWNINGACCOUNT: 567
  110. 110. Quand l’appliquer ?relation Ø-1on souhaite enrichir la relationil n’y a pas de valeurs par défaut raisonnablesinconvénient la navigation entre les 2 objets est indirecte
  111. 111. Pattern detachable 8quand on ne peut pas travailler avec une valeur inconnu ou inapplicablede façon répétitive et très nombreusealors Eiffel offre une primitive :Void le compilateur va garantir qu’on n’oublie pas un test
  112. 112. if touch.is_nogood then* touch.do_specialelse* touch.do_regularendif touch /= Void then* touch.do_specialelse* touch.do_regularendchou vert et vert chou, quand c’est fréquent
  113. 113. Quand l’appliquer ?selon la fréquence de ces tests si > 85% des algorithmesavantage le compilateur garantit qu’on oublie pas un test
  114. 114. EXERCICE
  115. 115. Table des matièresAPPLICATION la racine du systèmeIDEA un concept dans une arborescence/Mind Map nom, description tableau d’enfants
  116. 116. Tout est détachable !malheureusement développeur n’a pas perçu le bénéfice du Void-safe donc le code est difficile à lire, peu maintenablevotre mission supprimer les detachables, test /= Void, etc. en utilisant les 8 premiers patterns
  117. 117. APPLICATIONnote * * * toolbox.description := "9 patterns"* description : "Void-safe exercice, as a TOC" * * * create exercice* date : "$Date$" * * * exercice.name := "Exercice"* revision : "$Revision$" * * * create project_conversion * * * project_conversion.name := "Conversions"class * * * toc.add_child (void_safe)* APPLICATION * * * toc.add_child (language) * * * toc.add_child (practical_information)create * * * void_safe.add_child (eiffel_void_safe)* make * * * void_safe.add_child (micro_exercice) * * * practical_information.add_child (new_projects)feature {NONE} -- Initialization * * * practical_information.add_child (project_conversion)* make * * * new_projects.add_child (options)* * local * * * new_projects.add_child (void_clarity)* * * toc, void_safe, eiffel_void_safe, * * * new_projects.add_child (toolbox)** * * micro_exercice, language, * * * new_projects.add_child (exercice)* * * practical_information, new_projects, options, * * * toc.print_as_tree* * * void_clarity, toolbox, exercice, * * end* * * project_conversion : detachable IDEA end* * do* * * create toc* * * toc.name := "Formation Void-safe"* * * create void_safe* * * void_safe.name := "Void-safe"* * * void_safe.description := "Eviter une erreur"* * * create eiffel_void_safe* * * eiffel_void_safe.name := "Eiffel"* * * create micro_exercice* * * micro_exercice.name := "Micro-exercice"* * * micro_exercice.description := "A corriger"* * * create language* * * language.name := "Langage"* * * language.description := "Nouveautés"* * * create practical_information* * * practical_information.name := "Pratique"* * * create new_projects* * * new_projects.name := "Les nouveaux projets"* * * create options* * * options.name := "Options"* * * options.description := "Option pour le projet"* * * create void_clarity* * * void_clarity.name := "Void-clarity"* * * create toolbox* * * toolbox.name := "Boîte à outils"
  118. 118. IDEAnote * * the_children.count + 1)* description: "One idea/word in a Mind Map." * * * end* date: "$Date$" * * ensure* revision: "$Revision$" * * * children_not_void: attached children * * * child_added: attached children asclass * * * * the_children implies* IDEA * * * * the_children.has (an_idea)feature -- Access * * end* name: detachable STRING assign set_name feature {IDEA} -- Implementation* description: detachable STRING * print_as_tree_helper (spaces: INTEGER)* * * * assign set_description * * requireaspaces_positive: spaces >= 0* children: detachable ARRAY [IDEA] * * do * * * print_spaces (spaces)feature -- Display * * * if attached name as a_name then* print_as_tree * * * * print (a_name)* * do * * * else* * * print_as_tree_helper (0) * * * * print ("##unknown##")* * end * * * endfeature -- Element change * * * print_spaces (spaces)* set_name (a_name: detachable STRING) * * * print ("%N")* * require * * * if attached description as a_description then* * * name_not_void: a_name /= Void * * * * print_spaces (spaces)* * do * * * * print (">>")* * * name := a_name * * * * print (a_description)* * ensure * * * * print ("%N")* * * name_set: name = a_name * * * end* * end * * * if attached children as the_children then* set_description (a_description: detachable STRING) * * * * across the_children as cursor* * do * * * * loop* * * description := a_description * * * * * cursor.item.print_as_tree_helper (spaces +* * ensure 3)* * * description_set: description = a_description * * * * end* * end * * * end* add_child (an_idea: detachable IDEA) * * end* * require* * * idea_not_void: an_idea /= Void * print_spaces (spaces: INTEGER)* * do * * require* * * if not attached children then * * * spaces_positive: spaces >= 0* * * * create children.make_empty * * do* * * end * * * across 1 |..| spaces as i loop print ( ) end* * * if attached children as the_children then * * end* * * * the_children.force (an_idea, end* * * * * * *
  119. 119. EN PRATIQUE Conversion
  120. 120. AgendaQu’est-ce le Void-safe ?Nouveaux éléments de langageEn pratique Nouveaux projets Conversion d’un projet
  121. 121. Pré-conditionsparameter_not_void: parameter /= Voiddevenues inutiles pour les paramètres attachéslaissez-les, au moins dans un premier temps elles faciliteront d’autres aspects de la conversion elles permettent de compiler en void-safe ou non
  122. 122. if … /= Voidle plus gros effort indiquent que Void a un signification ils sont toujours vrais… donc on doit adapter un testà analyser au cas par cas
  123. 123. Ajuster les testsen utilisant nos patterns ré-écrire le test if stuff.is_nogood then utiliser une valeur par défaut ou un tableau videou le rendre detachablepréconditions /= Void, pas de problème
  124. 124. Compromis de contratpréserver autant que possible le contrat mais le défaut à changer entre attaché/détachable à évaluer au cas par caspour l’appelant, il est plus facile que vous retourniez des attachés acceptiez des détachables, si Void était permis

×