124
VOID-SAFE En Eiel

Void-safe en Eiffel

Embed Size (px)

DESCRIPTION

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.

Citation preview

Page 1: Void-safe en Eiffel

VOID-SAFEEn Eiffel

Page 2: Void-safe en Eiffel

Copyright 2012, Group SBenoît Marchal, Paul-Georges Crismer @declencheur @pgcrismer

Cette présentation est distribuée sous licence CC-BYPour les conditions d’utilisation, consulterhttp://creativecommons.org/licenses/by/2.0/be/

Page 3: Void-safe en Eiffel

Agenda

Qu’est-ce le Void-safe ?

Nouveaux éléments de langage

En pratique

Nouveaux projets

Conversion d’un projet

Page 4: Void-safe en Eiffel

Montrez-moi Void !

Page 5: Void-safe en Eiffel

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

Page 6: Void-safe en Eiffel

Banal

synonymes dans tous les langages

SQL, JavaScript, Java, C# : null

Lisp, Pascal : nil

VB : nothing

C/C++ : Ø ou null

Page 7: Void-safe en Eiffel

Parce que c’est utile

Page 8: Void-safe en Eiffel

Mais

l’appel sur une référence non attachée/void

erreur d’exécution

plus fréquent dans un langage orienté-objet

les objets sont accessibles via des références

que dans un langage procédural

où (hormis C) les pointeurs étaient moins utilisés

Page 9: Void-safe en Eiffel

Difficile à trouver

évidemment, on n’écrit pas

Void.do_something

create a_domain.make -- a_domain attachée

a_range := Void -- a_range détachée

a_space.lots_of_complex_stuff

a_space… heu… joker !

Page 10: Void-safe en Eiffel

Similaire à ÷Ø

en calcul sur des entiers

on a besoin du zéro

on a besoin de diviser des entiers

mais il ne faut jamais diviser par zéro

c’est une erreur à l’exécution

mais… plus d’appels sur références que de divisions

Page 11: Void-safe en Eiffel

De même, Void

Void

indispensable

source d’erreur difficile à détecter

références fréquentes dans un système orienté-objet

Page 12: Void-safe en Eiffel

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 /= Void

et le bogue courant c’est d’oublier un test

Page 13: Void-safe en Eiffel

Avoid a void

“That case occurs in system-oriented parts of programs, typically in libraries that implement fundamental data structures in the more application-oriented parts of a program, void references are generally unnecessary.[…] confine void references to specific parts of a system, largely preserving the application-oriented layers from having to worry about the issues [of void references]”

Page 14: Void-safe en Eiffel

Concrètement

ACCOUNT: 345 PERSON: John

PERSON: JackACCOUNT: 123

ACCOUNT: 567

owner

owner

Void ici signifie“je ne le connais pas.”

owner

Page 15: Void-safe en Eiffel

Et pourtant

ACCOUNT: 345 PERSON: John

PERSON: JackACCOUNT: 123

ACCOUNT: 567 PERSON: Unknown

is_nogood: False

is_nogood: False

is_nogood: True

owner

owner

owner

Page 16: Void-safe en Eiffel

Ou encore

ACCOUNT: 345 REAL_PERSON: John

REAL_PERSON: JackACCOUNT: 123

ACCOUNT: 567 UNKNOWN_PERSON

<<deferred>>PERSON

REAL_PERSON UNKNOWN_PERSON

owner

owner

owner

Page 17: Void-safe en Eiffel

Voire même

ACCOUNT: 345 PERSON: John

PERSON: JackACCOUNT: 123

ACCOUNT: 567 PERSON: Unknown

SHARED_UNKNOWN_PERSONShared_unknown: PERSON

is_unknown(person: PERSON): boolean

owner

owner

owner

{NONE}unknown_person

Page 18: Void-safe en Eiffel

A propos du SQL Null

norme ISO : information manquante ou non applicable

complexe (logique à 3 valeurs, join,…)

mais il ne s’agit pas d’une référence, pas d’appel

souvent traduit par une référence détachable en Eiffel

sans doute pas la meilleure représentation

