2012-02-23 4 views
1

У меня есть следующие классы и интерфейсы. Я хочу существенно заморозить интерфейс IOld (который будет устаревать) и заставить пользователей использовать интерфейс INew, который будет содержать те же методы, что и IOld. Однако метод INew Meth3 представляет ту же функциональность, что и IOld Meth2, но с другим типом возврата, и чтобы отличить их лучше, я думал, что этот дизайн будет подходящим. Мой вопрос в том, считается ли это хорошей практикой кодирования?Абстрактный базовый класс, реализующий методы интерфейса производного класса

ПРИМЕЧАНИЕ: IOld и INew живут в отдельных агрегатах. NewClass не может ссылаться на IOld каким-либо образом, поскольку он будет отображаться как удаленный объект (MarshalByRef), с которым клиенты будут подключаться через интерфейс INew. Я не хочу, чтобы новые клиенты ссылались на сборку IOld.

public interface IOld 
{ 
    void Meth1(); 
    double Meth2(int input); 
} 

public interface INew 
{ 
    void Meth1(); 
    float Meth3(int input); 
} 

public abstract class BaseClass 
{ 
    public virtual void Meth1() 
    { 
    } 

    public virtual double Meth2(int input) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class OldClass 
: 
    BaseClass, 
    IOld 
{ 
    public override double Meth2(int input) 
    { 
     return 0; 
    } 
} 

public class NewClass 
: 
    BaseClass, 
    INew 
{ 
    public float Meth3(int input) 
    { 
     return 0; 
    } 
} 

ответ

2

Я хотел бы попробовать что-то вроде этого:

public class OldClass : BaseClass, IOld 
{ 
    public override double Meth2(int input) 
    { 
     return 0.0; 
    } 
} 

public class NewClass : OldClass, INew // now implements IOld and INew using the Method2() from OldClass 
{ 
    [Obsolete("This method is deprecated . Use Method3() instead.")] 
    public override double Meth2(int input) 
    { 
     return base.Meth2(input); 
    } 
    public float Meth3(int input) 
    { 
     return return 0.0f; 
    } 
} 

Это считается лучшей практикой для флага метод, как рекомендуется, чтобы сообщить разработчику, что они должны обновить свой код, чем разбить его, убивая старый способ.

+0

+1 - взял на себя смелость немного редактирования, а также - Соз !! :-) –

+0

Спасибо за ваш вопрос; да, я буду отмечать интерфейс как устаревший, но хотел бы указать основной дизайн; Точка, которую я должен был сделать, - это то, что NewClass не может ссылаться на IOld каким-либо образом, поскольку он будет отображаться как удаленный объект, а клиенты, собирающие его через интерфейс INew, не могут подключиться к сборке IOld. Я соответствующим образом обновил свой вопрос. – Jeb

3

Сядьте вниз и постройте свою пирамиду с прочной основой. То, как вы это задали, абстрактный базовый класс и интерфейс - это конкурирующие методы выполнения одной и той же концепции. Вы делаете это прежде всего для того, чтобы облегчить «Старый» или «Новый», но при этом вы получите довольно забавный график зависимостей.

С тем, что вы написали, ваш единственный способ - это методы с той же подписью. Если бы не эта проблема, вы могли бы легко расширить старый интерфейс и не столкнуться с проблемами. Если этот метод изменяется в новом, это рефакторинг (приемлемый) или совершенно другой результат? Другими словами, может ли старый клиент вызвать новое? Если это так, нет необходимости использовать этот метод и в другом интерфейсе.

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

+0

Спасибо за вашу мысль; Нет, старый клиент не может назвать новое. Точка, которую я должен был сделать, - это то, что NewClass не может ссылаться на IOld каким-либо образом, поскольку он будет отображаться как удаленный объект, а клиенты, собирающие его через интерфейс INew, не могут подключиться к сборке IOld. – Jeb

+0

Вы используете источник управления? У вас есть возможность отрасли? Я спрашиваю, потому что это похоже на то, что старые клиенты будут продолжать использовать старые, пока код не будет обновлен, а новый всегда будет новым. Если это так, вы введете код и сохраните старый в ветви обслуживания и новый в текущей ветке. Отделение обслуживания предназначено только для исправлений ошибок. последний шаг состоит в том, чтобы убедиться, что вы продумывали версии и просто даете одну клиентскую версию 1 из библиотеки DLL и другую версию 2. Единственная проблема заключается в том, что для одного клиента требуется оба в течение определенного периода времени. Если нет, то это лишь часть изменения программного обеспечения. –

+0

К сожалению, мы не можем просить клиентов перекомпилировать их код (это будет стоить как обычно!), Если только не последнее средство, поэтому нам нужно быть обратно совместимым для IOld.Однако мы не будем поддерживать IOld, и любые исправления ошибок будут сделаны для INew, где мы посоветуем им перекомпилировать. Старые клиенты будут продолжать использовать старые интерфейсы/новые клиенты новыми без видимости друг друга, кроме как на сервере, где он справляется с удаленными вызовами от удаленных клиентов через 2 apis. – Jeb

2

Я бы предпочел добавить новый метод с немного другим именем вместо создания нового интерфейса.

Так старый интерфейс будет, например:

public interface IOld 
{ 
    void Meth1(); 
    [Obsolete("Use Meth22 instead.")] 
    double Meth2(int input); 
    float Meth22(int input); 
} 
+0

Спасибо - я добавил примечание в конце моего вопроса, что я не продолжаю с интерфейсом IOld. – Jeb

Смежные вопросы