<?xml version="1.0" encoding="ISO-8859-1"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title><![CDATA[Forum du club des développeurs et IT Pro - Blogs - Réac' programming par fcharton2]]></title>
		<link>https://www.developpez.net/forums/blogs/662093-fcharton2/</link>
		<description>Developpez.com, le Club des Développeurs et IT Pro</description>
		<language>fr</language>
		<lastBuildDate>Sat, 25 Apr 2026 13:17:09 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>15</ttl>
		<image>
			<url>https://forum.developpez.be/images/misc/rss.jpg</url>
			<title><![CDATA[Forum du club des développeurs et IT Pro - Blogs - Réac' programming par fcharton2]]></title>
			<link>https://www.developpez.net/forums/blogs/662093-fcharton2/</link>
		</image>
		<item>
			<title>Misères de la conception objet : notes et arrière-pensées</title>
			<link>https://www.developpez.net/forums/blogs/662093-fcharton2/b285/miseres-conception-objet-notes-arriere-pensees/</link>
			<pubDate>Tue, 03 Mar 2015 08:26:54 GMT</pubDate>
			<description>Quelques idées venues en...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><i>Quelques idées venues en écrivant le message précédent, livrées en vrac.</i><br />
<br />
Que nous apprend l’exemple du poker ? Plusieurs choses à mon avis. <br />
<br />
D’abord, que l’imitation du réel, qui nous vient naturellement quand on conçoit un programme, ne donne pas forcément la meilleure solution, ni même une bonne solution. C’était le sujet de l’article, inutile d’y revenir.<br />
<br />
Ensuite, que notre architecture s’est améliorée en passant d’une description « physique » du problème (les cartes et les mains), à une description plus algorithmique (les figures et la fonction de comparaison), à la représentation des données nécessaires au fonctionnement de l’algorithme (les « mains triées »).Je crois que ces trois étapes sont au cœur de toute conception informatique. Pour écrire un programme, on part d’une description naïve du réel, qu’on doit abandonner pour une vision plus algorithmique de ses règles de fonctionnement (ou plus précisément, de la partie des règles de fonctionnement qui nous importent),qu’on doit à nouveau abandonner pour une réflexion sur la représentation des données, dont on tire l’architecture finale.<br />
<br />
Dans la pratique, la dernière étape est souvent reportée à des jours meilleurs (c’est-à-dire jamais…), car elle est vue comme une « optimisation prématurée ». C’est à mon avis une très mauvaise idée (et un bien mauvais procès fait à Knuth). La réflexion sur les données, on le voit dans l’exemple du poker, et une façon de revenir sur les algorithmes, et d’arriver à une architecture plus simple (et plus facile à maintenir).<br />
<br />
En fait, la seconde étape est souvent bâclée, elle aussi. Une fois qu’ils ont la description naïve du système, beaucoup de développeurs se précipitent sur Google (ou DVP) pour y chercher des solutions en boîte, librairies toutes faites, ou solutions à appliquer aveuglément (c’est exactement l’idée des design pattern). Ceci part d’un bon sentiment, mais prise trop tôt, cette recherche de solutions toutes faites tue la conception en la figeant prématurément (parce qu’une fois qu’on aura décidé que c’est un problème de « cartes » et qu’on aura choisi la librairie cartelib.dll qui modélise toutes les cartes possibles et imaginables, il sera très difficile d’abandonner la conception, au profit d’une autre fondée sur les figures…)<br />
<br />
Et ceci m’amène à ce qui devrait peut-être être la vraie conclusion du billet précédent. La conception d’un programme part presque toujours d’une architecture naïve, qu’on critique et qu’on abandonne au profit d’une vision plus profonde, qu’on abandonnera probablement elle aussi pour une troisième. Plus le programme est important, plus il y aura d’itérations, et en général, très peu de code doit survivre d’une itération à l’autre (personnellement, je réécris complètement à chaque fois…).<br />
<br />
Je ne crois pas qu’on puisse se passer de ces étapes. En fait, je crois même que c’est en persistant longtemps dans une mauvaise idée qu’on finit par en comprendre les limites, et trouver une meilleure solution. Il faudra alors accepter de jeter ce qu’on à fait, donc probablement ne pas trop fignoler ces premières étapes, sous peine de trop s’attacher aux mauvaises solutions du début.<br />
<br />
Les mauvaises idées sont le fumier sur lequel poussent les bons programmes.<br />
<br />
<br />
<br />
<i>Pour ceux que la conception objet intéresse, je ne saurai trop recommander les écrits et les vidéos de Sandi Metz. C’est du Ruby et pas du C++, il y a un peu trop de tests unitaires à mon goût (j’y reviendrai), mais c’est toujours très clair. Dans les grands anciens, je recommande Brad Cox (l’inventeur de l’objective C) : Object Oriented Programming: An Evolutionary Approach.</i></blockquote>

]]></content:encoded>
			<dc:creator>fcharton2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/662093-fcharton2/b285/miseres-conception-objet-notes-arriere-pensees/</guid>
		</item>
		<item>
			<title>Misères de la conception objet, un cas pratique</title>
			<link>https://www.developpez.net/forums/blogs/662093-fcharton2/b253/miseres-conception-objet-cas-pratique/</link>
			<pubDate>Sun, 01 Mar 2015 13:27:04 GMT</pubDate>
			<description>Un des charmes de la...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Un des charmes de la programmation objet, c’est l’impression de « programmer le réel ». Finis les entiers, les tableaux, les fonctions, les fichiers. En objet, on manipule les concepts métiers, décrits par des classes, agissant au travers de fonctions, composés par assemblage d’autres concepts, ou par spécialisation de catégories générales. On programme un jeu d’aventure ? Nos programmes auront des classes portes, des classes monstres, des classes épées et des classes personnages. On fait de la gestion de personnel ? Il y aura des employés, des managers, des bureaux et des sociétés. <br />
<br />
Et comme l’approche objet est très répandue, cette vision de l’informatique comme imitation du monde se retrouve un peu partout. Elle est dans les formations et les manuels, remplis d’animaux qui courent, d’oiseaux qui volent, de voitures qui roulent, et qui ont un moteur, et qui sont des véhicules. Elle est aussi, dans les systèmes de modélisation ou dans les formats de données comme XML ou JSON. <br />
<br />
Cette approche est très séduisante. D’abord, parce qu’elle paraît simplifier les spécifications : il suffit de faire décrire à l’utilisateur son métier, pour en tirer une architecture. Ensuite, parce qu’elle semble certaine d’aboutir : on voit mal comment un programme qui décrit correctement le réel pourrait ne pas répondre aux besoins d’utilisateurs réels. Enfin, parce que dans certains cas complexes, elle fonctionne remarquablement bien. C’est évidemment l’approche idéale pour des programmes de simulation ou de suivi, mais elle est également très adaptée quand le « réel » qu’on prétend simuler est lui-même une construction informatique, par exemple un système de fenêtrage. <br />
<br />
Ce n’est pourtant pas une évidence. Un avion ne ressemble pas à un oiseau, un bateau n’a pas grand-chose de commun avec un canard, et pourtant l’un vole, et l’autre navigue. Et de fait, l’imitation du réel, en informatique, est souvent au cœur de mauvaises conceptions, de programmes inefficaces, voire d’architectures très éloignés de la conception objet. Je vais essayer de l’illustrer sur un exemple simple (et très classique).<br />
<br />
Essayons de concevoir un programme qui compare deux mains de poker. La réaction naturelle, en conception objet, consiste à se dire qu’on a des cartes, définies par leur couleur et leur rang, qui forment un premier concept, quelque chose comme (en C++, mais ce serait presque pareil dans d’autres langages)<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:132px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">enum</span> Couleur <span style="color: black;">&#123;</span>coeur,carreau,trefle,pique<span style="color: black;">&#125;</span> ;
<span style="color: #0000ff;">enum</span> Rang <span style="color: black;">&#123;</span>deux,trois, quatre, cinq, six, sept, huit, neuf, dix, valet, dame, roi, as<span style="color: black;">&#125;</span> ;
&nbsp;
<span style="color: #808080;">// struct car assemblage de donn&eacute;es publiques sans m&eacute;thodes</span>
<span style="color: #0000ff;">struct</span> Carte <span style="color: black;">&#123;</span> 
	Couleur couleur ;
	Rang rang ; 
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
Une main, que nous allons appeler Jeu (vu que main veut dire autre chose en C++) est une collection de cinq cartes, qu’on va agrémenter d’un opérateur de comparaison.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:108px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">enum</span> QuiGagne <span style="color: black;">&#123;</span>moi, personne, lui<span style="color: black;">&#125;</span> ;
&nbsp;
<span style="color: #0000ff;">class</span> Jeu <span style="color: black;">&#123;</span>
	Carte cartes<span style="color: black;">&#91;</span><span style="color: #cc66cc;">5</span><span style="color: black;">&#93;</span>; <span style="color: #808080;">// ou un vector si vous voulez&#133;</span>
	QuiGagne Compare<span style="color: black;">&#40;</span><span style="color: #0000ff;">const</span> Jeu &amp;j<span style="color: black;">&#41;</span> <span style="color: #0000ff;">const</span>;
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
Ceci nous donne un programme qui ressemble à<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">Jeu j1,j2 ;
<span style="color: #808080;">// chargement des donn&eacute;es &agrave; comparer</span>
<span style="color: #0000ff;">return</span> j1.Compare<span style="color: black;">&#40;</span>j2<span style="color: black;">&#41;</span> ;</pre></td></tr></table></pre>
</div><br />
On constate ici la puissance de l’imitation. On a à peine commencé, mais on a déjà un squelette de programme, très simple, qui pourrait être réutilisé pour n’importe quel jeu de cartes. On sent que l’architecte, le responsable méthodes et le chef de projet vont être fiers de nous. Il ne reste qu’à écrire le comparateur.<br />
<br />
Là encore, l’application naïve des règles du jeu donne une solution rapide. On a neuf cas, quinte flush, carré, full, couleur, suite, brelan, deux paires, paire, une carte. Pour chacun, on peut ajouter à notre classe une fonction de test estXXX() et une fonction de départage compareXXX(Jeu&amp;), appelée si les deux mains sont XXX. On va donc avoir une série de neuf fonctions membres : <br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">bool</span> EstQuinteFlush<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
<span style="color: #0000ff;">bool</span> EstCarre<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
<span style="color: #0000ff;">bool</span> EstFlush<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;</pre></td></tr></table></pre>
</div>…<br />
<br />
Neuf fonctions servant à départager les ex-aequos<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">QuiGagne CompareQuintesFlush<span style="color: black;">&#40;</span>Jeu&amp;j<span style="color: black;">&#41;</span> ; 
QuiGagne CompareCarres<span style="color: black;">&#40;</span>Jeu &amp;j<span style="color: black;">&#41;</span> ;</pre></td></tr></table></pre>
</div><br />
Et un opérateur de comparaison qui ressemble à :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td valign="top"><pre style="margin: 0">QuiGagne Compare<span style="color: black;">&#40;</span>Jeu &amp;j<span style="color: black;">&#41;</span> <span style="color: black;">&#123;</span>
	<span style="color: #808080;">// quintes flush</span>
	<span style="color: #0000ff;">bool</span> qf1=EstQuinteFlush<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
	<span style="color: #0000ff;">bool</span> qf2=j.EstQuinteFlush<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>qf1 &amp;&amp; !qf2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> moi ;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>!qf1 &amp;&amp; qf2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> lui ;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>qf1 &amp;&amp; qf2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> CompareQuintesFlush<span style="color: black;">&#40;</span>j<span style="color: black;">&#41;</span>
	<span style="color: #808080;">// carres</span>
	<span style="color: #0000ff;">bool</span> c1=EstCarre<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>;
	<span style="color: #0000ff;">bool</span> c2=j.EstCarrre<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>c1 &amp;&amp; !c2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> moi ;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>!c1 &amp;&amp; c2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> lui ;
	<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>c1 &amp;&amp; c2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> CompareCarres<span style="color: black;">&#40;</span>j<span style="color: black;">&#41;</span>
<span style="color: #808080;">// et ainsi de suite en descendant</span>
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
Mission accomplie, hein ? il n’y a plus qu’à écrire 18 fonctions de test et d’ex-aequo, et à assembler tout cela en une grande fonction de comparaison, avec ou sans boucle, qui traite les cas successivement. Ca ne va pas être très beau, ni très élégant, mais si on a le temps, on refactorisera. Et tout va bien se passer, vu qu’on a modélisé au plus près.<br />
<br />
En fait, c’est généralement là que les problèmes commencent. D’abord, on vient de choisir une solution qui impose d’écrire pas mal de code (18 fonctions), sans grande possibilité de mise en commun. Ceci veut dire plus de tests unitaires, plus de débogage, plus de risques d’erreur. Ensuite, parier sur une refactorisation « après », c’est être presque certain qu’elle n’aura jamais lieu : l’écriture, les tests et le débogage prendront plus de temps que prévu, et une fois qu’on aura quelque chose qui marche, la refactorisation sera presque toujours reportée à des lendemains qui chantent. En fait, la refactorisation, c’est souvent une vue de l’esprit : soit elle a lieu quand on développe, et ce n’en est pas une, soit c’est quelque chose qu'on imagine pour se donner bonne conscience. <br />
<br />
Mais le principal problème est théorique : notre élégante méthode de conception objet, censée nous produire de beaux programmes maintenables, réutilisables, flexibles, agiles, produit, sur ce cas simple, un affreux code procédural, avec une grosse fonction moche et un tas de sous fonctions utilisées une seule fois, qui sera probablement très lent. Dans une situation réelle, avec de vrais difficultés, et de vrais enjeux, est-ce bien raisonnable ?<br />
<br />
L’approche objet est-elle en cause ? Je ne crois pas. A mon avis, ce qui pêche ici, c’est la conception imitative. La question posée était l’évaluation d’une main de poker, mais on a préféré modéliser le jeu, et en particulier son ‘apparence physique’ (les cartes et les mains), parce que c’était plus facile. <br />
<br />
Oublions les cartes, et revenons à la question posée. Comment effectuer la comparaison de deux mains ? <br />
<br />
La fonction Compare() nous donne une partie de la solution. Comme on l’a vu, on a neuf « cas » (appelons les figures), ordonnés de la quinte flush à la carte unique, qu’on va examiner successivement. Pour chacune, on appliquera la règle de décision suivante (A et B étant les joueurs)<br />
<br />
Si A l’a et pas B, A gagne<br />
Si B l’a et pas A, B gagne<br />
Si A et B l’ont tous les deux : une fonction de départage est appliquée<br />
Sinon, on passe au cas suivant.<br />
<br />
Un cas général qui se décline en neuf cas particuliers ? Vous avez demandé l’héritage ? (ou la spécialisation de templates, ici, c’est à peu près la même chose) <br />
<br />
Abandonnons les classes Carte et Jeu, et repartons d’une nouvelle « classe de base », la classe abstraite « figure », ready to derive or to templatise.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:180px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">class</span> figure <span style="color: black;">&#123;</span>
	<span style="color: #0000ff;">bool</span> EstUn<span style="color: black;">&#40;</span>Jeu &amp;j<span style="color: black;">&#41;</span> ;  
	<span style="color: #0000ff;">int</span> ExAequo<span style="color: black;">&#40;</span>Jeu &amp;j1Jeu &amp;j2<span style="color: black;">&#41;</span> ;
        <span style="color: #0000ff;">int</span> Compare<span style="color: black;">&#40;</span>Jeu &amp;j1,Jeu &amp;j2<span style="color: black;">&#41;</span>  <span style="color: black;">&#123;</span>
		<span style="color: #0000ff;">bool</span> b1=EstUn<span style="color: black;">&#40;</span>j1<span style="color: black;">&#41;</span> ;
		<span style="color: #0000ff;">bool</span> b2=EstUn<span style="color: black;">&#40;</span>j2<span style="color: black;">&#41;</span> ;
		<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>b1 &amp;&amp; !b2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">1</span>;
		<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>b2 &amp;&amp; !b1<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">2</span>
		<span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>b1 &amp;&amp; b2<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> ExAequo<span style="color: black;">&#40;</span>j1,j2<span style="color: black;">&#41;</span> ;
		<span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">-1</span>;
	<span style="color: black;">&#125;</span>
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
On pourrait en dériver neuf sous classes, une par figure, chacune avec ses fonctions EstUn() et ExAequo(), mais qui partageront toutes la même fonction Compare(). Et le programme principal instanciera successivement les sous-classes, appellera Compare(), renverra le résultat (A, B, égalité) si la figure apparaît, ou passera à la figure suivante sinon. <br />
<br />
Notez bien qu’il ne s’agit pas « juste d’une refactorisation » du code précédent. Dans ce nouveau modèle, les jeux ne sont plus que des structures de données publiques (des struct), et la vraie classe de base, ce sont les figures, qui ne sont pas le concept métier qui vient le plus naturellement quand on pense au poker. <br />
<br />
Qu'a-t-on gagné? On a amélioré la conception, et on a probablement un programme un peu plus élégant. Mais c'est à peu près tout. Il nous reste toujours 18 fonctions à écrire (les mêmes qu'avant, en fait), et autant de risques d’erreur. Pour aller plus loin, poursuivons la réflexion et voyons dans quelle mesure on pourrait mutualiser les calculs de ces 18 fonctions.<br />
<br />
Au poker, la plupart des figures (6 sur 9) sont déterminées par la longueur des séries de cartes de même rang. Imaginons que les cartes nous arrivent triées, par longueur de série, puis par hauteur. On aurait ainsi, (2 10) (2 8) (1 R) (une paire de dix, une paire de 8, un roi), ou (3 8) (2 10) (full aux huit par les dix). C’est une représentation assez naturelle. En fait, c’est exactement comme cela qu’un joueur décrira sa main. On retrouve l'imitation du réel, mais sur un plan moins naïf que tout à l'heure: au lieu de tenter de copier les cartes à jouer, on s'inspire de la façon dont un joueur range ses cartes. <br />
<br />
Si les mains sont représentées de cette façon, on constate (essayez !) que tous les tests d’ex aequo deviennent identiques : on parcourt les paires (longueur/hauteur) dans l’ordre, si A est plus haut que B, A gagne, si B est plus haut de A B gagne, sinon, on passe à la paire suivante (et si on est au bout, il y a égalité).<br />
<br />
Ainsi, en modifiant la représentation des cartes dans les mains (ce que certains qualifieraient d’optimisation prématurée… ben tiens !), nous venons d’unifier la fonction ExAequo() sur toutes les figures, et donc de diviser par 2 le nombre de fonctions à écrire. Notre classe figure mutualise désormais deux fonctions sur trois. Cela semble justifier notre nouvelle architecture. <br />
<br />
Mais on peut faire mieux, en poussant le raisonnement. Les lecteurs les plus attentifs auront peut-être remarqué qu’avec cette représentation, en dehors des suites et des couleurs, toutes les comparaisons de figures s’unifient… (et six tests sur neuf deviennent inutiles): il suffit de comparer d’abord les longueurs des séries, puis les hauteurs en cas d’égalité.<br />
<br />
Par exemple un carré de 8 et un 10 (4,8) (1,10), est supérieur à un full aux rois par les dames (3,R) (2,D) (car 4&gt;3). Mais un carré de 9 et une dame (4,9) (1,D) sera supérieur (car 4=4 1=1 mais 9&gt;8).<br />
<br />
Imaginons un poker simplifié, dans lequel il n’y aurait ni suite ni couleur. On n’a plus besoin des classes figures, car toute l’évaluation à deux niveaux tient en une fonction (qu’on peut, si on le souhaite, rendre membre de la classe Jeu).<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">typedef</span> Jeu  vector&lt;pair&lt;<span style="color: #0000ff;">int</span>,<span style="color: #0000ff;">int</span>&gt; &gt; ;
&nbsp;
<span style="color: #0000ff;">int</span> Compare<span style="color: black;">&#40;</span>Jeu &amp;j1,Jeu &amp;j2<span style="color: black;">&#41;</span> 
<span style="color: black;">&#123;</span>
<span style="color: #0000ff;">int</span> sz1=j1.size<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
<span style="color: #0000ff;">int</span> sz2=j2.cartes.size<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
<span style="color: #0000ff;">int</span> sz=min<span style="color: black;">&#40;</span>sz1,sz2<span style="color: black;">&#41;</span> ;
<span style="color: #0000ff;">for</span><span style="color: black;">&#40;</span><span style="color: #0000ff;">int</span> i=<span style="color: #cc66cc;">0</span> ;i&lt;sz ;i++<span style="color: black;">&#41;</span> <span style="color: black;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>j1<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.first&gt;j2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.first<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>j1<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.first&lt;j2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.first<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">2</span>;
<span style="color: black;">&#125;</span>
<span style="color: #0000ff;">for</span><span style="color: black;">&#40;</span><span style="color: #0000ff;">int</span> i=<span style="color: #cc66cc;">0</span> ;i&lt;sz ;i++<span style="color: black;">&#41;</span> <span style="color: black;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>j1<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.second&gt;j2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.second<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #0000ff;">if</span><span style="color: black;">&#40;</span>j1<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.second&lt;j2<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>.second<span style="color: black;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">2</span>;
<span style="color: black;">&#125;</span>
<span style="color: #0000ff;">return</span> <span style="color: #cc66cc;">0</span>;
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
Tout ça pour ça ? Heureusement qu’il y a les suites et les couleurs, hein ? Parce que sinon, on aurait l’air malins, avec notre approche objet qu’on remplace par une fonction d’une dizaine de lignes, qu’on peut rendre membre ou pas. Pfff, tu parles d’un exemple bidon !<br />
<br />
Comment faire ? Abandonner une si élégante simplification pour trois misérables cas particuliers semble une capitulation en rase campagne. C’est le moment de nous souvenir de nos cours de programmation objet, et du principe selon lequel on doit cacher ces cas particuliers via l’encapsulation des données… <br />
<br />
Reformulons tout cela, donc, en revenant à la classe Jeu qu’on avait abandonnée lors de l’itération précédente. Certains disent que pour être informaticien, il faut être paresseux, je crois qu’ils se trompent. Pour être informaticien, il ne faut avoir aucune fierté, et ne pas hésiter à aller chercher dans la poubelle le modèle qu’on vient de déclarer nul et non avenu (ce qui est évidemment incompatible avec la paresse). <br />
<br />
On dirait donc qu’on aurait une classe Jeu, qui contiendrait une représentation interne d’une main de poker, constituée d’un vecteur de paires longueur/hauteur. Cette représentation serait bien évidemment privée, et serait calculée, lors de la création d’un Jeu, par une fonction dédiée appelée Trie().<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code C++ :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:120px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td valign="top"><pre style="margin: 0"><span style="color: #0000ff;">class</span> Jeu <span style="color: black;">&#123;</span>
<span style="color: #0000ff;">private</span> :
	vector&lt;pair&lt;<span style="color: #0000ff;">int</span>,<span style="color: #0000ff;">int</span>&gt; &gt; _cartes ;
<span style="color: #0000ff;">public</span> :
	Trie<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> ;
	Compare<span style="color: black;">&#40;</span>Jeu &amp;j<span style="color: black;">&#41;</span> ;
<span style="color: black;">&#125;</span></pre></td></tr></table></pre>
</div><br />
Si on jouait au poker simplifié, on conserverait la fonction Compare définie ci-dessus, et la fonction Trie() consisterait à <br />
<br />
1-	Trier les cartes par rang<br />
2-	Générer les paires « longueur/rang »<br />
3-	Trier les paires<br />
<br />
Avec le poker réel, il va falloir tenir compte de la quinte flush (supérieure au carré), de la couleur et de la suite (entre le full et le brelan). Il va falloir tenir compte des couleurs, et notre bel algorithme de comparaison s’effondre. Trop pas de chance, hein ?<br />
<br />
Oui, sauf que… la représentation de notre main, en une série de paires longueur/rang est maintenant privée, on pourrait la faire évoluer, en modifiant Trie(), de façon à réintégrer les trois cas particuliers. Commençons par la quinte flush.<br />
<br />
Dans notre représentation, une quinte flush au roi s’écrit (1,R), (1,D), (1,V) (1,10), (1,9). Et il nous faut ajouter un booléen, indiquant la couleur. Convenons qu’on l’écrit désormais : (5,R), (1,D), (1,V) (1,10), (1,9), ou simplement (5,R). Une petite modification est nécessaire dans Trie(), mais Compare() est inchangé, puisqu'il considère désormais la quinte flush comme cinq cartes égales, et donc mieux qu'un carré. Ah mais c’est un hack ? Oui oui, mais sur des données privées, avec un commentaire explicatif dans le code, et c’est exactement à cela que sert l’encapsulation…<br />
<br />
Et pour les quintes et les flush ? Comme elles sont entre un full (3,X)(2,Y) et un brelan (3,X) (1,Y) (1,Z) (1,T), l'astuce précédente ne marchera pas, et il va falloir tordre un peu plus le bras à la représentation privée. A mon avis, on a deux options : soit admettre des longueurs non entières , et on écrira alors (3,X) (1.6,Y) … pour un full et (3,X) (1.3,Y) pour une quinte. Soit multiplier les longueurs par trois, partout, pour pouvoir utiliser les « barreaux intermédiaires ». Comme pour la quinte flush, il suffira pour cela de bricoler la fonction Trie() (et de documenter le bricolage), et de garder la comparaison comme avant. <br />
<br />
La boucle est maintenant bouclée. Nous sommes revenus à nos classes Jeu, auxquelles nous avons ajouté une représentation interne un peu éloignée du monde réel, mais adaptée aux calculs, et qui unifie la fonction de comparaison. Vue de loin, notre architecture ressemble au réel : on a des cartes qu’on trie, puis qu’on compare. Vu de près, c’est plus compliqué (comme on dit sur les réseaux sociaux). Mais on arrive à un programme assez minimaliste : la fonction Compare fait une dizaine de lignes, la fonction Trie() guère plus.<br />
<br />
Ah mais c’est dégoûtant ? Pas vraiment. Ca coute quelques lignes de codes, et autant de commentaires, dans une seule fonction Trie(). Ah mais c’est pas objet ? Mais si, justement. Tout le principe de l’encapsulation, c’est de pouvoir être libre d’adapter la représentation interne des données (un des pionners de l’algorithmique, Aho, je crois, expliquait que l’informatique n’est qu’une question de représentation des données). Et rien, dans le paradigme objet, n'impose à nos classes de ressembler au monde réel. <br />
<br />
Ce qui était, d’ailleurs, l’objet de ce premier billet…</blockquote>

]]></content:encoded>
			<dc:creator>fcharton2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/662093-fcharton2/b253/miseres-conception-objet-cas-pratique/</guid>
		</item>
		<item>
			<title>Ca a commencé comme ça...</title>
			<link>https://www.developpez.net/forums/blogs/662093-fcharton2/b252/ca-commence-ca/</link>
			<pubDate>Sun, 01 Mar 2015 13:22:52 GMT</pubDate>
			<description>Mon nom est fcharton2, je...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Mon nom est fcharton2, je suis informaticien, et comme j’en ai un peu honte, je n’interviens sur ce forum que sur le fil politique. Pour ceux qui ne connaissent pas, le fil politique s’appelle « ça commence bien », il aura trois ans d’existence en Mai, et compte plus de 17 000 messages, soit plus que le forum langages fonctionnels, dans ta face Haskell, moi je dis. <br />
<br />
Mais hier après-midi, j’ai reçu de l’équipe DVP un message personnalisé m’annonçant que mon blog personnel avait été créé gratuitement, et qu’il était immédiat, facile, intégré, visibilité et bonus (à mon avis, l’auteur aurait mieux fait de s’en tenir à la règle des trois adjectifs : immédiat, facile, et intégré, comme dans ferrugineux, intarissable et glacé, mais bon). Trop la classe! Je me suis dit, un peu comme le jour où une grande blonde en patins à roulette avec un T Shirt M&amp;M m’a offert… un paquet de M&amp;M. Et comme je ne sais pas résister à ce genre d’offre personnalisée, voici ce blog, que je vais essayer de tenir régulièrement (un billet par semaine si Dieu le veut).<br />
<br />
Si vous lisez le fil politique, vous savez sans doute que je suis un affreux réactionnaire. Eh bien, en informatique, c’est exactement pareil. Il y a très longtemps, quand certains d’entre vous regardaient encore Gulli en rentrant du collège, ma précédente incarnation (qui s’appelait fcharton, il y a comme un pattern) écrivait sur les forums C++ et algorithmes, et se faisait parfois rappeler à l’ordre pour ses idées rétrogrades. Elle avouait, sans vergogne, aimer réinventer la roue, ne pas apprécier les design pattern et la pensée en boite, prendre un malin plaisir à écrire ses allocations de tableaux (oui oui, des new[] et des delete[]), n’avoir aucun complexe à écrire de grosses fonctions, et semblait même persuadée qu’il fallait optimiser son code le plus tôt possible lors de l’écriture. Rétrograde, je vous dis !<br />
<br />
Et comme ça ne s’est certainement pas amélioré avec l’âge, ça va certainement se ressentir au fil de  ce blog, qui ressemblera rapidement, je pense, à une compilation de mauvaises pratiques. Donc voilà, vous être prévenus. Je peux commencer…</blockquote>

]]></content:encoded>
			<dc:creator>fcharton2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/662093-fcharton2/b252/ca-commence-ca/</guid>
		</item>
	</channel>
</rss>