nous verrons quelques patterns alternatifs

Page 19: Void-safe en Eiffel

Donc, Void

indispensable

source 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

Page 20: Void-safe en Eiffel

EIFFEL VOID-SAFE

Page 21: Void-safe en Eiffel

Void safety

renforcer le contrôle des types de référence

attached

detachable

cas particulier, pour les aspects techniques

certified attachment patterns

garantie du compilateur : plus d’appels sur Void

Page 22: Void-safe en Eiffel

CAP

transforme un référence détachable en attachée

CAP 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

Page 23: Void-safe en Eiffel

Exemple de CAP

local* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend

Page 24: Void-safe en Eiffel

Erreur VEVI

Variable is not properly set.

local* text: attached STRINGdo* text.append (" or something")end

Page 25: Void-safe en Eiffel

Une solution possible

local* text: attached STRINGdo* text := "John"* text.append (" or something")end

Page 26: Void-safe en Eiffel

Erreur VUTA

Target of the Object_call is not attached.

local* name: detachable STRINGdo* -- …* name.append (" or something")end

Page 27: Void-safe en Eiffel

Une solution possible

local* name: detachable STRINGdo* -- …* if name /= Void then* * name.append (" or something")* endend

Page 28: Void-safe en Eiffel

Erreur VUAR

Non-compatible actual parameter in feature call.

local* name: detachable STRING* text: attached STRINGdo* text := "nothing"* -- …* text.append (name)end

Page 29: Void-safe en Eiffel

Une solution possible

local* name: detachable STRING* text: attached STRINGdo* text := "nothing"* -- …* if name /= Void then* * text.append (name)* endend

Page 30: Void-safe en Eiffel

MICRO-EXERCICE

Page 31: Void-safe en Eiffel

Créer un projet “Exo_VS”

Page 32: Void-safe en Eiffel

Sans le compiler

Page 33: Void-safe en Eiffel

Configurer le projet

2 34

1

Page 34: Void-safe en Eiffel

Configurer le projet (bis)

5

Page 35: Void-safe en Eiffel

Configurer le projet (ter)

6

Page 36: Void-safe en Eiffel

Compiler

Page 37: Void-safe en Eiffel

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

Page 38: Void-safe en Eiffel

par clarté, on indique explicitement attached/detachable

normalement, on n’indique que detachable

complétez deux routines

pour les rendre void-safe et compiler :-)

notez que ce n’est pas la même erreur

bonus : pourquoi ?

Enoncé

Page 39: Void-safe en Eiffel

Attaché

do_attached* local* * queen: attached STRING* do* * queen.mirror* * print (queen)* end

Page 40: Void-safe en Eiffel

Détaché

do_detachable (language: detachable STRING)* do* * language.append (" is void-safe")* * print (language)* end

Page 41: Void-safe en Eiffel

Proposition de solution

do_attached* local* * queen: attached STRING* do* * queen := "etihW wonS"* * queen.mirror* * print (queen)* end

Page 42: Void-safe en Eiffel

do_detachable (language: detachable STRING)* do* * if language /= Void then* * * language.append (" is void-safe")* * * print (language)* * end* end

Proposition de solution

Page 43: Void-safe en Eiffel

LANGAGENouvelles constructions

Page 44: Void-safe en Eiffel

Agenda

Qu’est-ce le Void-safe ?

Nouveaux éléments de langage

En pratique

Nouveaux projets

Conversion d’un projet

Page 45: Void-safe en Eiffel

VOID CLARITY

Page 46: Void-safe en Eiffel

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é

Page 47: Void-safe en Eiffel

En tous petits caractères

update_flag (a_document, a_file : STRING ; a_secretary : SELECT_CLASS)* require* * 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

lisible ?

Page 48: Void-safe en Eiffel

Contrats logiciels

dans 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

Page 49: Void-safe en Eiffel

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

Page 50: Void-safe en Eiffel

Bénéfices

délègue au compilateur les considérations techniques

moins de code à écrire, déboguer, etc.

sécurité accrue, par rapport aux préconditions

