J'ai testé la même page, avec la version 14.0.835.2 dev-m de Chrome.
Le lecteur semble bien s'afficher pendant 2 ou 3 secondes, puis paf des grandes zones bleues s'affichent de manière aléatoire.
En gros les mecs se branlent la nouille parcqu'ils ont réussi à faire un lecteur PDF en javascript, et sont maintenant persuadés qu'ils vont pouvoir faire n'importe quelle application avec ça.
En théorie c'est sexy, mais :
Ils mettent en avant les technologies web "standards" mais vont devoir ajouter des API proprio pour donner un accès en profondeur au téléphone, bref ils vont faire du proprio comme tout le monde, le W3C aura toujours 5 ou 10 de retard pour standardisé les API utiles aujourd'hui.
Ils mettent en avant les technologies web "standards", mais leur lecteur PDF ne tourne visiblement ni dans Chrome 14, ni IE 9 : en pratique ils font du proprio Gecko.
Au final API accès téléphone + HTML/JS/CSS, c'est ce que propose déjà de nombreux concurrents pour iPhone/Android (PhoneGap, Appcelerator & co). Rien d'innovant donc.
En même temps, si t'es sous Windows à chercher la doc de strcpy, t'es probablement sous Visual Studio. Auquel cas pour chercher sur la MSDN, tu fais encore plus simple :
0. Pré-requis : t'as déjà écrit strcpy
1. Tu appuis sur la touche "F1"
Par ailleurs, si tu n'as pas de connexion à Internet, si Google est hors service ou si MSDN est hors service, tu es baisé. Moi pas
La MSDN est disponible hors-ligne, c'est pas pour rien que l'installation complète de Visual Studio prend plusieurs Go.
Le soucis est que tu veux faire quelque chose d'aberrant (contrôler le rendu graphique depuis n'importe quel point de l'application).
Réponds par du code s'il te plaît : mon application a besoin de faire la modification que j'ai précisé, moi ca tient en une ligne, que proposes-tu qui soit plus maintenable et qui respecte la fameuse loi ?
Certes, mais je ne parviens toujours pas à comprendre l'intérêt de l'introspection.
L'intérêt ? De travailler au niveau du méta-modèle, de faire de la méta-programmation.
Découverte dynamique de type, de composants (plugins), sérialisation automatique, génération dynamique de proxy, de stub, de service web, programmation par aspect, etc.
Le C++ a essayé d'ajouter un minimum de support à travers le mot clé "typeid", mais ce n'est clairement pas suffisant. Qt a dû modifié le language pour introduire un concept un peu similaire.
Sauf qu'il faut vraiment en vouloir pour défoncer l'encapsulation. À ce moment, on en est plus à de la négligence mais à de la malfaisance.
Certes, l'exploitation de cette technique est de la malfaisance, mais parfois c'est un simple débordement de tampon par négigeance qui conduit à une faille exploitable (par malfaisance).
L'encapsulation est un outil qui permet aux développeurs de se protéger d'eux-même.
Le soucis du C++, c'est que l'utilisateur d'un composant ne peut pas ignorer sa structure interne : l'organisation des champs pourtant "privés", et la taille globale qu'ils représentent a un impact direct sur son utilisation.
Quand au graphe d'objet interne de la voiture, il ne serait pas disponible pour l'utilisateur de la classe, mais uniquement pour des visiteurs.
Là encore, tu théorises, sans vouloir écrire de code, mais va jusqu'au bout : tu vas obligé l'utilisateur/visiteur à implenter le pattern visiteur alors qu'il ne veut pas tout parcourir ? Comment vas-tu lui permettre d'atteindre sa cible ? (encore une fois, du code, merci).
Je pense que tu as un sérieux problème à séparé les responsabilités. Ici, on veut modifier un arbre XML. C'est le métier du code, donc il n'y a pas de soucis à faire ce qu'on fait ici.
Ah bah voilà ! C'est ce que je me tues à expliquer : par nature, certains API exposent "naturellement" pour l'utilisateur un arbre. J'ai pris 2 exemple : une API XML et une API de toolkit graphiques. Et il y a pleins d'autres exemples : API d'introspection, API SGBD, API de dessin vectoriel, API d'impression, API d'automatisation, etc.
objets. La programmation est une affaire de compromis, ce qui fait qu'appliquer bêtement la loi de Déméter est absurde. Mais c'est tout aussi absurde de la jeter avec l'eau du bain.
On est d'accord, c'est ce que je me tues à expliquer depuis le début : exposer des get/set n'est pas toujours absurde, bien au contraire. c'est pas pour autant qu'il faut systématiquement le faire.
Oui, avec une classe qui expose ce qui est nécessaire et suffisant au pilotage du composant.
...
Donc, vas-y, donne nous ta version de code qui fait la même chose en respectant la fameuse loi.
Je voulais parler des fonctionnalités utiles, pas des gadgets qui ne servent qu'à bricoler au runtime.
Trolleur :)
Ça n'a rien à voir avec le caractère orienté objet du langage.
Euh, pouvoir se balader avec un pointeur, c'est pouvoir défoncer n'importe quelle tentative d'encapsulation.
Exemple ?
Tu connais beaucoup d'API qui exposent leurs paramètres avec les types de la STL ? A ton avis, pourquoi ne le font-elles pas ?
Ça dépend du type d'API que tu développe.
Exemple ?
Mais l'assigner directement, c'est chercher les problèmes. Évidement qu'on peut mettre des observateurs dans tout les sens, mais est-ce que sa simplifie vraiment l'usage ?
Tu mets ce que tu veux dans le set hein, tu peux faire plein de contrôle, discuter avec la voiture toussa.
Mais oui, ca simplifie l'usage. Si on part de ton principe, cad mettre la méthode changeWheel sur la voiture, faisons de même pour toutes les pièces remplaçable de la voiture (1000 ?), tu fais une façade géante de 1000 méthodes ou tu éclates en un graphe d'objets ?
est-il pertinent de laisser n'importe qui venir modifier l'état interne d'un des composant.
Si c'est utile pour l'utilisateur, simple et intuitif, oui. Après tu fais ce que tu veux dans le setter pour assurer la cohérence globale. De toute façon le faire dans une fafade géante te conduiras à assurer le même niveau de cohérence.
Est-ce que modifier un nœud modifie l'état du parent ?
Oui potentiellement : si ton noeud parent a une propriété qui indique si elle contient d'autres éléments (HasChild), tu modifies bien son état (d'un point de vu utilisateur).
Tu remarquera que pour remplacer un nœud, dans le DOM, on assigne pas le nœud ou on de modifie pas le nœud : on demande à son parent de le remplacer.
Toutafé : on demande au parent (y'a pas le choix tu remplaces), et pas à l'ancètre le plus haut (le document) comme aurait dû y conduire la fameuse loi de Demeter.
Par code, ça donnerait, pour remplacer un noeud :
doc.getNode('item3').getChildNode('title').setChildNode(2, new Node("fr-FR"))
Si on avait suivi la fameuse loi, tu aurais écris quoi ?
Je crois que la loi de Demether a frappé là où tu ne l'attendais pas.
Arrête de théoriser, donne nous du code. Je m'évertue à montrer qu'en pratique cette loi ne marche pas, prouve le contraire en mettant l'équivalent de ce que j'écris.
On est effectivement en Java t'es pas à l'abris de tout : si ton programme Java accède à des ressources externes sous certaines conditions métiers qu'un attaquant arrive à violer parcque t'as pas fait les bons testsU, oui, t'as une faille potentielle de type "divulgation d'information". Et pour ça les outils de fuzzing sont nul.
Tu es aussi vulnérable aux failles potentielles de la VM elle-même, celle-ci étant écrite dans un langage non-sûre :)
D'où les recherches actuelles de MS, oui je me répète, sur son OS Singularity : utiliser un environnement "sûr" au coeur de l'OS, le plus bas possible, pour limiter les risques de failles de sécurité de type corruption de mémoire ou accès à des ressources illégales.
Si tu fais un FS (mettons via FUSE), tu vas corrompre ton FS.
Oui enfin là on parle de BOF, restons dans le sujet.
Java t'offre des garanties vis-à-vis des BOF et pBpG te montre que même avec les meilleurs outils du monde t'es pas à l'abri d'un BOF en C/C++ et donc d'une faille de sécu potentielle.
le probleme ne vient pas d une attaque!
Si le problème est reproductible, un attaquant peut très bien le reproduire, à plus forte raison s'il a accès au code (open-source par exemple).
Autocompletion pour les langages trop verbeux [...]
Ca n'est absolument pas une faiblesse du langage, au contraire, c'est la nature du langage qui permet d'obtenir une autocomplétion intuitive, par exemple si je tapes :
objet.
L'autocomplétion va me proposer l'ensemble des méthodes/propriétés accessible sur l'objet
L'accès rapide à la doc va m'afficher une courte phrase décrivant la méthode
Et ton exemple est bidon, car si tu geres mal tes threads, c est pas java qui va te sauver.
Ah si : si tu gères mal les threads, Java fera de toute façon en sorte que ca ne se transformera jamais en un BOF potentiel. Ton programme marchera peut être pas comme il faut, mais t'auras pas de faille de sécurité liée à un BOF potentiel.
CQFD.
Quel est le sens pour, un objet qui a accès à l'objet app, de modifier un détail de la représentation des données à l'écran ?
Bah ca peut être le controller de l'application tout simplement.
Où n'importe quoi, on s'en fou pas mal, ce qui compte c'est que ce type d'API existe réellement : il t'expose un arbre d'objets, et les méthodes sont placés sur les noeuds où c'est intuitivement là que tu les chercherais. Tu peux te placer au niveau que tu veux, imaginer le scénario que tu veux, l'API restera la même.
Ben oui, ils savent pas, ils font pas. Sauf si tu as une loop qui tourne fear
C'était ironique, j'ai indiqué la solution juste au-dessus : le patron de conception observateur. C'est pas de la théorie, c'est comme ça que c'est fait en pratique.
Je ne le ferais pas car ça n'a pas de sens, dans le cas présent.
Se cacher derrière la sémantique de l'exemple, c'est petit :) Imagine toi le scénario que tu veux, l'API reste identique.
Est-ce qu'un composant graphique doit être modifiable par n'importe quelle portion du code qui l'utilise ?
Quelque soit la portion de code, il faut qu'ils soient modifiables : tu fais l'API de composants graphiques, tu ne sais pas qui ni comment il va l'utiliser. Tu dois par contre exposer tes services : accès composant, modification des composants, etc.
Mais si tu vois un concept manquant, je suis tout ouïe.
L'introspection ?
Le fait que pleins de type de base ne soit pas eux-même des objets ?
Le fait que des fonctions puissent ne pas être raccroché à des définitions de classe ?
Le fait de pouvoir aller modifier n'importe quel objet avec un bête pointeur baladeur ?
Le fait qu'il n'est pas possible d'exposer une API C++ avec des templates qui soit réutilisable ?
Je suppose que tu voulais dire que la mercedes a la fonction :o)
Je voulais dire "que la mercedes ai la fonction" ;)
des boîtes noires avec une interface pour faire des choses
Ce que j'essai d'expliquer, c'est que cette fameuse interface peut être explosée en plusieurs interfaces et présentée à l'utilisateur sous la forme d'une arborescence, sans pour autant exposer plus d'information et donc enfreindre le principe d'encapsulation.
La loi de Demeter a un objectif, certe louable, mais qui ne penses pas utilisateur : quand tu fais une API, tu la conçois de telle sorte qu'elle soit simple, intuitive et aisée à découvrir. Si on suit la loi de Demeter, on a une espèce de façade géante à tous les étages : non seulement l'objectif n'est pas atteint (pleins de méthodes proxy totalement inutiles, donc plus de code à maintenir) mais ca fait une API totalement bloated.
Dans une API de voiture, je m'attend à pouvoir accéder au pneu sur l'objet roue que j'ai récupéré sur la voiture. Je m'attend pas à avoir 15000 méthodes directement sur mon objet voiture.
Dans une API de composants graphiques, je m'attends à ce que la méthode de redimensionnement d'un objet soit sur l'objet concerné, pas sur son parent, son grand-parent ou sa soeur.
Dans une API Xml, je veux pouvoir modifier un attribut d'un noeud directement sur le noeud et pas sur la classe Document.
Mais je penses qu'on est dans 2 façon différentes de penser :
* Je penses API, composants réutilisable par un tiers
* Tu penses objet et logique métier.
C'est pas forcement contradictoire, mais ce qui est sûr, c'est que la loi de Demeter est beaucoup trop théorique pour être applicable dans toutes les situations en pratique.
Ca changera rien, le programmeur, par soucis d'encapsulation et de cacher les détails d'implémentation ne t'as donné aucun get, même "protected" pour accéder à tes roues. Bref, t'es mort.
Et que proposes tu sur
app.getMainWindow().getContainer().getChild(1).resize(10,3)
?
Je penses qu'on est d'accord : il est évident qu'il ne faut pas se contenter d'utiliser des objets/données en se disant "j'ai mis des get/set, je fais de l'objet", et qu'il faut écrire des fonctions métiers plus élémentaires, tant qu'on parle de code métier.
Après le débat initial était surtout d'indiquer qu'il était largement préférable d'utiliser les get/set vs l'accès direct aux membres, même si à première vu le get ne faisait pas grand chose.
Tu changes le pneu sur la roue, sans notifier la voiture
C'est son problème, pas le miens.
Comment la voiture le sais ?
Bah rien ne l'empêche de communiquer avec ses roues, par exemple s'abonner avec le patron observateur pour savoir qu'il y a un truc qui l'intéresse qui se passe sur ses roues.
Prend un autre exemple, je veux redimensionner le bouton contenu dans une fenêtre :
Tu crois que le container et la Window sont inccapables de se redimensionner automatiquement parcque je ne les ai pas notifié ?
t'aurais fais comment sans les get ?
app.resizeFirstChildOfContainerInMainWindow(10, 3) ?
Comment prévoir tous ces cas ?
L'objectif est d'exposer une API conviviale et intuitive, après c'est le problème de celui qui créé la lib de s'assurer que l'état de tous les objets du graphe qu'il expose reste cohérent.
Et vu qu'en C++, on renvoie généralement des références sur const, ben, ton objet accédé ne sera pas mis à jour.
Oué enfin si on pouvait éviter de prendre le C++ comme langage de référence quand on parle programmation objet ca serait pas mal :)
Tu remarqueras qu'il n'y a pas d'accésseurs, mais uniquement des méthodes métier.
Oui bien sûr, mais ça suppose que ta mercedes est la fonction de changement de pneu. Donc si c'est une bibliothèque qui n'a pas prévu le coup, t'es mort, tu retournes voir le constructeur. C'est peut-être l'effet recherché tu me diras. Si t'es garagiste, tu peux avoir envie de bricoler sans t'en tenir aux seuls cas imaginer par le fabriquant.
Je pense que les accesseurs ne sont pas une bonne idée. Évidement, c'est Java qui a popularisé la méthode.
Qu'on soit clair : l'objectif n'est pas de dire "mettez des accesseurs sur tous vos membres". L'objectif est d'utiliser des accesseurs quand il y a une interface intéressante à exposer.
Le problème de ce principe, c'est qu'il oppose service et données : il faut effectivement penser "service", mais parfois ton service c'est d'exposer des données : DTO, Controller, DOM, Composants IHM, etc.
Reprends mon exemple de la voiture, moi je veux pouvoir changer moi même la roue, c'est ça le service que j'attend. Pas que la voiture m'expose un numéro de téléphone qui dépende de mon garagiste.
De plus ton principe n'est applicable que si tu as la main sur le code de la voiture car, auquel cas tu peux ajouter toi même la méthode doStuffOnFirstWheel. Et si cette méthode est dans une bibliothèque, tu fais comment ? tu dérives à tout va ? Piouuu.
Si je design une voiture en POO (l'exemple est un peu éculé, j'en suis désolé), ce qui m'intéresse c'est de la faire avancer, pas qu'elle ait 4 roues.
J'achèterai jamais ta voiture si tu ne t'assures pas que je puisse changer les roues : si tu me dis que les roues sont directement soudées sur l'arbre de transmission parcque t'avais oublié de mettre une interface de type écrou...
Par exemple, les getter et setter vont à l'encontre de la Loi_de_Déméter W
Bien au contraire ! Exposer des membres directement sans getter/setter, c'est exposer toutes les hypothèses de ton implémentation aux objets qui utilisent le tient. Hors ce que dit la loi, je cite :
"La notion fondamentale est qu'un objet devrait faire aussi peu d'hypothèses que possible à propos de la structure de quoi que ce soit d'autre, y compris ses propres sous-composants."
La seule façon de s'assurer que tu ne puisses pas faire d'hypothèse sur la structure d'un objet, c'est d'en cacher tous les détails d'implémentation, et un membre exposé directement sans getter/setter, c'est exactement ça.
"Un désavantage de la règle de Déméter est qu'elle requiert l'écriture d'un grand nombre de petites méthodes "wrapper" pour propager les appels de méthodes à leurs composants. "
En gros cette loi conduit au contraire à écrire encore plus de getter/setter :
Au lieu d'écrire :
obj.getVoiture().getFirstRoue()
tu te retrouves à ajouter à ton obj un autre getter :
obj.getFirstRoueFromVoiture()
C est pour ca que je code des tests unitaires qui inclus les tests qui valident que tout fonctionne quand tout est normal, mais aussi les cas extremes (fuzzing).
C'est vrai, et quelque soit le langage d'ailleur. Mais qui t'assure que tes tests sont correctement écrits ? Rien. Qui t'assures que tes tests sont complets ? Rien. Qui t'assures que les cas extrêmes sont tous couvert par le fuzzing ? rien. Qui te garantie que le contexte (archi, compilo, etc.) dans lequel tu exécutes ton fuzzing va rester valable dans un autre contexte ? Rien.
Ce type de tests, qui par nature ne garantisse rien, ne permettent que de se rapprocher, avec un coût exponentiel, vers l'absence totale de bug.
Il faut les utiliser, mais à bon escient, et accepter qu'ils ne sont pas suffisant. Un language de haut niveau, offre beaucoup plus de garantie, by design, qui ne fera que compléter ces bonnes pratiques pour offre une meilleure sécurité, à moindre coût.
En fait non, il existe des methodes assez claires,
Je ne parle pas de clareté mais de sécurité. La méthode peut être clair, la doc aussi, mais tout repose sur le programmeur qui ne doit pas se "planter" lorsqu'il code, sinon boum. D'où l'idée d'avoir un outil (langage + compilo + runtime) qui permet d'assurer l'absence des problèmes les plus courants, by design.
Tu as tout à fait raison.
C'est pourquoi il est important de systématiquement utiliser des getter/setter : même si ca paraît idiot dans un premier temps, celà reste une bonne pratique essentielle à des concepts fondamentaux de la programmation objet : l'encapsulation et le contrat d'interface. Je cache les détails d'implémentation, qui peuvent évoluer d'un simple accès une variable à un truc plus complexe, tout en évitant de casser le contrat d'interface exposé aux utilisateurs de ma classe.
Personnellement je pense que c'est un conseil à ne surtout pas suivre.
Qui peut affirmer maîtriser quelque chose sans avoir eu d'expérience avec ? Il faut bien commencer par être débutant, accepter de ne pas tout maîtriser, puis progresser. Et surtout ne jamais affirmer qu'on maîtrise : c'est la meilleur façon de se planter.
Tout d'abord, merci de faire revenir la conversation au débat initial.
Tu es tres a cote de la verite. ce que vous traitez de dangereux depuis le debut, ce sont des erreurs de debutants, laxisme, ou etourderie.
Oui, des erreurs du programmeur qui conduisent à bugs non détectés par un compilo ou un runtime, et qui se transforme en faille de sécurité potentielle. D'où le danger.
Disons que c'est le coeur du débat : d'un côté on reporte la faute sur le programmeur qui s'est coupé avec le scalpel, de l'autre on indique qu'il y a des langages qui évite justement 90% des conneries de l'utilisateur qui avait juste besoin de se couper une tranche de saucisson.
Peu importe la fonction et le langage, si tu connais pas, il faut lire sa doc.
Justement non. C'est 2 visions totalement différentes, mais pour de nombreux programmeurs une API bien faite est une API intuitive, où je n'ai pas besoin d'utiliser la doc, ou peu. Le problème c'est pas qu'il n'y a pas d'API intuitive en C, le problème c'est que le langage est tellement dangereux qu'il est extrêment complexe de faire une API 100% secure : il est donc effectivement indispensable de lire la doc pour tous les aspects non-intuitif inhérent à l'environnement technique.
L'exemple du strncpy, qui se veut secure mais ne l'est pas à 100% est un très bon exemple : l'équivalent fonctionnel est parfaitement implémentable dans des langages "modernes" sans tous ces problèmes de documentation indispensable à sa bonne utilisation.
Si c etait aussi difficile que vous le dites, comment on a fait pour dev tous ces programmes en C, ainsi que ces OS ?
Ben vous le faites, mais avec pleins de problème de sécurité qui conduisent à des failles, pourtant "classiques", mais qui auraient été évités avec un langage de plus haut niveau.
Il y a plein de bonnes raisons d'utiliser le C pour coder un OS, mais la contrepartie est une forte exposition aux problèmes de sécurité.
[^] # Re: mouais
Posté par TImaniac (site web personnel) . En réponse au journal Mozilla veut lancer son OS. Évalué à 1.
J'ai testé la même page, avec la version 14.0.835.2 dev-m de Chrome.
Le lecteur semble bien s'afficher pendant 2 ou 3 secondes, puis paf des grandes zones bleues s'affichent de manière aléatoire.
# mouais
Posté par TImaniac (site web personnel) . En réponse au journal Mozilla veut lancer son OS. Évalué à 7.
En gros les mecs se branlent la nouille parcqu'ils ont réussi à faire un lecteur PDF en javascript, et sont maintenant persuadés qu'ils vont pouvoir faire n'importe quelle application avec ça.
En théorie c'est sexy, mais :
Ils mettent en avant les technologies web "standards" mais vont devoir ajouter des API proprio pour donner un accès en profondeur au téléphone, bref ils vont faire du proprio comme tout le monde, le W3C aura toujours 5 ou 10 de retard pour standardisé les API utiles aujourd'hui.
Ils mettent en avant les technologies web "standards", mais leur lecteur PDF ne tourne visiblement ni dans Chrome 14, ni IE 9 : en pratique ils font du proprio Gecko.
Au final API accès téléphone + HTML/JS/CSS, c'est ce que propose déjà de nombreux concurrents pour iPhone/Android (PhoneGap, Appcelerator & co). Rien d'innovant donc.
[^] # Re: Réponses
Posté par TImaniac (site web personnel) . En réponse au journal ou sont les man ?. Évalué à 3.
En même temps, si t'es sous Windows à chercher la doc de strcpy, t'es probablement sous Visual Studio. Auquel cas pour chercher sur la MSDN, tu fais encore plus simple :
0. Pré-requis : t'as déjà écrit strcpy
1. Tu appuis sur la touche "F1"
La MSDN est disponible hors-ligne, c'est pas pour rien que l'installation complète de Visual Studio prend plusieurs Go.
[^] # Re: tada
Posté par TImaniac (site web personnel) . En réponse au journal Communauté... Tombe des nouveaux projets?. Évalué à 4.
Oui ! Le mec qui parle C# dans un journal Lisaac ! Oui c'est moi ! superconnard !
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
Réponds par du code s'il te plaît : mon application a besoin de faire la modification que j'ai précisé, moi ca tient en une ligne, que proposes-tu qui soit plus maintenable et qui respecte la fameuse loi ?
L'intérêt ? De travailler au niveau du méta-modèle, de faire de la méta-programmation.
Découverte dynamique de type, de composants (plugins), sérialisation automatique, génération dynamique de proxy, de stub, de service web, programmation par aspect, etc.
Le C++ a essayé d'ajouter un minimum de support à travers le mot clé "typeid", mais ce n'est clairement pas suffisant. Qt a dû modifié le language pour introduire un concept un peu similaire.
Certes, l'exploitation de cette technique est de la malfaisance, mais parfois c'est un simple débordement de tampon par négigeance qui conduit à une faille exploitable (par malfaisance).
Le soucis du C++, c'est que l'utilisateur d'un composant ne peut pas ignorer sa structure interne : l'organisation des champs pourtant "privés", et la taille globale qu'ils représentent a un impact direct sur son utilisation.
Là encore, tu théorises, sans vouloir écrire de code, mais va jusqu'au bout : tu vas obligé l'utilisateur/visiteur à implenter le pattern visiteur alors qu'il ne veut pas tout parcourir ? Comment vas-tu lui permettre d'atteindre sa cible ? (encore une fois, du code, merci).
Ah bah voilà ! C'est ce que je me tues à expliquer : par nature, certains API exposent "naturellement" pour l'utilisateur un arbre. J'ai pris 2 exemple : une API XML et une API de toolkit graphiques. Et il y a pleins d'autres exemples : API d'introspection, API SGBD, API de dessin vectoriel, API d'impression, API d'automatisation, etc.
On est d'accord, c'est ce que je me tues à expliquer depuis le début : exposer des get/set n'est pas toujours absurde, bien au contraire. c'est pas pour autant qu'il faut systématiquement le faire.
# tada
Posté par TImaniac (site web personnel) . En réponse au journal Communauté... Tombe des nouveaux projets?. Évalué à 0.
Je profites de ce journal pour inaugurer mon nouvel avatar \o/
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
...
Donc, vas-y, donne nous ta version de code qui fait la même chose en respectant la fameuse loi.
Trolleur :)
Euh, pouvoir se balader avec un pointeur, c'est pouvoir défoncer n'importe quelle tentative d'encapsulation.
Tu connais beaucoup d'API qui exposent leurs paramètres avec les types de la STL ? A ton avis, pourquoi ne le font-elles pas ?
Exemple ?
Tu mets ce que tu veux dans le set hein, tu peux faire plein de contrôle, discuter avec la voiture toussa.
Mais oui, ca simplifie l'usage. Si on part de ton principe, cad mettre la méthode changeWheel sur la voiture, faisons de même pour toutes les pièces remplaçable de la voiture (1000 ?), tu fais une façade géante de 1000 méthodes ou tu éclates en un graphe d'objets ?
Si c'est utile pour l'utilisateur, simple et intuitif, oui. Après tu fais ce que tu veux dans le setter pour assurer la cohérence globale. De toute façon le faire dans une fafade géante te conduiras à assurer le même niveau de cohérence.
Toutafé : on demande au parent (y'a pas le choix tu remplaces), et pas à l'ancètre le plus haut (le document) comme aurait dû y conduire la fameuse loi de Demeter.
Par code, ça donnerait, pour remplacer un noeud :
doc.getNode('item3').getChildNode('title').setChildNode(2, new Node("fr-FR"))
Si on avait suivi la fameuse loi, tu aurais écris quoi ?
Arrête de théoriser, donne nous du code. Je m'évertue à montrer qu'en pratique cette loi ne marche pas, prouve le contraire en mettant l'équivalent de ce que j'écris.
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
On est effectivement en Java t'es pas à l'abris de tout : si ton programme Java accède à des ressources externes sous certaines conditions métiers qu'un attaquant arrive à violer parcque t'as pas fait les bons testsU, oui, t'as une faille potentielle de type "divulgation d'information". Et pour ça les outils de fuzzing sont nul.
Tu es aussi vulnérable aux failles potentielles de la VM elle-même, celle-ci étant écrite dans un langage non-sûre :)
D'où les recherches actuelles de MS, oui je me répète, sur son OS Singularity : utiliser un environnement "sûr" au coeur de l'OS, le plus bas possible, pour limiter les risques de failles de sécurité de type corruption de mémoire ou accès à des ressources illégales.
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
Oui enfin là on parle de BOF, restons dans le sujet.
Java t'offre des garanties vis-à-vis des BOF et pBpG te montre que même avec les meilleurs outils du monde t'es pas à l'abri d'un BOF en C/C++ et donc d'une faille de sécu potentielle.
Si le problème est reproductible, un attaquant peut très bien le reproduire, à plus forte raison s'il a accès au code (open-source par exemple).
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 4.
Ca n'est absolument pas une faiblesse du langage, au contraire, c'est la nature du langage qui permet d'obtenir une autocomplétion intuitive, par exemple si je tapes :
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Ah si : si tu gères mal les threads, Java fera de toute façon en sorte que ca ne se transformera jamais en un BOF potentiel. Ton programme marchera peut être pas comme il faut, mais t'auras pas de faille de sécurité liée à un BOF potentiel.
CQFD.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Bah ca peut être le controller de l'application tout simplement.
Où n'importe quoi, on s'en fou pas mal, ce qui compte c'est que ce type d'API existe réellement : il t'expose un arbre d'objets, et les méthodes sont placés sur les noeuds où c'est intuitivement là que tu les chercherais. Tu peux te placer au niveau que tu veux, imaginer le scénario que tu veux, l'API restera la même.
C'était ironique, j'ai indiqué la solution juste au-dessus : le patron de conception observateur. C'est pas de la théorie, c'est comme ça que c'est fait en pratique.
Se cacher derrière la sémantique de l'exemple, c'est petit :) Imagine toi le scénario que tu veux, l'API reste identique.
Quelque soit la portion de code, il faut qu'ils soient modifiables : tu fais l'API de composants graphiques, tu ne sais pas qui ni comment il va l'utiliser. Tu dois par contre exposer tes services : accès composant, modification des composants, etc.
L'introspection ?
Le fait que pleins de type de base ne soit pas eux-même des objets ?
Le fait que des fonctions puissent ne pas être raccroché à des définitions de classe ?
Le fait de pouvoir aller modifier n'importe quel objet avec un bête pointeur baladeur ?
Le fait qu'il n'est pas possible d'exposer une API C++ avec des templates qui soit réutilisable ?
Je voulais dire "que la mercedes ai la fonction" ;)
La loi de Demeter a un objectif, certe louable, mais qui ne penses pas utilisateur : quand tu fais une API, tu la conçois de telle sorte qu'elle soit simple, intuitive et aisée à découvrir. Si on suit la loi de Demeter, on a une espèce de façade géante à tous les étages : non seulement l'objectif n'est pas atteint (pleins de méthodes proxy totalement inutiles, donc plus de code à maintenir) mais ca fait une API totalement bloated.
Dans une API de voiture, je m'attend à pouvoir accéder au pneu sur l'objet roue que j'ai récupéré sur la voiture. Je m'attend pas à avoir 15000 méthodes directement sur mon objet voiture.
Dans une API de composants graphiques, je m'attends à ce que la méthode de redimensionnement d'un objet soit sur l'objet concerné, pas sur son parent, son grand-parent ou sa soeur.
Dans une API Xml, je veux pouvoir modifier un attribut d'un noeud directement sur le noeud et pas sur la classe Document.
Mais je penses qu'on est dans 2 façon différentes de penser :
* Je penses API, composants réutilisable par un tiers
* Tu penses objet et logique métier.
C'est pas forcement contradictoire, mais ce qui est sûr, c'est que la loi de Demeter est beaucoup trop théorique pour être applicable dans toutes les situations en pratique.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Oui, merci, ca c'est la solution que je donnais 2 commentaires plus haut :)
Je demandes justement quelle solution ils proposent qui respecte la loi de Démeter sans faire appel aux get/set.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
Ca changera rien, le programmeur, par soucis d'encapsulation et de cacher les détails d'implémentation ne t'as donné aucun get, même "protected" pour accéder à tes roues. Bref, t'es mort.
Et que proposes tu sur
app.getMainWindow().getContainer().getChild(1).resize(10,3)
?
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Je penses qu'on est d'accord : il est évident qu'il ne faut pas se contenter d'utiliser des objets/données en se disant "j'ai mis des get/set, je fais de l'objet", et qu'il faut écrire des fonctions métiers plus élémentaires, tant qu'on parle de code métier.
Après le débat initial était surtout d'indiquer qu'il était largement préférable d'utiliser les get/set vs l'accès direct aux membres, même si à première vu le get ne faisait pas grand chose.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Prend un autre exemple, je veux redimensionner le bouton contenu dans une fenêtre :
app.getMainWindow().getContainer().getChild(1).resize(10,3)
Tu crois que le container et la Window sont inccapables de se redimensionner automatiquement parcque je ne les ai pas notifié ?
t'aurais fais comment sans les get ?
app.resizeFirstChildOfContainerInMainWindow(10, 3) ?
Comment prévoir tous ces cas ?
L'objectif est d'exposer une API conviviale et intuitive, après c'est le problème de celui qui créé la lib de s'assurer que l'état de tous les objets du graphe qu'il expose reste cohérent.
Oué enfin si on pouvait éviter de prendre le C++ comme langage de référence quand on parle programmation objet ca serait pas mal :)
Oui bien sûr, mais ça suppose que ta mercedes est la fonction de changement de pneu. Donc si c'est une bibliothèque qui n'a pas prévu le coup, t'es mort, tu retournes voir le constructeur. C'est peut-être l'effet recherché tu me diras. Si t'es garagiste, tu peux avoir envie de bricoler sans t'en tenir aux seuls cas imaginer par le fabriquant.
Qu'on soit clair : l'objectif n'est pas de dire "mettez des accesseurs sur tous vos membres". L'objectif est d'utiliser des accesseurs quand il y a une interface intéressante à exposer.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 3.
Mon deuxième exemple est une API classique pour accéder un à DOM XML.
Que proposes-tu concrêtement comme code pour un résultat identique ?
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Là encore, ca dépend fortement de ce que tu veux faire, si c'est par exemple :
obj.getVoiture().geetFirstRoue().setNewPneu(new Michelin())
autre exemple :
doc.getNodes().first().getNodeById("3").setAttribute("name", "toto")
Bon courrage pour le faire avec la loi pré-citée.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Le problème de ce principe, c'est qu'il oppose service et données : il faut effectivement penser "service", mais parfois ton service c'est d'exposer des données : DTO, Controller, DOM, Composants IHM, etc.
Reprends mon exemple de la voiture, moi je veux pouvoir changer moi même la roue, c'est ça le service que j'attend. Pas que la voiture m'expose un numéro de téléphone qui dépende de mon garagiste.
De plus ton principe n'est applicable que si tu as la main sur le code de la voiture car, auquel cas tu peux ajouter toi même la méthode doStuffOnFirstWheel. Et si cette méthode est dans une bibliothèque, tu fais comment ? tu dérives à tout va ? Piouuu.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 3.
"La notion fondamentale est qu'un objet devrait faire aussi peu d'hypothèses que possible à propos de la structure de quoi que ce soit d'autre, y compris ses propres sous-composants."
La seule façon de s'assurer que tu ne puisses pas faire d'hypothèse sur la structure d'un objet, c'est d'en cacher tous les détails d'implémentation, et un membre exposé directement sans getter/setter, c'est exactement ça.
En gros cette loi conduit au contraire à écrire encore plus de getter/setter :
Au lieu d'écrire :
obj.getVoiture().getFirstRoue()
tu te retrouves à ajouter à ton obj un autre getter :
obj.getFirstRoueFromVoiture()
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Oué je me fait avoir régulièrement, et le jour où j'ai gueulé, je me suis fait rembarré parcque c'était clairement documenté ;)
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
C'est vrai, et quelque soit le langage d'ailleur. Mais qui t'assure que tes tests sont correctement écrits ? Rien. Qui t'assures que tes tests sont complets ? Rien. Qui t'assures que les cas extrêmes sont tous couvert par le fuzzing ? rien. Qui te garantie que le contexte (archi, compilo, etc.) dans lequel tu exécutes ton fuzzing va rester valable dans un autre contexte ? Rien.
Ce type de tests, qui par nature ne garantisse rien, ne permettent que de se rapprocher, avec un coût exponentiel, vers l'absence totale de bug.
Il faut les utiliser, mais à bon escient, et accepter qu'ils ne sont pas suffisant. Un language de haut niveau, offre beaucoup plus de garantie, by design, qui ne fera que compléter ces bonnes pratiques pour offre une meilleure sécurité, à moindre coût.
Je ne parle pas de clareté mais de sécurité. La méthode peut être clair, la doc aussi, mais tout repose sur le programmeur qui ne doit pas se "planter" lorsqu'il code, sinon boum. D'où l'idée d'avoir un outil (langage + compilo + runtime) qui permet d'assurer l'absence des problèmes les plus courants, by design.
[^] # Re: Chacun son style
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 1.
Tu as tout à fait raison.
C'est pourquoi il est important de systématiquement utiliser des getter/setter : même si ca paraît idiot dans un premier temps, celà reste une bonne pratique essentielle à des concepts fondamentaux de la programmation objet : l'encapsulation et le contrat d'interface. Je cache les détails d'implémentation, qui peuvent évoluer d'un simple accès une variable à un truc plus complexe, tout en évitant de casser le contrat d'interface exposé aux utilisateurs de ma classe.
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 3.
Personnellement je pense que c'est un conseil à ne surtout pas suivre.
Qui peut affirmer maîtriser quelque chose sans avoir eu d'expérience avec ? Il faut bien commencer par être débutant, accepter de ne pas tout maîtriser, puis progresser. Et surtout ne jamais affirmer qu'on maîtrise : c'est la meilleur façon de se planter.
[^] # Re: Dépassement de tampon
Posté par TImaniac (site web personnel) . En réponse à la dépêche Naissance d'un géant : Java. Évalué à 2.
Tout d'abord, merci de faire revenir la conversation au débat initial.
Oui, des erreurs du programmeur qui conduisent à bugs non détectés par un compilo ou un runtime, et qui se transforme en faille de sécurité potentielle. D'où le danger.
Disons que c'est le coeur du débat : d'un côté on reporte la faute sur le programmeur qui s'est coupé avec le scalpel, de l'autre on indique qu'il y a des langages qui évite justement 90% des conneries de l'utilisateur qui avait juste besoin de se couper une tranche de saucisson.
Justement non. C'est 2 visions totalement différentes, mais pour de nombreux programmeurs une API bien faite est une API intuitive, où je n'ai pas besoin d'utiliser la doc, ou peu. Le problème c'est pas qu'il n'y a pas d'API intuitive en C, le problème c'est que le langage est tellement dangereux qu'il est extrêment complexe de faire une API 100% secure : il est donc effectivement indispensable de lire la doc pour tous les aspects non-intuitif inhérent à l'environnement technique.
L'exemple du strncpy, qui se veut secure mais ne l'est pas à 100% est un très bon exemple : l'équivalent fonctionnel est parfaitement implémentable dans des langages "modernes" sans tous ces problèmes de documentation indispensable à sa bonne utilisation.
Ben vous le faites, mais avec pleins de problème de sécurité qui conduisent à des failles, pourtant "classiques", mais qui auraient été évités avec un langage de plus haut niveau.
Il y a plein de bonnes raisons d'utiliser le C pour coder un OS, mais la contrepartie est une forte exposition aux problèmes de sécurité.