Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Faut-il bouder les warnings ?

Les warnings semblent moins intéresser que les erreurs, on le comprend, les unes sont bloquantes, les autres non. Mais certains warnings du compilateurs matérialisent des erreurs potentielles aux conséquences qu’il serait dangereux d’ignorer…

Les warnings

Posons le tout de suite, les warnings sont des erreurs comme les autres. ils peuvent même être pires encore car une erreur empêche de compiler donc de délivrer le produit. Un warning n’interdit rien et c’est plus tard qu’une erreur potentiellement grave se matérialisera, une fois le logiciel livré et en production…

Tous les warnings ne véhiculent pas le même niveau de danger potentiel c’est vrai. Mais ils devraient être traités avec attention, non par rigidité psychologique mais tout simplement car ce sont des erreurs mais d’une nature un peu différente.

La programmation asynchrone est source de grandes joies mais aussi de surprises étonnantes. Sa maîtrise n’est pas aisée, raison de plus pour ne pas laisser traîner des warnings la concernant ! Prenons deux exemples de warnings concernant la programmation asynchrone pour illustrer le propos.

Code CS1998

A part suggérer qu’il y a 1997 autres erreurs possibles – ce qui donne le vertige (mais la prochaine fera encore plus peur !) – ce warning ne vous dit-il rien ?

Le code CS1998 affiche le message suivant (en version US) :

warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

La cause est assez simple : vous avez spécifié le modificateur “async” dans l’entête de la méthode mais vous ne faites aucun usage de “await” dans cette dernière.

C’est un avertissement à prendre au sérieux. Soit vous avez placé cet “async” pour rien, et il faut le retirer… soit vous aviez prévu d’utiliser “await” et vous avez oublié de le faire ce qui risque de fausser “légèrement” le fonctionnement de la méthode. Situation à corriger immédiatement donc.

Code CS4014

Le vertige devient digne de celui d’un Baumgartner avant de sauter de son ballon sonde à 39000 m d’altitude… imaginez 4012(*) autres warnings à découvrir ! :-)

(*) les plus futés auront noté l’erreur… j’aurai du dire 4013 n’est-ce pas ? Ceux qui suivent vraiment auront compris qu’il n’y a pas d’erreur, puisque je vous ai déjà fait découvrir la 1998, il en reste bien 4012 à connaître !

Le message de celui-ci est tout aussi important à reconnaître :

warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

La cause : Vous appelez une méthode qui possède le modificateur “async” et qui retourne une Task<> et votre code ne fait rien pour attendre le résultat de cette dernière.

Peut-être est-ce volontaire. Le cas peut se produire (si le code qui suit l’appel ne se sert pas du résultat par exemple).

Si ce n’est pas intentionnel il est urgent de vérifier de le code appelant et le code appelé !

Si la situation est voulue, on peut supprimer le warning avec un #pragma. Cela est tout à fait acceptable car l’intention du développeur devient visible : il assume la situation. C’est mille fois préférable à un warning laissé en l’état. Exemple d’utilisation de pragma issu la doc Microsoft pour un autre warning :

image

On note que la suppression du warning doit s’accompagner d’une “remise en route” par un “restore” en spécifiant à nouveau le code du warning concerné. Cette double écriture est fastidieuse et surtout l’obligation de répéter le code du warning peut s’accompagner d’une faute de frappe masquant le warning pour tout le reste du code sans le savoir.

Une autre astuce consiste à tout simplement déclarer un variable qui ne sert à rien et lui affecter le résultat de l’appel, de type “var dummy = appelDeCodeAsync;”

Ne vous inquiétez pas pour cette variable supplémentaire, le compilateur est assez malin pour la supprimer totalement du code compilé. Son avantage est d’éviter un #pragma (et éviter de se tromper en répétant le code du warning). Comme cette solution ne coûte rien dans le code compilé elle est intéressante. Bien entendu elle sous-entend une parfaite compréhension du warning en question et ne doit pas servir à masquer une situation non maîtrisée ! Les puristes détesteront cette solution d’ailleurs…

Je préfère moi aussi le #pragma qui marque l’intention plus clairement d’une façon standardisée par le langage. Mais le risque de supprimer le warning dans tout le code (en cas d’erreur sur le second code) et de masquer des erreurs potentielles me chagrine tout autant.

A vous de voir…

Treat Warnings as Errors

La solution pour éviter la paresse naturelle qui consiste à considérer les Warnings comme des citoyens de seconde zone c’est justement de les élever au niveau des erreurs !

Les warnings de compilation peuvent être traités comme des erreurs bloquantes, il suffit de le paramétrer dans la page build du projet :

image


Conclusion

La programmation asynchrone est pleine de surprise. Mais il n’y a pas qu’elle qui peut donner lieu à des warnings, ce n’était qu’un exemple parmi des centaines d’autres ! Certains développeurs laissent parfois des tartines de warnings dans leurs projets. Pourtant il faut les traiter avec la même vigilance que des erreurs de compilation car derrière chaque warning peut se cacher de potentiels bugs très sournois.

Le cas des warnings 1998 et 4014 est intéressant à ce titre.

Les warnings sont des erreurs comme les autres, mais de nature plus vicieuse, c’est un peu la leçon à retenir…


Stay Tuned !

blog comments powered by Disqus