une vraie documentation lisible et riche

maintenance, reprise du code simplifiée

Page 51: Void-safe en Eiffel

LANGAGE

Page 52: Void-safe en Eiffel

4 objectifs

statique : vérifiable à la compilation

général : applicable à tous les types

simple : à comprendre et raisonnable à implémenter

compatible : avec le langage et les applications

en pratique, ce n’est que partiel, il faut porter

Page 53: Void-safe en Eiffel

Types attachés

qualifie l’attachement d’un type : attached/detachable

Void 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…

Page 54: Void-safe en Eiffel

Un choix logique

local* name:* text:do* text := "nothing"* -- …* if name /= Void then* * text.append (name)* endend

attached STRING

mais inverse d’aujourd’hui

detachable STRING

Page 55: Void-safe en Eiffel

Assignation

l’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_detachableend

Page 56: Void-safe en Eiffel

Initialisation

par 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

Page 57: Void-safe en Eiffel

CAP

certified 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

Page 58: Void-safe en Eiffel

Exemple de CAP

local* name: detachable STRINGdo* -- …* if name /= Void then* * name.append ("something else")* endend

Page 59: Void-safe en Eiffel

Autre exemple de CAP

local* current: detachable LIST_ITEM* -- …from* current := first_elementuntil* current = Void or else current.item.is_equal (sought)loop* current := l.rightend

Page 60: Void-safe en Eiffel

CAP et pré-condition

do_detachable (name: detachable STRING)* require* * name_attached: name /= Void* do* * name.append (" is famous")* * print (text)* end

Page 61: Void-safe en Eiffel

CAP et attributs

if x /= Void then* do_something* x.do_something_elseend

n’est pas void-safe si x est un attribut

multithreading : modification entre test et appel

monothread: do_something modifie l’attribut

Page 62: Void-safe en Eiffel

Stable

impossible d’assigner Void à un attribut stable

donc une fois attaché, il le reste

stable x: detachable TYPE

permet d’utiliser le CAP avec des attributs

puisqu’il ne peut être détaché après le test…

sucre syntaxique pour une conversion

Page 63: Void-safe en Eiffel

Test d’objet

if attached {TYPE} expression as a_local then* -- …* a_local.do_somethingend

teste le type de l’expression et l’assigne à local

remplace la tentative d’assignation ?=

restreint la portée de la variable locale au test

Page 64: Void-safe en Eiffel

Versions simplifiées

if attached expression as local then* -- …* local.do_somethingend

if attached local then* -- …* local.do_somethingend

Page 65: Void-safe en Eiffel

Et si on le “sait” ?

e.g., en combinant diverses pré-conditions

invariant : error implies attached message

report_error* require* * error_set: error* do* * -- message est attaché… pas pour le compilateur* end

Page 66: Void-safe en Eiffel

Check… then… plus lisible

if attached message as a_message then* a_message.do_somethingelse* -- que mettre ici ? une erreur ?end

check attached message as a_message then* a_message.do_somethingend

Page 67: Void-safe en Eiffel

Générique

un 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 habituelle

class GENERIC_CLASS[T -> attached ANY]

Page 68: Void-safe en Eiffel

Tableaux

les é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

Page 69: Void-safe en Eiffel

OPTIONS DU PROJET

Page 70: Void-safe en Eiffel

Options par cluster

cascade

Page 71: Void-safe en Eiffel

Full class checkingPERSON

make_with_names (a_first, a_last)first_name: STRINGlast_name: STRING

TAXI_DRIVERmake

taxi: CAR

make* -- first_name & last_name ne sont pas attachés !* do* * create taxi.make" end

make_with_names (a_first, a_last: STRING)* do* * first_name := a_first* * last_name := a_last* end

Page 72: Void-safe en Eiffel

Obligatoire en Void-safe

mais automatique en Eiffel 7.x

re-vérifie les features héritées dans le descendant

dans l’exemple, erreur VEVI

make_with_names (a_first, a_last: STRING)* do* * Precursor (a_first, a_last) * * create taxi.make* end

