Publicité
+ Répondre à la discussion
Page 1 sur 6 12345 ... DernièreDernière
Affichage des résultats 1 à 20 sur 112
  1. #1
    Expert Confirmé Sénior
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 711
    Points : 6 303
    Points
    6 303

    Par défaut [Débat] modèles full OO et sources de données, est-ce un mythe?

    Bonjour,

    Les bonnes pratiques nous ont poussé à séparer nos applications en différentes couches au nom de la séparation des responsabilités. La plupart d'entre nous ont identifié :

    1. La présentation (L'affichage web/swing/forms etc..)
    2. La persistence (accès BDD)


    Et entre deux la fameuse couche service qui sert de ciment entre les 2 choses. Si ces concepts de séparation sont facilement compris et acceptés, leur mise en pratique diffère fortement et c'est rien de le dire.

    De mon côté, j'ai tendance à penser cette couche de service comme une API de haut niveau destinée à l'UI, offrant des méthodes simples permettant de procurer un lot de données, insérer des enregistrements, exécuter des tâches métier sous forme de transactions.
    En contrepartie, les objets échangés entre la couche Ui et la couche Service sont plutôt simples car le plus souvent destinés à l'affichage, en fait ce sont souvent que de simples conteneurs de données avec assez peu de méthodes et de savoir-faire interne.

    Mon approche, cependant, est je le sais, fortement critiquée notamment par Martin Fowler qui considère que c'est un antipattern du point de vue OOP

    http://www.martinfowler.com/bliki/An...mainModel.html

    et que la logique devrait se situer dans des objets métier qui contiendraient ainsi les données et les méthodes pour travailler dessus conformément à la programmation orientée objet.
    Donc ce qui est prôné plutôt que mon approche non OO procédural d'un autre temps est donc de passer entre l'UI et le service des entités intelligentes incorporant toute la logique métier. Sur le fond je suis d'accord... Pourtant j'ai l'impression que dès qu'on a une source de données relationnelle derrière, ça coince.

    Pourquoi cela coincerait en fait? Et bien car dans des applications assez poussées, modéliser une simple commande de matériel en objet indépendant nécessiterait que vous ayez accès, par exemple, aux stocks, aux pays, aux conditions de livraison du client afin d'avoir tous les éléments pour implémenter une méthode aussi simple que MaCommande.AjouteProduit( Produit p).
    Alors que faites-vous? Vous chargez 250mo de données en mémoire depuis votre base SQL ou vous utilisez outrageusement le lazy loading pour que votre objet puisse se procurer ces informations à la demande?

    Je suis d'accord ça marcherait certainement sur une petite application de gestion toute bête, mais au bout d'un moment comment pourrez-vous concilier la versatilité de votre objet métier qui doit soi-disant *modéliser les interactions* et les performances?
    Et si vous devez modifier 1500 commandes pour marquer un retard de livraison, vous allez charger 1500 graphes pour appeler la méthode setLivraison()?

    En fait j'ai un peu l'impression que cette histoire de 100% objet est un mythe, un cas d'école qui n'est réalisable que dans les applications triviales. Est-ce qu'on peut vraiment concevoir ses objets métiers en faisant abstraction du système de stockage comme on semble nous vendre dans les recueils de bonnes pratiques?

    Qu'en pensez-vous?

  2. #2
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    avril 2004
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : avril 2004
    Messages : 1 257
    Points : 1 286
    Points
    1 286

    Par défaut

    J'en pense qu'il existe des "vues". Et que c'est également modélisable en poo.

  3. #3
    Membre Expert Avatar de chaplin
    Inscrit en
    août 2006
    Messages
    1 213
    Détails du profil
    Informations forums :
    Inscription : août 2006
    Messages : 1 213
    Points : 1 438
    Points
    1 438

    Par défaut

    Citation Envoyé par _skip Voir le message
    Et si vous devez modifier 1500 commandes pour marquer un retard de livraison, vous allez charger 1500 graphes pour appeler la méthode setLivraison()?
    Ton exemple est sérieux ou c'est une blague ?

  4. #4
    Expert Confirmé Sénior
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 711
    Points : 6 303
    Points
    6 303

    Par défaut

    Citation Envoyé par chaplin Voir le message
    Ton exemple est sérieux ou c'est une blague ?
    C'est un cas volontairement extrême, j'aurai du choisir une fonctionnalité qui aurait eu des effets de bord autres qu'une simple modification de valeur.

  5. #5
    Membre confirmé
    Inscrit en
    mars 2011
    Messages
    114
    Détails du profil
    Informations forums :
    Inscription : mars 2011
    Messages : 114
    Points : 250
    Points
    250

    Par défaut

    C'est toujours possible mais la question est de savoir si cela est nécessaire, voir si c'est souhaitable.

    La force du langage impératif, c'est que l'on peut comprendre "intuitivement" la manière dont sera exécuté le code sur la machine. Le langage objet, du fait de son niveau d'abstraction, pose un flou à ce niveau.
    Vu qu'en POO la méthode est liée à l'instance de l'objet la donnée devient donc active en initiant l'action, plutôt que passive en étant passé en paramètres à celle ci. L'avantage est que cela évite d'utiliser la mauvaise fonction sur la mauvaise donné.

    L’inconvénient est que tout ce qui est sécurité induit de la complexité. Que seul les bonnes méthodes puissent être utiliser avec la bonne instance est une sécurité. Cette complexité n'est pas au service de la fonctionnalité mais au service du développeur.
    L'instance devrait gérer la partie fonctionnelle du code. En plus de cela, elle gère les erreurs du développeurs et les erreurs d'exceptions qu'il s'agisse de l'infra ou de l'algo.

    Il vient ensuite la question de la refactorisation ou non du code. Il faut cependant savoir que la refactorisation n'élimine pas la complexité mais la déporte.
    L'avantage est que l'on peut se consacrer un temps à l’implémentation de la fonctionnalité et faire le reste dans un autre temps. L’inconvénient est qu'il faut architecturer l'ensemble et il y a autant d'architecture que d'architecte. Il y a à nouveau ajout de complexité.

    Bref beaucoup de complexité, donc beaucoup de bug potentiel et des pertes au niveau des perfs.

    La POO a été vendu comme étant plus facilement réutilisable. La POO n'est en fait qu'une façon de représenter le code.
    Ce paradigme se prête bien pour la représentation d’entités distinctes et indépendantes. Il n'est pas pertinent pour la représentation d'ensembles d'objets, de relations entre les objets, de procédure de traitement d'objets bref tout ce qui sort de l'objet.

    Les soit disant "best practices" sont de l'ordre de la masturbation intellectuelle.
    Le but est de faire du code qui marche comme prévu si possible et qui puisse être aisément modifiable si ce n'est pas le cas. Il ne s'agit pas de faire du pure objet avec des accesseurs systématiques obligatoirement en get/set.

    Les bonnes pratiques sont surtout des règles de bon sens. Il faut également insister sur les cas ou ces bonnes pratiques sont effectivement des bonnes pratiques.
    Par exemple:
    La restriction d'accès a une ressource c'est bien bonne chose sauf quand plusieurs objets doivent communiquer par celle ci.
    L'injection de dépendance est une mauvaise chose, sauf quand il s'agit d'améliorer la cohérence au sien d'un module.
    etc...

    Ces règles sont valables peut importe le type de langage.

  6. #6
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Citation Envoyé par _skip Voir le message
    Les bonnes pratiques nous ont poussé à séparer nos applications en différentes couches au nom de la séparation des responsabilités. La plupart d'entre nous ont identifié :

    1. La présentation (L'affichage web/swing/forms etc..)
    2. La persistence (accès BDD)


    Et entre deux la fameuse couche service qui sert de ciment entre les 2 choses. Si ces concepts de séparation sont facilement compris et acceptés, leur mise en pratique diffère fortement et c'est rien de le dire.

    De mon côté, j'ai tendance à penser cette couche de service comme une API de haut niveau destinée à l'UI, offrant des méthodes simples permettant de procurer un lot de données, insérer des enregistrements, exécuter des tâches métier sous forme de transactions.

    Je pense que ce qui pêche dans le modèle "couche de service" est qu'elle est identifiée comme UNE couche, alors qu'en fait c'est une série de couches.. (voir le modèle ISO)

    De même, la couche "persistence" confond la donnée avec le moyen avec lequel on l'obtient (BD, flat file, ou calcul).

    Il suffit de lire la partie "conception" de ce forum pour s'apercevoir des débats sans fins (et des problèmes) liés à l'attribution (ou non) d'une "méthode" dans telle ou telle section..


    Citation Envoyé par _skip Voir le message
    En fait j'ai un peu l'impression que cette histoire de 100% objet est un mythe, un cas d'école qui n'est réalisable que dans les applications triviales. Est-ce qu'on peut vraiment concevoir ses objets métiers en faisant abstraction du système de stockage comme on semble nous vendre dans les recueils de bonnes pratiques?

    Qu'en pensez-vous?

    Je pense simplement que cette vision tout OO est une aberration de principe :

    Pour reprendre un exemple que j'ai déjà cité dans un autre débat, il ne vient à l'idée de personne de penser qu'une lettre "possède" une méthode "se poster"..

    Si maintenant on prend un humain, le nombre d'actions est tellement gigantesque et imprévisible - non dénombrable - que l'action "poster" en est effectivement une, mais que l'on connaît a posteriori et non a priori

    Aussi, voir plus bas

    Citation Envoyé par psykokarl Voir le message
    La POO a été vendu comme étant plus facilement réutilisable. La POO n'est en fait qu'une façon de représenter le code.
    Ce paradigme se prête bien pour la représentation d’entités distinctes et indépendantes. Il n'est pas pertinent pour la représentation d'ensembles d'objets, de relations entre les objets, de procédure de traitement d'objets bref tout ce qui sort de l'objet.
    D'ailleurs, lors d'un autre débat (dans lequel je m'étais fait écharper pour avoir oser critiquer l'OO) un participant avait fait un excellent post expliquant la différence entre les 2 paradigmes (Avantages procédural par rapport à l'orientée-objet - post #61

    Mais il n'y en a pas de réelle différence !
    Il y a une différence entre percevoir le monde d'après le paradigme objet et percevoir le monde d'après le paradigme procédural. Dans le premier cas tu vois le monde comme des objets qui communiquent entre eux pour résoudre une tâche. Chaque objet connait ce qu'il a à faire et comment il a à le faire. Il envoie des messages, à lui ou aux autres pour demander quelquechose. La paradigme procédural voit le monde comme une ensemble de fonctions qui collaborent. C'est une vision plus « mathématique » bien qu'il faille faire attention à ne pas faire un parallèle sans nuance. Résoudre un problème c'est appeler la bonne fonction qui elle-même appellera les autres qui lui sont nécessaires.

    Est-ce qu'il y a opposition ? Non. Car les objets aussi doivent faire des actions et donc employer des procédures si on veut. Les fonctions elle s'appliquent sur des données et donc on retrouve des agrégats et d'autres données complexes qui peuvent être vu comme des « objets » aussi du monde.
    ...
    ...
    L'OO, c'est mettre les données en avant et décomposer le problème selon les relations (la complexité) entre ces données. Le procédural, c'est mettre les fonctionnalités en avant et décomposer le problème selon la complexité fonctionnelle. En pratique, on fait toujours un peu des deux. Les langages mettent juste plus l'emphase (attention anglicisme) sur l'une ou l'autre de ces points de vue en offrant une syntaxe et des propriétés qui s'y prêtent mieux. Mais finalement, on fait la même chose.
    Il n'est absolument pas intuitif de penser et de modéliser des choses en OO, pour quiquonque n'est pas informaticien (qui plus est ayant appris le concept), à cause, comme précisé plus haut, de l'aberration conceptuelle que cela sous-tend dans la majorité des cas..

    Physicien à la base, il m'est logique de penser un logiciel (qui est une suite de fonctionalités appliquées sur des objets) comme étant une suite de fonctionalités.

    Une personne lambda pensera de la même manière face à un problème..

    Alors pour les personnes ayant été "élevées" dans l'objet, il est difficile de concevoir autre chose, mais le fond du problème est , je pense, dû à une approche américaine de concevoir les choses : les américains en général pensent pratique, et donc commencent par identifier un élément, et généralisent à partir de cet élement : c'est une approche "bottom-up". Dans cette approche, il est donc logique que les parties "basses" aient des détails, quitte à ce qu'ils soient dupliqués plus on généralise. Les européens, et les scientifiques en général, fonctionnent de manière "top-down", c'est à dire que le but est d'établir une théorie permettant de décrire les éléments successifs par raffinements successifs, en partant d'un schéma unique : la Relativité Générale englobe la mécanique classique , qui en est un cas particulier, la sémantique est une théorie du langage qui s'applique à toutes les langues, l'ethnologie s'applique à toutes les civilisations, etc..

    Or, dans le domaine du logiciel, le Cahier des Charges, lorsqu'il est fourni, décrit des fonctionalités, et accessoirement les données sur lesquelles on travaille.

    Un logiciel est donc logiquement plus orienté fonctionalités que données..

    En fait, il me semble que l'impact de l'OO provient de l'importance des grandes banques et sociétés de services oeuvrant dans le domaine des banques, qui ont toujours manipulé des BDD relationnelles, où les relations entre les données étaient le schéma de base, occultant même l'architecture globale.. et dont les "penseurs" n'avaient pas l'esprit scientifique...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    Expert Confirmé Sénior
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 711
    Points : 6 303
    Points
    6 303

    Par défaut

    Merci pour ces réponses bien développées.

    Citation Envoyé par souviron34
    Pour reprendre un exemple que j'ai déjà cité dans un autre débat, il ne vient à l'idée de personne de penser qu'une lettre "possède" une méthode "se poster"..
    Ceci :

    Code :
    1
    2
    3
    4
    5
    6
    class Lettre
    {
         //(...)
         void poste();
    }
    ?

    J'ai beau avoir été élevé dans l'OO ou être tombé dans la marmite, ça ne me paraît pas non plus le rôle d'une lettre de savoir comment se poster.
    Pour moi, une lettre pourrait avoir une méthode permettant d'ajouter des paragraphes, de spécifier une signature.

    Mais essayons d'écarter le côté très discutable de la validité de l'exemple en terme d'OOP pour se concentrer sur la façon dont ceci pourrait s'implémenter :

    Plutôt qu'avoir une méthode d'action dans l'objet, j'aurai intuitivement plus l'intention de créer une classe ServicePostal ayant une méthode de ce genre :

    Code :
    1
    2
    void poster( Lettre lettre)
    voire carrément :

    Code :
    1
    2
    void poster( Lettre lettre, Adresse adresseLivraison)
    Pourquoi? Car le postage est une opération qui peut impliquer une série d'action comme par exemple :

    1) Vérification de l'adresse de destination
    2) Calcul du coût d'expédition, validation du timbre
    3) Enregistrement du pli

    Pas la peine de venir me dire que la poste ça ne fonctionne pas comme ça, ce n'est pas le point. Le fait est de dire que les actions ci-dessus vont forcément avoir besoin de données externes que notre lettre devra se procurer pour effectuer ce travail.
    Du coup notre objet lettre devra disposer de AnnuaireAdresses, Tarifs etc... On obtient rapidement une certaine quantité de dépendances, et notre méthode Lettre.Poste() dépasse passablement sa juridiction.

    Il me semble plus facile d'imaginer une lettre comme un conteneur de données, avec quelques méthodes basiques d'édition et éventuellement une validation de premier niveau, et de confier la logique à un service extérieur qui possède l'intelligence métier ainsi que le pouvoir de charger des données comme par exemples les tarifs, de les mettre en cache si nécessaire etc... En plus cela délimite bien les responsabilités de chaque couche.

    La lettre est un objet d'édition simple, il peut être sérializé sans risque et édité à distance dans une GUI quelconque, il n'a pas accès aux données et son comportement est délimité et maîtrisé.
    Cela éviterait d'avoir une lettre très lourde, capable de charger elle-mêmes les tarifs à la demande et tout ça. Cependant d'autres diront qu'on peut éviter le couplage en créant une méthode de ce genre

    Code :
    1
    2
    3
    4
    5
    6
    class Lettre
    {
         //(...)
         void poste(ServicePostal poste);
    }
    Ceci permettrait de limiter les dépendances et d'alléger le travail de la classe lettre mais est-ce vraiment mieux que l'autre solution? D'une façon ou d'une autre, il en ressort qu'à un moment donné, les actions devront utiliser des services pour se procurer ce qu'il leur faut. Cela ne changera pas vraiment d'après l'endroit où l'on veut les placer, ces actions.

    Donc dans le cas de l'objet lettre qui se poste toute seule, un moment donné, les services nécessaires à son travail devront être

    1) Soit fournis directement à la méthode (Avantage : l'objet reste serializable et fonctionne 100% détaché)
    2) Soit fournis au constructeur (Avantage : automatisable par IOC, mais non fonctionnel en détaché).

    Ou alors, on opte pour garder la classe Lettre simple et conne comme je le disais au tout début et on confie la responsabilité au service?
    Finalement peut-on dire qu'opter pour la solution du *fat service* est signe de mauvaise compréhension de "l'object oriented design" comme le prétendent certains bloggers et autres rédacteurs de bouquins ?

  8. #8
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Citation Envoyé par _skip Voir le message
    Finalement peut-on dire qu'opter pour la solution du *fat service* est signe de mauvaise compréhension de "l'object oriented design" comme le prétendent certains bloggers et autres rédacteurs de bouquins ?
    Je pense surtout que l"object-oriented design" est, tel qu'il est conçu, une aberration' conceptuelle..

    Si on reprend la citation que j'ai mentionnée :

    Dans le premier cas tu vois le monde comme des objets qui communiquent entre eux pour résoudre une tâche. Chaque objet connait ce qu'il a à faire et comment il a à le faire. Il envoie des messages, à lui ou aux autres pour demander quelquechose
    Le postulat de base est faux : un objet est inerte et n'a pas de "volonté", donc pas d'actions..

    Par contre, il subit des actions externes.. Mais il ne connaît rien... Une pierre peut autant servir à faire un mur qu'à être peinte par un artiste, qu'à être laissée là où elle est, qu'à taper sur son voisin, qu'à servir de cale ou de marche-pied, de projectile, ...



    Qu'un logiciel manipule des entités ou "objets", et qu'il soit conçu pour pouvoir les manipuler, c'est tout à fait normal et logique. Que par contre ce soit les objets qui définissent le logiciel est absurde..

    Si l'on reprend un exemple facilement "objectisable", un logiciel de traitement d'images : chaque image est effectivement un objet, une entité propre sur laquelle vont s'appliquer divers traitements.

    Que l'on modélise (de manière informatique) ce logiciel comme étant une classe image possédant des méthodes de traitements, outre le fait que, mis à part la lecture et l'écriture (pour cause de format), toutes les méthodes sont partageables par toutes les instances, cela peut s'envisager. On passera cependant à côté de quelques fonctionalités ne rentrant pas dans ce cadre (palettes de couleurs, outils de dessin, d'écrture....).

    Mais ce style de logiciel est de toutes façons très rare... La majorité manipule des "objets" non fixes, ou dépendants de fonctionalités précédentes...

    A mon avis donc l"OOD n'est applicable QUE pour un petit nombre de logiciels... Comme pouvant être une facilité de programmation..

    Mais la logique et la facilité de pensée, modélisation, et programmation, est souvent plus du côté du "procédural", manipulant des objets, que des objets effectuant des actions...


    Si l'on reprend même un exemple aussi "objectisable" que le traitement d'images, et si l'on se place dans le boulot d'un photographe, il est plus normal de penser que c'est le photographe qui va chosiir en fonction de la photo qu'il voit si il a besoin de lui appliquer tel ou tel traitement, que d'affubler chaque photo d'une série de méthodes dont la plupart n'ont aucun sens du point de vue du photographe pour cette photo en particulier...

    Il est aussi facile de modéliser un traitement d'image par une série d'actions appliquées sur des objets que l'inverse.


    Le fond est à mon avis souligné par mes 2 premières remarques : par définition l'OOD ne devrait être qu'une facilité de programmation pour certains cas et non pas un passe-partout de modélisation globale, pour la simple raison qu'un objet est inerte.

    Comme ce n'est pas ce qui est compris/propagé dans la plupart des cas, on arrive à des échafaudages encore plus compliqués à saisir (et élaborer !!!) que si l'on avait pris du procédural..

    Ma conclusion serait : l'OO oui, l'OOD non


    D'ailleurs, l'OO est un paradigme de programmation, il n'a jamais été conçu pour être un paradigme de conception...



    * Note : j'ai fait du traitement d'images en Fortran IV en 1982 : c'était bien de l'OO, puisqu'on manipulait des images ayant des caractéristiques propres (dimensions, origine, orientation..), et que les fonctionalités manipulaient un concept "image", mais ce n'était pas de l'OOD, puisque l'analyse se basait sur les fonctionalités.. Il en va de même pour un langage de commande style shell : le coeur est un gros "switch" qui appelle le programme identifié dans la chaîne qui lui est passée..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  9. #9
    Membre chevronné
    Inscrit en
    janvier 2011
    Messages
    266
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 266
    Points : 701
    Points
    701

    Par défaut

    Excellente question, ça fait du bien pour une fois dans ce forum se de plonger dans un débat vraiment technique et d'en explorer les détails

    Je pense que le stéréotype largement répandu selon lequel l'orienté objet a pour but de modéliser des objets du monde réel est en grande partie faux. Faire de l'orienté objet, ce n'est pas prendre un terme métier, en faire une classe et essayer de fourrer des méthodes dedans pour faire tourner notre appli.
    Ca l'est parfois, mais c'est aussi bien souvent inventer de nouveaux concepts abstraits qui vont constituer le langage de notre application. Des Stratégies, des Fabriques, des Spécifications, des Ordonnanceurs, des Coordinateurs, des Mappeurs, des Adapteurs... On peut les appeler Service si on veut. Mais on peut aussi faire preuve d'un peu d'imagination et de richesse de vocabulaire. Et en général, plus un objet a un nom spécifique, moins on sera tenté d'en faire un fourre-tout ( ce qui a souvent tendance à être le cas avec les "Services").

    A cet égard, l'exemple de la lettre qui se poste elle-même est un homme de paille, un argument fallacieux : c'est effectivement assez absurde d'y mettre la méthode Envoyer(). En revanche, pourquoi pas une classe CentreDeTri, DispatcheurCourrier ou que sais-je ? C'est certes un peu plus abstrait et moins décalqué du métier qu'une classe Chaise ou une classe Personne, mais c'est aussi de l'OO et ce n'est pas forcément un Service au sens gros bouzin procédural du terme.

    Deuxième argument qui me parait assez discutable : les exemples pris pour illustrer le bien fondé d'un Anemic Domain Model sont souvent des comportements coordinateurs qui exécutent une séquence d'actions appelant beaucoup d'objets tiers. Ces comportements existent et doivent être assurés, il ne s'agit pas de le nier. Mais il faut aussi penser à tous les autres types de comportements qui peuvent être encapsulés dans une classe :
    • se valider,
    • changer son état,
    • exécuter un algorithme,
    • effectuer une action sur une collection d'objets qu'on possède, sur ses enfants si on est dans une structure arborescente,
    • etc.


    Attention, un modèle du domaine riche (par opposition à anémique) n'empêche absolument pas d'avoir des services du moment qu'ils ont des responsabilités limitées et ne deviennent pas obèses. Dans Domain Driven Design, méthode citée par Fowler dans l'article que tu mets en lien et que certains considèrent comme "object oriented done right", Eric Evans identifie même 3 types de services :

    • Services de domaine : ils contiennent les fonctionnalités qui n'appartiennent pas naturellement à un objet métier du domaine. Généralement, ils sont un point d'accès pour plusieurs objets.
      Ex : on peut considérer que la méthode EffectuerVirement() n'appartient pas vraiment à la classe CompteBancaire car on voit difficilement un compte d'origine qui changerait le solde du compte de destination ou l'inverse. D'où un ServiceVirement qui va connaitre les 2 comptes et effectuer l'opération.
    • Services de la couche application qui sont au courant du déroulement de l'exécution du logiciel et coordonnent les tâches à effectuer.
    • Services de la couche infrastructure qui assurent les tâches de bas niveau transversales à l'application : envoi de mails, système de fichiers, etc.


    Cela n'empêche absolument pas cette vision de promouvoir aussi des objets du domaine riches (comprendre : données + comportement), à chaque fois que c'est possible.

    Pour résumer, je ne pense pas que l'opposition entre approche procédurale et approche orientée objet se situe au niveau de la "pureté métier" des structures utilisées. C'est un faux débat. L'orienté objet, c'est avant tout l'encapsulation de données et comportement à l'intérieur de petites unités de code dont on peut gérer finement les interdépendances grâce à l'inversion de contrôle. Le procédural, c'est l'exécution en séquence de routines et sous-routines, généralement de taille plus large, peu réutilisables, et opérant souvent sur des données (variables) partagées par toute l'application.

    Donc oui, je prends ta classe ServicePostal, et oui, c'est de l'OO, du moment qu'elle ne fait pas le café, le ménage et le repassage et ne chipe pas des responsabilités à de "vrais" objets métier

  10. #10
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Citation Envoyé par Luckyluke34 Voir le message
    Dans Domain Driven Design, méthode citée par Fowler dans l'article que tu mets en lien et que certains considèrent comme "object oriented done right", Eric Evans identifie même 3 types de services :

    • Services de domaine : ils contiennent les fonctionnalités qui n'appartiennent pas naturellement à un objet métier du domaine. Généralement, ils sont un point d'accès pour plusieurs objets.
      Ex : on peut considérer que la méthode EffectuerVirement() n'appartient pas vraiment à la classe CompteBancaire car on voit difficilement un compte d'origine qui changerait le solde du compte de destination ou l'inverse. D'où un ServiceVirement qui va connaitre les 2 comptes et effectuer l'opération.
    • Services de la couche application qui sont au courant du déroulement de l'exécution du logiciel et coordonnent les tâches à effectuer.
    • Services de la couche infrastructure qui assurent les tâches de bas niveau transversales à l'application : envoi de mails, système de fichiers, etc.
    Tout à fait, ça correspond à ce que je disais dans mon premier post :

    Je pense que ce qui pêche dans le modèle "couche de service" est qu'elle est identifiée comme UNE couche, alors qu'en fait c'est une série de couches..

    Citation Envoyé par Luckyluke34 Voir le message
    L'orienté objet, c'est avant tout l'encapsulation de données et comportement à l'intérieur de petites unités de code dont on peut gérer finement les interdépendances grâce à l'inversion de contrôle. Le procédural, c'est l'exécution en séquence de routines et sous-routines, généralement de taille plus large, peu réutilisables, et opérant souvent sur des données (variables) partagées par toute l'application.
    Disons que là je pense que tu caricatures (mais je 'ai fait en sens inverse ) le procédural..

    Le procédural n'agit pas "en séquence" comme tu sembles le croire, ni avec des fonctions plus "larges", ni en opérant sur des données valables à travers toute l'application...

    Il est simplement structuré en termes de fonctionalités...

    Chaque fonctionalité ou sous-fonctionalité peut avoir son propre type d'objet, et en général le découpage peut-être très fin en termes de taille (il suffit de voir les specs du cycle en V..)

    Comme le disait la citation que j'ai faite, il n'y a pas vraiment de différence entre les 2, à part l'optique (et donc la modélisation) que l'on se fait..

    C'est un faux problème la taille du code, la réutilisabilité, etc, ..qui serait au détriment du procédural.. N'importe quel gros soft en procédural n'est ni plus complexe ni plus long ni moins maintenable que le même en OO.

    Le choix est un choix philosophique..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #11
    Membre confirmé
    Inscrit en
    mars 2011
    Messages
    114
    Détails du profil
    Informations forums :
    Inscription : mars 2011
    Messages : 114
    Points : 250
    Points
    250

    Par défaut

    Citation Envoyé par Luckyluke34
    Je pense que le stéréotype largement répandu selon lequel l'orienté objet a pour but de modéliser des objets du monde réel est en grande partie faux. Faire de l'orienté objet, ce n'est pas prendre un terme métier, en faire une classe et essayer de fourrer des méthodes dedans pour faire tourner notre appli.
    Je suis d'accord. Ce que je reproche à la POO est surtout de la manière dont elle est enseignée/vendue.

    L'aspect donné est mis en avant mais le gros du travail du développeur porte sur la partie traitement. Quand je crée des classes pour un usage perso, je le fais dans une optique de simplification de lecture au niveau architecturale et non au niveau métier.

    Par exemple, mes méthodes pour l'objet Lettre se limiteraient à des accesseurs. Écriture/lecture de de l'adresse sur l'enveloppe, à l'écriture/lecture du message sur les feuilles de papier, présence ou non d'un timbre, etc. Des méthodes privées serviraient à calculer des propriétés cachées, comme le calcul du nombre de feuilles en fonction du nombre de caractère.

    La validation de l'adresse seraient faite par un objet CentreDeTri via une méthode recevoirCourrier() qui prend l'objet Lettre en paramètre. En fait, cette classe serait conçue pour accepter tout objets qui possède les accesseurs permettant de lire une adresse et le la valeur d'un timbre. La contrôle de la validité de l'adresse serait le boulot de cette classe ainsi l'objet CentreDeTri peut gérer des lettres mais également des colis de natures diverse.

    L'avantage est que l'objet lettre pourra également être passé à une classe objet Messager ou via une méthode PrendreCourier() ou la présence de timbre ne sera pas nécessaire et la validation de l'adresse ne répondra pas au même exigences que pour l'objet CentreDeTri. Un prénom connu de l'objet Messager suffirait

    Crois moi ou pas, ce type d'architecture est de la retranscription bête et méchante de ce que je fais en procédural: création de structure Lettre + passage en paramètre à des fonctions nommée CentreDeTri_prendreCourier().
    Les objets CentreDeTri et Messager ne sont même pas instancié (bien que cela soit possible). En objet la fonction ressemblera à CentreDeTri::prendreCourrier(). La belle affaire !
    Quand je présente ce genre d'architecture au niveau professionnel, on me regarde avec des yeux rond et on me dit: "ce n'est pas ça de la POO".

    Citation Envoyé par Luckyluke34
    Ca l'est parfois, mais c'est aussi bien souvent inventer de nouveaux concepts abstraits qui vont constituer le langage de notre application. Des Stratégies, des Fabriques, des Spécifications, des Ordonnanceurs, des Coordinateurs, des Mappeurs, des Adapteurs...
    Ces concepts existent en programmation procédurale depuis des éons. La différence est qu'elles ont rarement besoin d'être nommé. L'importance d'une fonction n'est pas son comportement mais sa fonctionnalité.

    Il m'arrive par exemple d'utiliser un pattern sans nom en POO. Du moins à ma connaissance.
    Je crée une famille de classes statiques "driver" qui proposent une série de méthodes statiques.
    Ces méthodes statiques sont passés en paramètre à des classes de la famille "architecture" qui proposent des méthodes standard permettant d’appeler les méthodes "drivers" passé en paramètre via des callback en interne.

    Cela me permet de changer mes algos de traitement et modifier la gestion de l'infrastructure à la volé sans changer l'architecture globale de mon projet.
    Ce pattern fait la même chose que une factory, l'injection de dépendance en moins, de la souplesse en plus et le tout pour un ajout en complexité algorithmique de l'ordre de la constante.

    Un autre exemple de repompage pur et simple de ce que je fais en procédural. Le procédural c'est loin d'être bouzin. Le fait est que la frontière qui sépare la donnée et le code de traitement est ténu. Le procédural est très souple à ce niveau. Tout ceux qui auront trop jouer avec les pointeurs pourront en témoigner et peuvent utiliser cet aspect avantageusement.

    Citation Envoyé par Luckyluke34
    Attention, un modèle du domaine riche (par opposition à anémique) n'empêche absolument pas d'avoir des services du moment qu'ils ont des responsabilités limitées et ne deviennent pas obèses. Dans Domain Driven Design, méthode citée par Fowler dans l'article que tu mets en lien et que certains considèrent comme "object oriented done right", Eric Evans identifie même 3 types de services :

    • Services de domaine : ils contiennent les fonctionnalités qui n'appartiennent pas naturellement à un objet métier du domaine. Généralement, ils sont un point d'accès pour plusieurs objets.
      Ex : on peut considérer que la méthode EffectuerVirement() n'appartient pas vraiment à la classe CompteBancaire car on voit difficilement un compte d'origine qui changerait le solde du compte de destination ou l'inverse. D'où un ServiceVirement qui va connaitre les 2 comptes et effectuer l'opération.
    • Services de la couche application qui sont au courant du déroulement de l'exécution du logiciel et coordonnent les tâches à effectuer.
    • Services de la couche infrastructure qui assurent les tâches de bas niveau transversales à l'application : envoi de mails, système de fichiers, etc.


    Cela n'empêche absolument pas cette vision de promouvoir aussi des objets du domaine riches (comprendre : données + comportement), à chaque fois que c'est possible.
    L'identification de ces trois types de services est arbitraire.
    • Les services de domaine qui n'appartiennent pas naturellement à un objet métier peuvent être remplacé par de simple accesseur. Le code métier étant déporté dans une autre classe qui manie ces accesseurs. De plus le fait qu'une méthode appartienne naturellement ou non à un objet est également arbitraire. Au niveau architecture on est pas tenu de coller à la réalité l'important est de faciliter la lecture.
    • Le déroulement de l'application n'est pas contenu uniquement dans les services de la couche application mais il est potentiellement diffusée dans l'ensemble du code. Un accesseur métier foireux peut avoir une incidence sur le déroulement du code métier. Le découpage est à nouveau arbitraire.
    • La nécessité de créer une couche infrastructure de bas niveau dépend de la fiabilité de l’accès à une ressource. Une simple allocation mémoire ne demande pas les même précaution selon que l'on soit sur une architecture distribuée ou non, selon le type et la qualité du matériel, selon la qualité des installations, l'environnement physique du hardware (possibilité de bruit), etc.


    Ce découpage dépend de la vision de l'architecte. Elle ne manque pas de pertinence mais elle est nécessairement influencer par les cas de figures sur lesquels il a travaillé.
    On ne peut pas en tirer de règle générale.

    Citation Envoyé par Luckyluke34
    Pour résumer, je ne pense pas que l'opposition entre approche procédurale et approche orientée objet se situe au niveau de la "pureté métier" des structures utilisées. C'est un faux débat. L'orienté objet, c'est avant tout l'encapsulation de données et comportement à l'intérieur de petites unités de code dont on peut gérer finement les interdépendances grâce à l'inversion de contrôle. Le procédural, c'est l'exécution en séquence de routines et sous-routines, généralement de taille plus large, peu réutilisables, et opérant souvent sur des données (variables) partagées par toute l'application.
    Personne n'a dit ça. La différence entre l'objet se situe au niveau de la représentation du code et uniquement à ce niveau.
    En programmation procédurale, les possibilités d'encapsulation, de modularité et la gestion des interdépendances peuvent être poussé à un point que tu n'imagines même pas.
    La réelle question est: "Faut il couper un cheveux en quatre pour faire créer un modèle 100% OO ?".
    J'ai tendance à penser que cela n'est pas pertinent. Cela ne se justifie pas forcément au niveau productivité, au niveau de la lisibilité et encore moins au niveau de l'optimisation. Creer un modèle 100% OO, pour créer un modèle 100% OO est de l'ordre de la masturbation intellectuelle.

    Si l'on voulait réellement faire du pur objet, il devrait y avoir des notations du type: "hello world !"->afficherEcran();. Cela permettrait de créer une méthode afficherEcran() qui procède à tout les contrôles nécessaire pour garantir l'affichage d'une simple chaine et envoyer une exception en cas d'échec. Si on ne le fait pas c'est parce que ça simplifie la gestion des chaines de caractère. Le même raisonnement peut s'appliquer sur des classes de plus haut niveau.

  12. #12
    Membre chevronné
    Homme Profil pro Jérôme Frossard
    Enseignant
    Inscrit en
    décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Nom : Homme Jérôme Frossard
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2007
    Messages : 191
    Points : 707
    Points
    707

    Par défaut

    J'ai tendance à penser que la programmation purement procédurale n'est guère applicable que lorsqu'il s'agit de programme fort simple. Dès lors qu'il s'agit de réaliser des applications d'une certaine complexité, on a besoin d'abstractions --- ces abstractions ne sont d'ailleurs pas l'appanage des informaticiens, si comme ingénieur électricien j'avais du appliquer les équations de Maxwell à chaque fois que je voulais réaliser un amplificateur, je n'aurais sans doute pas réalisé grand-chose --- et dès lors qu'on a besoin d'abstraction pour construire quelque chose on adopte une approche bottom-up, on réalise les abstractions (la pièce de légo -- qui peut d'ailleurs être très spécifique) dont on a besoin pour réaliser le tout, mais chacune de ces abstractions peut exister indépendamment les unes des autres (ce qui permet la réutilisation). Mais à un moment donné on doit, à l'aide de ces abstractions, réaliser un programme et à ce moment là l'approche est naturellement plutôt top-down. De plus, les deux approches ne sont pas appliquée de manière séquentielle, mais imbriquée; on réalise notre programme d'une manière top-down, à un moment donné on se rend compte qu'on a besoin d'une abstraction, on définit alors l'interface de cette abstraction et on suppose qu'on l'a à disposition pour poursuivre la conception.

    Ensuite que le language supporte ou non le paradigme orienté objet n'est pas si important, au minimum on pourra toujours réaliser des type de donnée abstraits qui sont tout à fait comparable aux classes d'un langage qui supporte l'OO. Pour ces derniers, il y a bien sûr des trucs bien utilise comme l'héritage d'implémentation, les interfaces, etc... Mais que l'on travail en Pascal, en C, en C++, en Scheme ou en Java, si on réalise un logiciel d'une certaine complexité on arrive presque forcément à de une programmation orientée objet.

    La pratique a montré que certaines manières de faire sont moins bonnes que d'autres et il est donc intéressant de s'intéresser au patterns et anti-patterns qui ont été identifiés au file du temps.

    Un domaine où pour moi l'orienté objet n'a rien à faire, c'est celui des bases de données mais c'est un autre débat.

  13. #13
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Citation Envoyé par ptah35 Voir le message
    si on réalise un logiciel d'une certaine complexité on arrive presque forcément à de une programmation orientée objet
    Je suis d'accord avec toi, mais le débat était par rapport au full object


    Citation Envoyé par ptah35 Voir le message
    Un domaine où pour moi l'orienté objet n'a rien à faire, c'est celui des bases de données mais c'est un autre débat.
    c'est pourtant à mon avis l'endroit où il est le plus logique et le plus appliqué...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #14
    Membre chevronné
    Inscrit en
    janvier 2011
    Messages
    266
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 266
    Points : 701
    Points
    701

    Par défaut

    Citation Envoyé par psykokarl Voir le message
    Crois moi ou pas, ce type d'architecture est de la retranscription bête et méchante de ce que je fais en procédural: création de structure Lettre + passage en paramètre à des fonctions nommée CentreDeTri_prendreCourier().
    Les objets CentreDeTri et Messager ne sont même pas instancié (bien que cela soit possible). En objet la fonction ressemblera à CentreDeTri::prendreCourrier(). La belle affaire !
    Quand je présente ce genre d'architecture au niveau professionnel, on me regarde avec des yeux rond et on me dit: "ce n'est pas ça de la POO".
    Je vais te poser une question qui à mon avis fait la différence entre POO et pas POO.
    Tu cites l'exemple d'un objet Messager et d'un objet CentreDeTri qui tous les deux transmettent un courrier. Dans la version POO, nous sommes d'accord que ces 2 classes pourraient hériter d'une même classe (ou interface) parente qui exposerait une méthode TraiterCourrier() dans son contrat. Un objet tiers qui voudrait simplement envoyer un courrier sans se soucier des détails de l'expédition pourrait juste manipuler un objet du type de la classe parente qu'on lui passerait, et grâce au polymorphisme le bon traitement serait appliqué : par messager ou par centre de tri. On aurait alors une bonne maintenabilité du système puisque pour étendre notre gamme de modes d'expéditions, il suffit de créer une nouvelle classe implémentant le contrat TraiterCourrier() et d'en passer une instance à l'objet qui souhaite envoyer un message. Pas besoin de "casser" le code de la classe appelante ni de la classe de base.

    Est-ce que la même chose serait possible dans le cas de fonctions statiques CentreDeTri_prendreCourier() et Messager_prendreCourier() et du code "procédural" que tu décris ? Si oui, et je veux bien savoir comment, je considère que c'est de l'orienté objet (ou du fonctionnel, à la limite).
    Et pour reprendre l'exemple d'origine, si on a un ServiceExpédition et 2 classes dérivées ServiceExpéditionCentreDeTri et ServiceExpéditionMessager, alors oui, c'est de l'orienté objet même s'il y a des solutions plus élégantes que d'utiliser le mot-valise "Service" pour ça.

    Ces concepts existent en programmation procédurale depuis des éons. La différence est qu'elles ont rarement besoin d'être nommé. L'importance d'une fonction n'est pas son comportement mais sa fonctionnalité.
    Là, je suis moins daccord. Oui, c'est la fonctionnalité qui compte mais c'est bien le nom (du module, de la fonction) qui permet de véhiculer le sens de cette fonctionnalité et d'avoir une acception commune partagée par les développeurs et qui facilite la compréhension du code.

    Il m'arrive par exemple d'utiliser un pattern sans nom en POO. Du moins à ma connaissance.
    Je crée une famille de classes statiques "driver" qui proposent une série de méthodes statiques.
    Ces méthodes statiques sont passés en paramètre à des classes de la famille "architecture" qui proposent des méthodes standard permettant d’appeler les méthodes "drivers" passé en paramètre via des callback en interne.
    Là j'ai l'impression qu'on se rapproche plus du paradigme fonctionnel (fonctions d'ordre supérieur)

    • Le déroulement de l'application n'est pas contenu uniquement dans les services de la couche application mais il est potentiellement diffusée dans l'ensemble du code. Un accesseur métier foireux peut avoir une incidence sur le déroulement du code métier. Le découpage est à nouveau arbitraire.
    Je ne parle pas du déroulement de l'application en termes de pile d'appels à des fonctions, je parle de l'état d'avancement des transactions métier qui sont entreprises par l'utilisateur. Typiquement si on prend un wizard, en DDD la couche Domaine ne sait pas si on est à l'étape 2 ou 3 du wizard, la couche application si.

    • La nécessité de créer une couche infrastructure de bas niveau dépend de la fiabilité de l’accès à une ressource. Une simple allocation mémoire ne demande pas les même précaution selon que l'on soit sur une architecture distribuée ou non, selon le type et la qualité du matériel, selon la qualité des installations, l'environnement physique du hardware (possibilité de bruit), etc.
    Et donc ? Je ne vois pas trop le rapport avec le sujet d'origine

    Ce découpage dépend de la vision de l'architecte. Elle ne manque pas de pertinence mais elle est nécessairement influencer par les cas de figures sur lesquels il a travaillé.
    On ne peut pas en tirer de règle générale.
    Bien sûr que les couches sont arbitraires. Je ne dis pas que c'est la panacée universelle, j'essaie juste de répondre à _skip en disant que les services ne sont pas forcément persona non grata dans une vision orientée objet avec des objets métier riches, et que ces services peuvent être à plein d'endroits.

    La réelle question est: "Faut il couper un cheveux en quatre pour faire créer un modèle 100% OO ?".
    J'ai tendance à penser que cela n'est pas pertinent. Cela ne se justifie pas forcément au niveau productivité, au niveau de la lisibilité et encore moins au niveau de l'optimisation. Creer un modèle 100% OO, pour créer un modèle 100% OO est de l'ordre de la masturbation intellectuelle.
    Je suis bien d'accord. Parfois, avoir juste des structures de données sans comportement, et des procédures qui agissent sur ces structures de données est bien pratique. Il y a une grosse marge entre un 100% pur objet chimérique où on se flagelle dès qu'un objet n'a pas de méthodes, et l'orienté objet qui est bien souvent teinté de procédural par endroits (et aussi, de plus en plus fréquemment, de fonctionnel).

  15. #15
    Membre chevronné
    Homme Profil pro Jérôme Frossard
    Enseignant
    Inscrit en
    décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Nom : Homme Jérôme Frossard
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2007
    Messages : 191
    Points : 707
    Points
    707

    Par défaut

    Dans mon intervention précédente j'étais un peu hors sujet, mais je tiens néanmoins à répondre rapidement aux remarques de souviron34.

    Selon l'état de mes connaissance, il n'existe pas de paradigme "full object". Le seul que je connaisse est le paradigme "object oriented". Je pense en outre, qu'il n'est pas possible de concevoir quelque chose de "100% objet" ou "pure objet" parce que le paradigme n'a pas de définition claire. Si on utilise la notion de classe ou de type abstrait, on fait de l'orienté objet. Au file des ans des personne d'autorité ont mis en évidence des patterns et des anti-patterns, il est souvent judicieux d'en tenir compte, ce n'est pas jamais une obligation ni une condition pour que le code puisse être qualifié d'orienté objet.

    Quand je disais que je n'aime pas l'orienté objet dans les base de données, je voulais dire que je n'aime pas tellement les bases de données orientées objet et leur préfère une base de données relationnelle dans presque tous les cas et à moins qu'on ne considère les relations comme des objets, celles-ci ne sont pas orienté objet.

    Pour en revenir au débat, selon moi, la couche de persistance ne dois pas forcement manipuler des objets métier. Je pense qu'il est tout à fait acceptable, voir même judicieux de passer par un "machin" intermédiaire qui transforme l'objet métier en un des ces objets "anémique" avant de le passer à la couche de persistance et inversement, qui construit un objet métier à partir d'un objet "anémique" que la persistance nous fourni. Peu importe la façon de faire, on violera l'encapsulation des données pour les sauvegarder, autant encapsuler cette "désencapsulation" dans une partie du code dont c'est l'unique responsabilité. En outre, ces objets soit-disant anémiques peuvent ne pas l'être; une classe n'est pas forcement une abstraction d'un concept métier, mais peut être une abstraction d'un concept "technique", on pourrait ainsi utiliser l'abstraction d'un nuplet pour y stocker les valeur à rendre persistante, on aurait ainsi la possibilité d'énumérer les champs, d'accéder aux champs par le nom, etc. Un tel objet est tout sauf anémique.

  16. #16
    Expert Confirmé Sénior
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    novembre 2005
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : novembre 2005
    Messages : 2 711
    Points : 6 303
    Points
    6 303

    Par défaut

    Citation Envoyé par Luckyluke34 Voir le message
    Excellente question, ça fait du bien pour une fois dans ce forum se de plonger dans un débat vraiment technique et d'en explorer les détails
    Ben oui c'est bien qu'on utilise aussi ce forum pour partager des idées et des points de vue.

    Citation Envoyé par Luckyluke34 Voir le message
    Deuxième argument qui me parait assez discutable : les exemples pris pour illustrer le bien fondé d'un Anemic Domain Model sont souvent des comportements coordinateurs qui exécutent une séquence d'actions appelant beaucoup d'objets tiers. Ces comportements existent et doivent être assurés, il ne s'agit pas de le nier. Mais il faut aussi penser à tous les autres types de comportements qui peuvent être encapsulés dans une classe :
    • se valider,
    • changer son état,
    • exécuter un algorithme,
    • effectuer une action sur une collection d'objets qu'on possède, sur ses enfants si on est dans une structure arborescente,
    • etc.
    C'est ce dont je parlais à travers la formule "validation de premier niveau", c'est à dire principalement ce que tu peux faire à l'intérieur de ta classe qui ne nécessiterait pas typiquement de chargement de données externes et resterait concentré sur la classe elle-même et ce qu'elle encapsule.

    Pour la validation j'ai dit premier niveau, car il peut être assez difficile lors de l'appel à une méthode setTimbre(Timbre t) ou colleTimbre(Timbre t) de pouvoir lever une erreur parce que le timbre "t" n'est pas suffisant par rapport à l'adresse (besoin adresses, tarifs, conditions d'expédition etc...).
    Cela dit, la validation immédiate et poussée peut être une exigence client, parce qu'on veut voir l'erreur sauter aux yeux de l'opérateur et pas seulement lui jeter une errorBox à la figure au moment de soumettre la transaction.
    On peut aussi dans ce cas imaginer un objet destiné à l'édition qui encapsule notre lettre et se sert des services pour assurer un maximum de pré-validation.

    Cependant, s'il est raisonnablement acceptable de faire la validation plus complexe dans le service qui se charge de l'enregistrement de l'objet saisi plutôt que dans les setteurs de cet objet, j'opterai plutôt pour cela.

    Attention, un modèle du domaine riche (par opposition à anémique) n'empêche absolument pas d'avoir des services du moment qu'ils ont des responsabilités limitées et ne deviennent pas obèses. Dans Domain Driven Design, méthode citée par Fowler dans l'article que tu mets en lien et que certains considèrent comme "object oriented done right", Eric Evans identifie même 3 types de services :

    • Services de domaine : ils contiennent les fonctionnalités qui n'appartiennent pas naturellement à un objet métier du domaine. Généralement, ils sont un point d'accès pour plusieurs objets.
      Ex : on peut considérer que la méthode EffectuerVirement() n'appartient pas vraiment à la classe CompteBancaire car on voit difficilement un compte d'origine qui changerait le solde du compte de destination ou l'inverse. D'où un ServiceVirement qui va connaitre les 2 comptes et effectuer l'opération.
    • Services de la couche application qui sont au courant du déroulement de l'exécution du logiciel et coordonnent les tâches à effectuer.
    • Services de la couche infrastructure qui assurent les tâches de bas niveau transversales à l'application : envoi de mails, système de fichiers, etc.
    Oui ok, de façon générale je parlais de services au sens qui :

    - représente la façade métier (API de haut niveau sur les fonctionnalités du logiciel)
    - interagit avec la couche d'accès aux données.

    Donc oui, je prends ta classe ServicePostal, et oui, c'est de l'OO, du moment qu'elle ne fait pas le café, le ménage et le repassage et ne chipe pas des responsabilités à de "vrais" objets métier
    En fait, de responsabilités que l'architecture de l'application nous *permettrait* de confier à ces objets si t'es bien d'accord avec ça. ( Comme pour l'exemple de la validation plus haut.)

    Citation Envoyé par psykokarl
    L'aspect donné est mis en avant mais le gros du travail du développeur porte sur la partie traitement. Quand je crée des classes pour un usage perso, je le fais dans une optique de simplification de lecture au niveau architecturale et non au niveau métier.

    Par exemple, mes méthodes pour l'objet Lettre se limiteraient à des accesseurs. Écriture/lecture de de l'adresse sur l'enveloppe, à l'écriture/lecture du message sur les feuilles de papier, présence ou non d'un timbre, etc. Des méthodes privées serviraient à calculer des propriétés cachées, comme le calcul du nombre de feuilles en fonction du nombre de caractère.
    Cela se rapproche de ce dont je parlais, un objet assez léger avec des fonctionnalités d'édition, et des "services" qui se chargent d'exécuter les gros traitements.

    Citation Envoyé par psykokarl
    Quand je présente ce genre d'architecture au niveau professionnel, on me regarde avec des yeux rond et on me dit: "ce n'est pas ça de la POO".
    Aux yeux de certains ce que tu décris n'est pas suffisamment OO, pourtant c'est simple à comprendre, à priori tout à fait simple à tester et par conséquent simple à maintenir. Donc en conséquence, n'est-ce pas signe que t'as pas trop mal bossé?
    En plus les entrées et sorties de ton application se font à travers et seulement à travers les services concernés, ce qui donne encore une abstraction convenable pour les éventuelles GUI et te permet aussi de bien contrôler ton accès aux sources de données.

  17. #17
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Citation Envoyé par Luckyluke34 Voir le message
    Là, je suis moins daccord. Oui, c'est la fonctionnalité qui compte mais c'est bien le nom (du module, de la fonction) qui permet de véhiculer le sens de cette fonctionnalité et d'avoir une acception commune partagée par les développeurs et qui facilite la compréhension du code.
    Oui, mais entre Colis.Poster() et Poster(Colis) c'est vraiment une question d'habitude et de mode de pensée plus que d'efficacité de code . Et du point de vue de la compréhension c'est purement une question d'habitude...


    Citation Envoyé par Luckyluke34 Voir le message
    Là j'ai l'impression qu'on se rapproche plus du paradigme fonctionnel (fonctions d'ordre supérieur)
    Je pense que le problème (de fond) vient d elà : des théoriciens et chercheurs en info ont fait débordé leurs domaines et vocabulaires dans le "gand public" des programmeurs et formations...

    Ce qui est décrit et à quoi tu réponds se pratique de manière absolument courante en procédural, sans que ça s'appelle "paradigme fonctionnel".

    Je crois qu'il y a eu une méconnaissance profonde de ce qui se faisait, et que des idées de recherche ont percé, portées par des formations et formateus n'ayant pas eu une vraie connaissance de ce qui se faisait...

    Il suffit de regarder le code de X11 : en C, écrit au début des années 80, fonctionnant totalement objet et avec ce que tu as l'air de nommer "fonctionel"...



    Citation Envoyé par ptah35 Voir le message
    Quand je disais que je n'aime pas l'orienté objet dans les base de données, je voulais dire que je n'aime pas tellement les bases de données orientées objet et leur préfère une base de données relationnelle dans presque tous les cas et à moins qu'on ne considère les relations comme des objets, celles-ci ne sont pas orienté objet.
    Ok, c'était pas clair


    Citation Envoyé par ptah35 Voir le message
    Pour en revenir au débat, selon moi, la couche de persistance ne dois pas forcement manipuler des objets métier. Je pense qu'il est tout à fait acceptable, voir même judicieux de passer par un "machin" intermédiaire qui transforme l'objet métier en un des ces objets "anémique" avant de le passer à la couche de persistance et inversement, qui construit un objet métier à partir d'un objet "anémique" que la persistance nous fourni. Peu importe la façon de faire, on violera l'encapsulation des données pour les sauvegarder, autant encapsuler cette "désencapsulation" dans une partie du code dont c'est l'unique responsabilité. En outre, ces objets soit-disant anémiques peuvent ne pas l'être; une classe n'est pas forcement une abstraction d'un concept métier, mais peut être une abstraction d'un concept "technique", on pourrait ainsi utiliser l'abstraction d'un nuplet pour y stocker les valeur à rendre persistante, on aurait ainsi la possibilité d'énumérer les champs, d'accéder aux champs par le nom, etc. Un tel objet est tout sauf anémique.


    Entièrement d'accord...

    Mais ça rejoint le second point... Fondamentalement je crois qu'il y a une méconnaissance profonde de l'antérieur, et une "théorisation" poussée qui veut mettre dans des cases ...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  18. #18
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 173
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 173
    Points : 12 819
    Points
    12 819

    Par défaut

    Juste un commentaire à propos de ce que _skip a relevé :

    Citation Envoyé par psykokarl Voir le message
    Quand je présente ce genre d'architecture au niveau professionnel, on me regarde avec des yeux rond et on me dit: "ce n'est pas ça de la POO".
    C'est bien le problème : cette "mode" du OO voudrait que tout soit OO pour le fait d'être OO...

    Le but d'un bon soft c'est primo de bien fonctionner, et secondo d'être facile à maintenir..

    A partir du moment où ces 2 conditions sont remplies, peu importe comment il a été fait ou sur quel paradigme il se base...

    Les gens qui te font ces remarques ne sont pas des "professionels", à mon sens, mais des gens avec des oeillères..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  19. #19
    Membre chevronné
    Homme Profil pro Jérôme Frossard
    Enseignant
    Inscrit en
    décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Nom : Homme Jérôme Frossard
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2007
    Messages : 191
    Points : 707
    Points
    707

    Par défaut

    Citation Envoyé par souviron34 Voir le message
    Juste un commentaire à propos de ce que _skip a relevé :



    C'est bien le problème : cette "mode" du OO voudrait que tout soit OO pour le fait d'être OO...

    Le but d'un bon soft c'est primo de bien fonctionner, et secondo d'être facile à maintenir..

    A partir du moment où ces 2 conditions sont remplies, peu importe comment il a été fait ou sur quel paradigme il se base...

    Les gens qui te font ces remarques ne sont pas des "professionels", à mon sens, mais des gens avec des oeillères..
    En ce qui me concerne, j'ai surtout quelques doutes à propos des compétences de celui qui fait des yeux ronds; selon moi une méthode "envoyer" sur la classe Lettre serait une erreur, car on devrait modifier la classe lettre si les modalité d'expédition étaient changées. Mais en même temps, ce n'est que mon avis et ne dit-on depuis fort longtemps que la raison du plus est toujours la meilleure, à fortiori quand c'est le chef :-P

  20. #20
    Membre chevronné
    Homme Profil pro Jérôme Frossard
    Enseignant
    Inscrit en
    décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Nom : Homme Jérôme Frossard
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2007
    Messages : 191
    Points : 707
    Points
    707

    Par défaut

    Citation Envoyé par Luckyluke34 Voir le message
    Là j'ai l'impression qu'on se rapproche plus du paradigme fonctionnel (fonctions d'ordre supérieur)
    L'un n'empêche pas l'autre, les paradigmes fonctionnel et orienté objet ne s'opposent ni ne s'excluent mutuellement. On oppose parfois procédural et orienté objet (même si ce n'est sans doute pas exacte), mais les deux paradigmes peuvent être utilisés tant avec des langages impératifs que fonctionnels.

    En outre, si les fonctions d'ordre supérieures sont nécessaires pour les langages fonctionnels, elles n'en sont pas l'apanage et sont effectivement monnaie courante dans les langages impératifs. Ce qui change peut-être c'est que dans la plupart des langage impératifs, les fonctions ne sont pas "first citizens" comme ils disent outre atlantique.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •