Question existentielle a propos des gett er et setter dans une classe.

Le
Mickael Wolff
Bonjour,

En développant aujourd'hui, je me suis posé une question existentielle
qui m'empêchera de dormir pendant plusieurs années : comment implémenter
proprement les accesseurs d'une classe. Je m'explique en prenant un
exemple simple (écrit en PHP5). J'ignore volontairement les tests pour
éviter d'alourdir les exemples. En fait, j'hésite toujours entre les
trois philosophies suivantes, sans pouvoir trancher réellement.

La première approche me semble être la plus proche de la philosophie
PHP5. On utilises que des méthodes magiques. Le problème ici est que si
on a plus d'une donnée à protéger dans sa classe, les méthodes __get et
__set deviennent rapidement illisibles. Et surtout, lors d'un héritage
on a des problèmes assurés avec le polymorphisme.

class directAccess
{
public function __construct($value)
{
$this->attribute = $value ;
}

public function __get($aname)
{
// Travail de vérification
return clone $this->$aname ;
}

public function __set($aname, $avalue)
{
// Travail de vériication
$this->$aname = $avalue ;
}

protected $attribute ;
}

La seconde approche serait plus proche du C++, mais avec la surcharge
des méthodes en moins. Le seul inconvénient qu'on peut y trouver, c'est
l'imposibilité d'assigner la valeur null sans devoir recourir à une
méthode supplémentaire.

class allInOne
{
public function __construct($value)
{
$this->attribute = $value ;
}

public function attribute($avalue=null)
{
if(is_null($avalue))
{
// Travail de vérification
return clone $this->attribute ;
}
else
{
// Travail de vériication
$this->attribute = $avalue ;
}
}

public function del($aname)
{
$this->$name = null ;
}

protected $attribute ;
}

La troisième méthode est certainement la plus propre d'un point de vue
de la conception. Le désavantage est la lourdeur d'écriture.

class javaStyle
{
public function __construct($value)
{
$this->attribute = $value ;
}

public function getAttribute()
{
// Travail de vérification
return clone $this->attribute ;
}

public function setAttribute($avalue)
{
// Travail de vériication
$this->attribute = $avalue ;
}

protected $attribute ;
}

Laquelle de ces méthodes utilisez-vous ? Peut-être un mélange ? Ou
encore en fonction de la situation rencontrée ? J'ai conscience que
c'est un concentré de troll, car personne n'est d'accord sur la façon de
développer. Mais ça m'intéresse d'avoir vos avis.

Merci !
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
slambert
Le #28220
En développant aujourd'hui, je me suis posé une question existentielle
qui m'empêchera de dormir pendant plusieurs années : comment implémenter
proprement les accesseurs d'une classe.


Salut !

Il y a eu un fil de discussion à ce sujet très interressant il y a quelques
mois [ 17 Mai 2007 14:08 "Getter et Setter generateur ????"].

Il en ressortait qu'il y avait grand débat entre ceux qui voulaient
encapsuler et tout mettre en protected, et ceux qui passaient tout en public
et qui ne se donnait la peine que pour des accesseurs de propriétés
calculées.

Un contributeur, gaetan, avait posté une solution innovante basée sur la
methode __call de PHP5 :
http://www.vmeste.fr/index.php?2007/05/31/131-simuler-des-accesseurs-en-php
(malheureusement le site semble ne pas répondre aujourd'hui).

Autrement, 100% d'accord., __get et __set ne sont pas réellement utilisables
, et les IDE que je connais ne génèrent pas ces méthodes à coup de grand
click droit comme cela existe pour les autres langages.

Tiens nous au courant si tu trouves d'autres pistes et d'autres
informations.

@++

Stef

Bruno Desthuilliers
Le #27727
Bonjour,

En développant aujourd'hui, je me suis posé une question existentielle
qui m'empêchera de dormir pendant plusieurs années : comment implémenter
proprement les accesseurs d'une classe.


En les implémentant pas ?-)

(en tous cas, c'est déjà ça de code en moins à écrire, débugger et
maintenir)

