Le Livre d'Argent

Plus le temps passe et plus je trouve que le système de visibilité de Java/Kotlin (internal/private/public) est mauvais. Je préfèrerais un système à la Python où la visibilité n'est qu'indicative mais le langage ne t'empêche pas d'aller mettre tes mains dans les entrailles du système.

Combien de fois j'ai pu patcher des bugs ou des fonctionnalités manquantes dans Django parce que Python me le permettait ?

Encore un exemple avec l'arrivée de Jetpack Compose dans Android, une bibliothèque dans laquelle il manque encore plein de fonctionnalités et que le système de visibilité de Java t'empêche activement de réparer/compléter et t'oblige à attendre que les équipes de Google daigne s'en occuper ou à tout ré-implémenter toi-même.

@AugierLe42e ouais j'ai toujours trouvé qu'il manquait une option genre une directive pour dire au compilo de te laisser accéder aux trups privés

@AugierLe42e j'ai d'ailleurs toujours pas compris comment on était censé faire pour tester des classes pour vérifier les valeurs de ses attributs privés, à part en faisant une copie de la classe avec l'attribut qu'on veut vérifier en public (stub spy mock je sais même pas c'est quoi le terme) et si on met l'attribut en public de base on se fait reprendre par nos profs que ça serait horrible d'un point de vue sécurité :c

@thea Mais oui, chuis d'accord avec toi : y'a un problème d'idéologie chez beaucoup de prof de programmation. Y'a un tas de croyances qui restent omniprésentes et qui viennent du mon Java qu'il faut de l'encapsulation, des design patterns (builders, factories, .of, etc.), qu'il faut pas de surcharge d'opérateurs… Rien de tout ça n'existe en Python et Python n'est pas un langage moins sécurisé que Java… ¯\_(ツ)_/¯

@AugierLe42e mettre un attribut en privé mais mettre un getter et un setter qui ne fait aucun check et dire que c'est une bonne pratique de code on se demande si eux même ils y croient 🫠

@thea Pour leur défense, les getter et setter, c'est effectivement une bonne pratique en Java parce que ça favorise la stabilité de l'API, nécessaire dans un langage qui force l'encapsulation. Mais ça c'est juste parce que Java est un mauvais langage qui n'a toujours pas d'accesseurs natifs comme Groovy, Kotlin voire même l'implémentation bizarre de Scala.

@AugierLe42e Le principe c'est que si c'est privé/protected t'es pas censé y avoir accès autrement que par les points d'accès données. Alors en tant qu'utilisateur de bibliothèques parfois c'est frustrant mais en tant que développeur de bibliothèque ou de projet commun a d'autre dev tu ne veux pas que les gens viennent trifouiller dans les trucs tel qu'ils sont prévu car ils estiment que ce serait plus simple/résoudrait des trucs de passer par là alors que pas du tout pour l'implémentation

@Schoumi Le problème c'est que cet argument ne repose sur rien. Python n'impose aucune visibilité. Il n'y a que des conventions indicatives. Et tout se passe très bien. De nombreuses fois j'ai pu monkey-patch une bibliothèque en attendant que ma PR soit mergée à la source, ce qui, dans le cas de Django, peut prendre une éternité.

C'est la différence entre un langage tricycle et un langage qui te prend pour un adulte. Et pour les changements d'API privés, bah on a les tests pour détecter ça…

@AugierLe42e
C'est pas une question d'adulte et de petite roulette.
En faisant tes modifs hijack c'est très bien, ça marche cool. L'implémentation interne change tu refais tout? ton code est à reprendre, etc

En terme de maintenabilité c'est se créer plus de problème que de solution que d'aller bricoler avec ce qui ne doit pas être visible pour toi.

Quand tu bosses avec plusieurs dizaines de personnes t'as pas envie de ça

Tu run les tests de la lib quand tu fais tes "modifs" hijack dedans?

@Schoumi

> L'implémentation interne change tu refais tout? ton code est à reprendre, etc

Bien sûr. Pareil que quand l'API publique change, parfois sans prévenir. Ça arrive même beaucoup plus souvent qu'on ne veut bien se l'avouer. C'est aussi pour ça qu'on écrit des tests unitaires. Et la visibilité stricte de Java n'a jamais protégé de ça… ¯\_(ツ)_/¯

@Schoumi

> c'est se créer plus de problème que de solution

Non. Ou alors source chiffrée parce que pour l'instant cet argument repose sur aucune base.

@Schoumi

> Quand tu bosses avec plusieurs dizaines de personnes t'as pas envie de ça

Et pourtant des énormes projets sont dévelopés en Python. Genre Dropbox ¯\_(ツ)_/¯

> Tu run les tests de la lib quand tu fais tes "modifs" hijack dedans?

Nan tu teste ton code qui monkey patch la lib. Ça marche très bien.

@AugierLe42e oui si l'api publique change c'est obliqué mais en privé tu peux changer un million de truc sans que ça change rien pour l'utilisateur de l'api publique qui n'a rien changé. Hors toi ton code tu dois le changer dès qu'ils font des changements car t'as contourner un truc.

@Schoumi Et alors ?

@AugierLe42e ouais et on fait plein de cobol encore partout et donc?
Le fait qu'ils utilisent python ne veut pas dire qu'ils font n'importe quoi avec la portée des variable, qu'il bricole les libs dont elles ont fourni une API publique parce qu'elle le peuvent.

C'est pas parce qu'un truc est possible dans un langage et que ça se passe vaguement bien car les gens font gaffe que c'est une si bonne idée. Sinon on peut parler des très bonne idée de javascript et dire qu'on devrait faire ça partout

@Schoumi Je vois pas le rapport avec Cobol et je vois toujours pas non plus en quoi c'est une mauvaise idée…

@AugierLe42e tu dis que python parce que c'est utilisé sur de gros projet ça permet de justifier que c'est une bonne idée.

Cas concret, ton code hijack tu l'a fait aujourd'hui. Tu reprends ce projet dans 2 ans, met a jour les libs. Tu as contourné un truc, ton code a l'air de toujours marché plutôt bien mais ça a un impact ailleurs. Il va te falloir combien de temps pour retrouver que c'est parce que t'as contourner l'api publique que ça merde ailleurs?

@Schoumi Ça s'appelle être développeur. Des bugs cryptiques qui demandent des heures de debugage, j'en ai rencontré dans tous les langages. Y compris Java/Kotlin ¯\_(ツ)_/¯

@AugierLe42e oui mais ce bug il n'était pas censé être là et n'aurait pas dû être là car tu n'a rien changer dans ton code l'api publique n'a pas changer.

@Schoumi Un bug n'est jamais censé être là. C'est le principe d'un bug ¯\_(ツ)_/¯

@Schoumi @AugierLe42e dans le même genre que la visibilité c'est le typage multiple. Python permet qu'une variable soit un coup un entier, un coup une chaine de caractère. Ce n'est pas parce c'est possible qu'il faut l'utiliser. En tout cas de mon point de vue ça ne peut être qu'une mauvaise idée.
Quand je developpais (ya longtemps) on pouvait faire de la reflection pour acceder aux méthodes privées mais quand tu le faisais, tu savais que ce n'est pas bien.

@valvin Je sors Schoumi qui ne veut plus avoir affaire avec la discussion.

La cas du typage est un peu plus particulier. Déjà parce qu'il y a des raisons techniques pour lesquelles la JVM ne peut pas le faire. Groovy sait le faire mais ça implique un surcoût en performence.

@valvin Dans le cas de Python, oui, effectivement, c'est déjà arrivé de se tirer dans le pied avec le typage dynamique. Mais ça veut pas dire que c'est une mauvaise idée pour autant. Python supporte les type hints depuis la version 3.5 et des outils de qualité de code comme MyPy ou bientôt Ruff permettent de vérifier le typage statiquement. Avoir des problèmes avec le typage dynamique de Python est aujourd'hui beaucoup moins courant qu'à une époque et probablement bien moi répandu que les NPE.

@valvin Dans tous les cas, ma réponse ne va pas varier : y a-t-il des éléments qui permettent de soutenir qu'une fonctionnalité est une mauvaise idée ? Dans le cas de la visibilité la réponse est non parce que personne ne s'est jamais tiré dans le pied avec ça. Dans le cas du typage dynamique, pas forcément, on a des solutions pour gérer correctement le problème.

@AugierLe42e Ça dépend, vraiment beaucoup, de ce que t'es en train de faire et de comment le truc est pensé.

Il y a des cas où il n'y a pas de vraie raison de restreindre l'accès d'un truc et où passer en privé est juste un mauvais choix de design, et ce serait bien mieux si tu pouvais aller monkey-patcher tout en Java comme tu le fais en Python.

Mais il y a aussi des cas où un truc ne devrait juste pas être accessible parce que ça n'apporterait rien mais que si t'y touches ça casse tout, et dans ce cas c'est Python auquel il manque un vrai mécanisme de visibilité (même si y a parfois moyen de contourner, mais bon, 'faut forcer).

