63 votes

Pourquoi est-il "plus facile de demander le pardon que la permission" en python, mais pas en Java ?

Il semble que cela soit accepté comme un code parfaitement bon dans la communauté Python :

def is_integer(input):
    try:
        return x % 1 == 0
    except TypeError:
        return False

En revanche, le code Java (presque) équivalent serait mal vu par la communauté Java :

boolean is_integer(Object input){
    try{
        Integer temp = (Integer)input;
        return true;
    }catch(ClassCastException e){
        return false;
    }
}

Pourquoi ?

Mise à jour :
Désolé pour le mauvais exemple ci-dessus. Je comprends qu'il existe de meilleures façons de gérer la situation spécifique décrite ci-dessus. Ma question est plus générale : Pourquoi la mentalité générale dans la communauté Python est-elle "Demander le pardon plutôt que la permission", mais pas en Java ? Est-ce à cause de la différence de langage ? De la différence de base d'utilisateurs ? Ou est-ce historique ? Quels sont les avantages et les inconvénients de ces deux mentalités différentes, etc.

Mise à jour2
La "mentalité Java" :
La capture d'une exception de type "Null Pointer" est-elle une odeur de code ?
Lien vers les parties pertinentes du célèbre livre "Java efficace 2e édition"
extrait du livre ci-dessus :

T simple : les exceptions sont, comme leur nom l'indique les exceptions sont, comme leur nom l'indique, à utiliser uniquement dans des conditions exceptionnelles ; elles ne doivent jamais être utilisées pour un flux de ordinaire.

La "mentalité python" :
Python - Vérifier qu'une variable est entière ou non
http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Exceptions

extrait de l'article de wikipedia ci-dessus :

Le style Python prévoit l'utilisation de chaque fois qu'une condition d'erreur d'erreur. Plutôt que de tester l'accès à un l'accès à un fichier ou à une ressource avant avant de l'utiliser, il est conventionnel en Python d'aller de l'avant et d'essayer de d'essayer de l'utiliser, et d'attraper l'exception si l'accès est refusé. l'accès est refusé. Les exceptions peuvent également être utilisées comme un moyen plus de transfert de contrôle non local [...] Les exceptions sont souvent [...] utilisées comme une alternative au bloc if. A Une devise souvent invoquée est EAFP, ou "Il est plus facile de demander pardon". [...] permission".

Autre exemple :

try:
    User.objects.get(username=username)
except User.DoesNotExist:
    return username
raise forms.ValidationError('Username is already taken.')

Mise à jour3
Voici peut-être un meilleur exemple. En Python, vous essayez simplement d'ouvrir un fichier et, s'il n'existe pas, vous attrapez l'exception et la transmettez à l'utilisateur. Dans la communauté Java, de nombreuses personnes considèrent qu'il est préférable de vérifier d'abord l'existence du fichier.

43voto

Stephen C Points 255558

La principale raison pour laquelle cette pratique est désapprouvée en Java est que l'instanciation d'objets d'exception est coûteuse. En effet, le comportement par défaut d'un constructeur d'exception consiste à capturer un grand nombre d'informations sur la pile d'appels afin de pouvoir les afficher ultérieurement dans la trace de la pile. Ce processus peut prendre des centaines ou des milliers d'instructions machine, et si aucune trace de pile n'est jamais produite (comme dans cet exemple), il s'agit simplement de cycles CPU gaspillés.

En revanche, un test de type explicite utilisant instanceof ou en comparant l'objet de la classe est susceptible de prendre moins d'une demi-douzaine d'instructions machine.


Le scénario "Catching NPE is code smell" est un peu différent. Le problème est que les NPE sont souvent lancés dans des endroits inattendus pour des raisons inattendues, et sont généralement des symptômes de bogues dans le code. Si vous commencez à lancer délibérément des NPE dans le cadre d'un flux de contrôle "normal", il y a un risque important que votre code attrape les mauvais NPE et, par conséquent, masque les bogues. (Il s'agit du même raisonnement que celui qui explique pourquoi c'est généralement une mauvaise idée d'attraper des exceptions).

