Convention lecture seule / écriture / privée

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Convention lecture seule / écriture / privée

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 21:39

je m'embête pas moi, pas besoin de bidouille
class maclasse
{
    private $mavar1;   //public 
    private $mavar2;   //readonly
    private $mavar3;   //private

    public function setMavar1($value)
    {
        $this->mavar1 = $value;
    }

    public function getMavar1()
    {
        return $this->mavar1;
    }

    public function getMavar2()
    {
        return $this->mavar1;
    }
}  
de tout façon même si on a 15 valeurs (et c'est rare) c'est que du copier coller et c'est plus claire, surtout niveau doc
Oui, au final, je m'étais trop basé sur C#. JAVA le fait, alors ... Le rajout d'appel Dynamique par __get et __set se serait un gadget. Je pense le mettre (Mes classes Graph sont des bacs à sable. J'essaie de faire un super code avec, et ils représentent des graphiques. Nul besoin de dire qu'il existe déjà d'excellentes bibliothèques pour ça ... mais c'est un très bon excercice).
voir la meme pour le public c'est en trop autant mettre direct public des fois, un truc sympa par contre si t'as envie d'un autre bon exercice c'est un classe qui créer des fichier de classes :wink:
Lol ... là l'idée est partie de l'intégration d'un simple graph comme stats pour mon entreprise. Je l'ai codé en procédural à l'arrache au début, ça marchait nickel, puis j'ai modelé, modelé ... je me trouve maintenant avec ColorGraph, BattonGraph (frère d'un éventuel futur CamemberGraph), MapGraph (qui gère les chiffres mais surtout qui implémente Iterator) et son enfant MonthMapGraph (qui se charge de créer une liste cohérente de chaque jours d'un mois/année), et son futur enfant YearMapGraph (liste cohérente sur l'échelle d'une année). Ainsi je lui dis

$machin = array(1=>31,5=>22,15=>35); // Si je commence par 0 ou que je mets des strings ou > au nombre de jours dans le mois (voir la suite), erreur !
$maliste = new MonthMapGraph($machin, 1, 2010); // Crée une liste du jour 1 au jour 28 à 31 (selon le mois donné et l'année), où il met 0 pour chaque jour non précisé
$mongraph = new BattonGraph ($maliste); // Simple instanciation avec déclaration de valeur par défaut, n'accepte que des MapGraph et enfants comme paramètre
$mongraph->labelText = "Mon graphique de Janvier 2010";
$mongraph->blocksColor = ColorMap::rgb (255,0,0); // Et là j'aimerais pouvoir lui dire ColorMap::red; Si je mets autre chose qu'un objet ColorGraph, erreur ! Si à colorGraph, je lui mets 256 de rouge, erreur ! Bref ... contrôle partout, mais au moins, BattonGraph s'occupe de dessiner un truc, pas de contrôler si la couleur qu'on lui donne ou la liste qu'on lui donne est bonne, c'est pourquoi il "délègue" à d'autres objets
$mongraph->draw(); // Me dessine et renvoie mon graphique, avec les valeurs par défaut sauf ceux que j'ai modifié

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 21:27

tu sais que pour vérifier les mail t'as filter_var avec FILTER_VALIDATE_EMAIL, la plupart des regexp qu'on trouve sont faux
La plupart oui. Ils interdisent par exemple les extensions > 3 caractères ... Je connais FILTER_VALIDATE_EMAIL, mais pas par coeur. Pour éviter d'aller chercher ça sur internet là, ce qui n'était pas la question, j'ai préféré mettre preg_match.

Par contre, les normes en matière d'email semblent très laxistes (parait qu'on peut mettre des espaces, et presque tous les caractères du clavier dedans), alors que les regex ET (d'après ce que j'ai entendu) FILTER_VALIDATE_EMAIL serait "trop" sévère. Moi je pense surtout que c'est pas très intelligent d'autoriser les espaces dans un email ... demain on trouvera peut-être http://www.$goo |gle.com ...

Re: Convention lecture seule / écriture / privée

par stealth35 » 13 oct. 2010, 21:25

je m'embête pas moi, pas besoin de bidouille
class maclasse
{
    private $mavar1;   //public 
    private $mavar2;   //readonly
    private $mavar3;   //private

    public function setMavar1($value)
    {
        $this->mavar1 = $value;
    }

    public function getMavar1()
    {
        return $this->mavar1;
    }

