Re[2]: бессмысленные интерфейсы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.02.22 07:27
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Поковырявшись еще в проекте, нашел немало перлов типа такого:


C>
C>if (text.ToUpper().Contains(...))
C>    doSomething();
C>else if (text.ToUpper().Contains(...))
C>    doSomethingElse();
C>else if (text.ToUpper().Contains(...))
C>    doSomethingDifferentElse();
C>


А в чём проблема — только в некэшировании результата ToUpper()?

C>Так что вопрос о качестве кода можно закрывать. Джуниор, которого покусал Гамма.


Почему не Влиссидес или Буч?

C>Всех, пто придумывал оправдания такому коду — поздравляю.


Я не придумывал, но заранее спасибо. Ты ж не показывал. А требование интерфейсов и оптимальность — почти не связаны.
The God is real, unless declared integer.
Re[8]: бессмысленные интерфейсы
От: elmal  
Дата: 19.02.22 07:38
Оценка:
Здравствуйте, netch80, Вы писали:

N>Хотя если это ConfigHelper().getFooValue() — то ещё более-менее норм.

Вот вообще не понимаю эту любовь к оператору new. Ну блин на хрена на ровном месте создавать объект чтобы там дернуть метод?
Конфиг он на то и конфиг, что он один. Если всякие DI фреймворки не используешь — сделай его глобальным и не мучайся, опиши только это в документации. Ничего страшного не случится если в проекте будет одна глобальная переменная вроде конфига, о которой все знают и правила доступа к которой известны и соблюдаются. Альтернативы в виде доступ через синглтоны всякие и фабрики со всякими копипастами — это по сути тоже глобальная переменная, вот только кода сильно больше получается и работает все гораздо запутаннее. А если используешь DI фреймворки — там все достаточно удобно все сделано, наработаны давно бест практики, кода будет абсолютно минимум и все удобно — живи да радуйся что у тебя все чистенько и по фен шую.
Re[9]: бессмысленные интерфейсы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.02.22 07:53
Оценка:
Здравствуйте, elmal, Вы писали:

E>Здравствуйте, netch80, Вы писали:


N>>Хотя если это ConfigHelper().getFooValue() — то ещё более-менее норм.

E>Вот вообще не понимаю эту любовь к оператору new. Ну блин на хрена на ровном месте создавать объект чтобы там дернуть метод?

Кто сказал, что там будет new? Сами придумали? Я такого не говорил.
Вполне возможно, что это уже метод чтения синглтона.
(Хотя если пример был строго для Java, то да, возвращаемся к import static.)

E>Конфиг он на то и конфиг, что он один.


Кто сказал? Конфиг это контекст. Контекстов может быть несколько. Например, несколько экземпляров стека протоколов на разных IP адресах или портах, с разными свойствами.

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

А ещё контекст может меняться при входе в какую-то функцию и возвращаться при выходе. Тогда он где-то в thread local data. А если акторы на асинке, то ещё и его замыкает в свойствах актора.

E> Если всякие DI фреймворки не используешь — сделай его глобальным и не мучайся, опиши только это в документации. Ничего страшного не случится если в проекте будет одна глобальная переменная вроде конфига, о которой все знают и правила доступа к которой известны и соблюдаются. Альтернативы в виде доступ через синглтоны всякие и фабрики со всякими копипастами — это по сути тоже глобальная переменная, вот только кода сильно больше получается и работает все гораздо запутаннее.


Про фабрики я не говорил. Синглтон в условиях современных языков это метод обеспечить защиту от изменения выбора объекта, где не надо. getInstance() всем, setInstance(), если есть, только тем, кому положено.

E> А если используешь DI фреймворки — там все достаточно удобно все сделано, наработаны давно бест практики, кода будет абсолютно минимум и все удобно — живи да радуйся что у тебя все чистенько и по фен шую.


Они позволяют сделать временную замену конфига на один вызов и пробросить это в отложенный коллбэк?
The God is real, unless declared integer.
Re[10]: бессмысленные интерфейсы
От: elmal  
Дата: 19.02.22 08:16
Оценка:
Здравствуйте, netch80, Вы писали:

N>Кто сказал? Конфиг это контекст. Контекстов может быть несколько. Например, несколько экземпляров стека протоколов на разных IP адресах или портах, с разными свойствами.

Я вообще то считал, что конфиг — это такое условно неизменное что то, а контекст — это что то постоянно меняющееся, соответственно это все совершенно разные вещи.

