Journal L’homme orchestre, partie 2 : écrire du code (en Java)

21
23
mar.
2016

Sommaire

Ceci est un article que je vient de publier sur mon blog et que je propose en lecture ici pour permettre la discussion, vu que j'ai désactivé les commentaires sur mon blog.
C'est la suite de mon précédent journal : L'homme orchestre, partie 1 : les casquettes

Depuis 4 ans, j’écris un MAM libre en Java. Comment arriver à ne pas se laisser dépasser par l’immensité du travail à fournir ? Un article en deux parties très subjectives et relèvent de l’expérience que j’ai pu tirer avec le temps (je ne suis pas développeur de métier ni de formation).

Les bon outils

Pour travailler, il faut de bons outils. Vos bons outils. Ceux que vous connaissez, que vous aimez. Toute l’énergie employée à lutter contre ses outils de travail, ne sera pas récupérée ailleurs.

Si vous avez un IDE, tunez le à fond. Police, couleurs, macros, plugins, tout doit être à vos goûts. Vos outils sont vos mains, ils doivent être naturels et logique. Votre logique. Et attention aux mises à jours qui peuvent casser ça : faites des backups de votre environnement de dev.

Pas de temps à perdre à apprendre

Je conçois mon développement de code selon une simple maxime : un nain sur des épaules de géant. Je repose sur des technologies réputés et fiables. Pas sur des bidouilles qui montrerons leurs limites (en terme de stabilité ou performance) au moment où ça sera trop tard. Pour cela je prends du temps pour choisir ces technologies. Il m’a fallu plus d’un an pour valider ElasticSearch, Cassandra, Play et Git.

Mais je ne perd pas de temps à les faire fonctionner. Pas de tutoriel ? Pas d’exemple ? Next ! Galère à installer ? Next ! Limité dans les plateformes ? Next ! Complètement abandonné ? Next ! Si l’équipe qui a écrit ce framework, ce serveur, cette API, cette bibliothèque, n’a pas pris le temps de faire un travail de présentation pour aider le néophyte, alors pourquoi je devrai faire cet effort ?

Je me limite donc qu’aux technologies qui me sont accessibles sans trop d’efforts. Et ça fini par payer : il m’a fallu assez peu de temps pour utiliser React ou Gson. Il m’en a fallu pas mal pour les utiliser correctement, mais au moins je n’ai pas mis un mois pour juste pour les découvrir, les essayer et voir qu’ils me convenaient.

Avancer pas à pas sur de bonnes bases mais abstraire ce qu’il faut
Un bon développeur fait un code lisible, avec le moins d’instructions possible, en allant directement au but. C’est l’idéal quand vous écrivez un script. Mais pas forcément quand vous devez construire une grosse application. Vous devez avoir un coup d’avance sur ce que vous allez peut-être avoir besoin, et le prévoir en amont. Mais attention, uniquement jusqu’a la prochaine itération ! Quand on dessine les plans d’un avion, on prévoit que l’on aura des passagers à « stocker » avant de prévoir la couleur du robinet des toilettes, mais on oublie pas que l’on aura aussi des toilettes à « stocker » dans l’avion, à côté des passagers, même si eux restent plus importants !

Autre exemple plus concret, je prévois l’analyse de documents bureautique dans MyDMAM. Je sais comment je vais procéder. J’ai besoin pour cela de l’analyse de PDF. Cette analyse à besoin d’une API pour abstraire le type de document et choisir moteur à employer pour le traiter. Je dispose actuellement d’une API pour traiter les fichiers graphique, audio et vidéo. J’ai prévu dans mon code la possibilité d’étendre cette API à autre chose et fait attention à ne pas trop mettre en dur les différents formats gérés. Quand je devrais gérer les PDF, je sais que je ne devrais pas casser grand chose pour y arriver. Et a ce moment là, je penserai à gérer les documents bureautique. Mais pour le moment, ce n’est pas prévu. C’est notamment ça le travail « d’architecte logiciel » que je parlais plus tôt.

La rigueur

Quand on part dans une direction, on s’y tient, ou alors on recule et on change de direction, on casse du code et on repart au propre. Le bricolage tout moche pour que « ça marche » est à bannir. Votre code est libre et publique ? Evitez d’écrire une rustine qui vous fera honte une fois que git blame vous dira que l’imbécile qui à écrit ça il y a bien longtemps, c’était vous.

Je suis lent à avancer dans l’écriture de mon code pour cette cause. Vu le temps que j’y ai passé, MyDMAM devrait couter l’équivalent d’une fortune en terme de temps de travail ! Mais je suis globalement fier du code déjà écrit. Les parties les plus anciennes sont à opposer aux parties récentes qui me montrent que j’ai progressé en terme de qualité et de rigueur.

N’oubliez pas que le problème avec une installation en carton, c’est quand les scotchs lâchent.

Bien nommer

Si vous ne savez pas noter une variable, une classe, une fonction, c’est qu’elle n’a pas a exister de la façon d’où vous la pensez. Quand vous avez le bon nom, c’est bon, continuez avec. Je suis maniaque des noms. J’utilise de longs noms, et je passe beaucoup de temps à y réfléchir. J’essaye de garder une grande cohérence dans les variables : si une variable s’appelle « toto » dans un coin du code, une fois passé dans une autre partie du code, elle ne doit pas s’appeler « tata ». C’est le meilleur moyen de s’embrouiller quand votre code fait 50 000 lignes. C’est très contraignant, mais Eclipse m’aide beaucoup avec ses fonctions de refactoring.

Java

Quand j’ai découvert Java, j’en ai eu très peur, moi qui « venait » du PHP, et qui avait écrit plein de bouses dans ce langage. Les fonctions de refactoring intégrés à Éclipse m’on sauvé. Sauvé car mon IDE est devenu omniscient. Il me déchargeait d’un tat de choses que je n’avais plus à penser. La mise en page, la vérification de d’erreurs de syntaxe, de cohérence entre les objets, l’auto complétion… c’est magique !

Après il y a des façons de faire en Java qui sont enseignées / conseillés et qui par expérience alourdissent le code.