Je m'explique en prenant un
exemple simple (écrit en PHP5). J'ignore volontairement les tests pour
éviter d'alourdir les exemples. En fait, j'hésite toujours entre les
trois philosophies suivantes, sans pouvoir trancher réellement.

La première approche me semble être la plus proche de la philosophie
PHP5. On utilises que des méthodes magiques. Le problème ici est que si
on a plus d'une donnée à protéger dans sa classe, les méthodes __get et
__set deviennent rapidement illisibles. Et surtout, lors d'un héritage
on a des problèmes assurés avec le polymorphisme.


Ca peut se résoudre en n'utilisant __get et __set que pour dispatcher
(par introspection) vers des accesseurs spécifiques. Ce qui résoud aussi
bien les problèmes de lisibilité que d'héritage. L'inconvénient, c'est
que ça n'améliore pas vraiment les perfs. Quoique là encore, ça peut
"s'amortir" quelque peu en "cachant" le résultat de l'introspection
(dans un tableau associatif) lorsqu'un attribut est accédé la première
fois. Mais bon, ça commence à devenir un poil usineàgazesque.

class directAccess
{
(snip)

}

La seconde approche serait plus proche du C++, mais avec la surcharge
des méthodes en moins. Le seul inconvénient qu'on peut y trouver, c'est
l'imposibilité d'assigner la valeur null sans devoir recourir à une
méthode supplémentaire.


Tu peux contourner ça en utilisant une valeur sentinelle bien spécifique
(par exemple avec une instance d'une classe ne servant qu'à ça - de
préférence un singleton-, et un test d'identité stricte).

class allInOne
{
(snip)

}

La troisième méthode est certainement la plus propre d'un point de vue
de la conception. Le désavantage est la lourdeur d'écriture.


<troll>
De toutes façons, à partir du moment où tu commences à utiliser des
accesseurs, hein...
</troll>

Mais bon, effectivement, l'inconvénient est que dans ce cas, tu dois
avoir des accesseurs explicites pour *tous* les attributs - ce qui
devient vite insupportable AMHA.

class javaStyle
{
(snip - le nom de la classe est assez explicite !-)

}

Laquelle de ces méthodes utilisez-vous ?


En PHP ? Aucune. L'utilisation de l'OO en PHP est AMHA d'un intérêt bien
trop restreint pour justifier de se prendre la tête avec ça. Mais bon,
accessoirement, je n'utilise personnellement PHP que contraint et forcé
(ok, disons que ce n'est pas mon choix par défaut...), et le principal
cadre dans lequel je l'utilise (nommément, Spip) est définitivement
procédural. Je suis donc probablement un peu biaisé !-)

Peut-être un mélange ? Ou
encore en fonction de la situation rencontrée ? J'ai conscience que
c'est un concentré de troll


Mais non, mais non !-)

, car personne n'est d'accord sur la façon de
développer.


Disont qu'il y a quelques grandes écoles... Et des langages qui se
prêtent plus naturellement à un style qu'à un autre. Vu le modèle
d'exécution de PHP (pas de long running process, nécessité de
'reconstruire le monde' à chaque requête) et sa vocation première (un
langage de template pour pages persos), et même en tenant compte des
évolutions du langage, il me semble préférable de faire au plus simple,
même si ce n'est pas le plus élégant ni le plus conforme au buzzword du
moment. Ca n'exclus bien sûr pas d'utiliser son cerveau, mais dans mon
expérience, à l'exception de quelques cas spécifiques [1], PHP se prête
plutôt mieux à une approche basée sur les listes/tableaux
associatifs/fonctions qu'à une approche OO sérieuse. Vu la complexité
moyenne assez faible d'un script PHP, on peut souvent faire simple *et*
propre (et même assez modulaire) à la fois.

[1] où l'utilisation de l'héritage et du polymorphisme s'imposent plus
ou moins naturellement - je pense entre autres à un petit générateur de
requêtes et de rapports que j'avais réalisé.

<pub-éhontée>
Accessoirement, si tu aimes vraiment l'OO, tu devrais regarder du côté
de Python ou de Ruby...
</pub-éhontée>


Mes deux centimes...

Mickael Wolff
Le #27728

