Что такое интерфейс?
Интерфейс представляет собой общую особенность для многих языков программирования, которые позволяют определить общественные свойства и методы, которые должен раскрывать класс, без необходимости определения того, как они реализованы. Затем вы можете сказать класс, чтобы использовать этот интерфейс, и этот класс будет содержать фактическую реализацию.
Другими словами, интерфейс определяет то, что, и класс определяет как.
Как глупый пример (здесь я использую C #), мы определим интерфейс Lasagnechef, ILasagnechef, который содержит метод cooklasagne.
public interface ILasagneChef { Lasagne CookLasagne(); }
Затем мы можем создать класс, который реализует интерфейс iChef:
public class ChefGordon : ILasagneChef { public Lasagne CookLasagne() { // Gordon's lasagne recipe return lasagne; } }
И это все, что нужно для определения и реализации интерфейса. Это может быть не ясно, почему это полезно. Надеюсь, приведенные ниже примеры убедите вас, почему вам нужно начать использовать интерфейсы в вашем коде.
Причина 1: создает свободно связанный код
Свободная связь означает, что каждый компонент в вашем коде не должен осознавать, как работает какой-либо другой компонент системы или зависит от любой конкретной реализации. Это облегчает создание и обслуживание кода, потому что это означает, что вы можете быть уверены, что изменение одного компонента в вашем коде не должны вызывать проблемы в других областях вашего кода.
В качестве примера плотно связанного кода давайте определим класс ресторана, который зависит от Chefgordon в качестве шеф-повара Lasagne, а также имеет метод упорядочения.
public class Restaurant { public ChefGordon LasagneChef { get; } public Restaurant(ChefGordon lasagneChef) { this.LasagneChef = lasagneChef; } public Lasagne OrderLasagne() { var lasagne = this.LasagneChef.CookLasagne(); return lasagne; } }
В другом месте в нашем коде мы могли бы разместить заказ LASAGNE со следующим кодом:
var chef = new ChefGordon(); var restaurant = new Restaurant(chef); var lasagne = restaurant.OrderLasagne();
Этот код будет работать нормально, если Cheengordon является шеф-поваром Lasagne для ресторана. Однако представьте, что мы заменили шеф-повар Гордон с Chefjamie в качестве лазагнехефа для ресторана. Теперь наш внешний код сломается, потому что он все еще ожидает, что ресторан будет использовать Chefgordon в качестве шеф-повара Lasagne.
Это тривиальный пример, но, надеюсь, вы можете, чтобы в более сложных системах, чтобы изменить код в другом месте в кодовой базе каждый раз, когда вы делаете небольшое изменение в вашем коде, сделают код довольно неуправляемым.
Решение этого является использование интерфейсов для проектирования слабо связанного кода.
В нашем примере, если мы вместо этого сделаем ресторан в зависимости от интерфейса ILAsagnechef, внезапно больше не имеет значения, какой шеф-повар мы используем, до тех пор, пока этот шеф-повар реализует интерфейсы ILASAGNECHEF.
public class ChefGordon : ILasagneChef { public Lasagne CookLasagne() { // Gordon's lasagne recipe return lasagne; } } public class ChefJamie : ILasagneChef { public Lasagne CookLasagne() { // Jamie's lasagne recipe return lasagne; } } public class Restaurant { public ILasagneChef LasagneChef { get; } public Restaurant(ILasagneChef lasagneChef) { this.LasagneChef = lasagneChef; } public Lasagne OrderLasagne() { var lasagne = this.LasagneChef.CookLasagne(); return lasagne; } } var gordon = new ChefGordon(); var jamie = new ChefJamie(); var restaurant1 = new Restaurant(gordon); var restaurant2 = new Restaurant(jamie); var lasagne1 = restaurant1.OrderLasagne(); var lasagne2 = restaurant2.OrderLasagne();
И это имеет смысл. Когда мы размещаем заказ на какую-то лазанью, мы не заботимся о деталях того, как производится лазань или, по какому шеф-повару, пока мы получаем то, что мы хотим, наша лазань.
Причина 2: улучшает оправдание
Написание хороших тестов – это необходимый навык в разработке программного обеспечения, поскольку он позволяет вам убедиться, что каждая часть вашей системы ведет себя так, будто она должна. Хорошие тесты особенно важны в крупных системах, так как оно поможет мгновенно выделить, если какие-либо изменения кода нарушили определенную часть системы.
Одно важное соображение при написании хороших испытаний – убедиться, что вы тестируете компонент в изоляции, без каких-либо зависимостей, чтобы вы знали, что результаты из теста полностью из-за тестируемого компонента, а не из-за каких-либо проблем в этих компонентах зависимости.
Если все компоненты зависимости являются интерфейсами, вместо классов, то очень легко заставить MOD-реализации этих интерфейсов, которые всегда дадут вам надежный, последовательный результат.
Например, если мы хотели проверить, что метод ресторана в ресторане вел себя должным образом, мы могли бы легко создать макет интерфейса ILASAGNECHEF.
var mock = new Mock(); mock.Setup(m => m.CookLasagne()).Returns(new Lasagne()); var mockLasagneChef = mock.Object; var restaurant = new Restaurant(mockLasagneChef); var lasagne = restaurant.OrderLasagne();
Если наши тесты потерпели неудачу, мы знаем, что проблема в методе упорядоченности, поскольку наш Mock Ilasagnechef всегда возвращает лазанью.
Причина 3: упрощает развитие
Это может быть в последний раз в списке, но это, безусловно, моя любимая часть использования интерфейсов в моем коде.
Поскольку вы разрабатываете проект, существует множество различных аспектов, которые необходимо учитывать и закодировать. Например, есть пользовательский интерфейс, логика, доступ к данным и т. Д. Попытка отслеживать все эти разные аспекты сразу заставляет весь опыт запутанным, расстраивающим, и вам слишком легко попасть в небольшие детали, которые могут легко измениться, так как проект перемещается вперед.
Вот почему я предпочитаю сосредоточиться сначала на том, что я хочу достичь, а затем заполнить детали того, как добиться этого позже. Конечно, это может быть достигнуто с использованием интерфейсов.
Например, я мог бы захотеть создать веб-приложение, которое отображает список изображений моей любимой лазанью. Для простоты это можно разделить на два различных компонента, получать данные и отображение данных.
Я хочу сначала сосредоточиться на отображении данных и беспокоиться позже о том, как я действительно получаю данные. Поэтому я определим следующий интерфейс:
public interface ILasagneRepository { ListGetLasagneImages(); }
Затем я могу разработать мой пользовательский интерфейс с помощью этого интерфейса.
@inject ILasagneRepository repository @{ var lasagneImages = repository.GetLasagneImages(); }
-
@foreach(var image in lasagneImages)
{
-
После того, как я написал весь код для моего пользовательского интерфейса, я могу подумать о том, как я действительно получаю данные, создавая класс, который реализует интерфейс ILASAGNEREPOITON.
public class DatabaseLasagneRepository : ILasagneRepository { public ListGetLasagneImages() { // code to get images from database return lasagneList; } }
Резюме
Мои лучшие 3 причины использовать интерфейсы в вашем коде:
- Причина 1: создает свободно пару кода
- Причина 2: улучшает оправдание
- Причина 3: упрощает развитие
Я надеюсь, что это убедило вас о преимуществах использования интерфейсов в вашем коде и начать использовать их в своих собственных проектах.
Если вам понравилось это прочитать, пожалуйста, следуйте за мной здесь или в Twitter: @dr_sam_walpole. Если вы хотите, вы также можете Купи мне кофе Действительно 😊.
Оригинал: “https://dev.to/dr_sam_walpole/top-3-reasons-to-use-interfaces-in-your-code-4kol”