Le deuxième aspect de l'affirmation selon laquelle "rattraper une NPE est une odeur de code" est que les gens y ont généralement recours parce qu'ils sont obtenir les NPE inattendus et les catch est une tentative de "réparer" l'erreur sans vraiment en comprendre la cause. C'est presque toujours une mauvaise idée.


Le scénario du fichier ouvert est à nouveau différent. En fait, les personnes qui préconisent de "vérifier d'abord" lors de l'ouverture d'un fichier en Java passent à côté de deux faits importants :

  1. Chaque vérification implique un appel de système et la somme des appels de système supplémentaires est probablement aussi coûteuse que les exceptions qu'ils essaient d'éviter ... surtout si l'ouverture est censée réussir parce que le fichier est généralement ouvrable.

  2. Si vous vérifiez puis ouvrez, votre code peut encore lancer IOException de toute façon en raison de :

    • des conditions de course ; par exemple, quelqu'un modifie les autorisations de fichier entre les vérifications de votre application et sa open tentative, ou
    • des événements tels que "système de fichiers plein" ou "erreur de périphérique" qui ne peuvent pas être (raisonnablement) testés.

En bref, ils ont tort.

8voto

IfLoop Points 59461

La différence fondamentale est qu'en Java, le type réel d'une valeur, qui ne peut être modifié une fois que l'objet est créé, détermine fortement la manière dont il est possible d'utiliser cet objet. Dans certains cas, il est possible de faire preuve d'ingéniosité et de tromper le système d'exécution Java en lui faisant faire des choses que le type n'est pas censé comprendre, mais cela nécessite souvent une extrême ingéniosité et est rarement possible en réalité. Ce n'est pas parce qu'un objet a un write ne signifie pas que le système de typage suppose que les méthodes sont réellement destinées à la même chose.

Python ne fait rien de tout cela. D'une part, une méthode nommée write (ou dans l'exemple que vous venez de donner, ce serait __iadd__ pour l'ajout sur place), est supposée être l'interface du type en question.

Cela nous amène à ce qui pourrait être une différence plus profonde dans Python, à savoir l'hypothèse selon laquelle "nous sommes tous des adultes consentants", et que c'est correct, et en fait un "problème de santé". bon Il est tout à fait possible d'utiliser le code de quelqu'un d'autre d'une manière qu'il n'avait pas prévue lorsqu'il l'a écrit, à condition qu'il ait la bonne interface.

Java fait tout son possible pour empêcher ce genre de choses de se produire, à presque tous les niveaux de la VM.

2voto

Andreas_D Points 64111

Le ferait-il ? Si la documentation indique clairement qu'il s'agit attendue pour obtenir une instance non entière et que la méthode renverrait faux dans ce cas, l'idée est bonne.

Bien qu'il soit beaucoup moins cher (du point de vue des performances) pour utiliser le instanceof au lieu de forcer la VM à lever une exception pour cette simple vérification.

2voto

Michael Anderson Points 21181

Vous combinez plusieurs questions en une seule, ce qui brouille inutilement les pistes.

  1. Les communautés sont-elles favorables à une fonction de type "is_xxx" ? Dans les deux cas, la nécessité d'une telle fonction est comprise, mais dans les deux cas, l'utilisation d'une telle fonction est désapprouvée. L'implémentation de cette méthode n'est probablement pas non plus ce que les développeurs de Java ou de Python trouveraient intéressant.

  2. Devrions-nous utiliser des exceptions pour le flux de contrôle ? Python, en tant que langage de script et de par ses conventions, a plus de tolérance pour ce type de comportement. En Java, les exceptions sont réservées aux situations exceptionnelles.

  3. Il y a également une différence dans la signification réelle des codes : Ce que vous utilisez en quelque sorte en python est canard dactylographique et de commettre une erreur sur tout objet qui ne supporte pas l'option += 1 . Ce que vous faites en Java, c'est un moulage de type et une erreur sur tout objet qui n'est pas moulable en un nombre entier (vraisemblablement, seul un objet de type nombre entier supportera cela ? Mon Java est rouillé )

1voto

Le typage dynamique de Python vous permet d'utiliser des caractères non int (et, bien sûr, non nombre ), tant que l'opération est valide.

Mais non, cela ne serait jamais considéré comme du bon code dans la communauté Python, exactement pour cette raison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X