Le souci avec la visibilité en Java, c'est surtout que le truc pousse pour l'utiliser sans réfléchir aux besoins réels.

@valvin Et ma réponse sera la même pour l'héritage multiple, l'autre bête noire de Java : en Python c'est possible, mais dans la commu Python tout le monde connaît l'existance et le fonctionnement du MRO et, certes, ça arrive, mais dans ma carrière j'ai eu plus de problèmes avec des NPE ou même juste des erreurs de compilation improbables de Gradle avec Android ou encore avec des changement de comportement des biblio Jetpack sur Android qu'avec des problèmes d'héritage multiple En Python.

@elzen

> Python auquel il manque un vrai mécanisme de visibilité

Ben non, il y a la notation `__`. Tous les IDE l'implémentent et tous les IDE te le signale quand tu fais un truc que tu devrais pas. C'est juste Python te laisse dire « je suis un adulte je sais ce que je fais ».

Bon, à la limite, j'accepterais un truc comme `private def/fun` qui t'empêche d'utiliser une API privée, à condition qu'il y ai un mode « ta gueule ». Mais le gain apporté ne me semble pas valoir l'effort.

@AugierLe42e après je suis convaincu qu'il faut accepter les règles du jeu du langage sur lequel on travaille et ne pas transposer ce qu'on apprécie d'un autre langage qu'on ne peut pas utiliser. il y a aussi la sensibilité de chacun, l'école.
je préfère le typage dur, définir la portée des variables et utiliser les méthodes de librairie que le développeur a prévu qu'on utilise.
ceci dit je comprends la frustration que ça représente de ne pas pouvoir le faire.

