OVH Cloud OVH Cloud

Differentes conceptions possibles

14 réponses
Avatar
jeremie.fouche
Bonjour

Je developpe plusieurs module (?) pour différents sites (newsletter,
livre d'or, agenda, gestion financiere, ...) sous forme de classes
PHP.

Prenons l'exemple de la newsletter : aujourd'hui, elle n'est qu'une
classe qui représente l'interface vers ma BdD, ie: Get, GetById,
Create, Update, Delete. Je fourni aux méthodes les valeurs "propres"
(validés) grace au script principal.

Ma structure est la suivantes :

newsletter.php : le script principal
newsletter.class.php : la class Newsletter

Dans newsletter.php je fais donc :

require_once('newsletter.class.php');
$newsletter = new Newsletter;
if (isset($_REQUEST['creer_message'])) {
# Test de la validation des champs
if ($isValid)
$newsletter->Create( $_REQUEST['message'], $_REQUEST['visible'] );
}

etc...

Je me dis que ce serait plus "logique" (?) de faire tous ces test dans
la classe Newsletter. Si je ne l'ai pas fais jusqu'a aujourd'hui,
c'est parce que je me dis que l'utilisateur n'utilisera pas forcement
les même noms pour les champs.
Bon, supposons que je documente suffisement cet outil pour expliquer
qu'il faille utiliser certains noms pour les champs, comment integrer
ca proprement ?
1 - Créer une méthode Start() qui ferait un test sur plusieurs valeurs
de $_REQUEST ? Donc ne pas oublier d'appeler $newsletter->Start() au
début du script.
2 - Mettre ca dans le constructeur de la classe (mais attention lors
de l'héritage, car il faut que la classe dérivé, si elle possede un
constructeur, appelle bien le constructeur de la classe parent) ?
3 - d'autres idées

Personnellement, j'ai un a-priori négatif sur les constructeur car
j'ai peur de souvent oublier d'appeller les constructeurs des classes
meres dans les classes dérivés.

Pour info, voici ma classe Newsletter (basée sur la PHPLib) :

class Newsletter
{
var $dbTable = 'newsletter';
var $maxNews = 20;

// Newsletter::GetNewsletter
function GetNewsletter($visibles=true, $mask='*')
{
$req = sprintf( "SELECT %s FROM %s WHERE %s ORDER BY id DESC LIMIT
%d"
, $mask
, $this->dbTable
, $visibles ? "visible LIKE 'O'" : '1'
, $this->maxNews );
$db = new Je_DB_Sql($req);

$newsletter = array();
while ($db->next_record())
{
$newsletter[] = $db->Record;
}
return $newsletter;
}

// Newsletter::GetNews
function GetNews($id, $mask='*')
{
$req = sprintf( "SELECT %s FROM %s WHERE id='%s' LIMIT 1"
, $mask
, $this->dbTable
, $id );
$db = new Je_DB_Sql($req);
$news = false;
if ($db->next_record())
{
$news = $db->Record;
}
return $news;
}

// Newsletter::CreateNews
function CreateNews($message, $bVisible)
{
$req = sprintf( "INSERT INTO %s VALUES('',NOW(),'%s','%s')"
, $this->dbTable
, mysql_escape_string($message)
, $bVisible ? 'O' : 'N' );
$db = new Je_DB_Sql($req);
return ($db->affected_rows()==1);
}

// Newsletter::UpdateNews
function UpdateNews($id, $message, $bVisible)
{
$req = sprintf( "UPDATE %s SET message='%s', visible='%s' WHERE
id='%s'"
, $this->dbTable
, mysql_escape_string($message)
, $bVisible ? 'O' : 'N'
, $id );
$db = new Je_DB_Sql($req);
return ($db->affected_rows()==1);
}

// Newsletter::DeleteNews
function DeleteNews($id)
{
$req = sprintf( "DELETE FROM %s WHERE id='%s'"
, $this->dbTable
, $id );
$db = new Je_DB_Sql($req);
return ($db->affected_rows()==1);
}
}

Toutes les critiques et informations sont les bienvenues.

--
Jérémie

10 réponses

1 2
Avatar
Vincent Lascaux
require_once('newsletter.class.php');
$newsletter = new Newsletter;
if (isset($_REQUEST['creer_message'])) {
# Test de la validation des champs
if ($isValid)
$newsletter->Create( $_REQUEST['message'], $_REQUEST['visible'] );
}

etc...

Je me dis que ce serait plus "logique" (?) de faire tous ces test dans
la classe Newsletter.


Pour les isset($_REQUEST[...]), je pense que c'est au script du display de
faire les tests.
Pour les tests de validation des champs, ca peut être sensé de le faire
faire par la classe newsletter si la validation est intrinseque (ex: si il y
a une adresse email, on sait comment l'adresse email doit être formattée,
mais si ta validation consiste à interdire certains mots, ca ne peut pas
aller dans la classe newsletter).

Si je ne l'ai pas fais jusqu'a aujourd'hui,
c'est parce que je me dis que l'utilisateur n'utilisera pas forcement
les même noms pour les champs.
Bon, supposons que je documente suffisement cet outil pour expliquer
qu'il faille utiliser certains noms pour les champs, comment integrer
ca proprement ?


Oui, mais moi je veux insérer dans ma newsletter des données qui viennent
d'autre part... Disons que j'ai un script qui lit une boite mail et comme ca
on peut envoyer générer une entrée dans la newsletter en envoyant un email.
Je fais comment si newsletter regarde necessairement $_REQUEST ?

--
Vincent

Avatar
bruno modulix
jeremie fouche wrote:
Bonjour


(snip)

Prenons l'exemple de la newsletter : aujourd'hui, elle n'est qu'une
classe qui représente l'interface vers ma BdD, ie: Get, GetById,
Create, Update, Delete. Je fourni aux méthodes les valeurs "propres"
(validés) grace au script principal.

(snip code)


Je me dis que ce serait plus "logique" (?) de faire tous ces test dans
la classe Newsletter.


Ca dépend lesquels... En ce qui me concerne, je suis partisan d'une
bonne séparation entre la logique 'métier' (ici ta classe newsletter),
la logique 'applicative' (l'appli qui utilise ta classe) et la
présentation. Bref, du MVC sauce web !-)

De ce point de vue, le fait d'avoir un script "controleur" qui
décortique la requête et dispatche vers les objets et méthodes qui vont
bien me semble parfaitement ok. Si quelqu'un veut réutiliser ta classe
dans un autre contexte, il a des chances de pouvoir le faire en n'ayant
que le contrôleur (et éventuellement les vues) à modifier.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"

Avatar
jeremie.fouche
bruno modulix wrote in message news:<425d515b$0$32081$...
Je me dis que ce serait plus "logique" (?) de faire tous ces test dans
la classe Newsletter.


Ca dépend lesquels... En ce qui me concerne, je suis partisan d'une
bonne séparation entre la logique 'métier' (ici ta classe newsletter),
la logique 'applicative' (l'appli qui utilise ta classe) et la
présentation. Bref, du MVC sauce web !-)

De ce point de vue, le fait d'avoir un script "controleur" qui
décortique la requête et dispatche vers les objets et méthodes qui vont
bien me semble parfaitement ok. Si quelqu'un veut réutiliser ta classe
dans un autre contexte, il a des chances de pouvoir le faire en n'ayant
que le contrôleur (et éventuellement les vues) à modifier.


Exactement. A la base, c'est ce que je voulais. Mais dans la partie
administration du site, je peux avoir potentiellement les mêmes tests
a effectuer que dans une autre partie du site, et aujourd'hui, mon
controlleur est le script principal de la page.

Exemple typique, un livre d'or : Dans la partie public, il faut le
remplir. Dans la partie administration, on peut laisser le choix de
corriger les fautes d'orthographes, permettre de valider le message
pour etre présent sur le site ou non... Bon, le controleur doit etre
présent 2 fois. Solution ? Etre bien attentif que si l'on change le
controleur dans la partie public, il faille le modifier aussi dans la
partie administration ? faire un script newsletter.control.php (qui
permet de centraliser dans un seul script le controleur, ce que tu
proposes) ?

Je veux bien mais n'est pas un peu lourd ? Surtout que je n'aime pas
appeler de scripts qui s'appuient sur des nomps de variables (car je
suppose que le controleur s'appuie directement sur une variable qui
s'appelle $newsletter de type class Newsletter). Peut etre créer une
class Controleur et hériter (NewsletterControler), qui serait une
variable membre de ma classe newsletter... Mais je divague la, non ?
J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.

--
Jérémie


Avatar
jeremie.fouche
Vincent Lascaux wrote in message news:<425d3b3e$0$6566$...
Je me dis que ce serait plus "logique" (?) de faire tous ces test dans
la classe Newsletter.


Pour les isset($_REQUEST[...]), je pense que c'est au script du display de
faire les tests.
Pour les tests de validation des champs, ca peut être sensé de le faire
faire par la classe newsletter si la validation est intrinseque (ex: si il y
a une adresse email, on sait comment l'adresse email doit être formattée,
mais si ta validation consiste à interdire certains mots, ca ne peut pas
aller dans la classe newsletter).


Je comprends.

Si je ne l'ai pas fais jusqu'a aujourd'hui,
c'est parce que je me dis que l'utilisateur n'utilisera pas forcement
les même noms pour les champs.
Bon, supposons que je documente suffisement cet outil pour expliquer
qu'il faille utiliser certains noms pour les champs, comment integrer
ca proprement ?


Oui, mais moi je veux insérer dans ma newsletter des données qui viennent
d'autre part... Disons que j'ai un script qui lit une boite mail et comme ca
on peut envoyer générer une entrée dans la newsletter en envoyant un email.
Je fais comment si newsletter regarde necessairement $_REQUEST ?


Et je suis même convaincu. Je vais donc garder cette interface.
Merci
--
Jérémie


Avatar
Vincent Lascaux
Je veux bien mais n'est pas un peu lourd ? Surtout que je n'aime pas
appeler de scripts qui s'appuient sur des nomps de variables (car je
suppose que le controleur s'appuie directement sur une variable qui
s'appelle $newsletter de type class Newsletter). Peut etre créer une
class Controleur et hériter (NewsletterControler), qui serait une
variable membre de ma classe newsletter... Mais je divague la, non ?
J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.


Peut être plus simplement dériver Newsletter vers CheckedNewsletter dans
laquelle les fonction Create, Delete... vérifient de façon plus "drastique"
les arguments (par exemple controle de droit pour Delete, empêcher le flood
pour Create...)
Peut être même trouver un meilleur nom que CheckedNewsletter.

C'est plus simple que le design avec NewsletterControler, mais on perd un
peu : on ne peut pas changer le controller en cours de route, on ne peut pas
construire des controlleurs complexes à partir de plusieurs controlleurs par
exemple.

--
Vincent

Avatar
bruno modulix
jeremie fouche wrote:
bruno modulix wrote in message news:<425d515b$0$32081$...


(snip)
De ce point de vue, le fait d'avoir un script "controleur" qui
décortique la requête et dispatche vers les objets et méthodes qui vont
bien me semble parfaitement ok.



(snip)

Exactement. A la base, c'est ce que je voulais. Mais dans la partie
administration du site, je peux avoir potentiellement les mêmes tests
a effectuer que dans une autre partie du site (snip).


Tu peux hiérarchiser tes controleurs (un controleur principal qui
effectue les traitements communs, puis dispatche à un controleur
spécifique), ou rappeler une API de vérif commune depuis chaque contrôleur.
(snip)

Bon, le controleur doit etre
présent 2 fois. Solution ? Etre bien attentif que si l'on change le
controleur dans la partie public, il faille le modifier aussi dans la
partie administration ?


Ceci devrait être éviter ("Dont Repeat Yourself", "Single Point Of
Truth", etc)

faire un script newsletter.control.php (qui
permet de centraliser dans un seul script le controleur, ce que tu
proposes) ?


C'est une solution.

Je veux bien mais n'est pas un peu lourd ?
Pourquoi ?


Surtout que je n'aime pas
appeler de scripts qui s'appuient sur des nomps de variables (car je
suppose que le controleur s'appuie directement sur une variable qui
s'appelle $newsletter de type class Newsletter).


Le contrôleur peut très bien instancier lui-même l'objet newsletter.

Peut etre créer une
class Controleur et hériter (NewsletterControler),


S'il y a du code à factoriser, ou si tu veux utiliser des template
method, oui. Sinon, ça n'a pas d'intérêt. En PHP - comme dans tous
langage dynamique - l'héritage n'est rien d'autre qu'un mécanisme de
réutilisation de code.

qui serait une
variable membre de ma classe newsletter...


Non.

Une classe métier n'a pas à connaitre quoi que ce soit d'autre que son
métier. Elle n'a pas à connaître ni le controleur, ni les vues. C'est le
controleur et les vues qui connaissent la (les) classe(s) métier.

Enfin, AMHA, c'est mon opinion que je partage, etc...

Mais je divague la, non ?
J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.


John est un pur et dur de l'ancienne école[1], et - au moins dans le
cadre du développement web en PHP - son avis vaut d'être écouté et
médité. Mais pas forcément suivi à la lettre !-)

S'acharner à copier Java est AMHA une très mauvaise idée. Maintenant, ça
n'interdit pas de réfléchir à une architecture propre, cohérente, et
permettant autant que possible la modularité, l'extensibilité et la
réutilisation[2].

Le challenge est de faire ça au plus simple, sans quoi on arrive à un
résultat à l'opposé du but recherché. En tout état de cause, moins une
classe métier dépend de son environnement (contrôleurs et vues), plus
elle a de chances de fonctionner correctement et d'être réutilisable
dans un autre environnement.

[1] ... ou en tous cas il fait tout son possible pour donner cette
image... non, John, pas taper, pas taper !-)

