Les propriétés en C # devraient-elles avoir des effets secondaires en plus de notifier un changement dans ses états?
J'ai vu des propriétés utilisées de différentes manières. Des propriétés qui chargeront la valeur lors de leur premier accès aux propriétés qui ont des effets secondaires massifs comme provoquer une redirection vers une page différente.
Réponses:
Je suppose que vous parlez de propriétés en lecture seule , ou du moins de getters de propriétés , car un configurateur de propriétés va, dans presque tous les cas, avoir des effets secondaires. Sinon, ce n'est pas très utile.
En général, un bon design suit le principe de la moindre surprise . Ne faites pas des choses que les appelants ne s'attendent pas à ce que vous fassiez, surtout si ces choses peuvent changer les résultats futurs .
En général , cela signifie que les acquéreurs de propriétés ne devraient pas avoir d'effets secondaires.
Cependant , faisons attention à ce que nous entendons par «effet secondaire».
Un effet secondaire est, techniquement, toute modification d'état. Ce pourrait être un État accessible au public, ou ... ce pourrait être un État totalement privé.
Les chargeurs différés / différés sont un exemple d'état presque exclusivement privé. Tant que ce n'est pas la responsabilité de l'appelant à libérer cette ressource, alors vous êtes en train réduirez la surprise et la complexité en général en utilisant l' initialisation différée. Un appelant ne s'attend pas normalement à devoir signaler explicitement l'initialisation d'une structure interne . Ainsi, l'initialisation paresseuse ne viole pas le principe ci-dessus.
Un autre exemple est une propriété synchronisée. Pour qu'une méthode soit thread-safe, elle devra souvent être protégée par une section critique ou un mutex. L'entrée dans une section critique ou l'acquisition d'un mutex est un effet secondaire; vous modifiez l'état, généralement l' état global . Cependant, cet effet secondaire est nécessaire afin d'éviter une sorte de surprise bien pire - la surprise de la modification des données (ou pire, partiellement modifiée) par un autre thread.
Je voudrais donc assouplir un peu la restriction comme suit: Les lectures de propriétés ne devraient pas avoir d' effets secondaires visibles ou d'effets secondaires qui changent leur sémantique .
S'il n'y a aucun moyen possible pour un appelant d'être affecté ou même conscient d'un effet secondaire, cet effet secondaire ne fait aucun mal. S'il vous est impossible d'écrire un test pour vérifier l'existence d'un effet secondaire particulier, alors il est suffisamment localisé pour être étiqueté comme un détail d'implémentation privé, et donc sans préoccupation légitime pour le monde extérieur.
Mais soyez prudent; en règle générale, vous devriez essayer d'éviter les effets secondaires, parce que souvent ce que vous pensez peut - être un détail de mise en œuvre privée peut fuir de façon inattendue et devenir public.
la source
Je répondrai à votre question par une question: que se passe-t-il lorsque vous modifiez la propriété Width d'un formulaire?
Juste au sommet de ma tête, cela:
(Avertissement: je suis un développeur Delphi, pas un développeur .NET. Ce n'est peut-être pas précis à 100% pour C #, mais je parie que c'est assez proche, surtout compte tenu de la quantité de framework .NET d'origine basée sur Delphi.)
Tous ces «effets secondaires» se produisent lorsque vous modifiez la propriété Width sur un formulaire. Certains d'entre eux semblent-ils inappropriés ou incorrects?
la source
Jetez un œil aux règles de conception de Microsoft , en particulier l'une d'entre elles:
CA1024: utilisez les propriétés le cas échéant
la source
Je pense que les propriétés ne devraient pas avoir d'effets secondaires. Il existe cependant une exception à cette règle: le chargement paresseux. Si vous voulez charger quelque chose paresseusement dans une propriété, c'est très bien, car le client ne peut pas dire que le chargement paresseux se déroule et ne s'en soucie généralement pas.
EDIT : Oh, encore une chose - le déclenchement d'un événement disant "PropertyXYZ a changé!" (par exemple
INotifyPropertyChanged
) - convient aux setters.la source
Outre le chargement paresseux mentionné précédemment, il existe également le cas des fonctions de journalisation. Ce serait rare mais pas hors de question.
la source
Il n'y a presque pas d'absolu dans la programmation, afin de répondre à votre question, nous devons examiner certaines propriétés souhaitables des objets et voir si cela s'applique à notre cas.
Si nous répondons oui à certaines de ces questions, c'est probablement une bonne idée de réfléchir très attentivement aux propriétés et à leurs effets secondaires. Je suppose que lorsque vous dites des effets secondaires, vous voulez dire des effets secondaires secondaires puisque la mise à jour de la valeur est un effet secondaire en soi.
Plus il y a d'effets secondaires en général, plus une classe sera difficile à tester. Plus les effets secondaires sont secondaires, plus la concurrence sera difficile à gérer, mais c'est un problème difficile qui nécessite probablement une réflexion majeure de toute façon.
Le gros problème est probablement pour les personnes qui traitent votre classe comme une "boîte noire", il ne serait pas facilement disponible qu'un état ait changé juste parce qu'ils ont lu une propriété ou que d'autres propriétés changent parce qu'une autre change (ce qui pourrait conduire aux mises à jour en cascade).
Donc en général non, nous voulons que les propriétés soient aussi faciles à raisonner et aussi simples que possible, c'est un peu impliqué dans la décision de conception, sinon ce serait une méthode. Un bon programmeur peut toujours enfreindre les règles cependant, assurez-vous simplement d'avoir une très bonne raison :)
la source