JeuWeb - Crée ton jeu par navigateur
Compass : East Oriented - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Compass : East Oriented (/showthread.php?tid=7165)

Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30


RE: Compass : East Oriented - Xenos - 20-05-2015

Sortir les case du switch aurait l'intérêt de permettre la réutilisation de ces cases (un autre FileAggregator pourrait avoir les mêmes conditions sur des PDF, et remplacer les DXF/DWG par des 3DS; un autre aggregator aurait des DXF/DWG/3DS et c'est tout, etc).


Justement, le cas 3 (Un policier me demande mes papiers, en West, je dois les retourner, en East, je peux juste me barrer) est réalisable aussi en West (puisque null est implicitement retourné par PHP; le policier ne récupèrera... rien).

A la limite, on aurait plus de liberté si, au lieu de retourner les papiers, on retournait un pot de vin, mais en East, ce n'est pas non plus possible (puisque le "retour" est un appel à une méthode aval, qui doit respecter la signature de l'interface à laquelle elle est associée).

West

interface Gens {
public Papiers getPapiers();
}
class Policier {
public void papierSvp(Gens $gens) {
$papiers = $gens->getPapiers();
}
}
class TypeNormal implements Gens {
public Papiers getPapiers() {
return this->papiers;
}
}
class Delinquant implements Gens {
public Papiers getPapiers() {
return null;
}
}

East:

interface Gens {
public Papiers donneTesPapiersA(PapiersReceveur pr);
}
interface PapiersReceveur {
public void voiciMesPapiers(Gens gens, Papiers papiers);
}

class Policier implements PapiersReceveur {
public void papierSvp(Gens $gens) {
$gens->donneTesPapiersA(this);
}
public void voiciMesPapiers(Gens gens, Papiers papiers) {
// ...
}
}

class TypeNormal implements Gens {
public Papiers donneTesPapiersA(PapiersReceveur pr) {
$pr->voiciMesPapiers(this, papiers);
}
}
class Delinquant implements Gens {
public Papiers donneTesPapiersA(PapiersReceveur pr) {
// Ne pas appeler voiciMesPapiers
}
}

Ou alors, c'est possible sur des langages "lâches" niveau typage (genre PHP), et West (class suiteProcess { function doSomething() { return $returned; }) ou East ($suiteProcess->doSomething($returned)) ont tous deux cette possibilité.


Citation :FileAggregator n'est pas dépendant de FileUploader, il sait travailler avec c'est différent.
FileAggregator n'a pas besoin de FileUploader pour travailler.
Je percute pas ça. En C++ (sûr), en PHP et en Java (quasi sûr), la classe FileUploader doit être importée par le FileAggregator. FileAggregator ne sait travailler avec FileUploader que parce que FileUploader respecte une signature de méthode, qui inclus ce que le FileAggregator retournais en West.
En West, FileAggregator n'a pas à s'inquiéter de FileUploader: quand une classe retourne une donnée, elle se moque de qui s'en sert, c'est donc une dépendance de moins?!


RE: Compass : East Oriented - srm - 20-05-2015

Sauf que c'est pas ce que j'ai demandé.
J'ai dit "je m'en vais", donc c'est pas return null, c'est :
$this->goAway();
return null;
Ce qui a pas de sens dans un getter Wink


RE: Compass : East Oriented - srm - 20-05-2015

C'est une dépendance de plus et pire, parce que tu as besoin de connaître le format de retour d'une méthode sans que ça soit formalisé nul part.


RE: Compass : East Oriented - Xenos - 20-05-2015

Oui, si tu conserves la vision du 1 getter = récupérer un attribut (et là, je suis d'accord depuis 5 bonnes pages: c'est une approche foireuse).
Rien n'interdis d'avoir une méthode, appelons-la un "asker" plutôt qu'un "getter", qui fait des trucs avant de passer à l'appelant l'objet qu'il veut.