[2] NB: ce dernier point ne se décrète pas, il nait de la réutilisation
effective - mais encore faut-il que cette réutilisation soit
techniquement possible.

Mes deux centimes...


--
bruno desthuilliers
ruby -e "print ''.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
John GALLET
Bonsoir,

Exemple typique, un livre d'or : Dans la partie public, il faut le
remplir. Dans la partie administration, on peut laisser le choix de
corriger les fautes d'orthographes, permettre de valider le message
pour etre présent sur le site ou non... Bon, le controleur doit etre
présent 2 fois.


Perso, je fais deux "controleurs" séparés qui appellent les mêmes
fonctions bas niveau car de toutes façons je ne valide pas les mêmes
données fonctionnelles dans le back et le front.

Eventuellement, je m'écris rapidement un petit générateur de code (deux
trois scripts awk, rien de compliqué) qui me pré-mâche la partie
syntaxiquement pénible à partie du create table s'il y en a un.

Pour plus d'informations sur ma gestion "usuelle" des interfaces types
formulaire html, tu peux consulter ou le pdf que je diffuse sur
www.saphirtech.com ou
http://groups-beta.google.com/group/fr.comp.lang.php/msg/5ef3ab01ba873698

Je veux bien mais n'est pas un peu lourd ? Surtout que je n'aime pas
appeler de scripts qui s'appuient sur des nomps de variables