Il y a eu un fil de discussion à ce sujet très interressant il y a quelques
mois [ 17 Mai 2007 14:08 "Getter et Setter generateur ????"].


Merci beaucoup pour la référence à la discussion.


Il en ressortait qu'il y avait grand débat entre ceux qui voulaient
encapsuler et tout mettre en protected, et ceux qui passaient tout en public
et qui ne se donnait la peine que pour des accesseurs de propriétés
calculées.


Ça m'intéresserait de savoir dans quels cas un attribut n'a pas besoin
d'être vérifié avant d'être inséré, et donc d'être purement public.
L'intérêt des fonctionnalités objets, c'est quand même de canaliser les
bogues, et donc d'éviter que le bogue puisse survenir d'une génération
spontanée :)

Bref, je vais encore y réfléchir...


Un contributeur, gaetan, avait posté une solution innovante basée sur la
methode __call de PHP5 :
http://www.vmeste.fr/index.php?2007/05/31/131-simuler-des-accesseurs-en-php
(malheureusement le site semble ne pas répondre aujourd'hui).


Il semble qu'il y ait eu un déménagement
Mais je n'arrive pas à en trouver l'intérêt. Dans ce cas, il vaut
effectivement mieux laisser l'attribut publique. Puisque c'est ce qu'il est.


Autrement, 100% d'accord., __get et __set ne sont pas réellement utilisables
, et les IDE que je connais ne génèrent pas ces méthodes à coup de grand
click droit comme cela existe pour les autres langages.


J'utilise Vim ;)


Tiens nous au courant si tu trouves d'autres pistes et d'autres
informations.


Je publierai mes essais ici de toute façon, pour passer au pilori :)

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Bruno Desthuilliers
Le #27726


Il y a eu un fil de discussion à ce sujet très interressant il y a quelques
mois [ 17 Mai 2007 14:08 "Getter et Setter generateur ????"].



Merci beaucoup pour la référence à la discussion.



Il en ressortait qu'il y avait grand débat entre ceux qui voulaient
encapsuler et tout mettre en protected, et ceux qui passaient tout en public
et qui ne se donnait la peine que pour des accesseurs de propriétés
calculées.



Ça m'intéresserait de savoir dans quels cas un attribut n'a pas besoin
d'être vérifié avant d'être inséré, et donc d'être purement public.


En pratique[1], dans une bonne majorité des cas - tant que la valeur ne
vient pas du monde extérieur, of course.

[1] C'est à dire par expérience effective de plusieurs années sur du
code en production. Et si mon expérience personnelle te sembles
insuffisante, il y a l'expérience collective accumulée par les
développeurs Python depuis plus de quinze ans, sur des projets de toutes
tailles et complexités.

L'intérêt des fonctionnalités objets, c'est quand même de canaliser les
bogues,


Ah bon ? Moi, j'aurais mis le polymorphisme en premier.

et donc d'éviter que le bogue puisse survenir d'une génération
spontanée :)


C'est très beau. Mais hélas pas nécessairement vrai. Tout code que tu
ajoutes est potentiellement source de bug, donc moins tu a de code (et
plus ton code est simple), moins tu a de bugs potentiels !-)


slambert
Le #27725
En pratique[1], dans une bonne majorité des cas - tant que la valeur ne
vient pas du monde extérieur, of course.
[1] C'est à dire par expérience effective de plusieurs années sur du code
en production. Et si mon expérience personnelle te sembles insuffisante,
il y a l'expérience collective accumulée par les développeurs Python
depuis plus de quinze ans, sur des projets de toutes tailles et
complexités.


Arguments non recevables.

Ce n'est pas parcequt tu as vu des gens faire quelque chose et que tu fais
apreil que cela devient une règle applicable pour tout le monde.

Preuve en est des techniques Java / C# et de quelques autres.

Après, qu'il y est plusieurs écoles et méthodologies actuellement en
pratique, cela par contre est fort possible. Mais il loin de moi l'idée de
dire qui a raison et de trancher le débat à la hache, meme si ma préférence
va aux accesseurs.

