2010-05-20 15 views
3

Personnellement, je pense que l'héritage est un excellent outil, qui, lorsqu'il est appliqué raisonnablement, peut grandement simplifier le code.L'héritage est-il devenu mauvais?

Cependant, il me semble que de nombreux outils modernes n'aiment pas l'héritage. Prenons un exemple simple: sérialiser une classe en XML. Dès que l'héritage est impliqué, cela peut facilement se transformer en désordre. Surtout si vous essayez de sérialiser une classe dérivée en utilisant le sérialiseur de classe de base.

Bien sûr, nous pouvons contourner cela. Quelque chose comme un attribut KnownType et d'autres choses. En plus d'être un démon dans votre code que vous devez vous rappeler de mettre à jour chaque fois que vous ajoutez une classe dérivée, cela échoue aussi si vous recevez une classe de l'extérieur de votre portée qui n'était pas connue au moment de la compilation. (Bon, dans certains cas, vous pouvez toujours contourner cela, par exemple en utilisant le sérialiseur NetDataContract dans .NET.) Un certain progrès.)

Dans tous les cas, le principe de base existe toujours: Sérialisation et héritage ne se mélangent pas bien. Considérant l'énorme liste de stratégies de programmation qui est devenue possible et même commune au cours de la dernière décennie, je suis tenté de dire que l'héritage devrait être évité dans les domaines liés à la sérialisation (en particulier les communications à distance et les bases de données).

Est-ce que cela a du sens? Ou suis-je en train de tout chambouler? Comment gérez-vous l'héritage et la sérialisation?

+1

mêmes problèmes avec les ORM – Andrey

+0

Serait-ce une autre raison de préférer la composition à l'héritage? –

+0

Je crois que la composition et l'héritage ont chacun leur propre application. Si l'héritage est le meilleur choix des deux, alors je veux vraiment l'utiliser. Je l'ai quand je suis obligé d'utiliser un design inférieur parce que la technologie ne supporte pas le mieux, le design correct. – mafu

Répondre

2

Il y a en effet quelques gotcha avec l'héritage et la sérialisation. La première est que cela conduit à une asymétrie entre sérialisation/désérialisation. Si une classe est sous-classée, cela fonctionnera de manière transparente pendant la sérialisation, mais échouera lors de la désérialisation, sauf si la désérialisation est mise au courant de la nouvelle classe. C'est pourquoi nous avons des balises telles que @SeeAlso pour annoter les données pour la sérialisation XML.

Ces problèmes ne sont cependant pas nouveaux en matière d'héritage. Il est fréquemment discuté sous la terminologie monde ouvert/fermé. Soit vous considérez que vous connaissez le monde entier et les classes, ou vous pourriez être dans un cas où de nouvelles classes sont ajoutées par des tiers. Dans une hypothèse de monde fermé, la sérialisation n'est pas vraiment un problème. C'est plus problématique dans une hypothèse de monde ouvert.

Mais l'héritage et l'hypothèse du monde ouvert ont de toute façon d'autres pièges. Par exemple. Si vous supprimez une méthode protected dans vos classes et que vous la modifiez en conséquence, comment pouvez-vous vous assurer qu'il n'y a pas de classe tierce qui l'utilise? Dans un monde ouvert, le public et interne API de vos classes doit être considéré comme congelé une fois mis à la disposition des autres. Et vous devez faire très attention à faire évoluer le système.

Il existe d'autres détails internes plus techniques sur le fonctionnement de la sérialisation qui peuvent surprendre. C'est pour Java, mais je suis sûr que .NET a des similitudes. Par exemple. Serialization Killer, par Gilad Bracha, ou Serialization and security manager exploit bug.

0

J'ai rencontré ce problème sur mon projet actuel et ce n'est peut-être pas la meilleure solution, mais j'ai créé une sorte de couche de service pour elle et ses propres classes. Je pense qu'il est sorti en tant que traducteur ObjectToSerialized et quelques interfaces. Typiquement c'était un un à un (l '"objet" et "sérialisé" avaient exactement les mêmes propriétés) alors ajouter quelque chose à l'interface vous permettrait de savoir "hé, ajoutez ceci ici aussi".

Je veux dire que j'avais une interface IToSerialized avec une méthode simple à des fins génériques et utilisé automapper pour la plupart des conversions. Bien sûr, c'est un peu plus de code, mais bon, ça marche et ça ne gomme pas d'autres choses.