J'ai du mal à voir ce que tu veux dire. Si tu veux dire
require($toto.'.php') alors oui, c'est la porte ouverte à n'importe quoi,
où alors il faut faire vachement gaffe que $toto ne soit JAMAIS repêché
directement d'où que ce soit (ni $_REQUEST, ni $_SESSION, ni le sgbd) mais
bien affecté de manière déterministe et explicite.

J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.


C'est tout à fait possible, mais j'avoue que je n'ai plus le contexte,
aurais-tu un msg-id STP ?

a++;
JG

Avatar
jeremie.fouche
John GALLET wrote in message news:...
Je veux bien mais n'est pas un peu lourd ? Surtout que je n'aime pas
appeler de scripts qui s'appuient sur des nomps de variables


J'ai du mal à voir ce que tu veux dire. Si tu veux dire
require($toto.'.php') alors oui, c'est la porte ouverte à n'importe quoi,
où alors il faut faire vachement gaffe que $toto ne soit JAMAIS repêché
directement d'où que ce soit (ni $_REQUEST, ni $_SESSION, ni le sgbd) mais
bien affecté de manière déterministe et explicite.


Non, non, ne t'inquiete pas, je ne fais jamais ca. Je parlais plutot
du contexte de variable global d'un script a l'autre. J'essaye de
faire en sorte que chacun de mes scripts soit entierement autonome.
En gros, si j'ai un script principal qui crée une variable
$newsletter, je n'ai pas tellement envie qu'un autre script se serve
de cette variable. J'ai bien entendu des fois ou je n'ai pas le choix,
mais j'essaye de limiter au maximum.