@valvin Je suis pas d'accord parce qu'il s'agit d'une question d'ergonomie. Un langage, comme n'importe quel outil a une ergonomie et, de ce point de vue, l'ergonomie de Java est abominable. D'ailleurs, personne n'accepte jamais complètement les règles de tous les langages sinon aucun langage n'évoluerait et même Java ajoute de nouvelles syntaxe. Pour ma part, je pense qu'il est important de questionner les choix de design à la base de tous les langages.

@valvin De ce point de vue, Java a fait — et continue de faire — des choix forts pour des raisons qui sont aujourd'hui, à mes yeux, assez discutables.

Ce genre de problème se pose aussi en Python. Par exemple il y a eu une grosse discussion sur l'opérateur `:=` en Python avec des arguments contre qui étaient assez valables.

@valvin Mais pour la visibilité en Java, pour l'instant, je n'ai rencontré aucun argument qui me convainque. Pas plus que pour l'absence de surcharge d'opérateur, d'accesseurs natifs ou l'obligation du point-virgule.

@AugierLe42e Alors, juste, non.

D'une part, le __ en début de nom est loin d'être une façon de rendre quelque chose privé, dans la mesure où justement, ça auto-documente le truc et donc te donne la possibilité d'aller le chercher facilement. À la limite, le _ seul fait un peu plus ce taff (et rend cette convention de nommage débile, mais passons).

D'autre part, la question n'est pas d'être un adulte qui sait ce qu'il fait ou pas, la question est d'identifier ce qui relève de la mécanique interne sensible pour pouvoir la protéger convenablement. C'est la même chose que pour les objets physiques : si un disque dur mécanique n'a pas sa tête de lecture à l'air libre, ce n'est pas parce que le fabriquant considère que t'es pas un adulte, c'est parce que si de la poussière se dépose dessus ça va moins bien marcher.

Une « API privée », c'est simplement contradictoire, hein. Soit le truc relève de la mécanique interne et doit être privé, soit tu mets en place une interface pour y accéder, les deux sont par définition mutuellement exclusifs. C'est une question de conception.

@elzen Chuis désolé mais je vois pas le rapport avec le disque-dur donc je sais pas quoi répondre.

Que je comprenne bien : toi tu voudrais un mécanisme qui cache les attributs privés de l'autocomplétion ? Ou carrément un truc qui t'empêche d'exécuter un script Python si t'accède à un attribut privé ?

@AugierLe42e On n'est pas non plus obligés de poursuivre la discussion, au pire, vu qu'on parle visiblement de choses un peu différentes :-)

Mais ce que je dis, c'est qu'il manque à Python (ou alors je ne l'ai pas encore trouvé) un mécanisme qui permet d'avoir un truc qui relève du fonctionnement interne de l'objet, et donc auquel l'extérieur n'a pas accès directement (déclencher une exception quand tu tentes d'y accéder depuis ailleurs serait une bonne façon de faire ça).

@elzen Ok, je vois mais… pourquoi ? Chuis vraiment sincère, hein, je comprends vraiment pas ce que ça apporte par rapport à `__` ?