Dans les deux cas, on peut tout de meme s'etonner que la "possibilité" ne
soit pas offerte. Non pas obligatoire, mais juste possible. Style generation
bouton droit comme eclipse/java , encapsulation interne VS/C#. Meme si cela
relève bien sur plus de l'IDE que du langage lui meme...

@++

Stef

Olivier Miakinen
Le #27723

Dans les deux cas, on peut tout de meme s'etonner que la "possibilité" ne
soit pas offerte. Non pas obligatoire, mais juste possible.


La possibilité de faire quoi ? Définir des accesseurs ? Il m'a pourtant
semblé que Mickael Wolff décrivait trois façons différentes de le faire.

Style generation bouton droit comme eclipse/java , encapsulation
interne VS/C#.


???

Meme si cela relève bien sur plus de l'IDE que du langage lui meme...


Ah ! Est-ce qu'il ne te suffit pas alors de définir tes propres macros
dans ton éditeur favori ?

Bruno Desthuilliers
Le #27724
En pratique[1], dans une bonne majorité des cas - tant que la valeur ne
vient pas du monde extérieur, of course.
[1] C'est à dire par expérience effective de plusieurs années sur du code
en production. Et si mon expérience personnelle te sembles insuffisante,
il y a l'expérience collective accumulée par les développeurs Python
depuis plus de quinze ans, sur des projets de toutes tailles et
complexités.


Arguments non recevables.


Argument on ne peut plus recevable, au contraire. Je sais par
expérience, et nous sommes des *milliers* de développeurs à partager
cette expérience, pour certains depuis plus de 15 ans, que l'accès
direct aux attributs fonctionne parfaitement dans une grande majorité
des cas. Sur des gros projets. En prod. Demande donc à Google ce qu'ils
en pensent...

Ce n'est pas parcequt tu as vu des gens faire quelque chose et que tu fais
apreil que cela devient une règle applicable pour tout le monde.


Tu ne me prendrais pas un peu pour un bleubite, là ?-)

Preuve en est des techniques Java / C# et de quelques autres.


Je ne m'étendrais pas sur C# que je n'ai guère utilisé (mais qui m'a
l'air partiellement moins débile que Java, au moins sur certains
points), mais en ce qui me concerne, Java est tout sauf une référence en
matière d'OO - ou alors, a contrario. La seule raison d'être des
getter/setter systématiques en Java (la seule qui ne relève pas du cargo
cult, j'entends), c'est une réserve pour refactorisation en l'absence de
support pour les attributs calculés. A preuve, dans environ 99% des cas,
les getters/setters ne font aucun contrôle d'aucune sorte. Donc dans un
langage qui supporte les attributs calculés - ce qui est le cas, entre
autre, de Python, Ruby et PHP - les accesseurs sont dans l'écrasante
majorité des cas purements et simplement inutiles.

Après, qu'il y est plusieurs écoles et méthodologies actuellement en
pratique, cela par contre est fort possible. Mais il loin de moi l'idée de
dire qui a raison et de trancher le débat à la hache, meme si ma préférence
va aux accesseurs.


Si tu codes en Java ou en C++, c'est un non-choix. En PHP, c'est à mon
très humble avis - lequel se base sur plusieurs années d'expérience
professionnelle - une perte de temps pure et simple (tant bien sûr que
tu n'a pas *effectivement* besoin de l'accesseur).

Dans les deux cas, on peut tout de meme s'etonner que la "possibilité" ne
soit pas offerte. Non pas obligatoire, mais juste possible. Style generation
bouton droit comme eclipse/java , encapsulation interne VS/C#. Meme si cela
relève bien sur plus de l'IDE que du langage lui meme...


Ca ne relève *que* de l'éditeur. Et - once again - dans un langage qui
supporte les attributs calculés, c'est inutile.


Mickaël Wolff
Le #27720
Bonjour,

J'ai un peu attendu pour répondre, afin d'avoir plusieurs avis.
Visiblement, la guerre entre ceux qui veulent contrôler, et ceux qui
font confiance à ce qui est renseigné par l'utilisateur de la classe
fait rage :) Et comme d'habitude, on oppose sécurité et performances.
C'est bien dommage je trouve. Enfin bref, je vais essayer de compulser
tout ça.