J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.


C'est tout à fait possible, mais j'avoue que je n'ai plus le contexte,
aurais-tu un msg-id STP ?


http://minilien.com/?BE3q5TfH8x

--
Jérémie


Avatar
John GALLET
Re,

Non, non, ne t'inquiete pas, je ne fais jamais ca. Je parlais plutot
du contexte de variable global d'un script a l'autre.


Cette notion est beaucoup plus ambigue avec les SSI. En ce qui me
concerne, quand je fais dans main.php l'instruction require('toto.php');
je considère que ces deux scripts ne font qu'un, donc que l'espace de
nommage est le même donc que j'ai toujours une variable locale.

En gros, si j'ai un script principal qui crée une variable
$newsletter, je n'ai pas tellement envie qu'un autre script se serve
de cette variable.


Dans ce cas le plus simple est de passer par des définitions de constantes
si aucun autre "module" (script, fonction, méthode d'objet, etc...) n'a
besoin d'en modifier le contenu, ou par des fonctions/méthodes. Mais à
part à se protéger différemment des injections de variables, avec les SSI,
bien souvent, ça ne sert pas à grand chose de plus.

J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.
http://minilien.com/?BE3q5TfH8x




Une fois de plus, j'ai la preuve que tous ceux dont c'est le métier de
s'autoproclamer experts en la matière de "l'auteur a voulu dire que"
feraient très souvent mieux de la fermer avant de l'ouvrir.

Ce que je dis dans cet article que tu pointes, ce n'est pas "masturbation
intellectuelle", ou plus précisement, même si on peut arriver à le déduire
de mes propos, c'est une conséquence très anodine et complètement à côté
du vrai message.

Ce que je voulais dire dans cet article, c'est qu'il y a un énorme
décalage entre la **simplicité du besoin** et la complexité de la solution
apportée. Dit autrement, tu prends une bombe atomique pour écraser une
puce. Certes, ça te débarrassera de la puce (encore que, c'est résistant
ces sales bêtes). Mais il y avait probablement une solution plus en
adéquation avec le besoin.

Ton besoin, pour faire du web dynamique, c'est quoi sur le fond ?

[avertissement pour la suite : Bruno a parfaitement raison de rappeler que
ce que je dis là s'applique à du web dynamique, je ne tiendrai pas le même
discours sur d'autres types d'applications]

A. au niveau d'une page individuelle

1. recevoir XX data, les filtrer pour des raisons évidentes de sécurité.

2. les valider fonctionnellement en fonction du traitement à leur
appliquer. Il y a eut au préalable aiguillage vers la bonne fonctionnalité
(ou en envoyant les données à toto1.php ou toto2.php, ou en ayant une
variable $action, ou en déduisant du contexte...)

3. si tout est bon, lancer le traitement, générer la page suivante et fin.

4. sinon (et ceci gère le cas de la première arrivée sur la page) générer
la page de saisie des données.

B. au niveau de la navigation
Gérer la notion de session.

C. Au niveau des traitements côté serveur
Gérer l'interaction bas niveau avec un sgbdr, un serveur de cours temps
réel, un annuaire ldap, un centre de tri disptcher par pigeon voyageur
etc...

Pour faire ça, on a besoin de quoi comme sous-modules de bidouille ?

- une fonction de filtrage efficace. Elle est générique au moins à une
application, mais sera éventuellement à raffiner selon les types de
données reçues par l'application (par exemple, j'ai besoin d'un type
'CODE_ISIN' si je fais une application qui gère des données boursières, je
m'en fous si je fais une application qui gère des données médicales, mais
là j'ai besoin d'un type 'NUMERO_SECU').