N>Они позволяют сделать временную замену конфига на один вызов и пробросить это в отложенный коллбэк?

Если потребовалось такое, то мы имеем не конфиг, а контекст чего то. Контекст привязан к чему то, например к текущему потоку, к пользователю, ну или к объекту, например к Http запросу. И да, фреймворки позволяют для конкретного HTTP запроса иметь свой контекст, в который можем класть что хотим и получать что хотим.
Re[7]: бессмысленные интерфейсы
От: · Великобритания  
Дата: 19.02.22 08:23
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>>>Но у меня — универсальный узел и интерфейс к нему.

AG>·>Нет, у тебя узел и иузел.
AG>Напомню, что в терминологии C++ (в отличие от C# и Java) понятие интерфейс отсутствует.
AG>Вместо него обычно применяется: абстрактный_класс:
AG>https://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm
Не знаю зачем ты это всё рассказал, но это я и так прекрасно знаю. Если этот код переписать на C#/Javа суть не изменится.
Даже хуже. В плюсах и так уже есть пара h/cpp, а ты ещё и третью штутку создаёшь.

AG>>>Именно наличие программного интерфейса — позволяет уменьшить связанность (coupling) в проекте.

AG>·>А конкретно в данном случае что именно уменьшается?
AG>Показана идея применения абстрактного_класса C++ в качестве интерфейса.
Замечательно, а в киеве дядька.

AG>Здесь (в приведенном примере) всё просто, поэтому избыточной связанности нет.

Ок. Т.е. и пользы от интерфейса (в приведённом примере) тоже нет (по крайней мере для устранения избыточной связности). ЧТД.

AG>>>За счёт этого, получим упрощение архитектуры и уменьшение количества ошибок.

AG>·>Введение новой сущности интерфейса не упрощает, а усложняет.
AG>Конкретно здесь — упрощает понимание (даже если незначительно и увеличивает объём кода).
Это субъективно. Просто делает код более привычным тебе лично. А объективное усложнение хотя бы по объёму кода точно есть. Плюс объективно появляется лишняя сущность в коде, которая требует поддержки.

AG>>>Конечно же, можно было обойтись и без интерфейса, однако так красивее и понятнее.

AG>·>Эмоции. "Я так всегда делал и мне нравится"
AG>Если быть точным, то делал я так не всегда.
AG>Первые лет пять/шесть разработки на C++ я практически не применял абстрактные классы.
AG>Но примерно с 2015-го понял, что такой подход упрощает понимание проекта.
AG>Даже мне самому легче понять то, что я разработал несколько лет назад.
Да. Я тоже таким был. А потом ещё пять-шесть лет опыта, научился пользоваться современными тулзами и начал понимать что надо _не_ делать.

AG>В литературе это именуют: best practices.

Не знаю конкретно какой код ты имеешь в виду, но в приведённом примере это именуется cargo cult.

AG>P.S. Мы не ждём, когда спроектируются новые узлы поезда/вагоны, а подготавливаем проект "рельсового пути" для существующих и новых поездов.

AG>Вы же предлагаете проектировать новые рельсы, как только появятся новые вагоны.
AG>YAGNI — если бы я предлагал проектировать поезд на магнитной подушке, для поездки по линии длиной 5 км, где вполне хватит обычного трамвая.
Ты приводишь аналогию из реального мира, где всё дорого и требует серьёзного планирования и распространяешь это на софтостроение, где изменения могут быть настолько дешевыми, что и не стоит задумываться.
Представь себе, что пустить поезд поезд на магнитной подушке или трамвай будет занимать 2 минуты — будет ли тебя заботить этот вопрос? Бросишь то, что попадётся под руку, поезд там, или самолёт, а если узнаешь, что всего 5км, то за минуту заменишь на трамвай.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: бессмысленные интерфейсы
От: AlexGin Беларусь  
Дата: 19.02.22 08:38
Оценка:
Здравствуйте, ·, Вы писали:

...
·>Не знаю зачем ты это всё рассказал, но это я и так прекрасно знаю.

Очень надеюсь, что кроме нас на КЫВТ есть ещё посетители, которым это будет интересно.
Не стоит думать, что все полезные советы люди смотрят на SO.

...
·>Да. Я тоже таким был. А потом ещё пять-шесть лет опыта, научился пользоваться современными тулзами и начал понимать что надо _не_ делать.

Какими именно тулзами? Что делают эти тулзы?
Re[11]: бессмысленные интерфейсы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.02.22 08:46
Оценка:
Здравствуйте, elmal, Вы писали:

N>>Кто сказал? Конфиг это контекст. Контекстов может быть несколько. Например, несколько экземпляров стека протоколов на разных IP адресах или портах, с разными свойствами.

E>Я вообще то считал, что конфиг — это такое условно неизменное что то, а контекст — это что то постоянно меняющееся, соответственно это все совершенно разные вещи.

Так нету здесь точной границы. Вот я зову GetServerAddress(). Это конфигурация? Очевидно, да. Оно раздельно в зависимости от того, какой из экземпляров стека протоколов нужно дёрнуть? Да.
Ну и как мне их сделать "разными вещами"?
Конфигурировать их, вероятно, можно тоже раздельно. А в случае Cisco style (частый в моём мире) скорее всего так и будет — подправил через CLI параметр в секции, изменился только он, пошла нотификация куда-то вглубь.

N>>Они позволяют сделать временную замену конфига на один вызов и пробросить это в отложенный коллбэк?

E>Если потребовалось такое, то мы имеем не конфиг, а контекст чего то. Контекст привязан к чему то, например к текущему потоку, к пользователю, ну или к объекту, например к Http запросу. И да, фреймворки позволяют для конкретного HTTP запроса иметь свой контекст, в который можем класть что хотим и получать что хотим.

Ну в типичном случае таки да. Для теста (если это не тест собственно механизма контекста) обычно не нужно делать в одном процессе одновременно, или вложенно по стеку, замену конфигурации.
Хотя в функциональные тесты может входить и одновременный запуск нескольких экземпляров контекста-конфигурации и взаимодействие между ними. (Хм, дефис тут удобен.)
The God is real, unless declared integer.
Re[9]: бессмысленные интерфейсы
От: · Великобритания  
Дата: 19.02.22 10:26
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>·>Не знаю зачем ты это всё рассказал, но это я и так прекрасно знаю.

AG>Очень надеюсь, что кроме нас на КЫВТ есть ещё посетители, которым это будет интересно.
AG>Не стоит думать, что все полезные советы люди смотрят на SO.
Это называется оффтопик. Т.е. к тезису что твой пример был примером бессмысленного интерфейса возражений не осталось?

AG>...

AG>·>Да. Я тоже таким был. А потом ещё пять-шесть лет опыта, научился пользоваться современными тулзами и начал понимать что надо _не_ делать.
AG>Какими именно тулзами? Что делают эти тулзы?
Рефакторинг, анализ кода, навигация, генерация документации по коду, моки поверх классов, етс.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: бессмысленные интерфейсы
От: AlexGin Беларусь  
Дата: 19.02.22 10:41
Оценка:
Здравствуйте, ·, Вы писали:

·>Это называется оффтопик. Т.е. к тезису что твой пример был примером бессмысленного интерфейса возражений не осталось?


Бессмысленность или наличие смысла — всегда зависит от контекста задачи.

Если я пояснил на примере пользу от интерфейса, пусть даже ценой небольшого увеличения объема кода,
это совсем не означает, что _каждый_класс_ в моих проектах имеет интерфейс
Имеют только те, которые по логике проекта (по логике архитектурных решений) должны его иметь.
Бессмысленным его наличие считать не следует.

·>Рефакторинг, анализ кода, навигация, генерация документации по коду, моки поверх классов, етс.


Это всё известные всем давно средства.
Надеялся найти в данной ветке что-то новое, но не судьба
Re[11]: бессмысленные интерфейсы
От: · Великобритания  
Дата: 19.02.22 11:12
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>·>Это называется оффтопик. Т.е. к тезису что твой пример был примером бессмысленного интерфейса возражений не осталось?

AG>
AG>Бессмысленность или наличие смысла — всегда зависит от контекста задачи.
Контекст обозначен явно в стартовом сообщении "каждый интерфейс реализован ровно в одном классе." По моему тезису в этом контексте интерфейсы бессмысленны. Ты с этим согласен или нет?

AG>Если я пояснил на примере пользу от интерфейса, пусть даже ценой небольшого увеличения объема кода,

Я не увидел пояснений, кроме как "мне понятнее". Ещё ты что-то написал про "уменьшить связанность", но потом ты согласился что тут оно не в тему.

AG>это совсем не означает, что _каждый_класс_ в моих проектах имеет интерфейс

И на том спасибо.

AG>Имеют только те, которые по логике проекта (по логике архитектурных решений) должны его иметь.

AG>Бессмысленным его наличие считать не следует.
По умолчанию следует считать всё бессмысленным. Пока нет явного конкретного объективного смысла.

AG>·>Рефакторинг, анализ кода, навигация, генерация документации по коду, моки поверх классов, етс.

AG>Это всё известные всем давно средства.
AG>Надеялся найти в данной ветке что-то новое, но не судьба
Вот простая новая для тебя мысль: интерфейс (как и любую другую сущность) надо вводить только когда без него нельзя обойтись.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[9]: бессмысленные интерфейсы
От: · Великобритания  
Дата: 19.02.22 12:47
Оценка:
Здравствуйте, elmal, Вы писали:

N>>Хотя если это ConfigHelper().getFooValue() — то ещё более-менее норм.

E>Вот вообще не понимаю эту любовь к оператору new. Ну блин на хрена на ровном месте создавать объект чтобы там дернуть метод?
E>Конфиг он на то и конфиг, что он один. Если всякие DI фреймворки не используешь — сделай его глобальным и не мучайся, опиши только это в документации. Ничего страшного не случится если в проекте будет одна глобальная переменная вроде конфига, о которой все знают и правила доступа к которой известны и соблюдаются.
Не надо глобальные переменные использовать.

E> Альтернативы в виде доступ через синглтоны всякие и фабрики со всякими копипастами — это по сути тоже глобальная переменная, вот только кода сильно больше получается и работает все гораздо запутаннее. А если используешь DI фреймворки...

А бы почему через конструктор не передать? Слишком просто что-ли?.. не солидно?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: бессмысленные интерфейсы
От: elmal  
Дата: 19.02.22 13:56
Оценка:
Здравствуйте, ·, Вы писали:

·>А бы почему через конструктор не передать? Слишком просто что-ли?.. не солидно?

Не всегда нужны классы, иногда для простоты и удобства гораздо проще до черта логики сделать обычными top level функциями. Во вторых, если классы все таки нужны, без DI фреймворков ты задолбаешься этот конфиг в каждый класс прокидывать и инициализировать. В случае использования фреймворков все понятно как мы поступаем. Если мы по какой то причине навороты не используем, ничего страшного если на весь проект будет одна глобальная переменная. Достаточно уважаемые люди такое, если что, делают иногда, например Gaving King в языке Ceylon предлагал логирование делать через глобальную переменную, ничего страшного не случалось на проектах в миллионы строк если что.
Re: бессмысленные интерфейсы
От: bnk СССР http://unmanagedvisio.com/
Дата: 19.02.22 15:09
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Некоторые люди делают для каждого класса по интерфейсу и фабрике чтобы создавать объекты, причем каждый интерфейс реализован ровно в одном классе.

C>В этом есть какой-то тайный смысл, или они просто идиоты?

Чего ты такой злой. Люди любой идиотизм могут делать из самых лучших побуждений.
Возможно их просто так где-то научили так делать, но не сказали, что так нужно делать не всегда.
Re[3]: бессмысленные интерфейсы
От: Codealot Земля  
Дата: 19.02.22 15:19
Оценка:
Здравствуйте, netch80, Вы писали:

N>А в чём проблема — только в некэшировании результата ToUpper()?


А, всего-то навсего накопипастил код?

N>Я не придумывал, но заранее спасибо. Ты ж не показывал. А требование интерфейсов и оптимальность — почти не связаны.


Умение писать адекватный код их связывает. И это даже не оптимальность, это просто азы качественного кода.
Ад пуст, все бесы здесь.
Re[2]: бессмысленные интерфейсы
От: Codealot Земля  
Дата: 19.02.22 15:19
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>Чего ты такой злой.


Жизнь такая.

bnk>Люди любой идиотизм могут делать из самых лучших побуждений.

bnk>Возможно их просто так где-то научили так делать, но не сказали, что так нужно делать не всегда.

Знаешь, куда вымощена дорога благими намерениями?
Ад пуст, все бесы здесь.
Re[3]: бессмысленные интерфейсы
От: bnk СССР http://unmanagedvisio.com/
Дата: 19.02.22 15:29
Оценка:
Здравствуйте, Codealot, Вы писали:

bnk>>Люди любой идиотизм могут делать из самых лучших побуждений.

bnk>>Возможно их просто так где-то научили так делать, но не сказали, что так нужно делать не всегда.

C>Знаешь, куда вымощена дорога благими намерениями?


Хочешь взять на себя ответственность за этот проект и блюсти его чистоту?
Ну что такого-то, просто лишние интерфейсы и фабрики, не конец света. С этим можно работать.
Может и правда когда-нибудь будут тесты. Пусть безобразно, зато однообразно. Так что все норм.
Re[4]: бессмысленные интерфейсы
От: Codealot Земля  
Дата: 19.02.22 15:41
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>Хочешь взять на себя ответственность за этот проект и блюсти его чистоту?


Как говорится в анекдоте, я таки единственный солдат в израильской армии?
Ад пуст, все бесы здесь.
Re[7]: бессмысленные интерфейсы
От: baxton_ulf США  
Дата: 19.02.22 16:00
Оценка:
Здравствуйте, elmal, Вы писали:


_>>и все, пока в mockito не появился mockStatic никаких зубодробительных юнит-тестов не напишешь. а если это не java, то возможно вообще не напишешь

E>Элементарно рефакторится.

да я что спорю что-ли? все правильно, все рефакторится. но если бы тесты писались вместе с кодом то рефакторить не пришлось бы.

у меня там получилось так — надо было сделать "супер быстрое изменение в одну строчку" и предел по покрытию уже выставили на 80% (что в общем то правильно).
в общем рефакторить пришлось мне и количество изменений и время работы выросли
Re[11]: бессмысленные интерфейсы
От: · Великобритания  
Дата: 19.02.22 16:49
Оценка:
Здравствуйте, elmal, Вы писали:

E>·>А бы почему через конструктор не передать? Слишком просто что-ли?.. не солидно?

E>Не всегда нужны классы, иногда для простоты и удобства гораздо проще до черта логики сделать обычными top level функциями.
Функции неявно зависящие от глобальных переменных?! Вот и передавай им serverAddress как параметр, а не извлекай из глобальных синглтонов.

E>Во вторых, если классы все таки нужны, без DI фреймворков ты задолбаешься этот конфиг в каждый класс прокидывать и инициализировать.

У тебя и вправду каждый класс зависит от serverAddress?!
Просто передавай ровно то что нужно и задалбливаться не придётся.

E>В случае использования фреймворков все понятно как мы поступаем.

Да, фреймворки в топку.

E>Если мы по какой то причине навороты не используем, ничего страшного если на весь проект будет одна глобальная переменная. Достаточно уважаемые люди такое, если что, делают иногда, например Gaving King в языке Ceylon предлагал логирование делать через глобальную переменную, ничего страшного не случалось на проектах в миллионы строк если что.

"Ceylon Stable release 1.3.3 / August 21, 2017; 4 years ago", ну да, ничего страшного.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: бессмысленные интерфейсы
От: elmal  
Дата: 19.02.22 17:49
Оценка:
Здравствуйте, ·, Вы писали:

E>>Во вторых, если классы все таки нужны, без DI фреймворков ты задолбаешься этот конфиг в каждый класс прокидывать и инициализировать.

·>У тебя и вправду каждый класс зависит от serverAddress?!
·>Просто передавай ровно то что нужно и задалбливаться не придётся.
Начнем с того, что в случае некоторых трюков с конфигом у меня и классов то не густо . Как по фен шую, я прекрасно сам знаю, и чаще всего рекомендациям следую, любое отклонение от рекомендаций я могу обосновать и даже во всяких ReadMe пишу почему так сделал. Естественно функции в большинстве случаев у меня чистые, никаких неявных зависимостей нет. Точнее почти нет. У тебя неявные зависимости тоже есть, например Locale. Запускаешь в одном окружении, у тебя так даты выводятся и запятая отображается точкой, а в другом окружении наоборот.

Ну и мой изначальный пост был немного ошибочным, я просто неверно воспринял выражение ConfigHelper().getFooValue(). Воспринял как new ConfigHelper().getFooValue(), слишком привыкнув к Java конвенции именовать функции и методы начиная со строчной буквы. А любовь ко всяким new для выполнения простейших действий даже в стандартной библиотеке меня несколько огорчает, а многие подобные подходы и в своем коде используют, что меня сильно печалит.

·>"Ceylon Stable release 1.3.3 / August 21, 2017; 4 years ago", ну да, ничего страшного.

Я как бы в курсе . На деле весьма хороший был язык, вроде как полностью перекрывается по фичам scala 3, которую все никак не соберусь попробовать. Некоторых фичей сейчас реально не хватает.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.