Принцип разделения интерфейса и удобство / вспомогательные методы
Как принцип сегрегации интерфейса применяется к вспомогательным / вспомогательным методам? Например:
Я хочу создать интерфейс, который представляет деловых партнеров. Минимум, который мне понадобится, - это метод установки и метод получения, который установит или получит полный список партнеров:
Interface Partners {
method getList();
method setList();
}
Я также хочу, чтобы у меня был метод contains(), чтобы сообщить мне, был ли определенный человек включен в список партнеров. Я считаю это вспомогательным или вспомогательным методом, потому что все, что он делает, это вызывает getPartners(), а затем проверяет, находится ли данный человек в этом списке.
Мое понимание принципа разделения интерфейса заключается в том, что я должен разделить свой метод contains() на отдельный интерфейс, поскольку кто-то может захотеть реализовать мой интерфейс Partners, не предоставляя реализацию для этого ненужного вспомогательного метода. В моем примере это не имеет большого значения, но список вспомогательных методов может быстро увеличиваться в размере (addPartner, addPartnerByID, addPartnerByUserid и т. Д.), Так что это практическая проблема.
Меня беспокоит то, что мне довольно трудно выбрать имя для интерфейса, в котором будет содержаться мой метод contains(), который не звучит громоздко, и я думаю, что каждый раз, когда у вас возникает такая большая проблема с присвоением имени, это красный флаг, который в вашем дизайне что-то не так. Кажется неправильным иметь интерфейс с именем PartnersSupportingSetInclusionChecks, и не очень хорошо иметь интерфейс с именем PartnerHelperMethods.
Как применить принцип разделения интерфейса к таким методам?
2 ответа
так как кто-то может захотеть реализовать интерфейс моих партнеров, не предоставляя реализацию для этого ненужного вспомогательного метода
акцент мой
Пожалуйста, обязательно есть contains()
метод, если вы считаете, что важно иметь в своем API. Особенно, если весь ваш клиентский код в настоящее время использует один.
Принцип сегрегации интерфейса заключается в том, чтобы не связывать полностью несвязанные методы с интерфейсом. Похоже, вы пытаетесь реализовать Repository
который должен иметь методы get, содержит и т. д., чтобы увидеть, какие элементы находятся в репозитории, и способ их получения.
Если у вас были другие виды методов, которые не имели ничего общего с получением или настройкой Партнеров, то следует применить ISP, чтобы создать для этого другой интерфейс.
Однако вы можете подумать о том, чтобы отделить ваши методы получения / содержимого от ваших методов установки / добавления, если вы считаете, что у вас будут клиенты, которые рассматривают этот репозиторий только для чтения и не должны иметь права его изменять, но у вас нет к.
Следующий ответ основан на языке C#. Это может быть недействительным на другом языке.
Я хочу создать интерфейс, который представляет деловых партнеров
Это первое предложение говорит мне, что вам, вероятно, нужен не интерфейс, а абстрактный класс верхнего уровня. И очень важно различать, нужен ли нам интерфейс или абстрактный класс.
Абстрактные классы представляют иерархии, где каждый потомок этой иерархии является специализацией, поэтому вы можете добавить больше членов для обогащения семейства. В этом случае отношение описывает "Это X - Y"
Интерфейсы представляют собой набор характеристик и поведения, не связанных с какой-либо иерархией. Следовательно, основное намерение - связать классы разных типов, которые будут иметь одинаковые функции или поведение. Отношение описывает "Этот Х может сделать Y"
Итак, предполагая, что в вашем описании лучше подходит абстрактный класс, я предлагаю следующее:
Одним из вариантов может быть установка методов "getList()" и "setList()" в качестве неабстрактных методов и предоставление в абстрактный класс поля для хранения списка
public abstract Partner
{
List<Partner> list;
public void SetList(List<Partner> list)
{
list = list;
}
public List<Partner> GetList(Partner partner)
{
return list;
}
}
Таким образом, метод "Contains" также может быть неабстрактным, поэтому вы не заставляете классы-потомки предоставлять реализацию.
public bool Contains(Partner partner)
{
return list.Contains(partner);
}
И давайте предположим, что в будущем вы захотите добавить новые методы помощников. Эти методы могут быть новыми неабстрактными методами в базовом классе, поэтому вы не будете влиять на своих текущих потомков "Партнера".
Если вам нужно изменить реализацию методов helpers, вы можете установить ее как "виртуальную", чтобы классы-потомки могли переопределять базовую реализацию.
public virtual void AddPartner(Partner partner)
{
list.Add(partner);
}