Bonjour,
J'ai un constructeur qui prend un argument.
Si la valeur de cet argument n'est pas valide, que puis-je faire ?
Jeter une exception ? Pas d'autres solution ?
Bonjour,
J'ai un constructeur qui prend un argument.
Si la valeur de cet argument n'est pas valide, que puis-je faire ?
Jeter une exception ? Pas d'autres solution ?
Bonjour,
Jeter une exception dans un constructeur est une très mauvaise pratique. En C#, ça va parce que tout est géré par le framework mais dans certains langages comme c++ ça peut être très problématique car tu peux te retrouver avec des objets incomplets.
Le meilleur à faire dans ton cas serait de créer une Factory qui vérifie ton argument et renvoie ton objet. Je te laisse googler ce design pattern afin d'en savoir plus mais il n'y a rien d'extrèmement compliqué![]()
Mon blog sur les technos .NET et Agile -> http://blog.developpez.com/maximepalmisano/
Je voudrais faire entendre un son de cloche différent. Lancer des exceptions depuis un constructeur ne pose aucun problème et, d'ailleurs, plusieurs types du framework font cela. Il ne faut donc surtout pas hésiter à mes yeux, surtout s'il ne s'agit que de quelques vérifications.
Cela dit, attention tout de même ! Si une exception est lancée dans le constructeur, il est vrai que l'objet ne sera pas accessible par le code qui instanciait, ce qui est bien (même en cas de bloc using sur un type implémentant IDisposable : on n'entrera jamais dans le bloc et Dispose ne sera jamais appelé). En revanche, l'instance a bien été créée et reste accessible par le seul GC qui appellera le destructeur. C'est la grosse différence avec le C++. Gaffe, donc, a bien écrire la destructeur avec cette perspective en tête.
Enfin, utiliser une méthode factory statique (MyType.Create()) me semble toutefois acceptable dans le cas d'un processus de création particulièrement coûteux (temps CPU, ressources systèmes, etc). Non pas que cela poserait problème si c'était fait dans un constructeur mais on attend intuitivement d'un constructeur qu'il soit léger. Garder le constructeur privé et fournir une telle méthode statique est donc une simple indication à l'usage des consommateurs de la classe. Mais c'est lourd et en abuser est à mes yeux un anti-pattern. Je garde plutôt ces méthodes pour les cas où je préfère renvoyer null plutôt que de lever une exception où, bien sûr, pour tous les cas où le pattern factory est approprié.
PS : MSDN est toujours une bonne source : Constructor design guidelines
salut
vu que ton constructeur prends un argument, rien n'empeche ton objet après construction de positionner un "état - Je suis pas bien construit"...
Après, en théorie, si la construction de ton objet est impossible parce que un argument contient une mauvaise valeur, alors il vaut peut-etre mieux une factory...
Ou alors, construire ton objet et avoir une méthode dans laquelle tu passes ton argument et qui te retournera un boolean pour dire si les choses à construire à partir de cet argument se sont construites![]()
ne pas répondre sur un langage avec des arguments d'un autre langage ...
et pour compléter DonQuiche que je puissoie, en général le throw est fait au début du constructeur, (if arg is null {throw argumentnullexception} par exemple) donc ça ne pose pas de soucis niveau mémoire
salut
moi, comme je suis un peu neuneu, ce que je fais est un peu ce que fait Microsoft...
Prenons l'exemple de la classe SerialPort qui permet de faire de la communication série. Si on regarde cette classe, dans le constructeur, on peut passer des arguments... Par contre, ce sont les méthodes de "communication" qui elles vont retourner une exception ou un boolean pour dire "Pas de Port Série".
Et pour moi, c'est plutot logique...
Pour moi, une classe devrait toujours pouvoir être construite. Par contre, si défaut d'argument, de ressources disponibles il y a , alors, les méthodes "obligatoires" de cette classe te le diront dès le premier appel.
J'ai JAMAIS au cours de ma courte carrière de développeur (27 ans de dév) eu une situation ou je me suis dit "Tiens, je vais lancer une exception dans mon constructeur"...
Peut-etre parce que je privilégie les choses simples aux choses compliquées, alambiquées, divines au niveau design mais impossible à réaliser dans le temps imparti.. Peut-etre parce que je pense qu'un logiciel doit avant tout apporter la réponse au besoin avant d'être "magnifique" d'un point de vue architecture...
En tout cas, même si la question est pertinente et interessante, j'avoue ne jamais avoir eu à traiter ce type de cas...
Peut-etre que je crois trop que l'informatique, c'est TOUJOURS simple...
Ma devise : "En informatique, rien n'est compliqué. Par contre, parfois, résoudre un problème peut-etre complexe"...![]()
je ne suis pas trop d'accord
en général dans une application on log les erreurs pour pouvoir débugger rapidement
si une classe demande un paramètre dans son constructeur et qu'elle en a réellement besoin, ca me parait plus logique de thrower tout de suite, au moins dans le stacktrace on saurait à quel moment le paramètre était null
car les objets peuvent venir de loin ... et si tu throw lors d'un appel à une méthode, tu ne sauras pas forcément à quel moment tu as instancié ta classe et donc le debug en sera moins aisé
CA ça me parait logique !
après si le paramètre n'est pas nécessaire au moment de la construction et peut etre fourni plus tard pas de soucis
Je suis aussi de cet avis,Envoyé par Pol63
Si un constructeur ou une méthode ne peut résoudre un problème,
Il est de son devoir d'en avertir au plus vite l'objet appelant ...
L'objet sera forcement créé mais seul le Garbage aura un pointeur dessus
(Ce qu'on appelle un «constructeur» est en fait un «initialisateur» ... La construction a déjà été faite avant ...
Dans certains langages, il est possible de faire son propre constructeur (ex: python))
Si le fait d'avoir un objet inutilisable qui traine au niveau du Garbage te gène,
(parce qu'il est trop lourd, et/ou parce qu'il y en aura peut être beaucoup)
Alors une Factory te sortirait de là ^^.
L'informatique généralement c'est simple, à échelle micro, par contre, à échelle macro, ça ne l'est pas toujours.
Et quand tu développes une solution IT qui répond à un besoin métier complexe, ta solution IT peut devenir complexe par extension (ou propagation...).
Du coup, oui, quand tu fais une solution IT pour un besoin IT, ça me parait totalement justifié d'avoir recours à ce genre de pratique :
Car dans ce cas, quelqu'un avec la compréhension métier de ton application qui doit un jour comprendre les mécanismes utilisés comprendra la raison.
Par contre, dans le case d'une solution IT pour un besoin business, ça me parait totalement justifié d'avoir recours à ce genre de pratique là :
Qui se traduirait par exemple par un :Envoyé par Pol63
Car dans ce cas, tu sais que telle création n'a pas fonctionné, c'est aussi simple que ça. Tu décomposes ainsi de façon plus "macro".
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 try { CreateCommand(product, customer); } catch(CommandCreationException cce) { /* do something */ }
Du coup, j'aurais tendance à dire que vous avez tous raison, mais que c'est le contexte d'application qui fait la différence.
Partager