Здравствуйте, IT, Вы писали:
Doc>>Как видим, зависимость никуда не делась, ибо value1 и value2 откуда-то должны браться. IT>Это уже проблема вызывающего класса. У обсуждаемого класса зависимостей нет вообще.
Дай угадаю, с классом выше ты поступишь так же? Или ты пишешь библиотеки, состоящие из одного класса?
Кстати, а что делать будешь, если нужны будут методы _service, в который нужно передать аргументы (которые скрыты внутри самого класса)?
Re: своё vs. сторонее
От:
Аноним
Дата:
15.10.13 09:21
Оценка:
CEM>Сам я обычно стараюсь ничего стороннего не брать, потому что:
Здравствуйте, Doc, Вы писали:
IT>>Это уже проблема вызывающего класса. У обсуждаемого класса зависимостей нет вообще. Doc>Дай угадаю, с классом выше ты поступишь так же? Или ты пишешь библиотеки, состоящие из одного класса?
Дай и я угадаю, в твоей луковице десятки классов выше. Ты пишешшь библиотеки, состоящие из одного класса на одну строчку функциональности?
Doc>Кстати, а что делать будешь, если нужны будут методы _service, в который нужно передать аргументы (которые скрыты внутри самого класса)?
Зависит. Ты же не думаешь, что в качестве параметра можно передавать только примитивные типы. Вообще-то ещё существуют делегаты, интерфейсы (да, да, интерфейсы можно использовать не только для сервисов!) и просто классы с методами, у которых вполне могут быть параметры.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Дай и я угадаю, в твоей луковице десятки классов выше.
Не понял вопрос. Если про общее число классов, то да. Если про глубину вызовов, то нет.
IT>Ты пишешшь библиотеки, состоящие из одного класса на одну строчку функциональности?
Если надо по архитектуре приложения, то ничего страшного не вижу. Но только не "класс ради класса".
IT>Вообще-то ещё существуют делегаты, интерфейсы (да, да, интерфейсы можно использовать не только для сервисов!)
Ух ты, method injection ? Все же используешь DI? Но в примере ты все равно от зависимости не избавился. Да, перенес её в другой класс, но и там её надо как-то разруливать. Плюс, еще не известно кто должен знать про _service — исходный класс или вызывающий. Но это уже от логики приложения.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, artelk, Вы писали:
A>>Этот проект, все же, несколько отличается от того, с чем приходится сталкиваться в энтерпрайзе.
IT>По поводу энтерпрайза. Как раз если и использовать DI для тестирования, то в таких проектах как linq1db. В энтерпрайзах 90% логики — это работа с базами данных. А в самых запущенных случаях вся логика вообще находится в сохранённых процедурах, т.е. в самой базе данных. И если у кого-нибудь хватит мозгов использовать DI, чтобы мокать такую логику, то что, скажите вы собираетесь тестировать, умение C# генерировать вызовы методов? Так это уже давно было сделано в MS.
IT>А те оставшиеся 10% нетривиальной логики, которую действительно нужно гонять на самых разных данных и желательно без БД, совершенно спокойно можно задизайнить таким образом, что всё, что ей нужно будет передаваться по необходимости. И всё. DI не нужен.
Вся логика в БД это крайне редкий случай. Сейчас средне умение писать SQL на столько низко, что мнгие не понимают что современные РСУБД это не только key-value storage.
Но даже если большая часть логики в БД, то обработка запроса выглядит так:
Нужно понимать что все методы, не примитивные, из одной строчки. Каждый их них потенциально может лезть в БД, использовать параметры и другие "сервисы" приложения. Тут DI начинает очень сильно помогать. Кроме того, для улучшения unit-тестирования самого Method1 можно часть вызываемых функций тоже подсовывать через DI. Другая часть функций может быть вынесена вне методов обработки запросов и внезапно такой AoP тоже реализуется через DI.
В итоге DI помогает собирать приложения по кусочкам, концентрируясь при этом на самих кусочках, а не на сборке.
Конечно бывает так, что разбить логику на несвязанные кусочки нельзя, тогда попытка применения DI выглядит жалко.
Здравствуйте, IT, Вы писали:
IT>DI от лукавого. Мне тут в соседней ветке пытались объяснить что такого даёт DI, очень долго пытались, но так и не смогли.
На правах юмора и флуда.
Всякие манагеры при разработке проекта во главу угла ставят дальнейшую поддержку и обслуживание. Всякие ФП/Немерле не катят по той причине, что нельзя будет нанять студента на этот проект.
Так вот, DI и прочие умные штуки дают следующее ценное свойство: они позволяют безбедно жить программистам, щедро впихнувшем в свои проекты именно эти фичи. Потому как мой некоторый личный опыт показывает следующее: те проекты, которые сделаны без этих умных фич, давно уже поддерживаются студентами/джуниорами, и первоначальным разработчикам ничего с них не перепадает. А вот те, где есть что-то эдакое, студенты не могут осилить, поэтому для внедрения каждой новой фичи обращаются к профессиональным разработчикам.
Здравствуйте, Doc, Вы писали:
IT>>Дай и я угадаю, в твоей луковице десятки классов выше. Doc>Не понял вопрос. Если про общее число классов, то да. Если про глубину вызовов, то нет.
Ну а если нет, то в чём проблема?
IT>>Ты пишешшь библиотеки, состоящие из одного класса на одну строчку функциональности? Doc>Если надо по архитектуре приложения, то ничего страшного не вижу. Но только не "класс ради класса".
Я могу тебе ответить тоже самое на твой вопрос.
IT>>Вообще-то ещё существуют делегаты, интерфейсы (да, да, интерфейсы можно использовать не только для сервисов!)
Doc>Ух ты, method injection ? Все же используешь DI?
Вот! То о чём я и говорю. Больные люди! Им везде мерещится DI.
Doc>Но в примере ты все равно от зависимости не избавился. Да, перенес её в другой класс, но и там её надо как-то разруливать.
И что? Я убрал нежелательную зависимость? Убрал. Да ещё так убрал, как DI и не снилось. А твой DI — это переливание из пустого в порожнее. Из одного места убираем, в другое добавляем, в треьем размазываем жидким слоем.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, koodeer, Вы писали:
K>Так вот, DI и прочие умные штуки дают следующее ценное свойство: они позволяют безбедно жить программистам, щедро впихнувшем в свои проекты именно эти фичи. Потому как мой некоторый личный опыт показывает следующее: те проекты, которые сделаны без этих умных фич, давно уже поддерживаются студентами/джуниорами, и первоначальным разработчикам ничего с них не перепадает. А вот те, где есть что-то эдакое, студенты не могут осилить, поэтому для внедрения каждой новой фичи обращаются к профессиональным разработчикам.
Это назвается job security. Манагерам и студентам надо понять одну простую вещь. Наличие в проекте DI — это очень чёткий признак over-design приложения. В 9 из 10 приложений DI нафиг не нужен, в том числе и для тестирования. Просто те, кто им начинает увлекаться уже по другому задизайнить приложение не в состоянии. Жалко их, людей с искалеченной DI судьбой.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
G>Нужно понимать что все методы, не примитивные, из одной строчки. Каждый их них потенциально может лезть в БД, использовать параметры и другие "сервисы" приложения. Тут DI начинает очень сильно помогать.
Если очень захотеть, то DI можно впихнуть куда угодно. Это не проблема. Только в твоём примере такой необходимости нет ни в одном месте. Валидация — это часть логики, какой-то тут DI? Юзер проверяется атрибутами, как правило доступен в контексте или обрабатвается более сложными способами вроде фильтрации данных SQL запросами, что фактически является частью безнес логики. Кеширование тоже лучше всего делается атрибутами, ну или простейшим хелпером на худой конец.
G>Кроме того, для улучшения unit-тестирования самого Method1 можно часть вызываемых функций тоже подсовывать через DI. Другая часть функций может быть вынесена вне методов обработки запросов и внезапно такой AoP тоже реализуется через DI.
Я же говорю, запихать можно куда угодно. Только надо ли?
G>В итоге DI помогает собирать приложения по кусочкам, концентрируясь при этом на самих кусочках, а не на сборке.
В собранном по кусочкам приложении невозможно разобраться. Зачастую, что бы понять его логику нужно запускать его под отладчиком. В общем, я уже устал это повторять. DI — это сломанная навигация по коду и логика, размазанная жидким поносом по всему приложению. Как правило от таких приложений смердит за версту и всякими другими архитектурными излишествами.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Ну а если нет, то в чём проблема?
А проблем и нет.
Doc>>Ух ты, method injection ? Все же используешь DI? IT>Вот! То о чём я и говорю. Больные люди! Им везде мерещится DI.
Просто сами шаблоны DI это не супер какая магия, а передача зависимостей. Их всего три — constructor injection, property injection и method injection. И та "магия", что творится в контейнере при создании экземпляра, к ним отношения не имеет.
Doc>>Но в примере ты все равно от зависимости не избавился. Да, перенес её в другой класс, но и там её надо как-то разруливать.
IT>И что? Я убрал нежелательную зависимость? Убрал. Да ещё так убрал, как DI и не снилось.
Ты перенес её в другой класс приложения. Вот тут как раз получается как ты и сказал "из одного места убираем, в другое добавляем, в треьем размазываем жидким слоем". С IoC не пришлось бы вызывающим классам знакомиться с _service.
Здравствуйте, koodeer, Вы писали:
K>Так вот, DI и прочие умные штуки дают следующее ценное свойство: они позволяют безбедно жить программистам, щедро впихнувшем в свои проекты именно эти фичи.
Здравствуйте, Doc, Вы писали:
Doc>Ты перенес её в другой класс приложения.
Я её не переносил, она там, где и должна быть. Ты слишком однобоко понимаешь применение инструментов. DI — это не только ценный мех, цена которого, кстати, 0.5 по 10-ти бальной шкале. Это ещё и привнесённая в приложение сложность и эта сложность на порядок больше пользы.
Doc>Вот тут как раз получается как ты и сказал "из одного места убираем, в другое добавляем, в треьем размазываем жидким слоем".
Нет, жидким слоем, это не про зависимости, это про логику. Вот смотришь на такие погрызенные DI-ем методы и думашеь, что же они делают? За деревьями леса не видно. Одни, мля, какие-то левые сервисы дёргаются.
Doc>С IoC не пришлось бы вызывающим классам знакомиться с _service.
В случае с DI с ними вообще трудно познакомиться. Даже разработчику. Захочешь, хрен найдёшь.
... << RSDN@Home 1.2.0 alpha 5 rev. 69>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Я её не переносил, она там, где и должна быть.
Лукавишь. Если изначально сервис должен был быть в вызывающих классах, то это был не пример "замены DI", а пример "исправления архитектуры".
Ты слишком однобоко понимаешь применение инструментов. DI — это не только ценный мех, цена которого, кстати, 0.5 по 10-ти бальной шкале. Это ещё и привнесённая в приложение сложность и эта сложность на порядок больше пользы.
IT>Нет, жидким слоем, это не про зависимости, это про логику. Вот смотришь на такие погрызенные DI-ем методы и думашеь, что же они делают? За деревьями леса не видно. Одни, мля, какие-то левые сервисы дёргаются.
Я так понимаю, это про то, что по F12 в сорцы не перейти (без всяких плагинов для VS)? При изучении кода конкретного метода то, что делает вызов (что должен делать) должно быть ясно из его названия и/или комментария и окружающего кода. А то, что реализующий это класс делает это корректно — из unit test-ов. Ты же не перечитываешь код System.String при каждой операции со строкой?
Хотя если методы сервиса называется DoAction1() итп то такой разработчик сам себе злобный буратино.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Dziman, Вы писали:
D>>Можно пример проблемы именно из-за DI?
IT>Я уже устал об этом говорить. DI ломает навигацию по проекту, что существенно затрудняет читабельность и понимабильность кода приложения. Бизнес логика разбивается на части и разносится по разным частям приложения. Это затрудняет модификацию приложения.
IT>А всегда ли это нужно?
Если DI нужно только для тестов, в С# например можно в качестве интерфейса использовать сами классы. Если нужно их мокнуть, то соответствующие методы делаются виртуальными.
IT>void MyVeryPrimitiveMethod()
IT>{
IT> var value1 = _service1.GetValue1();
IT> var value2 = _service2.GetValue2();
IT> var result = value1 * value2;
IT> _service3.SetResult(result);
IT>}
IT>
IT>И это всё вместо: IT>Как по-твоему где больше зависимостей?
Одинаково. Ваш код в полном виде выглядит как-то так:
{
///// far far awayvar value1 = _service1.GetValue1();
var value2 = _service2.GetValue2();
var result = MyVeryPrimitiveMethod(value1 * value2);
_service3.SetResult(result);
////
}
int MyVeryPrimitiveMethod(int value1, int value2)
{
return value1 * value2;
}
Хотя как по мне, что
_serviceInterfaceFromDI.GetValue1();
что
_concreteClass.GetValue1();
тоже в 99.9% случаях дают одинаковую зависимость, потому что в этих 99.9% в данном месте всегда будет одна и та же и совершенно конкретная имплементация.
Всё тлен, всё тщета.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>Нужно понимать что все методы, не примитивные, из одной строчки. Каждый их них потенциально может лезть в БД, использовать параметры и другие "сервисы" приложения. Тут DI начинает очень сильно помогать.
IT>Если очень захотеть, то DI можно впихнуть куда угодно. Это не проблема.
Необходимости в DI вообще никогда нет. Любой код может быть написан без DI. Но альтернатива в виде ball-of-mud архитектуры зачастую хуже, чем DI на каждый чих. Можно конечно писать слабосвязный код и без DI, но там мало кто умеет.
IT>Только в твоём примере такой необходимости нет ни в одном месте. Валидация — это часть логики, какой-то тут DI? Юзер проверяется атрибутами, как правило доступен в контексте или обрабатвается более сложными способами вроде фильтрации данных SQL запросами, что фактически является частью безнес логики.
Я же писал что весь AoP из атрибутов чаще всего реализуется средствами DI. Так что странно что ты предлагаешь использовать то, что сам в предыдущем предложении отвергаешь.
IT>Кеширование тоже лучше всего делается атрибутами, ну или простейшим хелпером на худой конец.
Ну вот хелпер у тебя зависит от ASP.NET, а метод — не зависит. Но если у тебя нет DI, то unit-тестами сложно будет покрыть метод.
G>>Кроме того, для улучшения unit-тестирования самого Method1 можно часть вызываемых функций тоже подсовывать через DI. Другая часть функций может быть вынесена вне методов обработки запросов и внезапно такой AoP тоже реализуется через DI. IT>Я же говорю, запихать можно куда угодно. Только надо ли?
Я видел фрейморки, которые использовали эти сам атрибуты без DI, это был ад. Так что я в этом случае за DI.
G>>В итоге DI помогает собирать приложения по кусочкам, концентрируясь при этом на самих кусочках, а не на сборке. IT>В собранном по кусочкам приложении невозможно разобраться. Зачастую, что бы понять его логику нужно запускать его под отладчиком. В общем, я уже устал это повторять. DI — это сломанная навигация по коду и логика, размазанная жидким поносом по всему приложению.
Если у тебя есть решарпер, то не проблема. Я уже и без решарпера научился разбирать сильно DI код.
IT>Как правило от таких приложений смердит за версту и всякими другими архитектурными излишествами.
Я такого и без DI видел много раз.
Здравствуйте, Doc, Вы писали:
IT>>Я её не переносил, она там, где и должна быть. Doc>Лукавишь. Если изначально сервис должен был быть в вызывающих классах, то это был не пример "замены DI", а пример "исправления архитектуры".
Я же говорю, люди с искалеченной DI-ем судьбой, по другому думать уже не могут. Кто тебе вообще сказал, что сервис должен быть изначально?
Doc>Я так понимаю, это про то, что по F12 в сорцы не перейти (без всяких плагинов для VS)? При изучении кода конкретного метода то, что делает вызов (что должен делать) должно быть ясно из его названия и/или комментария и окружающего кода. А то, что реализующий это класс делает это корректно — из unit test-ов. Ты же не перечитываешь код System.String при каждой операции со строкой?
Не надо путать божий дар с яичницей. Или тебе ообъяснить разницу между System.String и GetcustomerByID? Какие требования предъявляются при разработке к одному методу, а какие к другому.
Doc>Хотя если методы сервиса называется DoAction1() итп то такой разработчик сам себе злобный буратино.
Считать себя умнее других также плохо как и считать других глупее себя. Так что давай обойдёмся без абстрактных индусов.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
IT>>Если очень захотеть, то DI можно впихнуть куда угодно. Это не проблема. G>Необходимости в DI вообще никогда нет. Любой код может быть написан без DI. Но альтернатива в виде ball-of-mud архитектуры зачастую хуже, чем DI на каждый чих. Можно конечно писать слабосвязный код и без DI, но там мало кто умеет.
А кто сказал, что DI — это слабосвязный код? DI устраняет только один тип зависимости — зависимость от реализаций, но при этом добавляет новые сущности в систему и добавляет кучу зависимостей между системой и этими сущностями. И не известно ещё что хуже с точки зрения той же теории систем, которая утверждает, что общая сложность системы зависит прежде всего от количества связей между частями системы. В случае с DI у нас и частей стало больше и зависимостей между ними.
G>Если у тебя есть решарпер, то не проблема. Я уже и без решарпера научился разбирать сильно DI код.
Это не более чем умение ходить на ходулях по граблям. Зачем мне это, если без этого можно обойтись?
IT>>Как правило от таких приложений смердит за версту и всякими другими архитектурными излишествами. G>Я такого и без DI видел много раз.
Зато такого как с DI я не видел нигде.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Кто тебе вообще сказал, что сервис должен быть изначально?
Ага, т.е. сервис в том примере вообще лишний? Если так — то это тем более пример исправления кривой архитектуры, а не изгнания IoC
IT>Не надо путать божий дар с яичницей. Или тебе ообъяснить разницу между System.String и GetcustomerByID?
Если GetcustomerByID проходит unit test — мне без разницы что внутри, до того момента, как будут основания это проверить.
IT>Считать себя умнее других также плохо как и считать других глупее себя. Так что давай обойдёмся без абстрактных индусов.