Page 73: Void-safe en Eiffel

Void-safety

No void safety

compilation à l’ancienne, pas de contrôle

On demand void safety

vérifie l’initialisation des références attachées

Complete void safety

applique tous les contrôles

Page 74: Void-safe en Eiffel

Void control

Void safety

le compilateur garantit l’absence d’appel sur Void

Void confidence

le programmeur a confiance dans son code

par contrat et/ou “On demand void safe”

choix réaliste et suffisant ?

Page 75: Void-safe en Eiffel

Etat des lieux, Group S

2012

EiffelBase : Void-safe

EWF : Void-safe

ECLI/EPOM : Void-confident

Gobo : pas encore Void-safe (en cours)

EPOSIX : pas Void-safe

Page 76: Void-safe en Eiffel

Donc, en pratique

on peut viser la void confidence

au moins jusqu’à la migration de Gobo

remplacer EPOSIX par EiffelBase, si possible

le projet doit être “On demand Void-safe”

et utiliser les nouveaux ECF

Page 77: Void-safe en Eiffel

Syntax

Obsolete/transitional/standard syntax

note remplace indexing comme mot-clé

Provisional syntax

éléments en cours de normalisation

recommendation : Standard syntax

ISO 25436/ECMA 367

Page 78: Void-safe en Eiffel

Are 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

detachable

Type attachment

attached

Page 79: Void-safe en Eiffel

EN PRATIQUENouveaux projets

Page 80: Void-safe en Eiffel

Agenda

Qu’est-ce le Void-safe ?

Nouveaux éléments de langage

En pratique

Nouveaux projets

Conversion d’un projet

Page 81: Void-safe en Eiffel

BOITE À OUTILS

Page 82: Void-safe en Eiffel

De nouvelles habitudes

le void-safe est un outil

comme le système de type

comme les contrats logiciels

comme l’encapsulation

pour construire des systèmes plus robustes

Void-safe n’est pas un but en soi

Page 83: Void-safe en Eiffel

Dans le code applicatif

minimiser les références détachables

pas un but de les éradiquer mais un moyen

mais 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

Page 84: Void-safe en Eiffel

Pattern du zéro pointé

ARRAY[PHOTO]CAMERAtook

count = 54

CAMERA ARRAY[PHOTO]took

count = 0

PHOTO

54

1

1

Page 85: Void-safe en Eiffel

Void ici signifie

pas de photo donc zéro photo

soyons plus explicite encore

Référence détachable

CAMERAtook

à éviter

Page 86: Void-safe en Eiffel

si la référence est détachable

if attached took as a_took then* accross a_took as i loop i.item.something endend

si 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…

Page 87: Void-safe en Eiffel

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

Page 88: Void-safe en Eiffel

Pattern de la fourmi

inherit ANY redefine default_create end

create default_create

feature {NONE} -- Constructor* default_create* * do* * * Precursor* * * create text.make_empty* * end

2

Page 89: Void-safe en Eiffel

Référence attachée

lazy 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* a_text.append (something)end

habituellement c’est une optimisation à priori

à éviter

Page 90: Void-safe en Eiffel

Un compromis…Calcul (et donc bogues) Mémoire

Page 91: Void-safe en Eiffel

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

Et, bien entendu…

Page 92: Void-safe en Eiffel

Choisir le défaut

chaîne vide

message informatif

“Nom inconnu”

données de test

“4200 0000 0000 0000”

voir aussi le pattern Iznogoud

Page 93: Void-safe en Eiffel

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)

Page 94: Void-safe en Eiffel

Quand l’appliquer ?

dès qu’une valeur par défaut raisonnable existe

attention aux “faux nulls”

par exemple, dans la BD, la colonne est nulle

coût

légère surconsommation mémoire

Page 95: Void-safe en Eiffel

Pattern de la roue libre

feature -- Access* message: STRING* * attribute* * * create Result.make_empty* * end

initialise à une valeur par défaut

3

Page 96: Void-safe en Eiffel

Attribut

si 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

Page 97: Void-safe en Eiffel

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

Page 98: Void-safe en Eiffel