Citation :C'est une dépendance de plus et pire, parce que tu as besoin de connaître le format de retour d'une méthode sans que ça soit formalisé nul part.
Je sais pas, mais je comprends toujours pas: dans les langages fortement typés (C++, Java), on a un typage de retour qui est formalisé et connu.
Dans un langage comme PHP, on n'a pas (pour l'instant, mais si j'ai suivis ce que niahoo a dit, ce sera bientôt le cas) de typage de retour. Donc, il n'y a pas de dépendance, puisqu'on peut retourner ce qu'on veut (des papiers, un pot de vin, rien...) ?! En contre partie, en PHP, on devrait tester ce que chaque méthode retourne (puisqu'elles peuvent, et c'est un trait du langage, retourner ce qu'elles veulent).

Je remets ma base au clair, pour être en vrai PHP (et pas en mélasse Java/PHP... >.<)


interface Gens {
public function donneTesPapiersA(PapiersReceveur pr);
}
interface PapiersReceveur {
public function voiciMesPapiers(Gens gens, Papiers papiers);
}

class Policier implements PapiersReceveur {
public function papierSvp(Gens $gens) {
$gens->donneTesPapiersA(this);
}
public function voiciMesPapiers(Gens gens, Papiers papiers) {
// ...
}
}

class TypeNormal implements Gens {
public function donneTesPapiersA(PapiersReceveur pr) {
$pr->voiciMesPapiers(this, papiers);
}
}
class Delinquant implements Gens {
public function donneTesPapiersA(PapiersReceveur pr) {
// Ne pas appeler voiciMesPapiers
}
}

Maintenant, question: si au lieu de retourner ses Papiers, le Délinquant passe un PotDeVin au Policier, comment tu fais en n'éditant que Delinquant et Policier (ce sont les deux seules classes qui devraient être impactées)?

En PHP West, Delinquant retourne directement un PotDeVin (puisqu'on se sert du fait qu'il n'y a pas de typage de retour dans les méthodes), et Policier fait le tri.

En PHP East, tu fais comment? J'ai cherché, mais je me retrouve à chaque fois obligé ou bien de casser le contrat de Gens dans Delinquant (Deliquant n'implémente plus Gens, ce qui cassera des codes ailleurs), ou bien d'altérer l'interface Gens, ce qui cassera aussi des codes ailleurs


RE: Compass : East Oriented - srm - 20-05-2015

Si tu appel ton getter askPaper() pour pouvoir mettre dedans $this->goAway()
Comment tu règles ce cas là :
Cas 5 : avant de donner mes papiers je veux savoir le matricule du policier.

Même si tu type le retour, tu es dépendant du type de retour vu que ça n'est pas toi qui choisis le retour.
Quand tu passes une interface, toi l'interface tu n'es dépendant de rien c'est toi qui impose comment on te parle, l'autre à pas le choix. Donc FileUploader à aucune dépendance à FileAggregator.

Donc ça t'embête de mettre à jour une interface, mais pas de mettre à jour un type de retour pour qu'il retourne une nouvelle valeur connu nul part .

Cas 1 :
Tu mets à jour ton interface pour y ajouter des trucs, quiconque l'utilisait voit directement au lancement de son programme que c'est cassé.

Cas 2 :
Tu as changé le retour de ton getter pour pouvoir retourner PotDeVin, personne le sait sans regarder l'intérieur de ton code, quelqu'un qui lance son programme et qui ne savait pas que tu avais ajouté le type de retour PotDeVin peut avoir un gros bug dans son programme.


RE: Compass : East Oriented - Xenos - 21-05-2015

Cas 5 : avant de donner mes papiers je veux savoir le matricule du policier.
C'est sûr que si askPaper() ne reçoit pas l'objet Policier (qui n'est d'ailleurs pas nécessairement l'appeleur de la méthode), askPaper() ne pourra pas discriminer les tâches à faire sur la base du matricule du Policier (puisque askPaper n'a pas accès au Policier).
Ce n'est donc pas une question d'East/West, mais une question de passer les paramètres utiles à la méthode appelée.


Même si tu type le retour, tu es dépendant du type de retour vu que ça n'est pas toi qui choisis le retour.
J'ai toujours pas compris: l'appelé choisit le typage du retour, donc, pas de problème? L'appeleur ne le choisit pas, okay, mais c'est lui qui lance le message (appelle la méthode), donc, cela veut dire que cette méthode (et sont typage de retour suivant les langage) lui conviennent?!

Ou alors, si c'est le typage de retour qui ne convient pas à l'appeleur, c'est juste qu'il lui manque un pattern Adapter à appliquer?!


Donc, là, l'avantage que tu exposes, c'est détecter les erreurs à la compilation plutôt qu'au RunTime? Okay, ça, je suis d'accord sur le principe.

En revanche, cette situation est spécifique à PHP: on aura des erreurs de compile sur Java ou C++ par exemple, mais même dans le cas de PHP, j'ai deux objections:
• La prochaine version implémentera (d'après niahoo) le typage des retours, donc la compilation sera cassée
• Le langage PHP actuel part du principe que les retours sont non typés, donc si un code considère qu'un retour est toujours d'un typage donné, en PHP, c'est une erreur puisque le langage autorise n'importe quel retour. Du coup, les codes "mal faits" (qui "typent" les retours alors que le langage ne le fait pas) seront effectivement cassés. Les bons codes (qui vérifient les retours car ceux-ci sont non-typés) ne seront pas cassés: PotDeVin tombera dans les if (!is_a($retour, Papiers)) throw new \Exception(...);.

C'est pour cela que East me semble rajouter, au niveau du code du développeur, des composantes qui sont en fait du ressort du langage lui-même, et ce genre de mélange de couches, je suis contre (le jour où le langage évolue, tous les "bricolages" de dev qui visaient à compenser un truc du langage seront inutiles et pollueront le code).



D'ailleurs, en West, Delinquant pourra retourner un PotDeVin sans cassure de code:
• Créer une nouvelle interface PapiersFictifs
• Y mettre ce que l'interface Papiers avait
• Etendre l'interface PapiersFictifs dans Papiers (interface Papiers extends PapiersFictifs)
• Optionnel: supprimer le contenu de Papiers qui est remonté dans PapiersFictifs
• Créer l'interface PotDeVin qui étends PapiersFictifs
• Modifier le typage de retour dans l'interface Gens, pour retourner PapiersFictifs
• Retourner un PotDeVin dans Delinquant

Ainsi:
Delinquant et TypeNormal implémentent toujours l'interface Gens
• Les codes qui utilisaient le Papiers retourné par TypeNormal ne sont pas cassés



RE: Compass : East Oriented - srm - 21-05-2015

Cas 5 :
Bah pas vraiment c'est toute la logique derrière East, tu envoies toujours un message et tu donnes le moyen que l'on te réponde.
Tout le principe est basé là dessus.
Si tu ne faisais pas du East tu te dirais je fais askPaper($policier) car tu te dis qu'il peut demander autre chose au Policier avant de répondre. Mais tu ne le feras pas systématiquement, tout comme tu ne feras pas toujours un ask mais souvent un getter.
Vu que le principe de East c'est d'envoyer un message et de donner le moyen de te répondre, tu feras TOUJOURS askSomething($asker)
au minimum bien entendu.

Quand je fais :

<?php

interface Policier
{
public function askMatriculeByPersonne(Personne $personne);
}

interface Personne
{
public function askPapier(Policier $policier)
}

class Delinquant implements Personne
{
public function askPapier(Policier $policier)
{
// J'ai beau être un délinquant, je ne peux faire avec Policier
// qu'une seule chose askMatriculeByPersonne et rien d'autre
}
}

Le délinquant est obligé de parler avec Policier selon le choix du dialogue du Policier (via l'interface Policier)
C'est le Policier qui a demandé des choses à Personne, donc c'est normal que ça soit Personne qui s'adapte à son discours.


interface Personne
{
public function getPapier(): Papier
}

class Delinquant implements Personne
{
public function getPapier(): Papier
{
return $this->papier;
}
}

Là le délinquant parle au Policier de la façon dont il veut alors que c'est le Policier qui a demandé des choses à Personne.
Donc Policier doit s'adapter à Personne.

Ça peut sembler sans importance. Pourtant quand tu vas changer Delinquant pour qu'il puisse retourner autre chose que juste Papier,
tu vas devoir obligatoirement changer Policier, alors que tu voulais peut-être qu'il te retourne autre chose pour un besoin qui a aucun rapport à Policier.


RE: Compass : East Oriented - Xenos - 21-05-2015

Donc, dans le Cas 5, il suffit d'appliquer la règle je passe toujours l'appelant en paramètre à mes méthodes, sans forcément faire de East.
Mais du coup, tu passes l'appelant partout, même s'il n'y en a pas besoin: cela va surcharger le nombre de paramètres inutiles des méthodes. Ne passer que ce qui sert a l'avantage de limiter le contexte auquel l'objet appelé peut accéder.


Citation :Le délinquant est obligé de parler avec Policier selon le choix du dialogue du Policier (via l'interface Policier)
Je ne vois pas l'intérêt: d'un part, tu te places dans un système de transitions, et non un système d'états (si Delinquant est contraint par l'origine du message qu'il a reçu, alors il faudra autant de méthodes que d'origine de message possible...), d'autre part cela crée une dépendance circulaire (au moins par la déclaration des classes) entre Policier→Delinquant (car le Policier demande les papiers au Delinquant) et entre Delinquant→Policier (car le Delinquant doit retourner "manuellement" ses papiers ou son pot de vin).

East obligerait donc l'appelé à se plier aux choix de l'appelant? En quoi est-ce une bonne chose?


Exemple d'explosion combinatoire des méthodes:

Si Policier et Douanier peuvent demander les papiers, alors on a:
TypeNormal donne toujours ses Papiers au Policier et au Douanier
Delinquant se base sur le matricule du Policier, son grade, son âge, et son sexe; pour le Douanier, il se base sur son grade, le n° de son poste frontière, sa corpulence, et sa position géographique.
Mafieux se base sur le matricule et le grade du Policier ou du Douanier
Policier et Douanier ne donnent leurs papiers que si le grade de celui qui les demande est supérieur

→ En West, 1 getPapiers() pour chaque classe, 4 getters sur Policier, 4 getters sur Douanier

En East, tu fais cela comment? Parce que si Policier et Douanier ont un machinAskedByDelinquant et machinAskedByMafieux, cela va faire... 16 méthodes ?!
Policier->matriculeAskedByDelinquant, Policier->matriculeAskedByMafieux, Policier->gradeAskedByDelinquant, Policier->gradeAskedByMafieux, Policier->gradeAskedByPolicier, Policier->gradeAskedByDouanier, Policier->ageAskedByDelinquant, Policier->sexeASkedByDelinquant, Douanier->matriculeAskedByMafieux, Douanier->gradeAskedByDelinquant, Douanier->numeroPosteAskedByDelinquant, Douanier->corpulenceAskedByDelinquant, Douanier->positionGeoAskedByDelinquant, Douanier->gradeAskedByMafieux, Douanier->gradeAskedByPolicier, Douanier->gradeAskedByDouanier

Et encore, je ne compte pas les méthodes de "retour" où l'information revient à l'appeleur, type $delinquant->askPapiers(Policier $policier) → $policier->gradeAskedByDelinquant(Delinquant $delinquant) → $deliquant->voiciMonGrade(Policier $policier, Grade $grade


RE: Compass : East Oriented - srm - 21-05-2015

Cas 5 :
Si tu fais juste ça, tu ne fais pas du East non, et tu n'as pas tous les avantages du East.

Vu que tous tes types héritent de la même interface par exemple Personne, tu auras que des xAskedByPersonne.
De même pour le retour.

Et c'est une bonne chose parce que par exemple si tu as :
papierAskedByPolicier(Policier $policier)
papierAskedByDarling(Darling $darling)

Dans le second cas tu sais que tu peux faire $darling->giveKiss($this); en plus de lui donner tes papiers.
C'est là tout l'avantage et la force, tu t'adaptes à l'interlocuteur.


RE: Compass : East Oriented - Xenos - 21-05-2015

Bon, je vais abandonner l'affaire, car je ne vois toujours pas l'intérêt qu'on aurait à adapter les appelés aux appelants plutôt que les appelants aux appelés (IRL, sans compensation monétaire, l'appelant s'adapte à l'appelé, sinon ce serait invivable ^^).
Le Darling::askPapiers(Darling $caller) marche aussi très bien en West (là encore, à condition de ne pas considérer les getter comme des accès aux attributs, mais bien comme des requêteurs).

Bonne nuit Smile