Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2019-10-23T18:17:34+02:00Les derniers messages parus sur le forum de Zeste de Savoir.Programmation orientée objet sous Python, message #2102222019-10-23T18:17:34+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p210222<p>Merci Angelo. Ça va même plus loin que simplement garder l’id : l’objet métier du coureur doit être transporté dans toutes les vues ; c’est le comportement attendu d’un flux de données objets au sein d’une application. Ce qui veut dire que si on a accès au nom du coureur, on a également accès à son ID et à tous ses autres attributs. </p>Programmation orientée objet sous Python, message #2102182019-10-23T17:26:10+02:00DonKnacki/@DonKnackihttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p210218<figure><blockquote>
<p>Oui oui bien sûr que je peux avoir accès à l’ID à partir d’un nom <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>Mais de manière générale, j’ai du mal à comprendre l’intuition derrière ces méthodes de classes.</p>
<p>Je me répète, ET JE N’AI PAS ENCORE LU TOUT CE QUI EST <strong>getattr</strong> et autres choses auxquelles tu as fait référence, mais voilà, si je voulais récupérer un ID à partir d’un nom, tel que je vois les choses actuellement il faudrait faire:</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span></div><pre><code class="hljs language-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_name</span><span class="hljs-params">(self, name)</span>
</span></code></pre></div>
<p>Mais avec ce raisonnement-là j’implémente une nouvelle méthode par requête SQL, ce n’est pas possible…</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209956">Alexouu</a></figcaption></figure>
<p>Je pense que tu as mal compris la dernière suggestion de <a href="/membres/voir/Yarflam/" rel="nofollow" class="ping ping-link">@<span class="ping-username">Yarflam</span></a> <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>En gros, il te suggère d’avoir systématiquement sous la main (même si il n’est pas afficher) l’ID du coureur<br>
Ainsi inutile de faire X méthode, 1 seul suffit : celle qui delete (c’est pareil pour update d’ailleurs) via l’ID</p>Programmation orientée objet sous Python, message #2099562019-10-17T23:41:47+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209956<p>Oui oui bien sûr que je peux avoir accès à l’ID à partir d’un nom <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>Mais de manière générale, j’ai du mal à comprendre l’intuition derrière ces méthodes de classes.</p>
<p>Je me répète, ET JE N’AI PAS ENCORE LU TOUT CE QUI EST <strong>getattr</strong> et autres choses auxquelles tu as fait référence, mais voilà, si je voulais récupérer un ID à partir d’un nom, tel que je vois les choses actuellement il faudrait faire:</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span></div><pre><code class="hljs language-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_name</span><span class="hljs-params">(self, name)</span>
</span></code></pre></div>
<p>Mais avec ce raisonnement-là j’implémente une nouvelle méthode par requête SQL, ce n’est pas possible…</p>Programmation orientée objet sous Python, message #2099552019-10-17T23:29:00+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209955<blockquote>
<p>Mais j’essaie juste de me placer dans le cas où je voudrais delete "Antoine Dupont" mais que j’ai pas forcément son ID sous la main</p>
</blockquote>
<p>Tu l’as forcément pour mettre à jour tes données. Ton application va afficher une liste ou un profil utilisateur avec l'<strong>objet métier</strong> de ton coureur. Tu peux y glisser l’ID dans ton bouton de suppression.</p>Programmation orientée objet sous Python, message #2099522019-10-17T23:14:47+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209952<p>Yes c’est mon prof qui a fournit le bout de code d’AbstractDao.
Je vais aller voir le code source dont tu parles du coup.</p>
<p>Ok pour le cou^p de l’id qui n’existe pas il faut juste que je fasse en sorte d’afficher un message d’erreur si c’est le cas.</p>
<p>Pour le DELETE: Je comprends pourquoi tu dis que je me complique la vie, car l’ID est unique pour chaque coureur. Mais j’essaie juste de me placer dans le cas où je voudrais delete "Antoine Dupont" mais que j’ai pas forcément son ID sous la main (Oui il peut y avoir plusieurs Antoine Dupont, c’est pour cela que j’avais pris l’exemple de l’adresse mail à la place du nom_prenom</p>Programmation orientée objet sous Python, message #2099512019-10-17T22:52:41+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209951<figure><blockquote>
<p>1) Dans la classe AbstractDao (voir ci-dessous), il y a 5 méthodes définies mais dois-je en rajouter d’autres?</p>
<p>Par ce que par exemple à la ligne 8 c’est find_by_id mais ça pourrait tout aussi bien être find_by_nom_prenom, etc.. ?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209915">Alexouu</a></figcaption></figure>
<p>C’est ton prof qui t’as passé ce bout de code ? Techniquement, on est plus proche de l’ORM que de la DAO. En principe AbstractDao n’a pas besoin d’avoir toutes ces méthodes. Il suffit de regarder le code source de PySimpleDb pour s’en rendre compte, je te conseille de le dézipper pour lire le code source (./src/pysimpledb/sql.py).</p>
<p>Après comme je te l’ai expliqué plus tôt, tu peux utiliser une méthode magique pour récupérer tous les queryByX (<a href="https://stackoverflow.com/a/10879860">getattr - en savoir plus</a>) mais tout ça se met dans une classe manager qui hérite de AbstractDao (<a href="https://fr.wikipedia.org/wiki/Objet_d'acc%C3%A8s_aux_donn%C3%A9es">voir un exemple de classe technique / DAO</a>).</p>
<figure><blockquote>
<p>2) Maintenant si on se place dans le cas des classes DAO, qui j’ai bien compris héritent de la classe Abstract, et si je reprends une de leur méthode find_by_id:
J’aimerais être sûr que le coup du =self.id (ligne 9) fonctionne ici.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209915">Alexouu</a></figcaption></figure>
<p>L’héritage permet d’utiliser le patron de conception de la classe mère et de la classe fille, donc oui, une instanciation est possible et ça donne accès aux méthodes et propriétés des deux classes via le self.</p>
<figure><blockquote>
<p>Puis comment gérer le cas où l’id que j’entre n’existe pas? C’est à cela que correspond l’exception "raise NotImplementedError"?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209915">Alexouu</a></figcaption></figure>
<p>Non … <code>raise NotImplementedError</code> c’est pour prévenir le développeur que la méthode n’a pas encore été implémenté / développé. Si l’ID n’existe pas, tu recevras un tableau vide - ton curseur ne retournera rien.</p>
<figure><blockquote>
<p>3)Si je considère maintenant la méthode DELETE des classes DAO.</p>
<p>Mettons que je veuille DELETE un coureur par son id, je sais écrire la requête SQL associée mais je comprends pas si je dois mettre l’id en argument de la méthode DELETE.
Et aussi, on pourrait vouloir supprimer un coureur en le recherchant également par son mail, du coup il faudrait faire plusieurs requêtes (1 pour l’id et 1 pour le mail) ou alors on écrit "delete from Coureur where id=’X' or mail=’Y' "?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209915">Alexouu</a></figcaption></figure>
<p>Je pense qu’il faut éviter de se compliquer la vie. Le mieux c’est de prendre l’habitude d’utiliser systématiquement l’ID pour supprimer un élément. On sait que c’est ciblé / unique, y’a moins de risque que ça déborde sur des enregistrements que l’on avait pas considéré au départ. A cas échéant, si vraiment nous devons supprimer des quantités d’enregistrement dans ce cas-là on rajoute une méthode pour un champ spécifique. Mais tu ne fais pas encore de la Big Data ?! <img src="/static/smileys/smile.png" alt=":)" class="smiley"> donc ça va.</p>Programmation orientée objet sous Python, message #2099152019-10-17T11:04:50+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209915<p>Salut Yarflam,</p>
<p>merci de répondre à toutes mes questions même si je me rends compte après coup que certaines ne sont pas très pertinentes en effet !</p>
<p>Mais j’en ai encore plein d’autres ne t’en fais pas <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>1) Dans la classe AbstractDao (voir ci-dessous), il y a 5 méthodes définies mais dois-je en rajouter d’autres?</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractDao</span>:</span>
<span class="hljs-string">"""Classe abstraite dont les DAO doivent hériter. Permet de gérer simplement la connection, et d'avoir des noms
méthodes de base des DAO identique. Permet une meilleure lisibilité du code"""</span>
connection = get_connection()
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_id</span><span class="hljs-params">(self, id)</span>:</span>
<span class="hljs-string">"""Va chercher une élément de la base grâce à son id et retourne l'objet python associé"""</span>
<span class="hljs-keyword">return</span> NotImplementedError
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_all</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-string">"""Retourne tous les éléments d'une table sous forme de liste d'objets python"""</span>
<span class="hljs-keyword">return</span> NotImplementedError
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update</span><span class="hljs-params">(self, business_object)</span>:</span>
<span class="hljs-string">"""Met à jour la ligne en base de donnée associé à l'objet métier en paramètre"""</span>
<span class="hljs-keyword">return</span> NotImplementedError
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create</span><span class="hljs-params">(self, business_object)</span>:</span>
<span class="hljs-string">"""Insère une ligne en base avec l'objet en paramètre. Retourne l'objet mise à jour avec son id de la base"""</span>
<span class="hljs-keyword">return</span> NotImplementedError
<span class="hljs-meta"> @abstractmethod</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete</span><span class="hljs-params">(self, business_object)</span>:</span>
<span class="hljs-string">"""Supprime la ligne en base représentant l'objet en paramètre"""</span>
<span class="hljs-keyword">return</span> NotImplementedError
</code></pre></div>
<p>Par ce que par exemple à la ligne 8 c’est find_by_id mais ça pourrait tout aussi bien être find_by_nom_prenom, etc.. ?</p>
<p>2) Maintenant si on se place dans le cas des classes DAO, qui j’ai bien compris héritent de la classe Abstract, et si je reprends une de leur méthode find_by_id:</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_id</span><span class="hljs-params">(self, id)</span>:</span>
<span class="hljs-string">"""
:return : le club d'id donné
:param id:
:return:
"""</span>
<span class="hljs-keyword">with</span> self.connection.cursor() <span class="hljs-keyword">as</span> cur:
cur.execute(
<span class="hljs-string">"select id_coureur, nom, prenom, annee_naissance, sexe, adresse, mail, telephone, num_licence, association,id_club from coureur where id_coureur=self.id"</span>
)
<span class="hljs-keyword">raise</span> NotImplementedError
</code></pre></div>
<p>J’aimerais être sûr que le coup du =self.id (ligne 9) fonctionne ici.</p>
<p>Puis comment gérer le cas où l’id que j’entre n’existe pas? C’est à cela que correspond l’exception "raise NotImplementedError"?</p>
<p>3)Si je considère maintenant la méthode DELETE des classes DAO.</p>
<p>Mettons que je veuille DELETE un coureur par son id, je sais écrire la requête SQL associée mais je comprends pas si je dois mettre l’id en argument de la méthode DELETE.
Et aussi, on pourrait vouloir supprimer un coureur en le recherchant également par son mail, du coup il faudrait faire plusieurs requêtes (1 pour l’id et 1 pour le mail) ou alors on écrit "delete from Coureur where id=’X' or mail=’Y' "?</p>
<p>Je sais que j’ai de plus en plus de questions alors encore une fois merci de ton aide Yarflam !</p>
<p>Alexouu <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>Programmation orientée objet sous Python, message #2098272019-10-15T18:57:11+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209827<figure><blockquote>
<p>Je connais la notion d’héritage, cependant je ne comprends pas d’où sort cette classe abstraite, ce qu’il y a dedans et pourquoi elle est nécessaire <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p></p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209813">Alexouu</a></figcaption></figure>
<p>Il faut créer cette classe abstraite. Comme je l’ai expliqué dans ma précédente réponse, elle contient la connexion à la base de données. La logique est d’avoir une seule connexion pour tous les managers (d’où l’héritage).</p>
<p>Après une recherche sur Google, je suis tombé sur <a href="http://www.mikusa.com/pysimpledb/">PySimpleDb</a>, il semble que ton prof l’importe pour utiliser AbstractDao. Tu peux gagner un peu de temps là-dessus.</p>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractDao</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-string">"""
A simple base class for creating data access objects.
Each new DAO can simply inheit from this class and define its own set of
queries. A function is automatically generated for every query that is
defined.
Ex.
class MyObjectDao(AbstractDao):
def __init__(self, db):
self.queries = {
'get': {
'sql': 'SELECT * FROM mytable WHERE id = :id',
'execType': 'queryForObject',
'resultType': MyObject
}
}
AbstractDao.__init__(self, db, queries)
dao = MyObjectDao(db)
obj = dao.get(1)
As you can see from the example you define your queries inside of the
__init__ function and then pass them to the super class's __init__ function.
This will then automatically create a function for each query defined.
"""</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, db, queries)</span>:</span>
<span class="hljs-string">"""
Initializes an interal Sql object which is used to query the database.
In addition, the following self.queries options are defined...
defauktKeyParam - the default column name used as the key of the map.
execType - the way that this message should be called. This
corresponds to the functions that are defined by
the Sql object. The following choices are
available...
queryForMap
queryForObject
queryForList
queryForScalar
insert
update
delete
See the Sql object for more information on how each
of these functions behaves.
"""</span>
self.sql = Sql(db, queries)
<span class="hljs-keyword">for</span> query <span class="hljs-keyword">in</span> queries.values():
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> query.has_key(<span class="hljs-string">'execType'</span>):
<span class="hljs-keyword">if</span> query.has_key(<span class="hljs-string">'rowMapper'</span>):
query[<span class="hljs-string">'execType'</span>] = query[<span class="hljs-string">'rowMapper'</span>].DEFAULT_EXEC_TYPE
<span class="hljs-keyword">else</span>:
query[<span class="hljs-string">'execType'</span>] = <span class="hljs-string">'update'</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getattr__</span><span class="hljs-params">(self, attr)</span>:</span>
<span class="hljs-string">"""
Creates a dynamic function for each defined query.
One dynamic function is created for each query and has the same name
as the key in the queries dictionary.
"""</span>
<span class="hljs-keyword">if</span> attr <span class="hljs-keyword">in</span> self.sql.queries:
val = self.sql.queries[attr]
<span class="hljs-keyword">if</span> val.has_key(<span class="hljs-string">'execType'</span>):
execType = val[<span class="hljs-string">'execType'</span>]
execFunc = getattr(self.sql, execType)
<span class="hljs-keyword">if</span> execType <span class="hljs-keyword">in</span> (<span class="hljs-string">'queryForMap'</span>,):
keyParam = <span class="hljs-literal">None</span>
<span class="hljs-keyword">if</span> val.has_key(<span class="hljs-string">'defaultKeyParam'</span>):
keyParam = val[<span class="hljs-string">'defaultKeyParam'</span>]
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">callable</span><span class="hljs-params">(keyParam=keyParam, **kwargs)</span>:</span>
<span class="hljs-keyword">return</span> execFunc(attr, keyParam=keyParam, **kwargs)
<span class="hljs-keyword">elif</span> execType <span class="hljs-keyword">in</span> (<span class="hljs-string">'queryForObject'</span>, <span class="hljs-string">'queryForList'</span>):
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">callable</span><span class="hljs-params">(**kwargs)</span>:</span>
<span class="hljs-keyword">return</span> execFunc(attr, **kwargs)
<span class="hljs-keyword">elif</span> execType <span class="hljs-keyword">in</span> (<span class="hljs-string">'update'</span>, <span class="hljs-string">'batch'</span>):
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">callable</span><span class="hljs-params">(obj=None)</span>:</span>
<span class="hljs-keyword">return</span> execFunc(attr, obj)
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">"Invalid Query Type %s"</span> % execType)
<span class="hljs-keyword">return</span> callable
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">raise</span> AttributeError(<span class="hljs-string">"Missing method %s called."</span> % attr)
</code></pre></div><p>D’après les commentaires, tu as même des fonctions pour t’aider à construire tes méthodes.</p></div></div>
<figure><blockquote>
<p>Par ailleurs, dans une classe comme celle-ci (DaoCoureur), c’est ici qu’on devrait définir des méthodes qui font appel à des requêtes SQL, non?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209813">Alexouu</a></figcaption></figure>
<p>C’est le cas si tu regardes bien dans tes méthodes create et find_all. Je comprends même pas pourquoi tu poses la question. Y’a deux requêtes : un <strong>INSERT INTO</strong> (ligne 12) et un <strong>SELECT</strong> (ligne 36). Ton prof t’a laissé le soin de continuer find_by_id (<code>raise NotImplementedError</code>).</p>
<figure><blockquote>
<p>Je parle par exemple des queryByEmail que tu évoquais</p>
<p>Donc si je cherche à adapter cela au morceau de code que j’ai envoyé précédemment, ce serait une fonction comme celle qui vient?</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_id</span><span class="hljs-params">(self, id)</span>:</span>
<span class="hljs-keyword">return</span> (SELECT * FROM.....)
</code></pre></div>
<p></p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209813">Alexouu</a></figcaption></figure>
<p>Hé bien non, au mieux tu retournes une chaîne de caractères à ton contrôleur (si tu mets les guillemets). Il faut envoyer ta requête SQL via le connecteur MySQL.</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-keyword">with</span> self.connection.cursor() <span class="hljs-keyword">as</span> cur:
cur.execute(<span class="hljs-string">"SELECT * FROM ..."</span>)
</code></pre></div>
<p>Puis boucler sur les éléments retournés en instanciant les classes métiers.</p>
<p>Je réponds à ton commentaire sur le code source (je ne l’avais pas remarqué) :</p>
<blockquote>
<p>A votre avis pourquoi on fait pas select * from coureurs ?</p>
</blockquote>
<p>C’est pour être sûr du positionnement des champs. Ligne 39, y’a une instanciation de la classe métier avec le tableau item. Après c’est pas forcément ultra propre, le mieux serait d’utiliser un tableau associatif. Même si bon, je comprends que l’on puisse avoir la flemme … <img src="/static/smileys/heureux.png" alt=":D" class="smiley"></p>Programmation orientée objet sous Python, message #2098132019-10-15T13:46:57+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209813<p>Je connais la notion d’héritage, cependant je ne comprends pas d’où sort cette classe abstraite, ce qu’il y a dedans et pourquoi elle est nécessaire <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>Par ailleurs, dans une classe comme celle-ci (DaoCoureur), c’est ici qu’on devrait définir des méthodes qui font appel à des requêtes SQL, non?</p>
<p>Je parle par exemple des queryByEmail que tu évoquais</p>
<p>Donc si je cherche à adapter cela au morceau de code que j’ai envoyé précédemment, ce serait une fonction comme celle qui vient?</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_id</span><span class="hljs-params">(self, id)</span>:</span>
<span class="hljs-keyword">return</span> (SELECT * FROM.....)
</code></pre></div>Programmation orientée objet sous Python, message #2097902019-10-14T20:51:27+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209790<figure><blockquote>
<p>Encore une fois merci de ton temps Yarflam, je comprends petit à petit !</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209786">Alexouu</a></figcaption></figure>
<p>Avec plaisir Alexouu ! <img src="/static/smileys/langue.png" alt=":p" class="smiley"></p>
<figure><blockquote>
<p>Cependant, en adaptant un exemple qu’avait donné mon prof, une classe DAO (ou classe abstraite DAO?) ressemblerait à cela, pourrais-tu m’éclairer là dessus?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209786">Alexouu</a></figcaption></figure>
<p>Une classe abstraite est une classe que l’on peut pas instancier directement, elle nécessite un héritage. L’héritage ça permet tout simplement d’accéder à des attributs et à des méthodes communes à plusieurs instances de classe. Ici l’objectif est de permettre à tes managers d’utiliser le connecteur - typiquement l’instance qui se connecte à la base de données afin que tu puisses exécuter tes requêtes SQL.</p>
<p>Je vais détailler un peu …</p>
<p>L’héritage est présent dans la déclaration de ton manager <code>class DaoCoureur(AbstractDao):</code>, ça permet de dire à Python <strong>Ma nouvelle classe DaoCoureur hérite de AbstractDao</strong>. Dit autrement : tout ce que sait <strong>AbstractDao</strong>, ma classe <strong>DaoCoureur</strong> le sait aussi.</p>
<p>A l’intérieur de ta classe DaoCoureur, tu as quatre méthodes : create, find_all, find_by_id et update. Ce sont des méthodes te permettant d’ajouter, récupérer et mettre à jour tes objets (ces dernières instanciés par ta classe métier <em>Coureur</em>). Chacune des méthodes emprunte à la classe abstraite, l’instance de connexion <code>self.connection</code>. Y’a un léger raccourci, puis-ce qu’ici la méthode va directement récupérer le curseur. Le curseur c’est l’outil qui gère la pagination d’une requête - alors tout dépend du connecteur mais il va par exemple t’afficher les 10 premières entrées trouvées et tu pourras alors rappeler le curseur pour voir les 10 suivantes (ainsi de suite jusqu’à la fin). Après avec MySQL, ça ne m’étonnerai pas que ce soit une seule entrée …</p>
<p>En résumé :</p>
<ul>
<li>
<p>Classe Abstraite : elle a besoin d’un héritage pour être utilisée. Sauf si elle dispose de méthodes statiques (en Python on ajoute le décorateur <a href="/membres/voir/staticmethod/" rel="nofollow" class="ping ping-link">@<span class="ping-username">staticmethod</span></a>) ; pour le cas de AbstractDao c’est possible que ce soit le cas, ça permet de lui passer la connexion à la BDD.</p>
</li>
<li>
<p>Classe manager : c’est le rôle donnée à une classe DAO, ici DaoCoureur. Elle doit traiter avec la base de données afin de synchroniser les données avec les instances de classes métiers.</p>
</li>
<li>
<p>Classe métier : elle fabrique des d’objets spécifiques répondant aux différentes fonctionnalités de l’application (admin, utilisateurs, produits, coureurs etc).</p>
</li>
<li>
<p>Héritage : nom donné au comportement d’une classe mère qui donne accès à ses attributs et ses méthodes à une ou plusieurs classes filles.</p>
</li>
</ul>Programmation orientée objet sous Python, message #2097862019-10-14T19:44:59+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209786<p>Encore une fois merci de ton temps Yarflam, je comprends petit à petit !</p>
<p>Cependant, en adaptant un exemple qu’avait donné mon prof, une classe DAO (ou classe abstraite DAO?) ressemblerait à cela, pourrais-tu m’éclairer là dessus?</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DaoCoureur</span><span class="hljs-params">(AbstractDao)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create</span><span class="hljs-params">(self, coureur)</span>:</span>
<span class="hljs-string">"""
Insère un coureur en base, et retourne ce même coureur mis à jour de l'id généré par la base
:param coureur:
:return: l'coureur mis à jour de son id en base
"""</span>
cur = self.connection.cursor()
<span class="hljs-keyword">try</span>:
cur.execute(
<span class="hljs-string">"INSERT INTO coureur (nom, prenom, annee_naissance,sexe,adresse,mail,"</span>
<span class="hljs-string">"telephone,num_licence,association,id_club) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING id_coureur;"</span>,
(coureur.nom, coureur.prenom, coureur.annee_naissance, coureur.sexe, coureur.adresse,
coureur.mail, coureur.telephone, coureur.num_licence, coureur.association,coureur.id_club))
coureur.id_coureur = cur.fetchone()[<span class="hljs-number">0</span>]
<span class="hljs-comment"># la transaction est enregistrée en base</span>
self.connection.commit()
<span class="hljs-keyword">except</span>:
<span class="hljs-comment"># la transaction est annulée</span>
self.connection.rollback()
<span class="hljs-keyword">raise</span>
<span class="hljs-keyword">finally</span>:
cur.close()
<span class="hljs-keyword">return</span> coureur
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_all</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-string">"""
:return: l'intégralité des coureurs en base
"""</span>
<span class="hljs-keyword">with</span> self.connection.cursor() <span class="hljs-keyword">as</span> cur:
cur.execute(
<span class="hljs-string">"select id_coureur, nom, prenom, annee_naissance, sexe, adresse, mail, telephone, num_licence, association,id_club from coureur"</span>) <span class="hljs-comment"># A votre avis pourquoi on fait pas select * from coureurs ?</span>
<span class="hljs-comment"># on récupère des tuples et les transforme en objects Coureur</span>
result = [Coureur(id_coureur=item[<span class="hljs-number">0</span>], nom=item[<span class="hljs-number">1</span>], prenom=item[<span class="hljs-number">2</span>], annee_naissance=item[<span class="hljs-number">3</span>], sexe=item[<span class="hljs-number">4</span>],
adresse=item[<span class="hljs-number">5</span>],mail=item[<span class="hljs-number">6</span>],telephone=item[<span class="hljs-number">7</span>],num_licence=item[<span class="hljs-number">8</span>],association=item[<span class="hljs-number">9</span>],id_club=item[<span class="hljs-number">10</span>])
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> cur.fetchall()]
<span class="hljs-keyword">return</span> result
<span class="hljs-string">"""
Avec le choix d'utiliser une classe abastraite dont héritent les différentes DAO, il est obligatoire de creer
toutes les méthodes abstraites dans les classes filles, même si on ne leur code aucun comportement pour le moment.
Si vous utiliser PyCharm, il peut créer la définition des méthodes automatiquement.
"""</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_by_id</span><span class="hljs-params">(self, id)</span>:</span>
<span class="hljs-string">"""
:return : le club d'id donné
:param id:
:return:
"""</span>
<span class="hljs-keyword">raise</span> NotImplementedError
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update</span><span class="hljs-params">(self, business_object)</span>:</span>
<span class="hljs-keyword">raise</span> NotImplementedError
</code></pre></div>
<p>Merci,</p>
<p>ALexouu <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>Programmation orientée objet sous Python, message #2095772019-10-11T19:25:04+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209577<blockquote>
<p>Déjà, il faut bien créer une classe manager par table que l’on va avoir dans notre base de données c’est ça ?</p>
</blockquote>
<p>En effet, c’est une classe manager par table. Exception toutefois avec des tables de liaisons (= deux ou trois clés étrangères formant une clé primaire avec parfois un attribut en complément) car ça ne correspond pas à une logique métier en particulier - on n’a pas besoin de manipuler directement une relation.</p>
<blockquote>
<p>Puis au niveau des attributs et des méthodes, ça se passe comment ?</p>
</blockquote>
<p>Y’a pas d’attributs particuliers. Au niveau des méthodes, ça va correspondre aux opérations que tu cherches à automatiser. Par exemple, tu souhaites extraire la liste des coureurs ayant dépassé le 32 Km/h, tu vas devoir créer une méthode que tu nommeras par exemple <code>getBestRunnersKm()</code> qui exécutera la requête <code>SELECT * FROM coureurs WHERE moy_vitesse > 32</code>. En retour, tu recevras un tableau d’objets instanciant la classe Coureur avec les données de tes champions.</p>
<blockquote>
<p>Aussi pour reprendre ton exemple, à la ligne 10 tu écris "queryByEmail", mais ce n’est qu’un exemple de query, donc il faudrait toutes les lister normalement ?</p>
</blockquote>
<p>Non pas forcément, tu crées celles dont tu as besoin. Après tu peux les créer dynamiquement en utilisant une méthode magique. En Python c’est <a href="https://stackoverflow.com/a/10879860"><strong>getattr</strong></a>, ça te permet de capturer une méthode à la volée. Avec une simple détection, tu vérifies si une méthode type queryByX est appelé, si oui tu envoies ce X comme paramètre (Attention à la sécurité ! Déjà vérifies que le nom est accessible et puis ensuite un test de typage sur le paramètre).</p>
<blockquote>
<p>J’admets que c’est encore flou dans ma tête actuellement.</p>
</blockquote>
<p>Dans un premier temps, identifies les ensembles que tu vas devoir manipuler. Tu as des coureurs d’un côté, à quoi ils ressemblent ? Ont-ils un nom, prénom, email, âge, adresse etc ? Toutes ces caractéristiques vont appartenir à ta classe métier Coureur. Avec cette classe, je peux par exemple instancier Usain Bolt <code>usain = new Coureur('Usain', 'Bolt', 1986, 'Jamaïque')</code>, il existe ainsi virtuellement comme entité. Sauf que cette entité j’ai besoin quelle soit stockée en base. C’est à ce moment là que j’appelle ma classe CoureursManager pour lui demander d’ajouter mon nouveau coureur <code>CoureursManager.insert(usain)</code>. Son rôle est de récupérer les informations essentielles du coureur pour construire la requête correspondante (l’idéal c’est de récupérer l’ID auto-incrémenté après l’insert pour donner la possibilité à la classe manager de mettre à jour tout de suite après - ce serait bête de créer deux entrées).</p>
<p>Ensuite … aujourd’hui, je dois compter les points de la course 127 dans laquelle joue Usain Bolt. Il me suffira d’interroger une fois encore mon manager pour récupérer les joueurs <code>CoureursManager.queryByCourse(127)</code> parmi les instances retournés par la requête, j’aurai bien de nouveau un objet coureur instancié avec les données de Usain Bolt. Là, je modifie ses points <code>usain.setPoint(400)</code> et je synchronise l’objet avec la base en appelant de nouveau mon manager <code>CoureursManager.update(usain)</code>.</p>
<p>Ce que tu as dans tes classes métiers est (presque toujours) en miroir avec ce que tu as dans ta base de données et ce sont tes classes managers qui s’assurent de leurs cohérences. T’imagine si tu devais à chaque mise à jour ré-écrire ta requête ? Le temps perdu … le rôle de cette classe est indispensable ! <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>Schématiquement ça revient à effectuer cet échange :</p>
<p>Contrôleur —(Joueurs de la course <em>127</em> ?)—> CoureursManager.queryByCourse —(<code>SELECT * FROM coureurs WHERE course = 127</code>)—> BDD —(BDD.Objects)—> CoureursManager.queryByCourse —(Array<Coureur>)—> Contrôleur.</p>Programmation orientée objet sous Python, message #2095552019-10-11T00:16:16+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209555<p>Salut Yarflam,</p>
<p>Tout d’abord merci pour ta réponse détaillée ! <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>Néanmoins je n’ai pas tout compris, dans le détail comment ça marche une classe manager?</p>
<p>Déjà, il faut bien créer une classe manager par table que l’on va avoir dans notre base de données c’est ça?
Puis au niveau des attributs et des méthodes, ça se passe comment?</p>
<p>Aussi pour reprendre ton exemple, à la ligne 10 tu écris "queryByEmail", mais ce n’est qu’un exemple de query, donc il faudrait toutes les lister normalement? Du style queryByNom, querybyPrenom, queryByNom_Prenom, etc?</p>
<p>J’admets que c’est encore flou dans ma tête actuellement <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<p>D’autant plus que de l’autre côté, il va rester quoi comme méthodes dans les classes métier? </p>Programmation orientée objet sous Python, message #2095492019-10-10T22:23:34+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209549<p>Bonjour,</p>
<p>C’est bien de rappeler que <strong>DAO</strong> correspond à <strong>D</strong>ata <strong>A</strong>ccess <strong>O</strong>bject. Sur le coup ça me parlait pas, pourtant je l’utilise quotidiennement via une <strong>ORM</strong> (<strong>O</strong>bject <strong>R</strong>elationnal <strong>M</strong>apping). L’ORM est un peu le robot automatique de la DAO : on lui donne le modèle de la base de données et il va nous construire dynamiquement des classes managers.</p>
<p>En l’occurrence ici, pas d’ORM dans ton exercice, c’est à toi de construire les classes managers mais le principe reste le même. <img src="/static/smileys/clin.png" alt=";)" class="smiley"></p>
<p>Une classe manager va effectivement servir d’interface entre ta couche métiers (ton application) et ta base de données (tes données). Elle possède des méthodes permettant d’interroger, modifier ou altérer la BDD ; c’est elle qui contiendra les requêtes SQL (ou NoSQL).</p>
<p>Le principe est que ta classe manager traduit constamment tes objets métiers en requêtes SQL et inversement. Je vais prendre un cas très simple avec un utilisateur :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UtilisateurManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Connecteur</span> </span>{
insert(item) {
<span class="hljs-comment">/* Création de l'utilisateur */</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.query(
<span class="hljs-string">'INSERT INTO utilisateur (prenom, nom, email) '</span>+
<span class="hljs-string">'VALUES ("'</span>+item.prenom+<span class="hljs-string">'", "'</span>+item.nom+<span class="hljs-string">'", "'</span>+item.email+<span class="hljs-string">'")'</span>
);
}
queryByEmail(email) {
<span class="hljs-comment">/* Récupération d'un utilisateur via son email */</span>
<span class="hljs-keyword">let</span> items = <span class="hljs-keyword">this</span>.query(
<span class="hljs-string">'SELECT prenom, nom, email FROM utilisateur WHERE email = "'</span>+email+<span class="hljs-string">'" LIMIT 1'</span>
);
<span class="hljs-comment">/* Transcription */</span>
<span class="hljs-keyword">if</span>(items.length == <span class="hljs-number">1</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Utilisateur(items[<span class="hljs-number">0</span>].prenom, items[<span class="hljs-number">0</span>].nom, items[<span class="hljs-number">0</span>].email);
}
<span class="hljs-comment">/* Sans gestion d'erreurs */</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Utilisateur();
}
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Utilisateur</span> </span>{
<span class="hljs-keyword">constructor</span> (prenom='', nom='', email='') {
<span class="hljs-keyword">this</span>.prenom = prenom;
<span class="hljs-keyword">this</span>.nom = nom;
<span class="hljs-keyword">this</span>.email = email;
}
}
<span class="hljs-comment">/* Création d'un utilisateur */</span>
<span class="hljs-keyword">let</span> martin = <span class="hljs-keyword">new</span> Utilisateur(<span class="hljs-string">'Martin'</span>, <span class="hljs-string">'GUITARE'</span>, <span class="hljs-string">'mguitare@gmail.com'</span>);
UtilisateurManager.insert(martin);
<span class="hljs-comment">/* Récupération d'un utilisateur */</span>
<span class="hljs-keyword">let</span> test = UtilisateurManager.queryByEmail(<span class="hljs-string">'mguitare@gmail.com'</span>);
<span class="hljs-built_in">console</span>.log(test.prenom); <span class="hljs-comment">// affiche 'Martin'</span>
</code></pre></div>
<p>Alors je tiens juste à préciser, qu’il y’a plein de choses qui n’irait pas dans un contexte de production. Tout d’abord d’un point de vue sécurité, dans la requête on peut injecter tout et surtout n’importe quoi (il vaut mieux utiliser des bibliothèques de connexion disposant d’une couche de sécurité / pré-validation comme PDO en PHP). Ensuite j’ai totalement ignoré les getters et les setters, même si pour illustrer j’ai pris la structure du Javascript (c’est pour éviter d’alourdir la lecture du code). Au niveau de la modélisation, l’utilisateur n’a pas d’ID c’est pourtant essentiel que la clé primaire serve à garantir l’unicité de l’entrée (on va dire qu’ici c’est l’email). Pour terminer, j’ai choisi d’étendre mon manager à la classe Connecteur qui dispose des éléments de connexion à la base de données et d’un système primitif de requête (symbolisé par <code>this.query</code>) - ce n’est pas mauvais en production, c’est juste que la méthode d’instanciation est ambigu, je précise donc qu’il s’agit d’une classe statique (utilisable sans instanciation) - ce n’est pas une norme / obligation.</p>
<p>L’avantage de cette structure, c’est que l’on peut utiliser et modifier nos objets comme bon nous semble, sans se soucier de la requête à exécuter (en tout cas, une fois tout en place). Si je veux modifier l’email de Martin, il suffit d’écrire <code>martin.email = 'martintin@yahoo.fr';</code> et de passer l’objet dans le manager <code>UtilisateurManager.update(martin);</code> pour que celui-ci exécute la bonne requête.</p>
<p>En espérant que ce soit suffisamment compréhensible. <img src="/static/smileys/smile.png" alt=":)" class="smiley"> j’ai dû ré-écrire deux fois mon illustration parce qu’au départ, j’étais parti sur l’ORM avec lequel je suis plus familier - ça permet une meilleure cohésion entre les managers, les classes métiers et les models mais ce n’était pas la question initiale.</p>Programmation orientée objet sous Python, message #2095362019-10-10T19:37:37+02:00Alexouu/@Alexouuhttps://zestedesavoir.com/forums/sujet/13085/programmation-orientee-objet-sous-python/?page=1#p209536<p>Bonjour à tous,</p>
<p>Dans le cadre d’un exercice, je dois construire une application en POO sous PyCharm, mais sans interface graphique (on utilisera donc cette appli depuis la console). Je dois pour ce faire séparer les couches métier et DAO, ce que je n’avais jamais fait avant, et c’est entre autres cela qui me pose problème.</p>
<p>Voici en quoi doit consister l’application:</p>
<p>Elle doit gérer les temps et les classements de courses d’athlétisme, je m’explique:</p>
<p>Cette appli s’adresse d’une part à des visiteurs lambdas (sans besoin de se connecter) qui désirent soit rechercher des courses prévues, soit consulter des courses passées (classement et chronos de tout le monde) soit consulter une fiche coureur de n’importe quel coureur ayant déjà participé à une course (fiche regroupant tous les chronos+classements des courses auxquelles ce coureur a déjà participé).</p>
<p>D’autre part cette appli s’adresse également aux "organisateurs" de courses (besoin de se connecter).
Les organisateurs sont les seuls à:</p>
<p>-pouvoir inscrire (le un coureur à une course (c’est mal fait mais un coureur ne peut s’inscrire lui même)</p>
<p>-pouvoir créer/modifier/supprimer une nouvelle course (libellé/date et heure/lieu/distance)</p>
<p>-un organisateur peut créer autant de courses qu’il le souhaite mais ne peut pas toucher à celles des autres.</p>
<p>Ce que l’on me donne:</p>
<p>-Un ficher de quelques courses au format csv (je peux en ajouter ou en supprimer à ma guise)</p>
<p>-Un fichier csv répertoriant N coureurs.
Je n’ai pas besoin de créer d’autres coureurs supplémentaires, mais pour chaque course i, je vais appeler une API que l’on me donne pour générer Ni coureurs pari ces N</p>
<p>Comme je le disais au début, mon gros point de blocage est la DAO, notion que l’on vient de m’introduire.
En effet, je vais devoir créer sur SQL une table Coureurs, une table Courses ainsi qu’une table organisateurs (enfin je suppose).</p>
<p>D’après ce que j’ai compris la couche DAO, par le biais des requêtes SQL, va faire le lien entre la couche métier et mes tables SQL. Mais concrètement, je n’ai aucune idée de la manière d’implémenter cela…</p>
<p>Si quelqu’un pouvait m’éclairer sur ce sujet,</p>
<p>Merci d’avance,</p>
<p>Alexouu <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>Problème de compréhension, message #685822015-08-06T09:38:03+02:00grugru/@grugruhttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68582<p>Pour l'interfaçcage, il semblerait plus judicieux en Java de te conformer à JPA (Java Peristence API) qui définit plus ou moins une convention pour s'interfacer ensuite avec un ORM respectant cette convention. JPA définit aussi bien une norme pour décrire tes objets que pour y faire des recherches…</p>Problème de compréhension, message #685172015-08-05T19:54:21+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68517<p>On n'est jamais sûr de rien, pour commencer. <img alt=":)" src="/static/smileys/smile.png"></p>
<p>Et quand bien même tu ne changerais jamais de "système de persistance", cela me semble logique de faire en sorte qu'une classe se charge d'une et une seule chose à la fois.</p>
<p>Après, si les maîtres mots de ton projet sont "faut que ça marche", ben… Va dans ce sens-là.</p>Problème de compréhension, message #685112015-08-05T18:51:52+02:00kulturm@n/@kulturm%40nhttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68511<p>OK, je vois vaguement ce que tu veux dire mais supposons que je sois sûr de ne jamais changer de système de persistance(donc rester sur une BDR).</p>Problème de compréhension, message #685102015-08-05T18:35:36+02:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68510<p>J'en pense que fonctionnellement, c'est bien. Utilise les requêtes préparées le plus rapidement possible pour éviter les injections SQL.</p>
<p>D'un point de vue conceptuel, tu peux améliorer ça.</p>
<p>Je te ferais bien un exemple détaillé mais c'est chronophage, et j'ai du mal avec les noms de symboles à la française. <img alt=":P" src="/static/smileys/langue.png"></p>
<p>Essaie de faire une classe abstraite qui se contente de "trouver" les opérateurs en fonction de critères, puis des classes concrètes qui se contenteront de trouver ces opérateurs dans des sources de données différentes (base de données, fichiers xml, …). Comme ça, le jour où tu voudras utiliser une source de données différentes, tu n'auras qu'à écrire une nouvelle implémentation.</p>Problème de compréhension, message #685072015-08-05T17:46:03+02:00kulturm@n/@kulturm%40nhttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68507<p>Merci pour vos réponses. J'ai essayé de faire une méthode trouver un peu générique</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="codehilite"><pre><span class="kd">public</span> <span class="n">OperateurPhysique</span><span class="o">[]</span> <span class="nf">trouver</span><span class="o">(</span><span class="n">String</span> <span class="n">filtre</span><span class="o">,</span> <span class="n">Object</span><span class="o">...</span> <span class="n">objs</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">ResultSet</span> <span class="n">res</span><span class="o">;</span>
<span class="n">OperateurPhysique</span><span class="o">[]</span> <span class="n">ops</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="n">String</span> <span class="n">sql</span> <span class="o">=</span> <span class="s">"SELECT * FROM matable WHERE "</span><span class="o">;</span>
<span class="n">StringTokenizer</span> <span class="n">tokens</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringTokenizer</span><span class="o">(</span><span class="n">filtre</span><span class="o">,</span> <span class="s">";"</span><span class="o">);</span>
<span class="kt">int</span> <span class="n">t</span> <span class="o">=</span> <span class="n">objs</span><span class="o">.</span><span class="na">length</span><span class="o">;</span>
<span class="k">for</span><span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">t</span> <span class="o">;</span> <span class="n">i</span><span class="o">++)</span>
<span class="o">{</span>
<span class="k">if</span><span class="o">(</span><span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span>
<span class="n">sql</span> <span class="o">+=</span> <span class="n">tokens</span><span class="o">.</span><span class="na">nextToken</span><span class="o">()</span> <span class="o">+</span> <span class="s">" = "</span> <span class="o">+</span> <span class="n">objs</span><span class="o">[</span><span class="n">i</span><span class="o">];</span>
<span class="k">else</span>
<span class="n">sql</span> <span class="o">+=</span> <span class="s">"AND "</span> <span class="o">+</span> <span class="n">tokens</span><span class="o">.</span><span class="na">nextToken</span><span class="o">()</span> <span class="o">+</span> <span class="s">" = "</span> <span class="o">+</span> <span class="n">objs</span><span class="o">[</span><span class="n">i</span><span class="o">];</span>
<span class="o">}</span>
<span class="c1">//reste du code</span>
<span class="o">}</span>
</pre></div>
</td></tr></table>
<p>Ainsi </p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="codehilite"><pre><span class="n">trouver</span><span class="o">(</span><span class="s">"nom;prenom"</span> <span class="o">,</span> <span class="s">"Lupin"</span> <span class="o">,</span> <span class="s">"Arsene"</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>exécutera la requête</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="codehilite"><pre><span class="n">SELECT</span> <span class="o">*</span> <span class="n">FROM</span> <span class="n">matable</span> <span class="n">WHERE</span> <span class="n">nom</span> <span class="o">=</span> <span class="err">'</span><span class="n">Lupin</span><span class="err">'</span> <span class="n">AND</span> <span class="n">prenom</span> <span class="o">=</span> <span class="err">'</span><span class="n">Arsène</span><span class="err">'</span>
</pre></div>
</td></tr></table>
<p>Bien sur je compte utiliser des requêtes préparées plus tard.
Qu'en pensez vous? </p>Problème de compréhension, message #683842015-08-04T13:39:09+02:00grugru/@grugruhttps://zestedesavoir.com/forums/sujet/3790/probleme-de-comprehension/?page=1#p68384<p>Faut voir ce que tu utilises, mais Hibernate, toplink… sont des ORM en Java par exemple</p>