Quand l’appliquer ?

similaire à la fourmi

dè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

Page 99: Void-safe en Eiffel

Pattern Iznogoud

pourquoi 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étier

la plupart des routines ne font pas de différence

valeur par défaut et valeur inconnue

4

Page 100: Void-safe en Eiffel

Vive la logique booléenne

ACCOUNT: 345 PERSON: John

PERSON: JackACCOUNT: 123

ACCOUNT: 567 PERSON: Unknown

is_nogood: False

is_nogood: False

is_nogood: True

owner

owner

owner

Page 101: Void-safe en Eiffel

Inversons la charge

soit la valeur est utilisable, soit elle est inconnue

or 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

Page 102: Void-safe en Eiffel

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_nullelse* database.store_name (owner.name)end

Page 103: Void-safe en Eiffel

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

Page 104: Void-safe en Eiffel

Quand l’appliquer ?

extension des patterns précédents

dè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

Page 105: Void-safe en Eiffel

Pattern de l’héritier maudit 5

ACCOUNT: 345 REAL_PERSON: John

REAL_PERSON: JackACCOUNT: 123

ACCOUNT: 567 UNKNOWN_PERSON

<<deferred>>PERSON

REAL_PERSON UNKNOWN_PERSON

owner

owner

owner

Page 106: Void-safe en Eiffel

Quand l’appliquer ?

relation Ø-1

pour l’objet lié

des valeurs/traitements par défaut existent

variante plus intelligente du “Null object pattern”

inconvénient : deux classes supplémentaires

avantage : isole les créations par défaut

Page 107: Void-safe en Eiffel

Pattern singleton orphelin 6

ACCOUNT: 345

STRING: JohnACCOUNT: 123

ACCOUNT: 567 STRING: Unknown

SHARED_UNKNOWN_PERSONshared_unknown: STRING

is_unknown(person: STRING): BOOLEAN

owner

owner

owner

{NONE}unknown_person

ACCOUNT: 789 owner

STRING: John

Page 108: Void-safe en Eiffel

Quand l’appliquer ?

relation Ø-1

pour 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é

Page 109: Void-safe en Eiffel

Pattern de l’objet relation 7

OWNING

PERSON: JackACCOUNT: 123

ACCOUNT: 345 PERSON: John

OWNING

ACCOUNT: 567

Page 110: Void-safe en Eiffel

Quand l’appliquer ?

relation Ø-1

on souhaite enrichir la relation

il n’y a pas de valeurs par défaut raisonnables

inconvénient

la navigation entre les 2 objets est indirecte

Page 111: Void-safe en Eiffel

Pattern detachable

quand on ne peut pas travailler avec une valeur

inconnu ou inapplicable

de façon répétitive et très nombreuse

alors Eiffel offre une primitive :Void

le compilateur va garantir qu’on n’oublie pas un test

8

Page 112: Void-safe en Eiffel

if touch.is_nogood then* touch.do_specialelse* touch.do_regularend

if touch /= Void then* touch.do_specialelse* touch.do_regularend

chou vert et vert chou, quand c’est fréquent

Page 113: Void-safe en Eiffel

Quand l’appliquer ?

selon la fréquence de ces tests

si > 85% des algorithmes

avantage

le compilateur garantit qu’on oublie pas un test

Page 114: Void-safe en Eiffel

EXERCICE

Page 115: Void-safe en Eiffel

Table des matières

APPLICATION

la racine du système

IDEA

un concept dans une arborescence/Mind Map

nom, description

tableau d’enfants

Page 116: Void-safe en Eiffel

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 maintenable

votre mission

supprimer les detachables, test /= Void, etc.

en utilisant les 8 premiers patterns

Page 117: Void-safe en Eiffel

APPLICATIONnote* description : "Void-safe exercice, as a TOC"* date : "$Date$"* revision : "$Revision$"

class* APPLICATION

create* make

feature {NONE} -- Initialization* make* * local* * * toc, void_safe, eiffel_void_safe,* * * micro_exercice, language,* * * practical_information, new_projects, options,* * * void_clarity, toolbox, exercice,* * * project_conversion : detachable IDEA* * 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"