En utilisant Play! Framework, la v1 (c’est à dire la version Java/Groovy), et avec mon expérience personnelle, j’ai appliqué de nouvelles façon de travailler :

  • Prioriser le static, le plus possible. Si quelque chose est polyvalent pour tout le code, et n’a pas besoin d’être libéré/détruit alors il sera static.
  • Cacher les champs par défaut, et les ouvrir au besoins, bref, réduire le plus possible la visibilité.
  • Eviter les get/set de vos variables privés (sauf dans le cas ou vous avez besoin de faire un check en entrée ou une transformation en sortie) et remplacez les get/set par un accès direct à la variable.
  • Bannir les génériques en cascade comme des Map de List de List Ne pas hésiter à créer des classes pour étaler ses idées simplement, puis tout factoriser dans le moins de classes possible une fois que la logique est là.
  • Les annotations et la Reflexion sont très puissants, mais ça échappera à l’IDE omniscient. À utiliser pour simplifier des parties de code bien lourdes et répétitives et rendre le code « magique ». Je m’en sert notamment pour transformer une fonction Java en Contrôleur pour des dialogues avec JavaScript coté client, et en abstrayant les (dé) serialisations json avec des vrai objets Java.
  • Fabriquer ses propres génériques, c’est souvent casse gueule et parfois inutile. Au final, c’est rare que j’en ai eu une bon raison d’en faire. Ce qui existe déjà est très bien.
  • Si on ne peut pas déterminer à quoi sert quelque chose par son nom ou par l’IDE (avec la recherche de dépendance) alors il faut mettre un commentaire. Sinon commenter, c’est une perte de temps. Oui, j’assume cette phrase.
  • Des très long noms de variables et de classes sont autorisés… pourquoi s’en priver ?
  • Bien choisir son système de log ! Et apprendre à s’en servir ! Les threads permettent d’avoir des sous systèmes indépendants dans un seul processus. Il est fondamental de comprendre comment marche la synchronisation entre Threads (ce n’est pas très méchant, mais c’est pas évident de prime abord). D’autre part les Threads servent aussi à monter en performance en faisant des calculs en parallèles, mais ça demande d’avoir un très gros niveau technique pour y arriver, car si c’est mal fait, ce ne sera pas plus rapide ou alors ça fera boom ! Quand j’ai besoin de prefs, j’utilise toujours une librairie qui le fait mieux que moi. Je n’écris pas de tests unitaires. Je comprends le principe, mais je n’y adhère pas. J’ai 0 tests, et mon dev se porte très bien. Je travaille le plus proprement possible, et le travail conjoint entre mon IDE et mon historique Git m’a permis de ne quasiment jamais à avoir d’effets de bords lors de mes itérations d’implémentations et de corrections de bug. Maintenant, je travaille seul et sans contraintes extérieures.
  • Design pattern : c’est indispensable d’en connaître quelqu’uns ou au moins de connaître quelques principes. C’est comme ça que mon code est passé d’un tas de scripts pourris à une vraie structure de code. C’est une forme de maths, ça fait mal à la tete, mais ça permet de débloquer tellement de choses.
  • Les regex, c’est mal. Je les évite le plus possible. Une fois j’ai remarqué qu’un for sur les caractères d’une chaine avec plein de if allait 11 fois plus vite qu’une petite regex qui m’a pris des heures à écrire. Ça ma mis en rage quand j’ai découvert ça. Et puis en terme de lisibilité, on ne fait pas plus cryptique d’une regex. Le mal de tête quand on se dit que l’on va devoir en modifier une…

En détail

Commentaires/recherche de code

Je commente donc très peu. Mon code est écrit de tel façon que tout soit le plus clair possible. Les fonctions de refactoring/recherche de dépendances d’Eclipse sont là pour aider à comprendre une structure facilement. Et quand ce n’est pas suffisant, là, je met un commentaire.

Petites itérations

Mon cycle d’implémentations/debug/releases est très lent. Trop lent. Je devrais me contenter de faites des choses plus petites et d’incrémenter plus souvent mes versions, car plus les changements sont importants plus la transition est difficile. Je pense que ça viendra avec le temps.

Améliorez, progressez, réécrivez !

Tout ne peut pas être parfait du premier coup mais peut le devenir ! Je cherche toujours à améliorer les portions de code maladroites, afin d’éviter le plus possible de le compenser avec d’autres maladresses, et de me retrouver avec un tas de bazar ingérable. Ce qui fait qu’il m’arrive de récrire et d’améliorer plusieurs fois certains éléments pour arriver à quelque chose de plus propre, stable et évolutif. Par exemple, le code qui gère le service de Broker/Jobs/Queue distribué via Cassandra à été réécrit 4 fois et est maintenant plus stable et aboutit qu’il ne l’a jamais été.

Pas compile, pas commit

Une règle de base : garder son repository propre. Si ça ne compile pas, on corrige avant de commiter. Car sinon on ne saura pas si l’erreur qui arrivera au prochain pull viendra de son environnement de dev ou du nouveau code que l’on vient de pull. Une fois ça m’est arrivé, j’ai compris la leçon.

S’oxygéner l’esprit

On est pas des machines. J’ai remarqué qu’en codant pendant un bloc de 3 heures, mon code était « meilleur » que pendant 6 heures. La fatigue dégrade la qualité du code. 3 heures par jour, ce n’est pas beaucoup, mais au final j’avance plus vite que 4 jours à 6 heures et rien la semaine d’après. Cette phrase n’a pas de sens, mais je suis sur que vous l’avez compris.

Et régulièrement faire des pauses de l’esprit comme travailler un visuel pour le site du projet, fouiller du côté de nouvelles technologies, réfléchir à l’avenir et aux nouvelles fonctions géniales que l’on aimerait faire…

Enfin tout ce qui ne consiste à ne pas taper sur un clavier.

Et sortir. Parler de ce que l’on fait à d’autres humains « en vrai ». C’est toujours instructif car on peut avoir des « questions bêtes » dont la réponse semble évidente. On m’a demandé si ça marchait sous Windows (potentiellement oui, c’est du Java), mais en y réfléchissant je me suis rendu compte que j’avais jamais testé l’interface web sous IE… et qui ne c’est avérée pas du tout fonctionnelle !

