Я должен создать перегрузки для функций в существующем интерфейсе, не влияя ни на какие компоненты, которые в настоящее время реализуют или используют интерфейс (идеально).
Я полагаю, что у меня есть несколько опций:
Интерфейс Simplified Original:
public interface IServerComponent
{
bool Add(int a, int b);
}
Я могу добавить новые перегруженные функции к интерфейсу и вызвать каждый класс, который реализует интерфейс для реализации новых функций.
public interface IServerComponent
{
bool Add(int a, int b);
bool Add(int a, int b, int c);
}
Или я могу создать новый интерфейс, который реализует исходный интерфейс. Затем другие классы, которые используют оригинал, не должны будут изменяться, и любые новые классы могут реализовать новый интерфейс...
public interface IServerComponent2 : IServerComponent
{
bool Add(int a, int b, int c);
}
То, какова лучшая практика, является этой ситуацией? Действительно ли там какие-либо другие опции доступны?
Спасибо
Если новые методы могут быть выражены в терминах старых методов, вы можете использовать методы расширения:
// Original interface
public interface IServerComponent
{
bool Add(int a, int b, int c);
}
// New overload
public static class MyServerMethods
{
public static bool Add(this IServerComponent component, int a, int b)
{
return component.Add(a, b, 0);
}
}
Если методы не могут быть выражены таким образом (т.е. они действительно нуждаются в будут реализованы самими компонентами), то я бы рекомендовал определить новый интерфейс. Такой подход имеет максимальную обратную совместимость.
Я понимаю, что ваш пример надуманный, но я хочу дать вам надуманный ответ, который отличается от того, что вы выражаете, чтобы вы могли подумать об этом по-другому. Вместо того чтобы ваш метод интерфейса работал над чем-то конкретным, возможно, имеет смысл, чтобы он работал над чем-то абстрактным.
Например
public interface IAddableThings
{
int a;
int b;
}
public interface IOtherAddableThings : IAddableThings
{
int a;
int b;
}
public interface IServerComponent
{
bool Add(IAddableThings things);
}
Если это действительно Add, то я думаю, что это имеет гораздо больше смысла, но если это действительно больше похоже на Calculate(), то вы захотите перенести некоторые или все операции этого метода в объекты IAddableThings.
public interface IAddableThings
{
int a;
int b;
bool CalculateMe();
}
Это зависит от контекста - если существует много классов, реализующих исходный интерфейс, или если он опубликован, то единственный практический способ - представить новый. С другой стороны, наличие только одного интерфейса намного чище в долгосрочной перспективе, поэтому я бы сказал, что рефакторинг существующего, если вы можете себе это позволить.
Я думаю, что поддерживать один интерфейс проще, но второй подход с двумя интерфейсами лучше, потому что не каждый класс должен реализовывать bool Add(int a, int b, int c);
Если вам не нужно или вы не хотите изменять классы (сейчас или в будущем), которые уже реализуют старый интерфейс, вам следует просто создать второй интерфейс. Однако это больше похоже на взлом и может дать вам менее интуитивный код.
К тому же, по моему опыту, откладывать рефакторинг - плохая идея. Так что, если вы подозреваете, что вам понадобится реализовать интерфейс позже, вы можете просто изменить существующий и избавить себя от головной боли. Это определенно более чистый способ сделать это.
Если ваш интерфейс IServerComponent еще не отправлен или является внутренним интерфейсом, который реализуется только вашими собственными классами, а новые члены интерфейса имеют смысл для всех существующих классов, реализующих интерфейс, измените существующий интерфейс.
В противном случае создайте интерфейс IServerComponent2, расширяющий IServerComponent. IIRC, это то, что рекомендуют Руководящие принципы разработки инфраструктуры. Пример этого можно найти в .NET Framework в виде класса X509Certificate2 .
Однако, если новые элементы могут быть реализованы в терминах исходных элементов, вы также можете использовать методы расширения :
public interface IServerComponent
{
bool Add(int a, int b);
}
public static class ServerComponentExtensions
{
public static bool Add(this IServerComponent isc, int a, int b, int c)
{
return isc.Add(a, b) && isc.Add(b, c) && isc.Add(c, a);
}
}