Re: Интерфейсы и реализация
От: rosencrantz США  
Дата: 02.09.20 18:41
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Чем руководствуетесь, принимая решение выделять или не выделять интерфейс из класса, т.е. нужно ли разделить интерфейс и реализацию?


Б>Когда имеется несколько реализация — понятно, интерфейс обычно выделяют.

Б>Но если реализация только одна, для каких классов выделяете интерфейсы, а для каких нет?

Б>P.S. Возможно, ответ сильно зависит от используемого языка. По возможности, укажите используемый язык.


Мой ответ будет зависеть от ЯП, потому что в разных ЯП могут быть разные причины хотеть выделить интерфейс.

Отвечу в контексте Java. Выделяю интерфейс когда компонент решает более общую задачу, чем та, которую нужно решить в этой конкретной ситуации. Если во всём коде эта проблема встречается всего 1 раз и именно вот в таком виде, то есть варианты:

1. Заточить решение под эту конкретную ситуацию.
2. Оставить решение общим, и просто, да, использовать его всего 1 раз для этой конкретной ситуации.

Для п.2 интерфейс используется как граница между "вообще решением" и "решением для конкретной ситуации". Например задача — импортировать юзеров из CSV файла — в SQL базу.

interface UserHandler {
  void handleUser(User user);
}

class UserCsvReader {
  void readAllUsers(UserHandler userHandler) {
    ...
  }
}

class BatchInserter<TRow> {
  BatchInserter(String sql, int batchSize) {...}

  void insert(TRow row) {
    if (batch.size < batchSize) {
      batch.add(row);
    } else {
      connection.batchUpdate(sql, batch);
      batch.clear();
    }    
  }
}

class BatchInsertingUserHandler implements UserHandler {
  BatchInsertingUserHandler(BatchInserter<UserRow> batchInserter) {}

  void handleUser(User user) {
    UserRow r = makeRowFromUser(user);
    batchInserter.insert(r);
  }
}

BatchInserter<UserRow> batchInserter = new BatchInserter("insert into Users(...)");
BatchInsertingUserHandler userHandler = new BatchInsertingUserHandler(batchInserter);
UserCsvReader reader = new UsersCsvReader();
reader.readAllUsers(userHandler);


Здесь интерфейс UserHandler используется чтобы отрезать "читание users CSV" от "писания в БД". Интерфейс тут позволяет показать, что вот этот код он конкретно про читание. Он используется при импорте юзеров, но это не сам импорт, а один из инструментов, которые используются импортом.

Если интерфейс выкинуть и оставить только сам BatchInsertingUserHandler, тут возникает много неясностей по поводу как кого переименовать, чтобы не получилось, что холодильник знает о существовании духовки, потому что они оба на кухне.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.