[1] C'est à dire par expérience effective de plusieurs années sur du
code en production. Et si mon expérience personnelle te sembles
insuffisante, il y a l'expérience collective accumulée par les
développeurs Python depuis plus de quinze ans, sur des projets de toutes
tailles et complexités.


Ton expérience personnelle ne me suffit pas, mais m'aide grandement à
mûrir ma réflexion.
En ce qui concerne Python. J'avais placé beaucoup d'espoir, du fait
que partout la publicité qui en était fait affirmait que c'est un
langage fortement typé. Alors qu'il n'est pas typé du tout (ouais, parce
que déclarer des variables non-typer, et dire qu'elles sont fortement
typées, moi, ça me fait rire jaune).
Et pour parler du nombre d'utilisateurs d'un outil... tu m'excusera,
mais le succès d'une solution n'est pas pour moi un gage de qualité.
Ceci étant dit, Python ne m'a pas séduit car il n'est pas assez stricte
à mon goût. Je cherche toujours un langage qui répond exactement à mes
attentes.


Ah bon ? Moi, j'aurais mis le polymorphisme en premier.


<troll>Si c'était le cas, les fonctions de classes du C++ seraient
virtuelles par défaut !</troll> ;)

C'est très beau. Mais hélas pas nécessairement vrai. Tout code que tu
ajoutes est potentiellement source de bug, donc moins tu a de code (et
plus ton code est simple), moins tu a de bugs potentiels !-)


Je suis assez d'accord, mais je vois les getter et setter comme des
moyens d'éviter des gros bogues en risquant des petits bogues. Et pour
contourner l'absence des attributs calculés dont vous parlez plus loin.


Argument on ne peut plus recevable, au contraire. Je sais par
expérience, et nous sommes des *milliers* de développeurs à partager
cette expérience, pour certains depuis plus de 15 ans, que l'accès
direct aux attributs fonctionne parfaitement dans une grande majorité
des cas. Sur des gros projets. En prod. Demande donc à Google ce
qu'ils en pensent...


Est-ce qu'une collection de classes fainéantes implémentant l'accès à
des données stockées dans une SGBD entre dans ce cas-là ?


Preuve en est des techniques Java / C# et de quelques autres.


Je ne m'étendrais pas sur C# que je n'ai guère utilisé (mais qui m'a
l'air partiellement moins débile que Java, au moins sur certains
points), mais en ce qui me concerne, Java est tout sauf une référence en
matière d'OO - ou alors, a contrario. La seule raison d'être des
getter/setter systématiques en Java (la seule qui ne relève pas du cargo
cult, j'entends), c'est une réserve pour refactorisation en l'absence de
support pour les attributs calculés. A preuve, dans environ 99% des cas,
les getters/setters ne font aucun contrôle d'aucune sorte.


En C#, les getter/setter n'ont pas un nom de fonction, il sont appelé
suivant qu'on affecte ou qu'un consulter un attribut. Je crois qu'on
peut dire que c'est un attribut calculé ?

Donc dans un
langage qui supporte les attributs calculés - ce qui est le cas, entre
autre, de Python, Ruby et PHP - les accesseurs sont dans l'écrasante
majorité des cas purements et simplement inutiles.


[Bigsnip du troll ;)]

Ca ne relève *que* de l'éditeur. Et - once again - dans un langage qui
supporte les attributs calculés, c'est inutile.


Comment fais-tu les attributs calculés en PHP ? Avec __get/__set ?

Merci en tout cas de vos avis, ça fait plaisir de savoir que le
conflit qui me perturbe est universel.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org



--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org


slambert
Le #27232
Je vois qu'il y a là beaucoup de certitudes, voir limite une certaine
intolérance : )

Je rappelle que j'ai seulement dit que le fait de s'appuyer sur les usages
de certains n'était pas suffisant pour décréter que les usages d'autres
étaient inconvenants. J'ai aussi rajouté qu'il y avait les deux écoles et
que je me gardais bien de trancher de manière définitive meme si j'avais ma
préférence.