    public function getMavar2()
    {
        return $this->mavar1;
    }
}  
de tout façon même si on a 15 valeurs (et c'est rare) c'est que du copier coller et c'est plus claire, surtout niveau doc
Oui, au final, je m'étais trop basé sur C#. JAVA le fait, alors ... Le rajout d'appel Dynamique par __get et __set se serait un gadget. Je pense le mettre (Mes classes Graph sont des bacs à sable. J'essaie de faire un super code avec, et ils représentent des graphiques. Nul besoin de dire qu'il existe déjà d'excellentes bibliothèques pour ça ... mais c'est un très bon excercice).
voir la meme pour le public c'est en trop autant mettre direct public des fois, un truc sympa par contre si t'as envie d'un autre bon exercice c'est un classe qui créer des fichier de classes :wink:

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 21:23

je m'embête pas moi, pas besoin de bidouille
class maclasse
{
    private $mavar1;   //public 
    private $mavar2;   //readonly
    private $mavar3;   //private

    public function setMavar1($value)
    {
        $this->mavar1 = $value;
    }

    public function getMavar1()
    {
        return $this->mavar1;
    }

    public function getMavar2()
    {
        return $this->mavar1;
    }
}  
de tout façon même si on a 15 valeurs (et c'est rare) c'est que du copier coller et c'est plus claire, surtout niveau doc
Oui, au final, je m'étais trop basé sur C#. JAVA le fait, alors ... Le rajout d'appel Dynamique par __get et __set se serait un gadget. Je pense le mettre (Mes classes Graph sont des bacs à sable. J'essaie de faire un super code avec, et ils représentent des graphiques. Nul besoin de dire qu'il existe déjà d'excellentes bibliothèques pour ça ... mais c'est un très bon excercice).

Re: Convention lecture seule / écriture / privée

par stealth35 » 13 oct. 2010, 21:19

tu sais que pour vérifier les mail t'as filter_var avec FILTER_VALIDATE_EMAIL, la plupart des regexp qu'on trouve sont faux

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 21:17

Code : Tout sélectionner

public function setMailTo ($value) { if (!is_string($value)) throw ... if (!preg_match("/(mail)/",$value)) throw ... $this->mailTo = $value; }
La validation de mes données c'est ce qui me pousse à améliorer mon système actuel (enfin d'hier et d'avant hier). la fonction setMailTo s'occupe justement d'être un setteur, un validateur de type et un validateur de données. Ca peut paraitre beaucoup, mais au moins, la classe définit des règles précises à l'utilisateur, et quand elle utilise une propriété, elle est sûre qu'elle peut lui faire confiance (un is_null ou isset avant parait cependant nécessaire).

Pour revenir à Mail, il s'agit d'une classe crée auparavant avec ses vérifications (comme ma classe ColorGraph). Lorsque l'on utilise Mail (avec __tostring par exemple donc directement en tant que chaine, ou en réservant un getter de contenu de type $instanceMail->mail en lecture seule), on est sûr qu'il s'agisse bien d'une adresse e-mail "valide". Tout comme ma classe ColorGraph renvoit un objet ColorGraph, que l'on appelle ColorGraph::rgb(int r > 0 && < 256, int v > 0 && < 256, int b > 0 && < 256) ou ColorGraph::hex (string code); Ainsi ma classe BattonGraph peut tranquillement utiliser quelque instance ColorGraph que ce soit : elle sera toujours valide.

Ca part un peu du principe que, quand ça m'arrange, tout est objet.

Pour ColorGraph, on peut accéder aux canaux RVB avec $monColorGraph->red, ... en lecture seulement. Ca lui assure une intégrité parfaite. Seul hic par contre c'est que $x instanceof $y est très laxiste, et autorise tous les parents de $y ... get_class() répond certainement à cette problématique.

Re: Convention lecture seule / écriture / privée

par stealth35 » 13 oct. 2010, 21:10

je m'embête pas moi, pas besoin de bidouille
class maclasse
{
    private $mavar1;   //public 
    private $mavar2;   //readonly
    private $mavar3;   //private

    public function setMavar1($value)
    {
        $this->mavar1 = $value;
    }

    public function getMavar1()
    {
        return $this->mavar1;
    }

    public function getMavar2()
    {
        return $this->mavar1;
    }
}  
de tout façon même si on a 15 valeurs (et c'est rare) c'est que du copier coller et c'est plus claire, surtout niveau doc

Re: Convention lecture seule / écriture / privée

par Cyrano » 13 oct. 2010, 21:03

Mouais, sauf que tu n'es pas en Java mais en PHP. Faire un truc comme ceci :
public function setMailTo (Mail $value) 
{
    // Mail is class Mail comme le type Url pour AS3, on peut écrire aussi : if (!$value instanceof Mail) throw ...
    $this->mailTo = $value;
}
En PHP, ça sous-entend que ton paramètre doit être un objet de type Mail correspondant à une classe du même nom, et non une chaine.

J'ai l'impression que tu voudrais t'affranchir de quelques lignes de validation mais je crains fort que tu n'ailles au devant de déconvenues sur ce point. Mais ça ne signifie pas pour autant que tu doives écrire des millions de lignes de code : si tu reprends l'exemple que j'ai cité dans ma première réponse sur ce sujet, tu peux observer que j'utilise un tableau dans mon getter magique et un autre dans mon setter magique. L'idée qui pourrait être développée serait d'utiliser un tableau à deux dimensions qui te permettrait de stocker les types en premier niveau et les propriétés en second niveau selon le type. Et dans ce cas, tu rajoutes la validation du type de données à partir de l'index correspondant: Et là mon getter ne change pas, mais mon setter magique si, et la classe exemple de début deviendrait :
<?php
class maclasse
{
    const ACCES_PRIVE   = "Accès en %s à la propriété privée %s interdit";
    const TYPE_INVALIDE = "La propriété %s doit être de type %s, la valeur reçue est invalide";
    /**
     * @var String
     */
    private $mavar1;
    /**
     * @var Boolean
     */
    private $mavar2;
    /**
     * @var Int
     */
    private $mavar3;

    /**
     * Getter magique
     *
     * Retourne la valeur de la propriété uniquement si elle
     * est mentionnée dans les accès autorisés en lecture
     */
    public function __get($mavar)
    {
        $aLecture = array('mavar2', 'mavar3');
        if (in_array ($mavar, $aLecture))
        {
            return ($this->{$mavar});
        }
        else
        {
            $erreur = sprintf (self::ACCES_PRIVE, 'lecture', $mavar);
            throw new Exception ($erreur, E_USER_WARNING);
        }
    }
   
    /**
     * Setter magique
     *
     * Affecte la valeur à la propriété uniquement si elle
     * est mentionnée dans les accès autorisés en écriture
     * et que le type de valeur envoyé correspond au type attendu
     */
    public function __set($mavar, $valeur)
    {
        $aEcriture = array(
            'bool' => array('mavar2'),
            'int' => array('mavar3')
        );
        if (in_array ($mavar, $aEcriture['bool']))
        {
            if(is_bool($valeur))
            {
                $this->{$mavar} = $valeur;
            }
            else
            {
                $erreur = sprintf (self::TYPE_INVALIDE, $mavar, 'booléen');
                throw new Exception ($erreur, E_USER_WARNING);
            }
        }
        elseif (in_array ($mavar, $aEcriture['int']))
        {
            if(is_int($valeur))
            {
                $this->{$mavar} = $valeur;
            }
            else
            {
                $erreur = sprintf (self::TYPE_INVALIDE, $mavar, 'entier');
                throw new Exception ($erreur, E_USER_WARNING);
            }
        }
        else
        {
            $erreur = sprintf (self::ACCES_PRIVE, 'écriture', $mavar);
            throw new Exception ($erreur, E_USER_WARNING);
        }
    }
}
TU peux faire des variantes mais tu n'échapperas pas à la nécessité de valider les valeurs.

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 20:46

LOL ! Le même sujet quasiment ... http://stackoverflow.com/questions/8750 ... rs-in-java

La personne se pose au final à peu près la même question ...

D'ailleurs, je suis peut-être un peu bête ... je pourrais très bien définir des setMachin et getMachin partout et utiliser __get et __set pour rediriger automatiquement vers le bon setter ...

Du genre

public function __get ($var) {
if (methods_exists(array($this,'get' . ucfirst($var)))) return $this->('get' . ucfirst($var))(); // Attention, j'écris ça comme ça, c'est assez spéciale, il faudra peut-être passer par une fonction d'appel de méthode genre call_user_fnct ...
throw new Exception (...); // Si la méthode n'existe pas : t'as pas le droit d'écrire dessuss !!!
}

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 20:36

Je crois que je vais utiliser les getters setters en méthodes. Si ... j'ai bien compris, je ne suis pas vraiment novice en programmation, mais assez en programmation de groupe et conventionnelle. Ma méthode (ma ?) répond à toutes mes attentes, sauf à celle du contrôle de données. Et là, c'est finalement très embetant. En plus, elle se base d'un point de vue typage, à une valeur antérieure, ce n'est pas le top.

Au final, je pense que le setter devrait ressembler à ça

public function setBlocksWidth ($value) {
if (!is_int($value)) throw new ...
if ($value < 0) throw new ...
$this->blockWidth = $value;
}

On pourrait pousser plus loin, par exemple si on crée une classe d'envoi d'email.

ClassMail.setMailTo ("[email protected]"); // Coté utilisateur
ClassMail.setMailTo ("machin"); // Coté utilisateur
ClassMail.setMailTo (2); // Coté utilisateur

class (...)

public function setMailTo ($value) {

if (!is_string($value)) throw ...
if (!preg_match("/(mail)/",$value)) throw ...
$this->mailTo = $value;

}

et imaginer pour une programmation avancée un simple

public function setMailTo (Mail $value) {

// Mail is class Mail comme le type Url pour AS3, on peut écrire aussi : if (!$value instanceof Mail) throw ...
$this->mailTo = $value;

}

On sera alors certain (non ?) lors de l'envoi d'email que $mailTo sera correct ... après avoir vérifié qu'il a bien une valeur ;)

Cela me permettra ainsi aussi de vérifier que la valeur donnée correspont bien à une liste de constante de class comme BLOCKS_FULL, BLOCKS_BORDER, etc

Une critique ?

PS : Je n'aime pas trop C# pour son côté Microsoft, mais il faut bien lui accorder que les getters et setters en tant que propriété et non pas méthodes, c'est quand même top ... et les indexeurs aussi (JAVA fait aussi je crois) ;)

Re: Convention lecture seule / écriture / privée

par Cyrano » 13 oct. 2010, 20:21

Je me demande si ce que j'ai écrit plus haut a correctement été lu : il n'existe aucun lien direct entre la visibilité d'une propriété et son type. Je peux avoir des entiers privés, des tableaux public, des objets protégés et que sais-je encore dans toutes les variantes de combinaisons possibles : il n'y a pas de lien de cause à effet.

Quant au getter/setter, ce sont des méthodes qui nativement ne gèrent pas les types. Vous pouvez bien utiliser des astuces, mais encore faut-il qu'elles soit valables pour valider les types de données que vous envoyez. Or le fait qu'une propriété soit privée, publique ou protégée n'interdira pas qu'elle soit initialisée avec un type de données inapproprié si aucun test n'est fait avec les fonctions natives prévues pour ça.

Enfin, je rappelle que le PHP est un langage très faiblement typé. Ça offre une certaine souplesse même si ça demande en contre-partie un peu de rigueur.

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 20:08

Oops je viens de retirer JAVA de JAVA - C#. C# utilise des getters et setters en passant par la propriété (pour lire ou écrire sur le "champs"), mais JAVA apparemment, n'a rien de spécial. Il faut donc créer des getMachin etc. Par contre, le typage est plus facile, ainsi un setteur tient sur une expression de code. Alors que là il faudrait lui dire (is_int($var)) ? $this->machin = $var : throw new Exception ("pov type !");

Bref, c'est vrai qu'au final, c'est pas forcément différent ;) Je trouve en tout cas que définir un getter et setter principal est plutot pas mal et allège le code, en plus du type.

Ce que j'apprécie vraiment dans ça, mais j'aime savoir tout ce qu'il y a autour, d'où la discution, c'est que c'est un codage réduit (deux méthodes, contre 40 pour 20 propriétés lecture-ecriture, qui dit mieux ?), tout en passant "directement" par les propriétés (en apparence pour l'utilisateur de la classe), tout en controlant le type, ...

De toutes façons, le seul argument qui m'a poussé à ne pas utiliser "public" pour ces propriétés, c'est le typage ... :)

Re: Convention lecture seule / écriture / privée

par Cyrano » 13 oct. 2010, 19:37

...ca éloigne de l'esprit JAVA et C#...
Dans un sens, ça tombe bien, ici on fait du PHP :-*

Re: Convention lecture seule / écriture / privée

par devlop78 » 13 oct. 2010, 19:34

Soucis pour les variables ?

Oui car passer par setPropriété, c'est passer (pour l'utilisateur), par une méthode et non par la propriété, pareil pour getPropriete, c'est très long pour des dizaines de propriétés (comme dans mon cas), et en plus ... oui je suis un grand flemmard. J'ai pas envie de m'amuser à taper éternellement if (is_int($var)) dans chaque setPropriété ... je préfère le faire qu'une fois, et au lieu de "int var" ou de "var:int" (as3), je fais $var = 0 et Hop, dans mon setter, il sait que j'attends un integer. Et c'est valable pour tout. D'ailleurs ça me fait penser à un beug ... si j'oublie de lui mettre une valeur il risque de tout interdire ^^. En tout cas, ça m'évite de me retrouver avec des chaines de caractères là où j'attends un nombre, et c'est une vérification et un risque en moins. Par contre, je dois contrôler en plus, et là, pas le choix (sauf en AS3, avec uint pour > 0 héhé) le contenu (par exemple, vérifier que le nombre est > 0 ou qu'il est inclu entre 0 et 3 ou qu'il est égale à une des constantes de la classe, etc.

Re: Convention lecture seule / écriture / privée

par stealth35 » 13 oct. 2010, 10:53

j'ai jamais eu ce soucis moi, c'est par flemme de faire des getVariable et setVariable ?