- un module de validation de la cohérence des données entre elles. Tu peux
toujours essayer de faire du générique, tu n'y arriveras jamais. Même
entre le front et le back, il peut arriver que l'on souhaite que
l'administrateur puisse stocker des choses non autorisées par les lusers.
Le mieux que tu puisses faire, c'est ou de la génération automatisée de
code, ou des descripteurs de données (un fichier de configuration
décrivant les relations entre les données reçues, mais c'est compliqué.
Par exemple, il faut gérer les données conditionnellement obligatoires,
comme le numéro de tva intracommunautaire si l'entité est 1) une société,
2) dont le siège social fait partie de la zone euro, alors que cette
données n'a pas de sens pour un particulier, etc...)

- l'interaction bas niveau avec le SGBDR. Là , tu peux te faire plaisir un
minimum, même si de toutes façons ce sera toujours dépendant de ton schéma
de sgbdr.

- l'affichage des pages. Plus dépendant de l'application et voire même de
l'humeur du moment de l'infographiste, y'a pas. Je refuse d'adhérer à
cette théorie qui dit que quand on change la présentation on ne changera
pas le code. Si on utilise des templates, on changera l'emplacement du
placeholder. Si on utilise php en tant que moteur de template on changera
de place les <?php echo $toto; ?>. Mais surtout dans la plupart des cas,
le client voudra que ce qui était sur la troisième page en bas à gauche en
vert fuchsia soit désormais en haut à droite de la première page en jaune
cocu et évidemment on a pas encore de jaune, et en haut à droite de la
première page il y a autre chose qu'il veut désormais sur la 7ème page...


