Найти в Дзене
IT's BIM | Revit и C#

Интерфейсы в C#: что такое контракт и как он позволяет быть мобильнее

Краткое содержание: Вы написали плагин, настройки хранятся в JSON. Через месяц инженеры просят хранить настройки в проекте Revit. Ещё через неделю — вернуть обратно. Если код завязан на конкретную реализацию, каждое изменение превращается в переписывание. И в этой статье мы посмотрим, как интерфейсы спасают от этой боли — с теорией, аналогией и реальным кодом.
Представьте: вы написали плагин для
Оглавление

Краткое содержание: Вы написали плагин, настройки хранятся в JSON. Через месяц инженеры просят хранить настройки в проекте Revit. Ещё через неделю — вернуть обратно. Если код завязан на конкретную реализацию, каждое изменение превращается в переписывание. И в этой статье мы посмотрим, как интерфейсы спасают от этой боли — с теорией, аналогией и реальным кодом.

Проблема: когда требования меняются каждый месяц

Представьте: вы написали плагин для расстановки арматуры. Настройки хранятся в JSON-файле — удобно, работает.

Проходит месяц. Приходит инженер:

«А давай теперь настройки будем держать прямо в проекте Revit? Чтобы при передаче файла коллегам всё ехало вместе».

Вы лезете в код. Меняете хранение в JSON на хранение в проекте, тестируете.

Через неделю приходит тот же инженер:

«Верни как было — раньше было удобнее, а то мы теперь друг другу портим настройки».

Если код написан «всё в одном файле» — вы снова лезете в те же места, переписываете вручную. Даже с гитом это боль: мердж-конфликты, страх сломать что-то ещё.

А с интерфейсами — меняете одну строчку в конфигурации. И готово.

Что такое интерфейс? Контракт, а не рецепт

Интерфейс — это не «как сделать», а «что должно получиться».

Аналогия из жизни: меню в ресторане

Вы заказываете стейк. Не спрашиваете:

  • Кто режет мясо?
  • Кто жарит?
  • Сколько соли положил повар?

Вы знаете одно: принесут стейк.

Меню — это и есть интерфейс. Оно обещает: «закажешь — получишь». Как именно выполнится обещание — уже не ваша забота.

Так и в коде: интерфейс говорит «я умею это делать». Как именно — решает реализация. Вы работаете с контрактом, не вдаваясь в подробности.

Почему это важно?

Потому что требования меняются. Постоянно. Особенно в коде — сегодня нужно одно, завтра другое, а потом опять одно.

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

Если вы пишете через интерфейсы — меняется только исполнитель. Контракт остаётся тем же. И переписывать половину проекта не нужно.

Практика: как это выглядит в коде

Теория — это хорошо. Но давайте посмотрим на реальный пример.

Мой логгер

У меня есть логгер. Он пишет отладку: что делает плагин, где упал. Но как — ему всё равно:

Код логгера
Код логгера

За provider стоит контракт ILogProvider. Логгер вызывает Write() и не парится — как запишут, решает реализация.

Сам интерфейс — всего один метод

Интерфейс провайдера
Интерфейс провайдера

Реализуй этот интерфейс — и ты в игре.

Примеры реализаций

В консоль:

Провайдер, пишущий логи в консоль
Провайдер, пишущий логи в консоль

В файл:

Провайдер, пишущий логи в файл
Провайдер, пишущий логи в файл

Хочу видеть лог в консоли — добавляю ConsoleProvider.

Нужно писать в файл — добавляю FileProvider.

Хочу и туда, и туда — добавляю оба. Без изменения логики логгера.

Где это живёт в плагине

Всё просто. Хочу загрузить настройки — обращаюсь к ISettingsRepository. Хочу рассчитать арматуру — вызываю IRebarCalculator. Здесь я хочу результат. Логика — не важна.

А конкретную реализацию подключаю один раз — в точке входа плагина:

Выбор конкретных реализаций
Выбор конкретных реализаций

Пришёл инженер и говорит: «Храним настройки в проекте». Меняю одну строчку:

Меняем реализацию, при этом settingsService будет работать корректно, так как он принимает в себя именно ISettingsRepository, от которого унаследованы и JsonSettingsRepository, и ProjectSettingsRepository.
Меняем реализацию, при этом settingsService будет работать корректно, так как он принимает в себя именно ISettingsRepository, от которого унаследованы и JsonSettingsRepository, и ProjectSettingsRepository.

Остальной код не трогаю. Контракт тот же — реализация другая. Архитектура цела.

Главное

Интерфейс — это не только про «правильный код».

Это про мобильность и легкость изменения.

Когда вы работаете через контракт, а не через конкретную реализацию, вы:

  • Меняете логику без страха сломать всё остальное
  • Тестируете отдельные части независимо
  • Масштабируете проект без боли

--

Понравилась статья? Пользовались ли вы интерфейсами? Делитесь в комментариях!