Долгое время у меня не было интерфейсов.

Я имею в виду интерфейсы как конструкции программирования на статических языках, таких как Java, C# и C++[1].

Я думал, что это странно иметь интерфейсы в коде. Зачем использовать интерфейс, когда у меня есть настоящий класс? Почему я должен прятать его за интерфейсом? Что не так с этим?

Опытные разработчики могут посмеиваться над наивностью моего младшего разработчика. Многие программисты, как и я в прошлом, не имеют полного представления об интерфейсах и о том, как они помогают создавать хорошо продуманные системы. Я надеюсь, что эта статья прольет немного света на интерфейсы.

Да, интерфейсы — это соединители.

Например, розетка или фаркоп на автомобиле также являются реальными примерами разъемов.

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

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

Чтобы проиллюстрировать это далее, давайте инвертируем решение с розеткой в ​​мысленном эксперименте.

Предположим, что бытовые приборы подключены через стационарные силовые кабели. Если вы хотите переместить тостер, вам придется вызвать электрика, подождать пару недель, пока он не появится, а затем он переделает его в другом месте — за плату в размере 300 долларов.

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

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

«Хорошо, — говорите вы, — я понимаю, почему полезно иметь дома универсальный разъем для питания. У меня много электроприборов, которыми я пользуюсь. Возможность подключить их везде — это здорово. Но как это относится к программному обеспечению и моему коду?

Интерфейсы в программном обеспечении выполняют аналогичную функцию — они расширяют систему подключаемым модульным образом.

Хорошо, пример в порядке.

Пример — подключаемость базы данных

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

Почему это может быть полезно?

Что ж, мы можем обнаружить, что исходная технология базы данных не масштабируется.

Почему мы не выбрали заранее хорошо масштабируемую базу данных?

Потому что никто не знает будущего. Требования меняются. Сценарии использования, которые, как мы думали, будут популярны, не были таковыми. Следовательно, реальный профиль использования базы данных отличается от предполагаемого — выбранная технология базы данных не оптимальна и, по возможности, должна быть заменена.

Следовательно, не будет ли не полезным спроектировать нашу систему таким образом, чтобы можно было отключить всю подсистему и подключить другую один? Мы бы оставили варианты с такой архитектурой системы.

Да, я думаю, это было бы полезно.

Спроектируйте свою систему, чтобы предоставить себе варианты.

Вернемся к нашему примеру с подключаемостью базы данных.

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

Сначала, скажем, мы используем SQL Server в качестве нашей технологии базы данных. Вот реализация интерфейса IDataAccess для SQL Server.

Теперь, если бы мы хотели изменить базу данных с SQL Server на MongoDB без каких-либо переделок, а просто отключив SqlDataAccess и подключив новую реализацию IDataAccess для MongoDB, мы могли бы это сделать. Вот код реализации MongoDB:

Представьте себе это — подключение совершенно новой базы данных без необходимости вносить изменения в компонент бизнес-логики кода приложения вообще!

Когда вы достигаете этого и начинаете использовать это, это своего рода волшебство.

Вот что такое интерфейсы — предоставление возможности создавать и соединять модульные системы!

Вывод

Мы обнаружили, что основная цель конструкции интерфейса — позволить нам писать подключаемое и, следовательно, легко изменяемое программное обеспечение. Повседневные интерфейсы, такие как розетки, также позволяют расширить наши дома с помощью электрических устройств. Программные интерфейсы предоставляют такую ​​же возможность переключения функциональности приложений.

[1] C++ не имеет интерфейсов как таковых. Функциональный эквивалент — это абстрактный класс только с чисто виртуальными функциями.

Присоединяйтесь к сотням инженеров-программистов и получайте мои советы по программированию на Code Coach каждый будний день.