Стало ли наследство плохим? - PullRequest
3 голосов
/ 20 мая 2010

Лично я считаю наследование отличным инструментом, который при разумном применении может значительно упростить код.

Однако мне кажется, что многие современные инструменты не любят наследование. Давайте рассмотрим простой пример: сериализация класса в XML. Как только наследование вовлечено, это может легко превратиться в беспорядок. Особенно, если вы пытаетесь сериализовать производный класс, используя сериализатор базового класса.

Конечно, мы можем обойти это. Что-то вроде KnownType атрибута и прочего. Помимо того, что вы испытываете зуд в своем коде, который вы должны помнить, чтобы обновлять каждый раз, когда вы добавляете производный класс, это также может дать сбой, если вы получите класс из-за пределов вашей области действия, которые не были известны во время компиляции. (Хорошо, в некоторых случаях вы все еще можете обойти это, например, используя сериализатор NetDataContract в .NET. Конечно, определенное улучшение.)

В любом случае, основной принцип все еще существует: сериализация и наследование плохо сочетаются. Рассматривая огромный список стратегий программирования, которые стали возможными и даже распространенными в последнее десятилетие, я испытываю соблазн сказать, что следует избегать наследования в областях, связанных с сериализацией (в частности, удаленное взаимодействие и базы данных).

Это имеет смысл? Или все портит? Как вы справляетесь с наследованием и сериализацией?

Ответы [ 2 ]

2 голосов
/ 20 мая 2010

Есть действительно несколько ошибок с наследованием и сериализацией. Во-первых, это приводит к асимметрии между сериализацией / десериализацией. Если класс находится в подклассе, он будет работать прозрачно во время сериализации, но потерпит неудачу во время десериализации, если десериализация не проинформирована о новом классе. Вот почему у нас есть такие теги, как @SeeAlso для аннотирования данных для сериализации XML.

Однако эти проблемы не новы в отношении наследования. Это часто обсуждается под терминологией открытый / закрытый мир . Либо вы считаете, что знаете весь мир и классы, либо вы можете быть в случае, когда новые классы добавляются третьими сторонами. В предположении закрытого мира сериализация не является большой проблемой. Это более проблематично в предположении открытого мира.

Но наследование и предположение об открытом мире в любом случае имеют и другие недостатки. Например. если вы удалите метод protected в ваших классах и соответственно выполните рефакторинг, как вы можете убедиться, что не существует стороннего класса, который его использовал? В открытом мире общедоступный и внутренний API ваших классов должны рассматриваться как замороженные после того, как они стали доступны другим. И вы должны быть очень внимательны, чтобы развивать систему.

Существуют и другие технические подробности того, как работает сериализация, и это может удивить. Это для Java, но я уверен, что .NET имеет сходство. Например. Убийца сериализации , от Гилада Брача, или Менеджер сериализации и безопасности Исправление ошибки.

0 голосов
/ 20 мая 2010

Я столкнулся с этим в моем текущем проекте, и это может быть не лучшим способом, но я создал своего рода служебный слой для него и его собственных классов. Я думаю, что он был назван ObjectToSerialized переводчиком и парой интерфейсов. Как правило, это был один к одному («объект» и «сериализованный» имели одинаковые свойства), поэтому добавление чего-либо в интерфейс позволило бы узнать «эй, добавьте это и здесь».

Я хочу сказать, что у меня был интерфейс IToSerialized с простым методом на нем для общих целей и для большинства преобразований использовался автоматический преобразователь. Конечно, это немного больше кода, но, как бы то ни было, это сработало и не мешает другим вещам.

...