Сообщение Re[14]: Инициализация приложения - внедрение зависимостей в от 10.11.2023 21:30
Изменено 10.11.2023 21:34 ·
Re[14]: Инициализация приложения - внедрение зависимостей в
Здравствуйте, vmpire, Вы писали:
V>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
V>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>В любом случае эта проблема не зависит от наличия или отсутствия DI
Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка". Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
V>>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
V>·>Так мой поинт, что никогда не даёт.
V>Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
V>Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.
Угу, т.к. все эти обобщённые реализации — по сути переливание из пустого в порожнее.
V>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
V>Как я писал уже в ответе ТС, простейший вариант -
Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
V>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.
Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
V>·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):
V>Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
И получилась яркая иллюстрация, внезапно. Ты показал типичный код который обычно логически соответствует типичной конфигурации контейнера и сразу бросилось в глаза — какой же кривой косячный код, и насколько же он хрупкий и где что может пойти не так. Так никто вменяемый писать не будет и реьвю такое уж точно не пройдёт.
А вот если это говно завернуть блестящей обёрткой IoC-фреймворка — так внезапно — конфеткой называть начинают.
V>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.
Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.
V>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
V>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
V>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
wiring code — основан на DI тоже.
V>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
V>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>В любом случае эта проблема не зависит от наличия или отсутствия DI
Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка". Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
V>>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
V>·>Так мой поинт, что никогда не даёт.
V>Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
V>Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.
Угу, т.к. все эти обобщённые реализации — по сути переливание из пустого в порожнее.
V>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
V>Как я писал уже в ответе ТС, простейший вариант -
Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
V>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.
Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
V>·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):
V>Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
И получилась яркая иллюстрация, внезапно. Ты показал типичный код который обычно логически соответствует типичной конфигурации контейнера и сразу бросилось в глаза — какой же кривой косячный код, и насколько же он хрупкий и где что может пойти не так. Так никто вменяемый писать не будет и реьвю такое уж точно не пройдёт.
А вот если это говно завернуть блестящей обёрткой IoC-фреймворка — так внезапно — конфеткой называть начинают.
V>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.
Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.
V>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
V>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
V>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
wiring code — основан на DI тоже.
Re[14]: Инициализация приложения - внедрение зависимостей в
Здравствуйте, vmpire, Вы писали:
V>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
V>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>В любом случае эта проблема не зависит от наличия или отсутствия DI
Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка". Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
V>>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
V>·>Так мой поинт, что никогда не даёт.
V>Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
V>Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.
Угу, т.к. все эти обобщённые реализации — по сути переливание из пустого в порожнее.
V>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
V>Как я писал уже в ответе ТС, простейший вариант -
Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
V>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.
Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
V>·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):
V>Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
И получилась яркая иллюстрация, внезапно. Ты показал типичный код который обычно логически соответствует типичной конфигурации контейнера и сразу бросилось в глаза — какой же кривой косячный код, и насколько же он хрупкий и где что может пойти не так. Так никто вменяемый писать не будет и реьвю такое уж точно не пройдёт.
А вот если это говно завернуть блестящей обёрткой IoC-фреймворка — так внезапно — конфеткой называть начинают.
V>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.
Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.
V>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
V>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
V>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
wiring code — основан на DI тоже.
V>>>Если нужны одинаковые конфигурации для тестов и прода, то кто мешает слелать эту конфигурацию в одном куске кода и переиспользовать?
V>·>В этом случае придётся бороться с фреймворком как вменяемо разделять конфигурации.
V>В любом случае эта проблема не зависит от наличия или отсутствия DI
Эээ... Не путай. DI это DI, а фреймворк это фреймворк.
Допустим ты имел в виду "не зависит от наличия или отсутствия IoC-фреймворка". Как раз зависит. Когда ты пишешь wiring code на самом ЯП — у тебя есть вся выразительная сила ЯП. Хочешь интерфейсы, хочешь классы, хочешь if/switch/циклы/методы/лямбды — полный арсенал. А с фреймворком — только полтора типичных паттерна в которые умеет фреймворк, и целая наука каких-то плагинов, магических расширений и аннотаций, и это всё может понадобиться чтобы реализовать какой-нибудь банальный switch.
V>>>В тех случаях, когда не даёт, можно ведь им не пользоваться. Я же сразу написал, что это нишевый инструмент.
V>·>Так мой поинт, что никогда не даёт.
V>Так вы же сами рассматриваете контейнер как вариант реализации, если нужно выносить общую логику создания объектов либо делать разные управляемые времена жизни.
V>Вся разница в том, что Вы для этого не хотите использовать готовые обобщённые реализации.
Угу, т.к. все эти обобщённые реализации — по сути переливание из пустого в порожнее.
V>·>А какие другие возможные механизмы? Нужна коллекция объектов, граф типов зависимостей и т.п. Это и есть контейнер.
V>Как я писал уже в ответе ТС, простейший вариант -
Простейший вариант это new IndexPageController(new ProfileService(new ProfileRepository())). Даже класс и поля необязательны.
V>это тупо класс с полями, в которых либо сами реализации объектов, либо их factory functions.
Это как-то не очень подходит под общепринятое понятие IoC-контейнер.
V>·>А причём тут wiring/контейнер?! За такой говнокод в любой части проекта надо сильно по голове бить. И переписать хотя бы вот так (или какой там синтаксис switch expression?):
V>Это код просто для иллюстрации проблемы. Я сам прекрасно вижу его косяки.
И получилась яркая иллюстрация, внезапно. Ты показал типичный код который обычно логически соответствует типичной конфигурации контейнера и сразу бросилось в глаза — какой же кривой косячный код, и насколько же он хрупкий и где что может пойти не так. Так никто вменяемый писать не будет и реьвю такое уж точно не пройдёт.
А вот если это говно завернуть блестящей обёрткой IoC-фреймворка — так внезапно — конфеткой называть начинают.
V>Это упрощённый вариант для объяснения того, что где-то в создании объектов может быть ошибка, которую всё равно не отловит компилятор.
Именно. К этому я и клоню — такой код (wiring-код в том числе) никто в здравом уме не пишет и таких ошибок просто не будет.
V>>>По сути, точно такая же ошибка, как если бы забыли зарегистрировать объект в DI контейнере.
V>·>Такая ошибка может быть в любом коде. Wiring тут не при чём.
V>Именно это я и хотел продемонстрировать. Эта ошибка может быть и в wiring коде и в регистрации объектов в контейнере, поэтому с этой точки зрения без разницы, использовать контейнер или нет.
Как видишь — эта ошибка в wiring коде стала сразу явной и обнаруживаемой на раз, если не компилятором, то хоть статическим анализом. А если использовать контейнер — то просто навернётся на проде. Спасибо, что помог доказать мой тезис Почему ты не видишь эту разницу — неясно.
V>·>Так тут не надо никакой код по сути писать. Суть того, что делает контейнер, это оборачивает обычные конструкции ЯП new/if/switch в библиотечные классы.
V>·>Зачем тебе нужнен фреймворк, чтобы написать фабрику? Фабрика это просто _один_ метод, иногда даже просто лямбда.
V>Чтобы написать — не нужен. А чтобы хранить ссылку на эту фабрику для её использования из разных мест нужен либо библиотечный контейнер либо самописный.
Где хранить? Зачем? Фабрика это по сути например Func<HttpRequest, RequestContext> и собственно всё.
V>По сути контейнер есть ни что иное как глобальная переменная. Весь вопрос в её типизации и формате использования.
О. Спасибо, что напомнил. Знатный антипаттерн — глобальная переменная. А здесь даже публичная глобальная переменная свалка.
V>Если хотите её использовать в стиле "дай мне ссылку на текущюю реализацию базы данных" — тогда можно использовать просто свой класс. Плюс — наличие переменной проверяется компилятором, в простых случаях проверяется и её инициализация.
V>Если хотите её использовать в стиле "дай мне ссылку на реализацию интерфейса IБазаДанных" — тогда удобнее использовать словарь или библиотечный контейнер. Плюс — проще реализовать различные времена жизни.
Ты опять запутался. Это уже не DI, а печально известный Service Locator — ещё более знатный и злой антипаттерн. И вот это всё говно в комплекте с любым фреймворком. Закопать надо давно.
V>Если писать свою программу без всяких фреймворков, то это просто вопрос личных предпочтений.
V>Если в рамках готового фреймворка, который уже основан на DI, то разумно этот стиль и поддерживать.
wiring code — основан на DI тоже.