J'ai récemment lu le billet de blog Three Big Lies et j'ai du mal à justifier le deuxième mensonge, qui est cité ici:
(LIE # 2) LE CODE DEVRAIT ÊTRE CONÇU AUTOUR D'UN MODÈLE DU MONDE
Il n'y a aucune valeur à ce que le code soit une sorte de modèle ou de carte d'un monde imaginaire. Je ne sais pas pourquoi celui-ci est si convaincant pour certains programmeurs, mais il est extrêmement populaire. S'il y a une fusée dans le jeu, soyez assuré qu'il y a une classe "Rocket" (en supposant que le code est C ++) qui contient des données pour exactement une fusée et fait des choses rockety. Sans aucune considération pour ce que la transformation des données est réellement en cours, ou pour la disposition des données. Ou d'ailleurs, sans comprendre fondamentalement que là où il y a une chose, il y en a probablement plus d'une.
Bien qu'il existe de nombreuses pénalités en termes de performances pour ce type de conception, la plus importante est qu'elle n'est pas évolutive. Du tout. Cent roquettes coûtent cent fois plus qu'une roquette. Et il est extrêmement probable que cela coûte encore plus que cela! Même pour un non-programmeur, cela ne devrait pas avoir de sens. Économie d'échelle. Si vous avez plus de quelque chose, cela devrait coûter moins cher, pas plus cher. Et la façon de le faire est de concevoir correctement les données et de regrouper les choses par des transformations similaires.
Voici mes problèmes avec ce mensonge en particulier.
Le code est un modèle / carte d'un monde imaginaire, car la modélisation du monde imaginaire aide (au moins moi, personnellement) à visualiser et à organiser le code.
Avoir une classe "Rocket" est, pour moi, un choix parfaitement valable pour une classe. Peut-être que les "fusées" pourraient être décomposées en types de fusées comme AGM-114 Hellfire, etc. qui contiendraient la force de la charge utile, la vitesse maximale, le rayon de braquage maximal, le type de ciblage, etc. et une vitesse.
Bien sûr, avoir 100 fusées coûte plus d'une fusée. S'il y a 100 Rockets à l'écran, il doit y avoir 100 calculs différents pour mettre à jour leur position. Le deuxième paragraphe semble donner à penser que s'il y a 100 fusées, cela devrait coûter moins de 100 calculs pour mettre à jour l'état?
Mon problème ici est que l'auteur présente un modèle de programmation «imparfait» mais ne présente aucun moyen de le «corriger». Peut-être que je trébuche sur l'analogie de la classe Rocket, mais j'aimerais vraiment comprendre le raisonnement derrière ce mensonge. Quelle est l'alternative?
la source
Réponses:
Tout d'abord, regardons un certain contexte: il s'agit d'un concepteur de jeu écrivant sur un blog dont le sujet est en train de sortir la dernière baisse de performance d'un CPU Cell BE. En d'autres termes: il s'agit de la programmation de jeux sur console, plus spécifiquement, la programmation de jeux sur console pour la PlayStation 3.
Maintenant, les programmeurs de jeux sont un groupe curieux, les programmeurs de jeux sur console encore plus, et le Cell BE est un processeur plutôt étrange. (Il y a une raison pour laquelle Sony a opté pour un design plus conventionnel pour la PlayStation 4!)
Nous devons donc examiner ces déclarations dans ce contexte.
Il y a aussi quelques simplifications dans ce billet de blog. En particulier, ce mensonge n ° 2 est mal présenté.
Je dirais que tout ce qui fait abstraction du monde réel est un modèle dans un certain sens. Et comme le logiciel n'est pas réel, mais virtuel, c'est toujours une abstraction et donc toujours un modèle. Mais! Un modèle n'a pas besoin d'avoir une correspondance 1: 1 nette avec le monde réel. C'est, après tout, ce qui en fait un modèle en premier lieu.
Donc, dans un certain sens, l'auteur a clairement tort: le logiciel est un modèle. Période. Dans un autre sens, il a raison: ce modèle n'a pas du tout à ressembler au monde réel.
Je vais donner un exemple que j'ai déjà donné dans d'autres réponses au fil des ans, le (in) fameux exemple d'introduction au compte bancaire OO 101. Voici à quoi ressemble un compte bancaire dans presque toutes les classes OO:
Donc:
balance
c'est des données , ettransfer
c'est une opération .Mais! Voici à quoi ressemble un compte bancaire dans presque tous les logiciels bancaires:
Donc, maintenant
transfer
c'est des données etbalance
c'est une opération (un repli à gauche sur le journal des transactions). (Vous remarquerez également queTransactionSlip
c'est immuable,balance
est une fonction pure, leTransactionLog
peut être une infrastructure de données "presque" immuable uniquement en annexe… Je suis sûr que beaucoup d'entre vous ont repéré les bogues de concurrence flagrants dans la première implémentation, qui disparaissent maintenant comme par magie .)Notez que ces deux sont des modèles. Ces deux éléments sont également valables. Les deux sont corrects. Ces deux modèles la même chose. Et pourtant, ils sont exactement duaux les uns aux autres: tout ce qui est des données dans un modèle est une opération dans l'autre modèle, et tout ce qui est une opération dans un modèle est des données dans l'autre modèle.
Donc, la question n'est pas de savoir si vous modélisez le "monde réel" dans votre code, mais comment vous le modélisez.
Il s'avère que le deuxième modèle est en fait aussi le fonctionnement de la banque dans le monde réel. Comme je l'ai laissé entendre ci-dessus, ce deuxième modèle est principalement immuable et pur, et à l'abri des bogues de concurrence, ce qui est en fait très important si vous considérez qu'il y a peu de temps, il y
TransactionSlip
avait de vrais bouts de papier envoyés via cheval et calèche.Cependant, le fait que ce deuxième modèle corresponde réellement à la fois au fonctionnement des services bancaires dans le monde réel et au fonctionnement des logiciels bancaires dans le monde réel, ne le rend pas automatiquement plus «correct». Parce que, en fait, le premier («mauvais») modèle se rapproche assez étroitement de la façon dont les clients bancaires perçoivent leur banque. Pour eux ,
transfer
c'est une opération (ils doivent remplir un formulaire), etbalance
c'est une donnée au bas de leur extrait de compte.Donc, il peut très bien être vrai que dans le code moteur du jeu de base d'un jeu de tir PS3 haute performance, il n'y aura pas de
Rocket
type, mais il y aura quand même une modélisation du monde en cours, même si le modèle a l'air bizarre à quelqu'un qui n'est pas un expert dans le domaine de la programmation du moteur physique des jeux sur console.la source
balance
comme des données et des transactions comme plus de données et des transferts comme des opérations, car c'est ce que l'utilisateur voit, même si le back-end peut le traiter différemment.Je ne suis pas d'accord avec chaque "mensonge" qu'il propose.
TL; DR L'auteur de cet article essayait d'être controversé pour rendre son article plus intéressant, mais les soi-disant «mensonges» sont acceptés par les développeurs de logiciels pour de bonnes raisons.
Mensonge n ° 1 - Big O est important à des fins de mise à l'échelle. Personne ne se soucie si une petite application prend plus de temps, ce qui est la seule constante de temps qui compte, ils se soucient que lorsqu'ils doublent la taille d'entrée, cela ne multiplie pas le temps d'exécution par un facteur de 10.
Mensonge n ° 2 - La modélisation des programmes d'après le monde réel permet à un programmeur qui examine votre code 3 ans plus tard de comprendre facilement ce qu'il fait. Le code doit être maintenable ou vous devrez passer des heures à essayer de comprendre ce que le programme essaie de faire. Une autre réponse suggère que vous pouvez avoir des classes plus génériques comme
LaunchPad
etMassiveDeviceMover
. Ce ne sont pas nécessairement de mauvaises classes, mais vous en auriez toujours besoinRocket
. Comment quelqu'un est-il censé savoir ce queMassiveDeviceMover
fait ou ce qu'il bouge? S'agit-il de montagnes, de vaisseaux spatiaux ou de planètes? Cela signifie essentiellement que l'ajout de classes commeMassiveDeviceMover
rend votre programme moins efficace (mais peut-être bien plus lisible et compréhensible).De plus, le coût du temps de développement a commencé à dépasser le coût du matériel il y a longtemps. C'est une horrible idée de commencer à essayer de concevoir avec l'optimisation au premier plan de vos pensées. Vous le programmez de manière simple et compréhensible, puis ajustez votre programme après avoir découvert les parties de vos programmes qui prennent beaucoup de temps à s'exécuter. N'oubliez pas: 80% du temps d'exécution est utilisé par 20% du programme.
Mensonge n ° 3 - Le code est extrêmement important. Un code bien écrit (et modulaire) permet une réutilisation (permettant d'économiser d'innombrables heures de travail). Il vous permet également de passer au crible et de reconnaître les mauvaises données afin qu'elles puissent être traitées. Les données sont merveilleuses, mais sans le code, il serait impossible d'analyser et d'obtenir des informations utiles.
la source
Dans un système de commerce électronique, vous ne traitez pas de «fusées» au niveau d'une classe, vous traitez de «produits». Cela dépend donc de ce que vous essayez d'accomplir et du niveau d'abstraction souhaité.
Dans un jeu, on pourrait soutenir que les roquettes ne sont qu'un des nombreux "objets en mouvement". La même physique s'applique à eux qu'à tous les autres objets en mouvement. Donc, à tout le moins, la "fusée" va hériter d'une classe de base "d'objets en mouvement" plus générale.
Quoi qu'il en soit, l'auteur du passage que vous avez cité semble avoir un peu exagéré son cas. Les roquettes peuvent toujours avoir des caractéristiques uniques, comme la «quantité de carburant restante» et la «poussée», et vous n'avez pas besoin d'une centaine de classes pour représenter cela pour cent roquettes, vous n'en avez besoin que d'une. La création d'objets est assez peu coûteuse dans la plupart des langages de programmation décents, donc si vous avez besoin de suivre des choses semblables à des fusées, l'idée que vous ne devriez pas créer des objets Rocket parce qu'ils pourraient être trop chers n'a pas beaucoup de sens.
la source
Le problème avec le monde réel est tout ce maudit physique. Nous séparons les choses en objets physiques dans le monde réel parce qu'ils sont plus faciles à déplacer que les atomes individuels, ou un laitier fondu géant de quelque chose qui pourrait potentiellement être une fusée.
De même, le monde réel fournit un certain nombre de fonctionnalités utiles sur lesquelles nous nous appuyons. Il est vraiment facile de faire des exceptions Penguin - "tous les oiseaux volent, sauf ...". Et c'est vraiment facile d'étiqueter les choses comme des fusées, je veux dire si j'appelle ce pingouin une fusée et que je l'allume ... ça ne marche tout simplement pas.
Donc, comment nous séparons les choses dans le monde réel fonctionne conceptuellement sous ces contraintes. Lorsque nous faisons des choses dans le code, nous devons séparer les choses pour bien fonctionner sous ces contraintes, qui sont décidément différentes.
Pensez aux réseaux. Nous ne modélisons pas les ports, les fils et les routeurs en code. Au lieu de cela, nous résumons la communication réseau en connexions et protocoles. Nous le faisons parce que c'est une abstraction utile quelle que soit la mise en œuvre dans le monde réel. Et il met des contraintes utiles (par exemple: vous ne pouvez pas communiquer jusqu'à ce que la connexion soit ouverte) qui ne comptent que dans le code .
Alors oui, parfois modéliser du code après que le monde réel fonctionne, mais c'est une coïncidence . Lorsque les gens parlent de POO, les objets ne sont pas des objets du monde réel. Que les écoles et les tutoriels disent le contraire est une tragédie de plusieurs décennies.
la source
Rocket
type dans le code de ce type, je suis prêt à parier qu'il existe néanmoins un modèle de…L'alternative est de modéliser les choses qui intéressent vos programmes. Même si votre programme traite des roquettes, vous n'aurez peut-être pas besoin d'avoir une entité appelée a
Rocket
. Par exemple, vous pourriez avoir uneLaunchPad
entité et uneLaunchSchedule
entité et uneMassiveDeviceMover
entité. Le fait que tout cela aide au lancement de roquettes ne signifie pas que vous manipulez vous-même les roquettes.la source
C'est le vrai problème, mais je vais vous donner mon avis en tant que développeur, peut-être que cela vous aidera.
Tout d'abord, je ne dirais pas que tout cela est un mensonge, comme des idées fausses courantes. Le dire est un battage médiatique.
Celui qu'il a raison, à certains égards. Je ne vais pas y consacrer beaucoup de temps, car cela ne fait pas partie de la question. Mais en substance, il a raison. Je pourrais reformuler ceci comme «ce qui fonctionne dans un laboratoire peut ne pas fonctionner dans la vraie vie». Trop souvent, les développeurs s'en tiennent à une conception qui fonctionne dans un "laboratoire" mais échoue dans les applications du monde réel.
Three Sounds un peu de savon pour moi, mais essentiellement il a encore raison. Mais cela pourrait être réécrit pour "écrire du code autour de vos besoins, n'essayez pas d'adapter les besoins à votre code."
Deux fois encore, ici il a raison. J'ai vu des développeurs passer des semaines ou plus à développer une classe "fusée" alors qu'une classe "véhicule" simple fonctionnerait, ou une classe "mobile" encore plus simple. Si tout ce que votre fusée doit faire est de se déplacer du côté gauche de l'écran vers la droite et d'émettre un son, alors vous pouvez utiliser la même classe que vous avez utilisée pour les voitures, les trains, les bateaux et les mouches. Le 100 devrait coûter moins que l'argument 1 * 100 semble être consacré au temps de développement, et pas tellement aux coûts de calcul. Bien que s'en tenir à moins de classes générales à réutiliser soit «moins cher», alors de nombreuses classes spécifiques ne peuvent pas être réutilisées. Cela pourrait probablement être réécrit car "les classes générales sont meilleures que les classes spécifiques,
Essentiellement, l'article entier pourrait être réécrit, avec moins de mots à la mode et ce ne serait au mieux qu'un paragraphe long. Cela dit, il s'agit d'un article de blog axé sur un domaine étroit de la programmation. J'ai fait de la programmation intégrée, et je suis d'accord, avec l'idée générale derrière ces déclarations, bien qu'il y ait pas mal de "fluff" autour d'eux pour le rendre approprié pour une présentation à GDC.
Une dernière note, l'article a été écrit en 2008 (du mieux que je puisse dire). Les choses changent rapidement. Les déclarations sont vraies aujourd'hui, mais les systèmes embarqués sont beaucoup plus courants aujourd'hui qu'à l'époque, et les modèles de développement changent. Peut-être même en réponse à cet article / discours.
la source
Je trouve intéressant que ces mensonges tournent autour des préoccupations académiques: la plate-forme, l'efficacité de l'utilisation de la mémoire et les données. Mais il ignore complètement l'élément humain.
Le logiciel vise à répondre aux besoins des gens. En règle générale, cela est quantifié en termes commerciaux - il y a des clients qui veulent quelque chose et des bailleurs de fonds qui sont prêts à payer pour y arriver. Si un logiciel est écrit de manière à répondre aux besoins des deux côtés de l'équation, alors c'est un bon logiciel, sinon, c'est un mauvais logiciel.
Si la plateforme n'est pas importante pour le client, alors la plateforme n'est pas importante. Si l'efficacité de la mémoire n'est pas importante pour le client, elle n'est pas importante. Si les données ne sont pas importantes pour le client, les données ne sont pas importantes. Si le code fonctionne, mais ne peut être lu ou maintenu, et que le client souhaite des changements rapides et fiables à un prix décent, alors un code mal écrit est une mauvaise chose. Si le code fonctionne, mais ne peut pas être lu ou maintenu, et que le client ne se soucie pas ou est prêt à payer pour des refacteurs coûteux, un code mal écrit est une bonne chose.
Le gros mensonge est que tout sauf l'élément humain compte. Pourquoi les données sont-elles importantes? Parce qu'il y a un client ou une partie prenante qui en a besoin. Telle est la "grande vérité".
la source
À mon humble avis, si le code est "conçu autour d'un modèle du monde", il est plus facile à comprendre, tant pour les concepteurs et les développeurs que pour les responsables. Mais je pense que ce n'est pas seulement moi, et pas seulement un logiciel. Tiré de Wikipédia: La modélisation scientifique est une activité scientifique dont le but est de faciliter la compréhension, la définition, la quantification, la visualisation ou la simulation d'une partie ou d'une caractéristique du monde en la référant à des connaissances existantes et généralement acceptées.
la source