Bien. Maintenant l'affirmation à contre-courant : à part pour faire la
couche d'accès multi-sgbdr, je ne vois pas l'intérêt de faire des
"frameworks" dans tous les coins pour des besoins qui sont aussi simples
et surtout aussi peu réutilisables. C'est quasiment toujours du one shot,
et c'est super **simple** comme besoin. Faire watt-milliards de classes,
leur factory associée, des templates avec des regexps partout, etc, etc...
je n'en vois ni l'intérêt, même pas pédagogique, ni le besoin, même pas
esthétique.

Evidemment, on a toujours des librairies/framework pour des besoins
classiques de connexion sgbdr, d'envoi de mails,etc, etc... mais ça rentre
pour moi dans la "toolbox" de base du développeur moyen.

Il est beaucoup plus facile d'écrire des kilomètres de couches empilées
traversées avec plus ou moins de déboires et d'effets de bord sous
prétexte de généricité que de faire du code **simple sans être simpliste**
qui réponde aux besoins réels de l'application.

My 2cents.
JG



Avatar
Bruno Desthuilliers

(snip)
Cette notion (NB :partage de variable entres scripts)
est beaucoup plus ambigue avec les SSI. En ce qui me
concerne, quand je fais dans main.php l'instruction require('toto.php');
je considère que ces deux scripts ne font qu'un, donc que l'espace de
nommage est le même donc que j'ai toujours une variable locale.


De toutes façons, PHP ne connait que deux espaces de nommages (ce que je
trouve à ch..., mais bon), donc...

Ce qui me gènes avec ce principe est qu'on a très vite un code imbitable
où il faut remonter toute l'arborescence possible des requires et
includes pour comprendre où est déclarée une variable. Tant qu'on a
quelque chose de très simple, très cadré et très bien documenté, ça peut
encore passer - mais la plupart des exemples (de ce type de
programmation) que j'ai vu pour le moment était un salmigondi de
globales et d'includes conditionnels.