Par contre, je n'estime pas nécessaire d'arriver au stade des noms d'oiseaux
et des exhibitions d'"arguments" personnels. 1/ je n'ai rien a prouver à qui
que ce soit et je n'ai pas envie de mettre mes atouts personnels dans la
balance comme un écolier de classe de 4ème. 2/ cela reste une discussion
technique.

Tentons tout de meme de récapituler quelque peut :


[1] C'est à dire par expérience effective de plusieurs années sur du
code en production. Et si mon expérience personnelle te sembles
insuffisante, il y a l'expérience collective accumulée par les
développeurs Python depuis plus de quinze ans, sur des projets de toutes
tailles et


Arguments non recevables.
Argument on ne peut plus recevable, au contraire.



Non.

Arguments non recevables.

Je peux aller te chercher des sommités et des développeurs au CV bien plus
conséquent que le tien ou le mien, qui te dirons le contraire. Et cela ne
sera pas non plus évident qu'ils aient raison.

D'une manière générale, dans ce domaine, c'est rarement celui qui crie le
plus fort qui a raison. Celui qui s'en sort le mieux est généralement celui
qui comprend de quoi on parle et qui s'adapte aux environnements et aux
besoins qu'il croise.


Je sais par expérience


Tiens c'est marrant, moi aussi. Ca nous fait une belle jambe, n'est ce pas ?

Sur des gros projets. En prod. Demande donc à Google ce qu'ils en
pensent...
Je te dirais que ça dépend des projets. Je ne suis pas très loin de leur

centre de Dublin [ils en ont un deuxième en Allemagne], et vu ce que m'ont
rapporté les collègues qui y travaillent, ca dépend vachement des personnes
et des technos. Et surtout, la qualité des développements internes de Google
est tout sauf une référence, surtout ces derniers temps.


Tu ne me prendrais pas un peu pour un bleubite, là ?-)


Argument inutile et encore une fois non recevable. Nous sommes tous les
débutants de quelques domaines comparés a d'autres sur ces meme domaines. Il
est impossible de tout savoir meme après une vie entière, Cela me désole de
devoir le rappeler ainsi encore une fois dans ce contexte. De plus j'ai
absolument horreur de la vulgarité et de cette violence verbale. A ce
rythme, tu vas finir par devenir violent avec tes collaborateurs quand vous
devrez parler technique, et c'est un mode de fonctionnement qui m'insupporte.

Si tu codes en Java ou en C++, c'est un non-choix. En PHP, c'est à mon
très humble avis - lequel se base sur plusieurs années d'expérience
professionnelle - une perte de temps pure et simple (tant bien sûr que tu
n'a pas *effectivement* besoin de l'accesseur).


Il se trouve que régulièrement, j'ai BESOIN des accesseurs. Cf le post de
Mai dernier que visiblement tu n's pas pris le temps de lire avant de
dégainer plus vite que ton ombre. Et svp évitons encore une fois les
arguments personnels, surtout quand on ne sait pas a qui l'on parle.

Dans les deux cas, on peut tout de meme s'étonner que la "possibilité" ne
soit pas offerte. Non pas obligatoire, mais juste possible. Style
génération bouton droit comme eclipse/java , encapsulation interne VS/C#.
Meme si cela relève bien sur plus de l'IDE que du langage lui meme...
Ca ne relève *que* de l'éditeur. Et - once again - dans un langage qui

supporte les attributs calculés, c'est inutile.


Oui. C'est bien. Car c'est de cela qu'il s'agissait.

Mais tout de meme : que de certitudes.....

S.L.



slambert
Le #27233
Meme si cela relève bien sur plus de l'IDE que du langage lui meme...
Ah ! Est-ce qu'il ne te suffit pas alors de définir tes propres macros

dans ton éditeur favori ?


Nous y voila.....

Effectivement, qu'est ce qui m'en empèche....

Voyons voir....

Le temps ?
:))))))

Ceci dit, vu qu'on est jamais mieux servi que par soi meme, un de ces 4 je
vais aller farfouiller dans l'écriture d'un ajout Eclipse....

Un jour....

@++

Stef


Publicité
Poster une réponse
Anonyme