2010-05-20 4 views
3

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

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

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

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

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

+1

те же проблемы с ORM – Andrey

+0

Можно ли назвать это еще одной причиной, чтобы предпочесть композицию над наследованием? –

+0

Я считаю, что у композиции и наследования есть свое приложение. Если наследование является лучшим выбором из двух, то я действительно хочу его использовать. Я __hate__ это, когда я вынужден использовать более низкий дизайн, потому что технология не поддерживает лучший дизайн _correct_. – mafu

ответ

2

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

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

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

Есть еще несколько технических подробностей о том, как работает сериализация, что может быть неожиданным. Это для Java, но я уверен, что .NET имеет сходство. Например. Serialization Killer, by Gilad Bracha, или Serialization and security manager ошибка.

0

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

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