Même si d'un point de vue purement technique, l'approche OO n'est pas
toujours nécessaire en PHP, elle a au moins le mérite d'ajouter un
espace de nommage supplémentaire - un objet n'étant jamais à la base
qu'un module instanciable. Cet espace de nommage permet en général de
rendre le code à la fois plus lisible (au moins du point de vue évoqué
ci-dessus) et plus modulaire (moins de dépendances entre les scripts). A
condition bien sûr (est-il besoin de le préciser ? hélas oui) de coder
*proprement*. J'ai vu en PHP des exemples d'utilisation des mécanismes
objets d'une débilité sans égale, et dont le seul résultat pratique est
de rendre le code *définitivement* impossible à maintenir.

J'en avais un peu parlé avec John Gallet il y a quelque temps qui
m'avait répondu quelque chose du style "masturbation intellectuelle",
et apres reflexion, j'ai approuvé.



http://minilien.com/?BE3q5TfH8x


(snip)

Ce que je voulais dire dans cet article, c'est qu'il y a un énorme
décalage entre la **simplicité du besoin** et la complexité de la solution
apportée.


(snip)

Ton besoin, pour faire du web dynamique, c'est quoi sur le fond ?

[avertissement pour la suite : Bruno a parfaitement raison de rappeler que
ce que je dis là s'applique à du web dynamique, je ne tiendrai pas le même
discours sur d'autres types d'applications]


Petite précision : ce n'est pas AMHA spécifique au développement web,
mais à un certain modèle d'exécution, qui est celui des CGI et de PHP,
où tout doit être 'reconstruit' à chaque requête. Il est évident que
dans ce modèle d'exécution, il vaut mieux faire au plus simple. Il
existe d'autre modèles d'exécution (long running process) où l'OO offre
un intérêt bien plus évident (cf Zope par exemple).

Ceci étant, la recherche de la simplicité n'en est pas moins nécessaire...

A. au niveau d'une page individuelle

(snip)


4. sinon (et ceci gère le cas de la première arrivée sur la page) générer
la page de saisie des données.


C'est très vrai pour une application de gestion de données, moins pour
un système de gestion de contenu (disons que ça reste vrai pour une
partie du backend, mais il y a plus que ça dans un CMS...)

(snip)

- un module de validation de la cohérence des données entre elles. Tu peux
toujours essayer de faire du générique, tu n'y arriveras jamais.


A ce niveau là d'une appli, non, puisqu'on est dans la logique propre à
l'appli.

(snip)
Le mieux que tu puisses faire, c'est ou de la génération automatisée de
code, ou des descripteurs de données (un fichier de configuration
décrivant les relations entre les données reçues, mais c'est compliqué.


Une utilisation conjointe des mécanismes objets et des aspects
dynamiques du langage peut s'avérer fonctionnellement équivalente à la
combinaison de ces deux techniques (génération de code et description de
données), mais il est vrai que la plomberie nécessaire n'est pas
forcément simple à mettre en oeuvre, et surtout s'avérer d'une
efficacité très moyenne (!) à l'exécution - particulièrement en PHP (des
langages comme Python ou Ruby permettent de mettre en oeuvre ce genre de
choses avec bien moins d'acrobaties et un peu moins de pénalités).

Par exemple, il faut gérer les données conditionnellement obligatoires,
comme le numéro de tva intracommunautaire si l'entité est 1) une société,
2) dont le siège social fait partie de la zone euro, alors que cette
données n'a pas de sens pour un particulier, etc...)


Un cas d'école en OO !-)

(Attention, je n'ai pas dit "un truc simple", ni "une raison pour
vouloir absolument solutionner le problème avec de la POO". Juste que
c'est un cas classique en conception objet.)

(snip)

- l'affichage des pages. Plus dépendant de l'application et voire même de
l'humeur du moment de l'infographiste, y'a pas. Je refuse d'adhérer à
cette théorie qui dit que quand on change la présentation on ne changera
pas le code.


Ca dépend de quel code, et ça dépend du type de modification. Si la
modif ne concerne qu'un type de donnée ("type" au sens ADT, et pour ne
pas impliquer que cela nécéssite d'utiliser les mécanismes OO du
langage), et qu'on a bien séparer la logique interne au type de sa
présentation, il n'y a que la vue (template ou autre) à modifier.