Bref, on pourrai en parler pendant des heures, chaque développeur à ses envies et ses préférences. Et encore plus quand l’on est pas développeur comme moi, et que l’on pas eu la « chance » d’avoir eu une formation formatant l’esprit de comment on doit faire et ne pas faire. Mais ça, c’est une autre histoire.

  • # Chouette recul

    Posté par . Évalué à 2.

    Si seulement les développeurs de formation / métier pouvaient avoir ne serait-ce que la moitié de ton recul / ta réflexion, ça serait super !
    Je n'adhère pas à toutes tes idées (principalement sur les tests de non régression - et non unitaires) mais l'ensemble me semble relativement cohérent.

    Et je te souhaite encore plein de découvertes ! ;-)

    • [^] # Re: Chouette recul

      Posté par (page perso) . Évalué à 1.

      Merci pour le compliment ! Je tricote du code depuis 15 ans, j'ai encore à découvrir.

      Mes idées sont de simples constatations naturelles que j'ai pu faire, en dehors de toute théorie.

  • # Merci

    Posté par . Évalué à 6.

    Ton retour est super intéressant !

    Mais j'ai quelques remarques :

    Éviter les get/set de vos variables privés (sauf dans le cas ou vous avez besoin de faire un check en entrée ou une transformation en sortie) […]

    Ok.

    […] et remplacez les get/set par un accès direct à la variable.

    Wow ! Non ! Tu expose le fonctionnement de ton objet, c'est vraiment pas génial comme fonctionnement.

    Collection<String> ids = // init
    obj.ids = ids;
    obj.foo();
    ids.clear(); // je viens de faire un clear() sur le champ ids de l'objet obj...
    obj.foo(); // BOUM ! 

    Au contraire on conseil de faire des recopies de sécurité dans les setter, mais le mieux c'est tout simplement d'éviter autant que possible les setters et d'utiliser des fonctions métier.

    Bannir les génériques en cascade comme des Map de List de List Ne pas hésiter à créer des classes pour étaler ses idées simplement, puis tout factoriser dans le moins de classes possible une fois que la logique est là.

    C'est bien. J'ajouterais juste que j'ai tendance à essayer d'utiliser les références les plus abstraites possibles. Mes fonctions prennent souvent des Collection en paramètre par exemple (sauf si j'ai besoin de quelque chose de plus précis).

    D’autre part les Threads servent aussi à monter en performance en faisant des calculs en parallèles, […]

    Pas toujours, bien souvent avoir plus de threads que de CPU n'apporte pas grand chose. Je te propose de regarder la littérature autour de la programmation réactive (en vf il y a ça de pas mal : http://blog.octo.com/jusquou-peut-aller-un-simple-ordinateur-de-bureau-avec-une-application-web-java-reactive/).

    […] mais ça demande d’avoir un très gros niveau technique pour y arriver, car si c’est mal fait, ce ne sera pas plus rapide ou alors ça fera boom !

    Personnellement, j'essaie toujours de bien comprendre l'organisation de mes threads. Lancer des threads via la classe Thread ne devrait AMHA presque jamais être fait par exemple.

    Une fois j’ai remarqué qu’un for sur les caractères d’une chaine avec plein de if allait 11 fois plus vite qu’une petite regex qui m’a pris des heures à écrire. Ça ma mis en rage quand j’ai découvert ça.

    Je ne comprends pas très bien ton exemple, mais est-ce qu'elle était compilée (ça sert à générer la machine à état une bonne fois pour toute ce qui prend pas mal de temps) ? Les regex ont un overead certain, mais sont meilleures quand tu commence à avoir des cas tordus.

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Merci

      Posté par (page perso) . Évalué à 2.

      L'avantage d'une variable exposée à l'air libre, c'est que l'on suppose rien. Celui qui veut s'en servir sait qu'il devra la tester avant de faire quoi que ce soit.
      Je m'en sert bcp quand j'ai un object qui est désérialisé depuis l'extérieur : on est jamais sur de ce qu'il contient. A chacun de faire ses vérifications au besoin.
      Après, l'exemple en warning que tu donne valide le fait que ce n'est pas applicable tout le temps, bien sur.

      Pour ce qui est d'utiliser des Threads pour faire des calculs, je n'ai pas été assez clair : mon avis est de ne pas le faire directement, mais via une lib spécialisée.
      J'utilise bcp les Threads pour faire des sous-services : un while(true) avec un sleep (enfin quelque chose du genre) afin de pouvoir executer quelque chose très régulièrement, comme un get de db ou un scan de dossier.

      Mon exemple de regex foireux était, pour un regex instancié en static, de chercher et de remplacer des caractères par d'autres et rechercher quelques séquences pour les remplacer (genre supprimer deux espaces par un seul). J'ai galéré pour y arriver a en faire un regex, lent. Mais un for sur chaque caractère l'a éclaté en terme vitesse d'execution et de lisiblité de code. Autre exemple de code ou j'ai dit non a un regex.

    • [^] # Re: Merci

      Posté par . Évalué à 3.

      Au contraire on conseil de faire des recopies de sécurité dans les setter, mais le mieux c'est tout simplement d'éviter autant que possible les setters

      J'abonde en ce sens, trop souvent je tombe sur du code avec un constructeur vide, créant un objet dans un état incohérent et dont c'est au code derrière de s'assurer que l'objet est bon.

      Un objet n'est pas une collection de valeurs sans aucune logique entre elle, c'est une entité qui doit être cohérente.

      De même j'ai tendance à privilégier les membre finaux (final).

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # Les tests

    Posté par . Évalué à 9.

    Je n’écris pas de tests unitaires. Je comprends le principe, mais je n’y adhère pas. J’ai 0 tests,

    Prioriser le static, le plus possible. Si quelque chose est polyvalent pour tout le code, et n’a pas besoin d’être libéré/détruit alors il sera static.

    Eviter les get/set de vos variables privés (sauf dans le cas ou vous avez besoin de faire un check en entrée ou une transformation en sortie) et remplacez les get/set par un accès direct à la variable.

    Design pattern : c’est indispensable d’en connaître quelqu’uns ou au moins de connaître quelques principes.

    Avancer pas à pas sur de bonnes bases mais abstraire ce qu’il faut

    C’est notamment ça le travail « d’architecte logiciel » que je parlais plus tôt.

    Et un jour tu découvriras le TDD, tu feras en sorte d'écrire du code testable depuis le début, tu deviendras test infected et les notions d'emergent design tu embrasseras et le surdesign tu éviteras … naturellement

    Petit florilège de liens:
    Le singleton c'est le mal:
    http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons
    Les methodes static sont un antipattern:
    http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
    du bon usage du privé avec les tests:
    http://programmers.stackexchange.com/questions/100959/how-do-you-unit-test-private-methods

    Tu découvriras d'abord Powermock et tu comprendras que plus on dépend de framework plus on se rajoute de la dette technique.
    Et tu concevras ton code pour éviter ces pièges et tu atteindras le level "Classic TDDist" en utilisant les bons types de doublures dans ton code et en n'utilisant le petit frère Mockito qu'à bon escient:
    http://martinfowler.com/articles/mocksArentStubs.html
    http://coding-is-like-cooking.info/2013/04/the-london-school-of-test-driven-development/

    Puis tu accéderas au nirvana en t'imprégnant de l'emergent design:
    http://www.ibm.com/developerworks/library/j-eaed2/
    http://www.aniche.com.br/wp-content/uploads/2013/04/asq-tdd.pdf

    Puis dans le DDD (http://www.infoq.com/articles/ddd-in-practice) tu flotteras et l'anemic domain model (inhérent à cretain frameworks) tu exécreras (http://www.martinfowler.com/bliki/AnemicDomainModel.html)

    Bon cheminement
    Et pour conclure ton billet était intéressant

    • [^] # Re: Les tests

      Posté par (page perso) . Évalué à 0.

      Merci pour ton compliment.

      Ce que tu soulève est interessant. Je n'ai pas le niveau pour comprendre l'implication que les points que tu soulève ont dans mon code.
      C'est surement mal. Mais je m'en passe. Aujourd'hui, je refactore sans problème, j'évolue facilement. Quand je doit casser du code, c'est parce qu'il est mal écrit ou mal pensé. Je doute que des TDD peuvent m'éviter d'écrire du caca. En tout cas le TDD, ça m'embrouille plus qu'autre chose.

      N'oublie pas que je ne suis pas pro, ni même payé pour écrire du code. Et je suis seul a mètre la main à la tache sur mon projet. Change ces paramètres, et tu aura de fait totalement raison, je pense.

      Le singleton et le static m'ont permis de simplifier et d'alléger grandement mon implémentation et l'approche de la structure de mon application. C'est surement pas bien, mais pour le moment, et surtout depuis que je fait comme ça, ça n'a que des avantages à mes yeux.

      • [^] # Re: Les tests

        Posté par (page perso) . Évalué à 5. Dernière modification le 23/03/16 à 22:11.

        Je doute que des TDD peuvent m'éviter d'écrire du caca. En tout cas le TDD, ça m'embrouille plus qu'autre chose.

        En fait, "TDD" est mal nommé. Quand j'écris en TDD, c'est pas tant les tests qui m'intéressent mais la description comportementale attendue de mon code.
        Dans la même logique, lorsque je veux comprendre le code d'un collègue qui bosse en TDD, je ne vais pas voir son code, mais tout d'abord ses tests, ça en dit beaucoup plus sur ce qu'on doit attendre du code.

        N'oublie pas que je ne suis pas pro, ni même payé pour écrire du code. Et je suis seul a mètre la main à la tache sur mon projet.

        On ne fait pas du TDD parce qu'on est pro ou juste par plaisir de perdre du temps à pondre des lignes de code, mais parce que ça confère des avantages indéniables à court, moyen et long terme. Ces avantages ne s'arrêtent pas (comme le nuage de Tchernobyl) à la frontière qui sépare les pros des amateurs.

  • # Stalin programming

    Posté par (page perso) . Évalué à 7. Dernière modification le 23/03/16 à 23:34.

    En complément des conseils de ce nourjal plein de bon sens, je recommande de coder et d'architecturer comme un vieux dictateur, cad de se demander pour chaque bout de code et chaque élément du SI:

    1. est-ce que mon système se maintiendra quoiqu'il arrive, quelles que soient ses erreurs et ses contradictions?
    2. est-ce que je pourrais à tout moment savoir ce qui se passe, ce qui s'est passé et trouver les coupables?
    3. est-ce que si un module ou une personne devient inutile ou dangereux je peux le supprimer ou l'exiler?

    Se poser et trouver des réponses à ces trois questions permets de survivre à la plupart des anomalies techniques (bugs, surcharge, perte de connexions, coupure de courant…) et humaines (utilisateurs idiots ou malveillants, démissions…).

    http://devnewton.bci.im

    • [^] # Re: Stalin programming

      Posté par (page perso) . Évalué à -1.

      Oui, je suis assez d'accord. Surtout sur le coté sans pitié de l'approche.
      Ecrire du code, c'est se construire un monde, dans lequel on se rapproche du contrôle absolu de tout ce qui s'y passe.

  • # Barbecue

    Posté par . Évalué à 2.

    Le bricolage tout moche pour que « ça marche » est à bannir.

    La méthode agile, qui consiste simplement à à tout prix trouver le code qui fait un truc bien précis (et sera maintenable) est pas forcément moche…

    • [^] # Re: Barbecue

      Posté par (page perso) . Évalué à 0.

      Bien sur !
      Je pensais plutôt à un vomis de code dans main() avec des variables sans vrais noms que l'on écrit pour vérifier une théorie ou tester un truc.

      • [^] # Re: Barbecue

        Posté par . Évalué à 2.

        Tu évolues dans quel milieu bas de gamme pour avoir à eu tâter du code écrit aussi cradement ?

        • [^] # Re: Barbecue

          Posté par (page perso) . Évalué à 3.

          L'audiovisuel.
          Dans lequel on écrit du code quand on a pas le choix, quand on y est obligé, donc on va vite car on a pas le temps et les moyens de le faire.
          Un monde où l'on préfère payer quelqu'un se taper une tache fastidieuse à la main plutôt que de faire faire écrire un bout de code qui fera ça plus vite.

          En 10 ans j'ai quasiment jamais été confronté à un travail de dev. propre. Ce que je fait (un MAM libre et gratuit) c'est un OVNI dans nos métiers.

  • # Show me the code

    Posté par . Évalué à 10.

    On peut voir l'article comme intéressant ou pas selon comment on le prend. Il contient plein de choses avec lesquelles on ne peut pas être en désaccord (ie. "il est important de bien nommer et moi je nomme bien").

    Maintenant je passe mon temps à rencontrer des gens avec le même discours qui pondent des horreurs sans nom. Tout le monde est persuadé de bien faire. Tu utilises d'ailleurs l'expression "un bon développeur". Les développeurs c'est comme les conducteurs, ça se divise entre les bons et les mauvais. Les bons développeurs étant ceux qui font comme moi (enfin comme le moi de maintenant pas le moi d'il y a quelques mois).

    Ce biais est encore renforcé pour les gens qui reçoivent peu de feedback, comme les auto-didactes, et qui s'enferment petit à petit dans leur façon de faire (idée développées par Kevlin Henney dans Individuals and Interactions over Processes and Tools.

    Je serais donc très intéressé de voir à quoi correspond une base de code écrite par quelqu'un comme toi: amateur, visiblement passionné, qui dit pas mal de choses censées, mais souvent suffisamment vague pour qu'on ne puisse être en désaccord de toute façon, et qui en même temps laissent quelques indices sur le fait que tu pourrais t'être bâti ton propre monde (les tests me servent à rien, j'ai eu un problème de perf avec les regexp que je n'explique pas mais j'en généralise que "les regex c'est mal", "fabriquer ses propres générics" etc.).

    Si j'ai un peu de temps j'irai jeter un œil à ton dépôt. Je n'ai aucune idée d’à quoi m'attendre entre le meilleur ou le pire.

    • [^] # Re: Show me the code

      Posté par . Évalué à 4.

      Sur les regex, je peux pas dire que t'aies tord (ca sent le sapin son argument), mais il a pas tord sur le cote immaintenable et tres facile a peter.
      Sans parler des conos qui sont convaincus de pouvoir parser du html avec une regex (j'en connais).

      Linuxfr, le portail francais du logiciel libre et du neo nazisme.

      • [^] # Re: Show me the code

        Posté par . Évalué à 10.

        Comme la plupart des outils, il y a des cas ou c'est adapté et d'autres non.

        En l'occurrence les regex peuvent effectivement être extrêmement piegieuses d'un point de vue performance. J'ai déjà vu des regex en ** mettre plusieurs minutes à répondre en matchant une url. La réponse est de comprendre comment marchent les regex NFA vs DFA, quand comment fonctionne le backtracking pour décider de quand et comment les d'utiliser. Dire simplement c'est pas bien est juste idiot. Tout est potentiellement trop lent et piégeur pour quelque chose.

        Mais ça c'était juste un point précis qui met la puce à l'oreille. J'ai été rapidement voir le code (Log2 et MyADM) et s'est malheureusement très très très moyen.

        • le code semble peut-être très lisible et bien nommé à son auteur. Il y bien pire mais c'est pas la joie non plus. Les noms sont longs mais c'est pas pour ça qu'ils sont bons
        • Le design ressemble aux débutants java du début des années 2000. Du static partout fortement couplé, du synchronized partout etc.
        • La gestion d'erreur est pourrie du type j'attrape une exception dans un catch qui log et je continue comme si de rien était alors que la db vient de m'envoyer chier.
        • etc.

        Bref un discours entoushiaste et plaisant n'est pas forcément suivi de faits. C'est exactement pour ça que demander aux gens de parler de leurs projets en interview ne marche pas. Tu peux être impressionné pendant 30mn avec ce genre de discours avant de découvrir qu'en fait le mec optimise du trading haute fréquence pour avoir un jitter max < ms avec des printf et un timer qui a une résolution inférieur à l'objectif… La tu backtrack sur tout ce qu'il a dit et tout s'ecroule.

        • [^] # Re: Show me the code

          Posté par (page perso) . Évalué à 4.

          Un code très très très moyen, mais un code qui marche H24 et qui évolue depuis 3 ans sur 5 nodes maintenant ! Ecrit par un mec dont c'est pas le métier, qui n'est pas payé pour cela, qui fait ça sur du temps libre, qui ne prétend pas être un pro ni même un formateur.

          Pour moi un code très très moyen, c'est un code qui juste marche et que l'on ose plus toucher car ça ferai boom. Je pense pas que ce soit mon cas ici.

          Log2 est ancien et abandonné. Ça m'a bien aidé, mais je n'en suis plus satisfait. J'ai pas mal progressé depuis.

          De même qu'il y a un vrai gap de progression entre différentes parties de MyDMAM.

          Le static partout (plutôt souvent que partout) est un choix qui c'est fait progressivement. Ça m'a permis de simplifier beaucoup la structure. Et de me permettre des phases de dev plus simples et plus légères.

          Le synchonized partout (pas partout non plus) me permet de me protéger de désagréments potentiels. Malgré ça je n'ai pas de problèmes de lock, de perfs ou même de mémoire.

          Les pb de bases de données sont parfois catchés dans les logs… quand cela n'a pas de vrai impact dans l'activité, du genre "si il n'y est pas arrivé, ce n'est pas grave".
          Les accès Bdd ne sont pas forcément une priorité ! Et de fait, en prod j'ai déjà perdu le réseau pendant quelques heures, mon code à gueuler, mais a survécu et a repris le travail quand le réseau est revenu. J'ai vu trop d'applis partir en vrille lors d'une perte temporaire de la bdd.

          Tu as très certainement raison et moi tord, mais mon code marche très bien et évolue beaucoup. Pour moi, c'est le deal.

          • [^] # Re: Show me the code

            Posté par . Évalué à 9. Dernière modification le 24/03/16 à 14:40.

            Ne prends pas ombrage de ses remarques. Toi même tu demandes un feedback. Je souscris à pas mal de ses remarques sauf une:
            celle qui semble insinuer qu'un autodidacte ne saurait fournir du code de qualité. Et je ne vais pas m'embarquer dans ce débat.

            Tu appelle à un retour, tu sembles attaché à la qualité de la documentation. Je te cite:

            Pas de tutoriel ? Pas d’exemple ? Next !

            Bien nommer
            Si vous ne savez pas noter une variable, une classe, une fonction, c’est qu’elle n’a pas a exister de la façon d’où vous la pensez.

            Pourtant lorsqu'on t'objecte certains point tu sembles mal le prendre. Je suis d'accord que la forme importe mais il me semble que ton contradicteur est resté courtois.

            Je me suis aussi un peu penché sur ton code et je m'exprime peut-être à tort, je ne connais pas le framework Play donc je peux raconter des bêtises.
            Tu appelles aux contributions et pourtant tu ne documentes pas ton architecture, tes conventions de codage… Tu ne laisses rien qui puisse permettre de l'appréhender. Qu'à cela ne tienne, en lisant ton journal, on pourrait se dire que l'on a affaire à un adepte du "Clean code" (Je t'invite vraiment à lire http://www.amazon.fr/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) et que la lumière se fera au travers lui. Comme évoqué par quelqu'un plus haut, un des avantages à disposer de tests est que ceux-ci représentent un forme de spécifications et aident à mieux comprendre le code de production (le Sytem under Test). Tu n'en disposes pas. Soit …

            Mon habitude, personnellement dans ce genre de cas, pour comprendre de quoi ça parle, c'est de découvrir le domaine: les classes métiers.
            Si j'en juge par la description de Play! On a bien affaire un framework MVC (https://www.playframework.com/documentation/1.4.x/main#mvc). A priori, tu l'as adopté entre autre parce qu'il est bien documenté.
            Lorsque je me penche sur tes modèles voici ce que j'y découvre:
            https://github.com/hdsdi3g/MyDMAM/tree/master/app/models
            Des profils utilisateur, des ACLs.
            Que fait ton appli ? Je me renseigne donc sur ce qu'est un DMAM …
            Je m'attendais à trouver des entités "Média", "Utilisateurs" et bien d'autres … et il faut fouiller dans ce fourre-tout que tu as nommé "hd3gtv" pour trouver un semblant de classe métier comme ce qui aurait pu s'appeler "MetaData": https://github.com/hdsdi3g/MyDMAM/blob/master/app/hd3gtv/mydmam/metadata/MetadataCenter.java

            Si on se penche sur un de tes rares modèles https://github.com/hdsdi3g/MyDMAM/blob/master/app/models/UserProfile.java
            J'ai l'impression qu'on se trouve devant un problème d'affectation des responsabilités.
            Par exemple, que vient faire une méthode comme celle-ci là au milieu ?

            private static String cleanFileName(String value)
            A t'elle un sens métier ?
            Si elle n'est utile que pour d'autre méthodes de la classe pourquoi n'est elle pas privée ?
            Si tu la rends publique, c'est donc que tu considères que c'est la responsabilité d'autres classes de formater correctement l'email d'un profil utilisateur ?
            Sinon pourquoi ne pas l'isoler dans une classe utilitaire si tu considère qu'elle pourrait être réutilisable ?

            Je n'évoquerai pas ces contrôleurs à qui (me semble t'il) tu confies la tâche de persister certaines de tes données.

            Je ne te parlerai même pas d'injection des dépendances dont je ne trouve pas trace et qui hormis la testabilité t'apporte une vraie liberté pour "refactorer" ton code, comme tu l'évoques si bien en te permettant de changer d'implémentation de manière très souple.

            Encore une fois ne prends pas ombrage, mais cette profusion de méthodes statiques sont le signe d'une conception très procédurale (qu'un autre l'a appelé de l'an 2000).
            J'ai l'impression que tu n'as pas saisi certains des concepts fondamentaux du paradigme de programmation orientée objet.
            Je t'encourage à approfondir ces concepts et le plus important d'entre eux l'encapsulation qui veut que les données et les traitement et les données sont regroupées et qui confère un avantage sur le procédural. Avant de partir sur les design patterns du Gof comme tu l'évoquais, tu devrais peut-être faire un petit détour par les patterns de responsabilité, les fameux GRASP: https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)

            Et pour finir je te reparlerai de ce "modèle de domaine anémique" qu'on rencontre parfois et que j'ai déjà évoqué plus haut.
            En général, on le reconnait à des entités qui ne disposent d'aucune logique métier et ne sont que des passe plat à base getter et setter.
            Le tien, je ne sais pas comment le qualifier à part que j'ai l'impression qu'il est inexistant ou dilué (encore une fois je peux me tromper). Mais tu n'es pas obligé de me croire.
            C'est pourquoi je t'invite une nouvelle fois à te pencher sur la documentation du framework que tu as adopté.
            Il y est fait une mention explicite au lien sur Martin Fowler que je t'ai pointé plus haut:
            https://www.playframework.com/documentation/1.2/model

            A common Java anti-pattern is to keep the model as a set of simple Java Beans and put the application logic back into a “service” layer which operates on the model objects.

            Martin fowler again has named this anti-pattern Anemic object model

            Si j'ai pris la peine de rédiger cette longue bafouille ce n'est pas pour te faire la leçon mais au contraire pour t'encourager à poursuivre ton cheminement dans une direction peut-être trop consensuelle pour toi mais qui permettrait vraiment d'ouvrir ton code aux contributions autrement que par la licence. Tu as déjà fait une belle partie du chemin seul, ne t'arrête pas au milieu du gué.

            • [^] # Re: Show me the code

              Posté par (page perso) . Évalué à 1.

              Merci pour ce retour détaillé.

              Pour les détails de l'architecture et tous les détails techniques, ça viendra. Ce n'est pas ma priorité, car ce n'est pas un outil pour dev, mais pour un "utilisateur final", et c'est un outil très spécialisé qui ne s'utilise pas sur un coup de tête.

              Pour la partie ACLs/Utilisateurs, le code que tu montre est un code écrit juste pour que ça marche. C'est un vieux code qui sera refait totalement. Je n'utiliserais plus le moteur de Play pour accéder aux données, et donc plus besoin du Model de Play.

              J'abandonnerai aussi progressivement les vues en Groovy pour du 100% React.

              Play n'est pas le centre technique. Et il va l'être de moins en moins. C'est juste la partie interface web. Il y une partie service système (Probe) et un CLI. Il y a aussi maintenant un serveur FTP.
              Si tu cherche du code métier, tu va en avoir dans transcode, dans metadata. Le centre technique, tu le trouvera plutôt dans manager.

              Quand a MetadataCenter, c'est un point de départ pour instancier les moteurs d'analyse et de génération de bas débits. Le nom n'est peut-être pas le meilleur, j'avoue, mais cette classe à beaucoup changée au cours du temps.

              Et n'oublie pas qu'il s'agit d'une alpha et il manque encore pas mal de chose, notamment la partie action utilisateur.

              Les controleurs Play sont un peu anciens. C'est possible que j'y ai laissé par simplicité de la persistance. Pour les controleurs AsyncJS (mon API qui me permet d'abstraire coté JS et coté Play des échanges de Json entre les deux qui sont dé/sérialisés automatiquement via Google Gson), c'est autement probable vue que le Controleur n'a plus grand chose à faire et me sert juste à passer les plats.

              L' "injection des dépendances", j'en ai déjà entendu parlé. J'ai un système de module (une extension de celui de Play) et de surcharge d'une API qui détecte via le classpath des éléments externes, mais je pense pas que tu parle de ça. Et je me sens déjà très libre quand je refactorise.

              Encore une fois ne prends pas ombrage, mais cette profusion de méthodes statiques sont le signe d'une conception très procédurale (qu'un autre l'a appelé de l'an 2000). […]

              Pense tu avoir fait suffisamment le tour de mon code pour penser ça ? J'ai une masse de classes, d'API, et d'interfaces pas du tout statiques ! Je souhaite plus que tout éviter le coté script de coin de table. Et j'ai commencer le Java en apprenant le 0 statique. Puis j'ai évolué avec l'expérience. Et plus généralement, ou est le problème, je veux dire, fondamentalement ? Qu'est ce que je risque ? De me perdre dans mon code ? De me retrouver bloqué ? Au final, je m'en suis toujours sorti, avec assez peu de bugs. A chaque fois que j'ai du dégager du code, c'était pour remplacer une approche trop limitée ou trop simpliste pour quelque chose de plus élégant et évolutif. Par exemple, pour changer mon système de log (plus de 1000 messages), ça m'a pris au total une bonne journée. Le plus long à été de repenser certain messages écrits un peu vite (et ultra verbeux).

              J'ai l'impression que tu n'as pas saisi certains des concepts fondamentaux du paradigme de programmation orientée objet.

              Peut-être, oui ! Mais j'évolue en permanence. React, par exemple, m'a beaucoup appris.

              […] Le tien, je ne sais pas comment le qualifier à part que j'ai l'impression qu'il est inexistant ou dilué (encore une fois je peux me tromper). […]

              Cette partie de code va surtout dégager !
              J'ai un peu mal à te suivre sur ce qui est du Java anti-pattern. Je comprends que j'ai l'air de faire quelque chose de mal, mais je ne vois pas trop de quelle façon !

              […] qui permettrait vraiment d'ouvrir ton code aux contributions autrement que par la licence. […]

              Pour le moment, mon code est publique, ainsi que et mon activité lié (Issues, site, historique Git). Je n'ai pas encore de politique de projets à plusieurs, pour différences raisons, mais surtout par ce qu'il me manque encore des socles techniques indispensables pour que le tout soit cohérent (comme les actions utilisateurs). Mon dev est pour le moment dirigé vers des fonctions métiers pointues comme l'analyse de médias et leurs transformation automatique.
              Quand tout ceci aura décanté, et que ma base sera plus propre qu'elle n'est, notamment au niveau de la dete technique, je m'attaquerai à de la vrai doc, et ferai le nécessaire pour inciter à mettre dans les mains dans le moteur. Et là j'écrirai un README à la racine du Git !

              • [^] # Re: Show me the code

                Posté par . Évalué à 3.

                Le retour de ckyl est très intéressant et constructif. Il te donne une multitude d'exemples concrets.

                Tu as une réaction assez normale (je me défend aussi quand je présente un projet et qu'il se fait démonter) lorsque l'on expose son travail publiquement mais je crois que tu es beaucoup sur la défensive, la justification et la minimisation des remarques qui ont été faites.

                Pour le moment, mon code est publique, ainsi que et mon activité lié (Issues, site, historique Git). Je n'ai pas encore de politique de projets à plusieurs, pour différences raisons, mais surtout par ce qu'il me manque encore des socles techniques indispensables pour que le tout soit cohérent (comme les actions utilisateurs).

                Je ne pense pas que cela soit un problème de socle technique. Un nouveau venu ne connaîtra jamais le code aussi bien que toi et sans politique de test il sera incapable de s'assurer qu'une modification ne cassera pas la compatibilité.
                Pire, imagine qu'il t'arrive un accident et qu'une personne doive reprendre ton code en urgence. Combien de temps pour que le nouveau dev soit à l'aise?

                Comme t'es parti dans l'aventure de l'ouverture pourquoi ne pas pousser la logique jusqu'au bout?
                Beaucoup des réactions remontent que tu devrais t'entourer d'une équipe. Le nez dans le guidon ça va un moment. Alors pourquoi ne pas redémarrer le projet from scratch avec une bonne base et une équipe dès le début?

              • [^] # Re: Show me the code

                Posté par . Évalué à 4.

                Pour les détails de l'architecture et tous les détails techniques, ça viendra. Ce n'est pas ma priorité,

                Ceci entre en contradiction avec cela:

                Mais pas forcément quand vous devez construire une grosse application. Vous devez avoir un coup d’avance sur ce que vous allez peut-être avoir besoin, et le prévoir en amont.

                L'architecture ça se résume à ca: Réfléchir … un peu… avant de te lancer. Les mauvais choix d'aujourd'hui sont le temps perdu de demain. La fameuse dette technique que tu évoques.

                Je vais à nouveau essayer de t'illustrer en quoi il est utile d'apprendre contrairement à que tu as écrit en gros:

                Pas de temps à perdre à apprendre

                Prenons déjà le framework Play.
                Tu écris:

                Pour la partie ACLs/Utilisateurs, le code que tu montre est un code écrit juste pour que ça marche. C'est un vieux code qui sera refait totalement. Je n'utiliserais plus le moteur de Play pour accéder aux données, et donc plus besoin du Model de Play.

                Play était-il le bon choix pour ton besoin ? Il semble que non. A présent que devras tu casser pour réécrire les fonctionnalités équivalentes ?
                Déjà certains de tes contrôleurs embarquent de la logique de persistance. Play par simplicité encourage à embarquer toute ta logique de persistance en même temps que ta logique métier (le comme ici :

                    public static CrudOrmEngine<UserProfile> getORMEngine(String key) throws Exception {
                        UserProfile userprofile = new UserProfile();
                        CrudOrmEngine<UserProfile> engine = new CrudOrmEngine<UserProfile>(userprofile);
                        if (engine.exists(key)) {
                            userprofile = engine.read(key);
                        } else {
                            userprofile = engine.create();
                            userprofile.key = key;
                            engine.saveInternalElement();
                        }
                        return engine;
                    }

                N'eut t'il pas été préférable de les séparer ces 2 aspects (par exemple en utilisant des DAOs) et de les isoler dans 2 couches sans tout disséminer y compris dans les contrôleurs. Car à présent le passage vers un autre framework va t'obliger a tout réécrire ou à créer une couche d'abstraction pour rediriger tous tes appels aux méthodes CRUD de Play. Comment cela se passera t'il si finalement Cassandra ne fait plus l'affaire et que tu veuilles partir sur du Mongo ? Comment t'assureras tu que tu fonctionnes correctement alors que tu n'as aucun test ?
                Imagine que le départ tu aies conçu ton architecture avec juste des classes métiers (celles qui traiteraient de Médias, de répertoires et de métadata pas d'ACLs) de simples POJO et que tu aies séparé la persistence.
                Le travail ne serait-il pas plus simple. Au départ tu te concentres que sur ça et comme tu ne peux pas tester ton appli dans son ensemble que tu n'as pas de GUI ou de CLI, tu écris quelques tests pour valider tes "itérations" comme tu les appelles. Bienvenu dans le monde du TDD.
                De plus de ce que je vois de Play, il s'agit d'un framework basé sur l'héritage ("extends Model"). Il t'oblige à surcharger ou à utiliser ses méthodes par héritage. Tu es donc fortement couplé à lui et il me parait intrusif.
                Pour des problématiques techniques transverses tel que la persistence (ou même le logging que tu réécrit from scratch) il existe la programmation par aspect qui vient en complément et un framework comme Spring MVC me parait plus adapté.

                Toujours pas convaincu du fait que l'architecture (qui inclue la testabilité) et la conception se concoivent au fil de l'eau et pas après ?

                Prenons cette fois-ci cette classe MetadataCenter que tu m'a explicitée.

                Quand a MetadataCenter, c'est un point de départ pour instancier les moteurs d'analyse et de génération de bas débits. Le nom n'est peut-être pas le meilleur, j'avoue, mais cette classe à beaucoup changée au cours du temps.

                Lorsque je vois des switchs partout ou des bouts de code de ce genre:
                ```java
                try {
                addProvider(new ImageMagickAnalyser());

                        addProvider(new FFprobeAnalyser());
                        addProvider(new FFmpegInterlacingDetection());
                        addProvider(new FFmpegSnapshot());
                        addProvider(new FFmpegAlbumartwork());
                
                        addProvider(new ImageMagickThumbnailer(FullDisplay.class, PreviewType.full_size_thumbnail, FullDisplay.profile_name));
                        addProvider(new ImageMagickThumbnailer(Cartridge.class, PreviewType.cartridge_thumbnail, Cartridge.profile_name));
                        addProvider(new ImageMagickThumbnailer(Icon.class, PreviewType.icon_thumbnail, Icon.profile_name));
                        addProvider(new ImageMagickFFmpegThumbnailer(FullDisplay.class, PreviewType.full_size_thumbnail, FullDisplay.profile_name));
                        addProvider(new ImageMagickFFmpegThumbnailer(Cartridge.class, PreviewType.cartridge_thumbnail, Cartridge.profile_name));
                        addProvider(new ImageMagickFFmpegThumbnailer(Icon.class, PreviewType.icon_thumbnail, Icon.profile_name));
                
                        addProvider(new FFmpegLowresRenderer(JobContextFFmpegLowresRendererLQ.class, PreviewType.video_lq_pvw, false));
                        addProvider(new FFmpegLowresRenderer(JobContextFFmpegLowresRendererSD.class, PreviewType.video_sd_pvw, false));
                        addProvider(new FFmpegLowresRenderer(JobContextFFmpegLowresRendererHD.class, PreviewType.video_hd_pvw, false));
                        addProvider(new FFmpegLowresRenderer(JobContextFFmpegLowresRendererAudio.class, PreviewType.audio_pvw, true));
                    } catch (Exception e) {
                        Loggers.Metadata.error("Can't instanciate Providers", e);
                    }
                }
                
                Ca m'évoque ce qu'on  appelle un "code smell" et j'ai envie de sortir tout ça pour en faire quelque chose de plus souple qui évitera de modifier mon code à chaque fois que je veux rajouter un provider  et faire en sorte que cette classe ne "change" pas au cours du temps comme ici:
                https://github.com/hdsdi3g/MyDMAM/commit/bb024c2f1aa8f7f994be38ea740c7bf7feae3534#diff-dbab17a2baa241511ef42fd413ac083c
                J'imagine que tout ces providers sont appellés par un comportement quelquepart, peut-être déjà regroupés dans un interface ou alors peut-être que tu es obligé de modifier ton code à plein d'endroits.
                Je soupçonne que ceci se prêterait bien à une Factory: http://www.jmdoudoux.fr/java/dej/chap-design-patterns.htm
                
                Revoici encore l'intérêt principal du paradigme objet. En réunissant code et données au même endroit, en usant du polymorphisme, tu n'as besoin de le changer qu'à un endroit.
                
                Apprendre la technique est très bien mais la théorie aussi a du bon.
                
            • [^] # Re: Show me the code

              Posté par . Évalué à 3.

              celle qui semble insinuer qu'un autodidacte ne saurait fournir du code de qualité. Et je ne vais pas m'embarquer dans ce débat.

              Non. J'ai dit que autodidacte et travailler seul sont un sérieux handicap à la progression. Pas que c'est impossible.

              Tous les deux pour la même raison. Il n'y a personne qui te pousse de savoir extérieur, qui confronte ses opinions aux tiennes, qui te force à t’expliquer, articuler tes pensées, à faire des compromis et donc faire la même chose de différentes façons etc.

              Travailler avec des gens, et encore plus avec des gens extrêmement compétents et d'opinions diverses, est un accélérateur incroyable de connaissance et maturité.

              Après tu trouveras toujours des gens excellent venant de tout horizon.

      • [^] # Re: Show me the code

        Posté par (page perso) . Évalué à -1.

        Pour les regex : je vais être clair : ça me saoule, c'est vite compliqué et illisible. Je sais que c'est sacré et que cela ne ce fait pas d'en dire du mal, mais écrire une déclaration de magie noire ne me motive pas plus que ça.
        Je voulais juste dire que l'on est pas forcément obligé de s'infliger cette peine quand on a de petits besoins simples.

        • [^] # Re: Show me the code

          Posté par . Évalué à 4.

          Je sais que c'est sacré et que cela ne ce fait pas d'en dire du mal

          Absolument pas. Dire des choses dogmatiques et idiotes est plus gênant par contre.

          Les regexps sont parfaitement adaptées d'un point de vue fonctionnel et non-fonctionnel à une grande classe de problèmes. Ne pas les utiliser dans ce cas est parfaitement idiot.

          Je suis parfaitement capable de me coder n'importe quelle machine a état / lexer / parser pour analyser du texte lorsque c'est nécessaire. Maintenant est ce qu'une regexp est plus adaptée lorsqu'elle fait le même job ? Oui. Je suis juste en train d'écrire une spécialisation de la conversion d'un langage régulier vers un DFA/NFA.

          Avec l'inverse ils existent aussi beaucoup de situations où les regexp sont inadaptées, non souhaitables, overkill, piégeuses etc.

          • [^] # Re: Show me the code

            Posté par (page perso) . Évalué à 1.

            Je suis certain de manquer d'expérience pour juger de l'employabilité des regex, notamment par mes besoins limités.
            J'ai toujours évité de me trouver dans une situation de parsing de texte ou il faut en effet sortir les grands moyens.

        • [^] # Re: Show me the code

          Posté par (page perso) . Évalué à 3.

          Je sais que c'est sacré et que cela ne ce fait pas d'en dire du mal

          C'est curieux comme façon de voir les choses : c'est comme si tu nous disais que c'est sacré et que cela ne se fait pas de dire du mal des tournevis.

          Tout cela reste des outils, ça ne sert à rien de passionner le débat.

          Si des gens aiment viscéralement les expressions régulières au point d'en mettre même là où elles utilisées à mauvais escient (pour valider une adresse email par exemple /troll), fuis ces gens !

          • [^] # Re: Show me the code

            Posté par (page perso) . Évalué à 1.

            Je crois que mes besoins de regex se limitent à ça !

            • [^] # Re: Show me the code

              Posté par . Évalué à 1.

              Alors t'as pas le cul sorti des ronces ;) Valider une adresse email est bien plus compliqué que juste vérifier la présence d'un @ :)

              si tu aimes l'à peu près (cette re ne gère pas tous les cas) :

              private static final Pattern rfc2822 = Pattern.compile(
                      "^[a-z0-9!#`{mathjax} %&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?`"
              );
              
              if (!rfc2822.matcher(email).matches()) {
                  throw new Exception("Invalid address");
              }

              ou sinon plutôt que réinventer la roue utiliser ce qui existe déjà :)

              http://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/routines/EmailValidator.html

              Par contre c'est utiles dans pas mal de cas et savoir s'en servir peut simplifier beaucoup de traitements (comme capturer quelques éléments de certaines chaines, vérifier que les données d'entrées respectent certaines règles, repérer des éléments dans un texte/fichier… )

              Donc, pour résumer les regex c'est pas pour valider les emails :)

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

              • [^] # Re: Show me the code

                Posté par . Évalué à 3. Dernière modification le 25/03/16 à 13:25.

                Donc, pour résumer les regex c'est pas pour valider les emails :)

                https://github.com/apache/commons-validator/blob/trunk/src/main/java/org/apache/commons/validator/routines/EmailValidator.java#L40

                Bin heu en fait si quand même… C'est pas par ce que y'a un appel de méthode qui masque le caca que le caca existe pas :)

                En fait les vrais questions sont:

                1. Est-ce que quelqu'un a déjà résolu ce problème qui n'est pas mon cœur de métier de matière satisfaisante pour mon besoin ? Si oui je prends et je passe à autre chose. (Attention à ne pas croire que tout ce qui est dispo sur le web fait l'affaire et le fait correctement, syndrome dit de stackoverflow ou de npm)
                2. Sinon, je vais lire la RFC pour trouver la grammaire du truc et possiblement les validations à ajouter au dessus de la grammaire. Je lis aussi la partie où on m'explique la façon la plus facile de valider la grammaire (beaucoup de RFC contiennent les regex correspondante à la grammaire BNF) et dans ce cas j'applique bêtement. Autrement je buche la grammaire pour voir comment on implémente au mieux la grammaire. Selon les cas des regexp, un bête parser basé sur une machine à état fait a la mano, ou un flex/bison/antlr autre seront plus adaptés.

                En fait ce qui est compliqué dans la vie c'est que y'a rarement une réponse binaire qui découle d'un raisonnement simple et correct ! Ça semble causer beaucoup de tourment aux informaticiens :)

                • [^] # Re: Show me the code

                  Posté par . Évalué à 4.

                  J'ai un petit peu simplifié, si tu regardes le code, il décompose d'abord la chaine en deux parties avant de les valider séparément. (en gros un capture de tout jusqu'au dernier @, puis du dernier @ jusqu'à la fin).

                  Il ne fait pas une regex pour valider la chaine, mais 3, la regex seule ne fait pas tout, et quand bien même la chaine valide tout ce que tu as c'est l'assurance que la chaine est valide, pas que l'adresse est la bonne.

                  Le plus simple, ça reste de faire un if( chaine.indexof("@") > 0 ), et d'envoyer un mail de vérification, comme pour toutes les inscriptions; certes ça laissera passer quelques adresses non valide, mais ça évite de tirer une dépendance ;), et le mail est validé par le gars qui s'inscrit ;)

                  Il ne faut pas décorner les boeufs avant d'avoir semé le vent

              • [^] # Re: Show me the code

                Posté par . Évalué à 3.

                C'est ce que fait hibernate pour la bean validation : https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/EmailValidator.java

                Email::Valid en fait un usage encore plus violent : http://cpansearch.perl.org/src/RJBS/Email-Valid-1.198/lib/Email/Valid.pm (ce dernier va assez loin puisqu'on lui demander de vérifier les enregistrements DNS du domaine).

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Show me the code

      Posté par (page perso) . Évalué à 1.

      Attention à ne pas me prêter des attentions qui ne sont pas les miennes !

      Jamais je dit que je détiens et suit des méthodes de travail idéales, mais juste ce que j'ai le plus constaté, à force. C'est plus un retour d'expérience qu'un cours de code, et je sais très bien qu'un pro de métier saura facilement me dire que j'ai tord et pourquoi.

      Quand je parle de bien nommer, bien sûr, ça peut toujours être mieux.
      En fait je faisais allusion au fait que c'est l'un des trucs les plus compliqués qui soit quand on code. Et que j'ai vu trop de code ou visiblement ce travail saoulait le dev et était bâclé.

      • [^] # Re: Show me the code

        Posté par . Évalué à 8.

        En fait je faisais allusion au fait que c'est l'un des trucs les plus compliqués qui soit quand on code. Et que j'ai vu trop de code ou visiblement ce travail saoulait le dev et était bâclé.

        Pour moi un code très très moyen, c'est un code qui juste marche et que l'on ose plus toucher car ça ferai boom. Je pense pas que ce soit mon cas ici.

        Si je pouvais te conseiller de retirer un seul truc de ce que je dis, c'est que tu émet un avis sur le code d’autrui avec un œil extérieur mais juge ton propre travail.

        Que tu sois satisfait de ton travail très bien, que tu t'y retrouves très bien, que ca réponde à ton besoin aussi. Mais ça ne juge en rien que tu fais un bon boulot d'archi, d'écrire du code lisible ou autre qui est le sujet du journal. Ça prouve juste que tu te comprends toi même. Et plus on travail tout seul et plus on est auto-didacte, plus on risque s'enfermer dans "son style" qui devient une partie de sa personnalité. Parfaitement limpide pour soit mais uniquement pour soit.

        Les vrais avis viennent toujours d'autrui. Personne n'en a rien a faire que je pense avoir écrit le meilleur code du monde. Si mes deux code reviewer me disent qu'ils ne comprennent pas quelque chose, j'ai forcément tord. Ils peuvent avoir tord aussi, mais même dans ce cas j'ai tord: ils n'ont pas réussi a me comprendre ou n'ont pas confiance dans le fait qu'ils voudront maintenir ce code. S'en suivent les discussions intéressante qui permettent à chacun de progresser.

        • [^] # Re: Show me the code

          Posté par (page perso) . Évalué à 0.

          Je suis d'accord avec toi dans le sens ou je manque de retour précis sur mon travail. En en parlant ici, je fait un début de chemin, et je sais à quoi je m'expose.
          Les static, les regex, les Threads et les try sont un parti pris volontaire, fait après réflexion et amené par l'expérience. Et c'est cette expérience que je montre ici. Qu'elle soit bonne ou mauvaise.

          Je me suis permis d'émettre un avis sur le travail d'autres surtout parce que dans ces cas, il y avais vraiment un je-m'en-fout dans l'approche du travail du dev. Et ceci avait une vraie répercussion sur la suite.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.