Здравствуйте, ·, Вы писали:
·>Здравствуйте, rosencrantz, Вы писали:
R>>·>Ок. Вот тогда твой пример с UserHandler непонятен. Я так и не понял накой там interface UserHandler, чем плох просто class UserHandler.
R>>·>И уж тем более кошмарик BatchInsertingUserHandler, как будто ты имя класса так придумал.
R>>·>Я для сравнения привёл код без интерфейса — по каким критериям он хуже?
R>>Он не обязательно хуже, он просто не обладает теми свойствами, которыми обладает мой вариант. Плохо это или хорошо — я ж как раз пытаюсь донести — зависит от восприятия автора/читателя.
·>Ок. Каким образом в коде выражается это разбиение на модули? Ну т.е. представь себе ты написал код, закоммитил, я открываю твой код и я там увижу эти модули? Как читатель узнает твоё авторское восприятие этого кода?
Ну серьёзно? "Ну т.е. представь себе ты написал код, закоммитил, <скип> Как читатель узнает твоё авторское восприятие этого кода?" — про это пишутся сотни книжек и ведутся регулярные срачи на рсдн. Какой ответ вы ожидаете услышать?
R>>Интерфейс UserHandler здесь нужен для того, чтобы показать границу между модулем 1 (как мы читаем CSV) и модулем 3 (когда мы читаем CSV, что мы с этим делаем). Модуль 1 в этом случае именно вполне самостоятельный модуль. Его можно без изменений переиспользовать для например написания конвертора из CSV — в XML. Но это не очень важно. Важно что самодостаточная концепция изолирована от остального мира
То же самое, что ваша иллюстрация про "файловая система не должна знать про сеть" — у меня "читалка csv не должна знать про писалку в бд", просто масштаб другой.
·>Тут я топлю за принцип YAGNI.
А не вкусовщина ли это?
·>Вот когда нам не станет хватать, что наш class UserHandler пишет батчами в бд, вот тогда мы отрефакторим код и у нас получится interface UserHandler и реализующие его class DbUserWriter, class XmlUserWriter — с не вымученными enterprisified именами, а явно продиктованными новыми появившимися требованиями.
Я совершенно за YAGNI, но только там где противопоставляются более накрученное решение и более простое. Добавление 1 интерфейса не делает решение более сложным — ни в восприятии, ни в реализации, ни в сопровождении. Для тех, кто не сечёт фишку, решение по сложности — такое же, как и без интерфейса, для тех, кто сечёт — это "граница интерфейса, точка расширения"
Можно провести аналогию с поясняющей переменной:
if (person.age >= 21) {
...
}
Всё тут в порядке? YAGNI не чешется?
bool isAllowedToDrinkBear = person.age >= 21;
if (isAllowedToDrinkBear) {
...
}
Нужна поясняющая переменная? Или YAGNI и потом отрефакторим? Вносит она проблемы? Увеличивает сложность экспоненциально? Что насчёт поясняющей функции?
if (isAllowedToDrinkBear(person)) {
...
}
Тут как? YAGNI? Что насчёт выноса этой функции в отдельный класс?
if (bearDrinkingDecisionMaker.isAllowedToDrinkBear(person)) {
...
}
Во всех случаях (кроме первого) появление имени "isAllowedToDrinkBear" — это тот самый ввод интерфейса.
R>>В вашей версии если UserHandler превращается в BatchInsertingUserHandler, модуль 1 исчезает и его содержимое становится частью модуля 3. Конвертор CSV->XML вы уже не напишете без правок кода, но такой цели и не было. Но вообще чтение CSV у вас теперь гвоздями прибито к вставке в базу.
·>Модуль 1 не исчезнет, а станет состоять из только лишь класса UserCsvReader.
Это не модуль. Модуль — это когда можно провести границу. В вашем случае границу провести не получится