* * * toolbox.description := "9 patterns"* * * create exercice* * * exercice.name := "Exercice"* * * create project_conversion* * * project_conversion.name := "Conversions"* * * toc.add_child (void_safe)* * * toc.add_child (language)* * * toc.add_child (practical_information)* * * void_safe.add_child (eiffel_void_safe)* * * void_safe.add_child (micro_exercice)* * * practical_information.add_child (new_projects)* * * practical_information.add_child (project_conversion)* * * new_projects.add_child (options)* * * new_projects.add_child (void_clarity)* * * new_projects.add_child (toolbox)** * * new_projects.add_child (exercice)* * * toc.print_as_tree* * endend

Page 118: Void-safe en Eiffel

IDEAnote* description: "One idea/word in a Mind Map."* date: "$Date$"* revision: "$Revision$"

class* IDEAfeature -- Access* name: detachable STRING assign set_name* description: detachable STRING* * * * assign set_description* children: detachable ARRAY [IDEA]

feature -- Display* print_as_tree* * do* * * print_as_tree_helper (0)* * endfeature -- Element change* set_name (a_name: detachable STRING)* * require* * * name_not_void: a_name /= Void* * do* * * name := a_name* * ensure* * * name_set: name = a_name* * end* set_description (a_description: detachable STRING)* * do* * * description := a_description* * ensure* * * description_set: description = a_description* * end

* add_child (an_idea: detachable IDEA)* * require* * * idea_not_void: an_idea /= Void* * do* * * if not attached children then* * * * create children.make_empty* * * end* * * if attached children as the_children then* * * * the_children.force (an_idea,* * * * * * *

* * the_children.count + 1)* * * end* * ensure* * * children_not_void: attached children* * * child_added: attached children as* * * * the_children implies* * * * the_children.has (an_idea)* * endfeature {IDEA} -- Implementation* print_as_tree_helper (spaces: INTEGER)* * requireaspaces_positive: spaces >= 0* * do* * * print_spaces (spaces)* * * if attached name as a_name then* * * * print (a_name)* * * else* * * * print ("##unknown##")* * * end* * * print_spaces (spaces)* * * print ("%N")* * * if attached description as a_description then* * * * print_spaces (spaces)* * * * print (">>")* * * * print (a_description)* * * * print ("%N")* * * end* * * if attached children as the_children then* * * * across the_children as cursor* * * * loop* * * * * cursor.item.print_as_tree_helper (spaces + 3)* * * * end* * * end

* * end

* print_spaces (spaces: INTEGER)* * require* * * spaces_positive: spaces >= 0* * do* * * across 1 |..| spaces as i loop print (' ') end* * endend

Page 119: Void-safe en Eiffel

EN PRATIQUEConversion

Page 120: Void-safe en Eiffel

Agenda

Qu’est-ce le Void-safe ?

Nouveaux éléments de langage

En pratique

Nouveaux projets

Conversion d’un projet

Page 121: Void-safe en Eiffel

Pré-conditions

parameter_not_void: parameter /= Void

devenues inutiles pour les paramètres attachés

laissez-les, au moins dans un premier temps

elles faciliteront d’autres aspects de la conversion

elles permettent de compiler en void-safe ou non

Page 122: Void-safe en Eiffel

if … /= Void

le plus gros effort

indiquent que Void a un signification

ils sont toujours vrais…

donc on doit adapter un test

à analyser au cas par cas

Page 123: Void-safe en Eiffel

Ajuster les tests

en utilisant nos patterns

ré-écrire le test

if stuff.is_nogood then

utiliser une valeur par défaut ou un tableau vide

ou le rendre detachable

préconditions /= Void, pas de problème

Page 124: Void-safe en Eiffel

Compromis de contrat

préserver autant que possible le contrat

mais le défaut à changer entre attaché/détachable

à évaluer au cas par cas

pour l’appelant, il est plus facile que vous

retourniez des attachés

acceptiez des détachables, si Void était permis