La programmation de sans si-états?
Je me souviens de quelques temps (années, probablement) il y a, j'ai lu sur Stackoverflow sur les charmes de la programmation avec aussi peu de cas-tests que possible. Cette question est peu pertinente, mais je pense que l'accent était mis sur l'aide de nombreuses petites fonctions qui ont retourné des valeurs déterminées par des tests en fonction du paramètre qu'ils reçoivent. Un exemple très simple serait d'utiliser ce:
int i = 5;
bool iIsSmall = isSmall(i);
avec isSmall()
ressemblant à ceci:
private bool isSmall(int number)
{
return (i < 10);
}
au lieu de simplement faire ceci:
int i = 5;
bool isSmall;
if (i < 10) {
isSmall = true;
} else {
isSmall = false;
}
(Logiquement ce code est juste un exemple de code. Il ne fait pas partie d'un programme que j'ai fais.)
La raison pour faire cela, je crois, parce qu'elle ressemble plus belle et fait un programmeur moins sujettes à des erreurs logiques. Si cette convention de codage est appliqué correctement, vous verrez pratiquement pas de si les tests n'importe où, sauf dans les fonctions dont seul but est de faire ce test.
Maintenant, ma question est: est-il de la documentation sur cette convention? Est-il n'importe quel endroit où vous pouvez voir les débats entre partisans et adversaires de ce style? J'ai essayé de chercher pour le Stackoverflow post qui m'a fait cela, mais je ne le retrouve plus.
Enfin, j'espère que cette question n'a pas obtenir abattu parce que je ne suis pas à demander une solution à un problème. Je suis simplement dans l'espoir d'entendre plus sur ce style de codage et peut-être augmenter la qualité de tout le codage je vais le faire dans l'avenir.
La programmation de sans si-états? Sûr: while(Condition){/*trucs*/break;}
sournois!
OriginalL'auteur Lee White | 2013-04-19
Vous devez vous connecter pour publier un commentaire.
Tout ce "si" vs "pas si" la chose qui me fait penser à la L'Expression De Problème1. Fondamentalement, c'est une observation que de la programmation avec les si les déclarations ou sans if est une question d'encapsulation et de l'extensibilité et qu'il est parfois préférable d'utiliser des instructions if2 et parfois il vaut mieux utiliser la dynamique de dispatching, avec des méthodes et des pointeurs de fonction.
Quand on veut modéliser quelque chose, il y a deux axes à s'inquiéter:
Une façon de mettre en œuvre ce genre de chose est avec des instructions if /filtrage /le modèle visiteur:
L'autre moyen est d'utiliser l'orientation de l'objet:
Il n'est pas difficile de voir que la première version à l'aide des instructions if il est facile d'ajouter de nouvelles opérations sur notre type de données: il suffit de créer une nouvelle fonction et de faire une analyse de cas à l'intérieur. D'autre part, il est difficile d'ajouter de nouveaux cas de notre type de données car cela voudrait dire passer par le programme et la modification de tous les les instructions de branchement.
La deuxième version est un peu le contraire. Il est très facile d'ajouter de nouveaux cas au type de données: il suffit de créer une nouvelle "classe" et de dire ce qu'il faut faire pour chacune des méthodes, nous avons besoin de mettre en œuvre. Toutefois, son désormais difficile d'ajouter de nouvelles opérations à l'interface car cela signifie l'ajout d'une nouvelle méthode pour toutes les anciennes classes en œuvre de l'interface.
Il existe de nombreuses approches différentes langues à utiliser pour tenter de résoudre le Problème de l'Expression et de faciliter l'ajout de deux nouveaux cas et de nouvelles opérations pour un modèle. Cependant, il ya des avantages et des inconvénients de ces solutions3 donc, en général, je pense que c'est une bonne règle de base pour choisir entre OO et si les déclarations selon quel axe vous voulez le rendre plus facile à étendre choses.
De toute façon, pour en revenir à votre question il y a le couple o choses que je voudrais souligner:
La première est que je pense que l'OO "mantra" de se débarrasser de tous si les déclarations et les remplacer par la méthode d'envoi a plus à voir avec la façon dont la plupart des langages à objets n'ont pas de typesafe Types de Données Algébriques qu'il a à faire avec des "si statemsnts" étant mauvais pour l'encapsulation. Car la seule manière d'être sûr est d'utiliser les appels de méthode, vous êtes encouragés à les convertir à l'aide de programmes si les déclarations dans les programmes à l'aide de la Modèle Visiteur4 ou pire: convertir les programmes qui devraient être en utilisant le modèle visiteur dans les programmes à l'aide de simple méthode de répartition, par conséquent, faire l'extensibilité facile dans la mauvaise direction.
La deuxième chose, c'est que je ne suis pas un grand fan de freinage choses dans des fonctions simplement parce que vous le pouvez. En particulier, je trouve que le style dans lequel toutes les fonctions ont juste 5 lignes et d'appeler des tonnes d'autres fonctions est assez difficile à lire.
Enfin, je pense que votre exemple n'a pas vraiment de se débarrasser de si consolidés. Essentiellement, ce que vous faites est d'avoir une fonction à partir de nombres Entiers à un nouveau type de données (avec deux affaires, l'une pour les Grands et un pour les Petits), puis vous devez les utiliser si les déclarations lors du travail avec le type de données:
Revenir à l'expression du problème de point de vue, l'avantage de la définition de notre toSize /isSmall fonction est de mettre la logique du choix de ce cas, notre nombre s'inscrit dans un lieu unique et que ses fonctions ne peut fonctionner que sur le cas par la suite. Toutefois, cela ne signifie pas que nous avons supprimé si les déclarations de notre code! Si nous avons la toSize étant une fonction de fabrication et nous avons de Grands et de Petits être des classes partage d'une interface, alors oui, nous aurons enlevé si les déclarations de notre code. Toutefois, si isSmall retourne un booléen ou enum ensuite, il sera tout autant, si les déclarations qu'il y avait avant. (et vous devez choisir la mise en œuvre qu'à utiliser en fonction de si vous voulez faire plus facile d'ajouter de nouvelles méthodes ou de nouveaux cas - dire de Moyenne dans l'avenir)
1 - le nom de La problème vient de le problème où vous avez une "expression" de type de données (nombres, des variables, addition/multiplication des sous-expressions, etc) et que vous souhaitez mettre en œuvre des choses comme les fonctions d'évaluation et d'autres choses.
2 Ou pattern matching sur des Types de Données Algébriques, si vous voulez être plus sécurisé...
3 - Par exemple, vous pouvez définir tous les multimethods sur le "haut niveau", où le "répartiteur" peut les voir. C'est une limitation par rapport au cas général, puisque vous pouvez l'utiliser si les états (et les lambdas) profondément imbriquée à l'intérieur d'un autre code.
4 - Essentiellement d'une "église" codage d'un type de données algébrique
OriginalL'auteur hugomg
Est-il vraiment d'une convention? Doit-on tuer minime si-constructions simplement parce qu'il y a de la frustration?
Ok, si les déclarations ont tendance à croître hors de contrôle, en particulier si de nombreux cas particuliers ont été ajoutés au fil du temps. Branche après branche est ajouté et à la fin, personne n'est capable de comprendre ce que tout fait sans passer des heures de temps et quelques tasses de café dans ce grwon exemple de code spaghetti.
Mais est-ce vraiment une bonne idée de tout mettre en séparer les fonctions? Le Code doit être réutilisable. le code doit être lisible. Mais l'appel de la fonction crée le besoin de regarder plus haut dans le fichier source. Si toutes les fi sont mis à l'écart de cette façon, vous venez de sauter dans le fichier source de tous les temps. Est-ce à l'appui de la lisibilité?
Ou d'envisager un if qui n'est pas réutilisé n'importe où. Faut-il vraiment aller dans une fonction séparée, juste pour le plaisir de la convention? il y a une surcharge en jeu ici, aussi. Les problèmes de performances peuvent être pertinents dans ce contexte, trop.
Ce que j'essaie de dire: à la suite des conventions de codage est bon. Le Style est important. Mais il y a des exceptions. Juste essayer d'écrire du bon code qui s'adapte à votre projet et de le garder pour l'avenir. En fin de compte, des conventions de codage sont que des lignes directrices qui tentent de nous aider à produire du bon code sans appliquer n'importe quoi sur nous.
OriginalL'auteur Lord Wolfchild
Je n'ai jamais entendu parler d'une telle convection. Je ne vois pas comment il fonctionne, de toute façon. Sûrement le seul point d'avoir un
iIsSmall
est pour plus tard branche (éventuellement en combinaison avec d'autres valeurs)?Ce que je ont entendu parler de est un argument pour éviter d'avoir des variables comme
iIsSmall
à tous les.iIsSmall
est juste de stocker le résultat d'un test que vous faites, de sorte que vous pouvez par la suite utiliser ce résultat pour rendre une décision. Alors pourquoi ne pas tester la valeur dei
au point où vous en avez besoin pour prendre la décision? c'est à dire, au lieu de:il suffit d'écrire:
De cette façon, vous pouvez dire au point de ramification de ce que vous êtes réellement ramification sur parce que c'est là. Ce n'est pas dur dans cet exemple, de toute façon, mais si le test a été compliqué, vous n'allez probablement pas être capable d'encoder le tout dans le nom de la variable.
C'est aussi plus sûr. Il n'y a pas de danger que le nom
iIsSmall
est trompeuse, car vous avez modifié le code afin d'essais autre chose, ou parce quei
a été modifiée après que vous avez appeléisSmall
de sorte qu'il n'est pas nécessairement petit plus, ou parce que quelqu'un a juste pris un muet nom de la variable, etc, etc.Évidemment, cela ne fonctionne pas toujours. Si le
isSmall
test est coûteux et vous avez besoin de branche sur son résultat de nombreuses fois, vous ne voulez pas exécuter de nombreuses fois. Vous aussi vous pourriez ne pas vouloir dupliquer le code de l'appeler plusieurs fois, sauf si c'est trivial. Ou vous pouvez retourner le drapeau à être utilisé par un visiteur qui ne connaît pasi
(même si ensuite, vous pouvez simplement retournerisSmall(i)
, plutôt que de le stocker dans une variable et ensuite de retour à la variable).Btw, la fonction séparée enregistre rien dans votre exemple. Vous pouvez inclure
(i < 10)
dans une affectation à unbool
variable aussi facilement que dans une instruction de retour dans unbool
fonction. ex: vous pouvez tout aussi bien écrirebool isSmall = i < 10;
- c'est ce qui évite l'instruction si, pas la fonction séparée. Code de la formeif (test) { x = true; } else { x = false; }
ouif (test) { return true; } else { return false; }
est toujours stupide; il suffit d'utiliserx = test
oureturn test
.OriginalL'auteur Ben
Cette pourrait être un bon endroit pour commencer. J'ai reçu que de cette question.
OriginalL'auteur Louie