@AugierLe42e Qu'est-ce qu'un tuple/un frozenset apporte par rapport à une list/un set pour lequel t'aurais mis une petite note de documentation disant « ne modifiez pas le contenu s'il-vous-plaît » ?

(Voire, qu'est-ce qu'un set apporte par rapport à une list où tu demandes explicitement aux gens qui vont s'en servir de faire bien gaffe au moment d'insérer des données qu'elles ne soient pas déjà dedans ?)

C'est généralement techniquement possible de coder en ne mettant aucune restriction et en croisant les doigts pour que les gens qui s'en serviront ne viennent pas faire de conneries avec, donc strictement parlant, on peut tout à fait argumenter que ça n'apporte rien d'en placer, des restrictions. Mais c'est quand même bien quand l'outil est capable de veiller à sa propre intégrité et où ce qui risque de te pêter à la tronche est protégé comme il faut.

@elzen Ben justement j'ai déjà au des soucis avec des collections immuables. En Django request.GET et request.POST, qui contiennent les données d'une requête HTTP, sont immuables. Sauf que j'ai déjà rencontré un cas où la solution la plus élégante était de modifier la donnée.

Mais à la limite, pourquoi pas. Sauf que la collection t'empêche pas d'en faire une copie modifiable et de travailler avec. Donc le problème se pose pas.

@elzen C'est très différent de fermer l'accès à un attribut avec une exception où, là, on peut rien faire. Sauf qu'encore une fois : j'ai déjà rencontré (souvent) des cas en Python où, en attendant qu'une de mes PR soit fusionnée en amont, j'ai pu temporairement patcher le truc en local. Et il me semble que c'est une bonne fonctionnalité qui permet d'itéré rapidement sur un projet.

@elzen Alors oui chuis d'accord, y'a des fois où monkey-patch le truc c'est pas une bonne idée, c'est trop précaire ou ça risque de devenir plus pérenne qu'on ne le voudrait. Mais c'est pour ça que je parle d'être professionnel : c'est un compromis à trouver, à discuter avec ses pairs. Mais le langage ne m'en empêche pas. Il dit juste « écoute moi je t'ai prévenu, tu fais comme tu sens »

@AugierLe42e On en revient donc à ce qu'on disait initialement tous les deux :-)

Le point qui est gênant avec la visibilité privée n'est pas sa présence, mais le fait qu'elle soit utilisée abusivement, dans des cas où tu peux avoir un intérêt à y accéder depuis l'extérieur. C'est un problème de conception, pas un problème avec la fonctionnalité elle-même.

Perso quand je bosse sur des trucs, j'essaye de les concevoir d'une façon qui les rend aussi extensibles que possible de base, pour que tu puisses intervenir dessus sans avoir besoin de monkey-patcher, mais il reste toujours quelques attributs que j'essaye de protéger parce que si t'y touches, tout pète.

@elzen Là par contre, j'ai le cas d'une bibliothèque Jetpack où tout est opaque avec un bug que je peux pas corriger à cause de l'opacité. Donc chuis obligé de me reposer sur Google pour réparer sa merde. Je suis sans solution, à part tout ré-implémenter…

@elzen Je peux entendre cet argument mais le soucis, c'est que tu peux jamais prévoir correctement ce qui est abusivement privé ou pas. Simplement parce que tu peux jamais imaginer tous les cas d'usage. Surtout dans la commu Java qui a pour habitude de mettre le max de trucs en privé 🫤

@AugierLe42e Pour le coup, je te demanderais bien de jeter un œil à du code à moi pour voir si tu arrives réellement à trouver des cas où accéder à ce que j'essaye de rendre privé serait intéressant sans être problématique, mais ce serait probablement te faire perdre ton temps pour pas grand chose d'utile au final :-)

On est en tout cas d'accord sur le fait que l'usage majoritaire en Java utilise la visibilité d'une façon qui a l'air d'être plus automatique que réfléchie et donc pose facilement problème.
replies
1
announces
0
likes
1

@AugierLe42e j'ai le sentiment que dans tous les cas, tu ne seras pas convaincu. j'aurais tendance à conclure en disant que ce langage ne te convient pas ;-)

@valvin Java ? Non, clairement c'est un langage qui me convient pas 😅

@elzen Ah ça je sais pas. En vrai c'est un truc qui se montre avec le temps. Perso en Python, j'ai de moins en moins tendance à déclarer des trucs en privé. Je mets plutôt en protected. Je vois de moins en moins l'intérêt de privé.

Voilà. Les modificateurs d'accès, c'est de droite 👀

https://degaucheoudedroite.delemazure.fr/

Capture d'écran de la page de de l'URL dans le post.