Evidemment, si la modif "de présentation" implique en fait de modifier
le modèle de données, c'est un autre débat - mais dans ce cas, ce n'est
pas une simple "modif de présentation", c'est une modif de la logique
applicative.


Bien. Maintenant l'affirmation à contre-courant : à part pour faire la
couche d'accès multi-sgbdr, je ne vois pas l'intérêt de faire des
"frameworks" dans tous les coins pour des besoins qui sont aussi simples
et surtout aussi peu réutilisables.


Pour des applis type CMS, il est intéressant d'avoir un 'environnement'
assez générique pour être adaptable aux besoins spécifique (organisation
du site, gestion des workflow de publication, types de contenus
spécifiques pouvant s'intégrer à l'existant, etc). Je ne parle bien sûr
pas de ces "portails" tout fait (et le plus souvent ni faits ni à
faire), qui ne sont généralement "modulaires" et "extensibles" que sur
le papier. A vrai dire, je cherche encore un tel environnement en PHP
(ça existe dans d'autres langages).

Ceci étant précisé, je rejoins tout à fait John sur le fond : le modèle
d'exécution spécifique de PHP (et des applis mode CGI) nécessite des
modèles de conceptions assez différent de ceux utilisés dans la plupart
des applis - ou des implémentations très différentes de ces mêmes
modèles -, et monter des usines à gaz à la mode Java me semble
parfaitement aberrant dans ce contexte.

Comme je le disais dans un autre post, un code est (AMHA) rarement
"générique" et encore moins "réutilisable" par décret - il le devient
*éventuellement*, à force de réutilisation et de refactoring - et à
condition d'être à l'origine suffisament simple et propre pour pouvoir
évoluer.

Mon expérience est qu'à vouloir deviner à l'avance si, quand et comment
un programme va évoluer, le plus souvent, on se mets le doigt dans
l'oeil, et on se retrouve avec un bousin monstrueux qui en théorie fait
même le café, et dans la pratique est impossible à faire *effectivement*
évoluer.

C'est autre chose, par contre, que de se constituer une boite à outils
(que ce soit sous la forme de bibliothèque de fonctions ou de classes -
ou d'un mélange des deux) qui soit effectivement utilisable dans
différents contextes - ce qui implique que ces outils ne fassent pas -
ou le moins possible - d'hypothèses sur l'environnement dans lequel ils
seront utilisés. D'où le conseil que je donnais à l'OP de bien conserver
la séparation entre son composant 'newsletter', les scripts utilisant ce
composant, et les templates (au sens large) qui peuvent lui être
associé: c'est le code spécifique (à une appli) qui doit dépendre du
code générique (la boite à outil), et non l'inverse.

Il est beaucoup plus facile d'écrire des kilomètres de couches empilées
traversées avec plus ou moins de déboires et d'effets de bord sous
prétexte de généricité que de faire du code **simple sans être simpliste**
qui réponde aux besoins réels de l'application.


+1 sur le "simple sans être simpliste". C'est effectivement le fond du
challenge, et pas uniquement (seulement un peu plus...) dans le cadre du
développement web.

Il me semble aussi (mais bon, ce n'est peut-être que mon cas
particulier) que cette philosophie vient avec l'expérience, et qu'il y a
souvent, dans le parcours d'un programmeur, une phase où on a tendance à
vouloir à tout prix mettre en oeuvre tous les beaux concepts qu'on a
(plus ou moins bien...) assimilé jusque là, au lieu de se concentrer sur
le problème en cours et d'y chercher une solution simple, fonctionnelle
et robuste (qui n'est pas forcément, loin s'en faut, la plus facile à
trouver).


Mes deux centimes (et demi)
Bruno




1 2