No video

Примеры C#. DataGenerator. Dependency Injection

  Рет қаралды 27,416

Программирование - это просто

Программирование - это просто

Күн бұрын

Создаем новые интерфейсы, разбираемся с зависимостями между классами, применяем паттерн Dependency Injection.
Тема на CyberForum www.cyberforum....
Поддержи развитие канала! money.yandex.r...
Qiwi Wallet +79534684569
Группа ВКонтакте: easycomp

Пікірлер: 29
@Yarkendar
@Yarkendar 8 жыл бұрын
Спасибо, это лучший урок по внедрению зависимостей. Было бы очень удобно видеть урок в виде статьи :)
@NatuNuarat
@NatuNuarat 8 жыл бұрын
Сегодня на работе искала информацию по dependency injection и случайно набрела на Вашу статью на хабре. Узнала автора по аватарке XD Это было так приятно, как будто встретила старого знакомого! Спасибо за Ваши уроки! Они помогли мне освоить азы чтобы стать сейчас стажером-программистом =)
@vitalygaponenko4184
@vitalygaponenko4184 6 жыл бұрын
Самое лучшее объяснение из тех, что мне удалось посмотреть. Все понятно. Спасибо! Все отлично.
@AlexS-gn9tq
@AlexS-gn9tq 6 жыл бұрын
ВАУ!!!Спасибо огромное. Это настолько простое и наглядное объяснение! Я перечитал кучу разных статей но никак не мог въехать что это такое и зачем надо, а здесь всё так просто! Супер! Спасибо!
@user-du2fo9tn4p
@user-du2fo9tn4p 2 жыл бұрын
Спасибо, лучшее объяснение!
@Milording
@Milording 8 жыл бұрын
Очень круто. Жду продолжения и надеюсь, будут темы с IoC и IoC-контейнерами, а то пока это все в голове слабо связывается с DI
@sergepikovsky3385
@sergepikovsky3385 8 жыл бұрын
30. Самое время подумать о классе который будет предоставлять данные. 1-ин класс - 1-а задача! ScriptGenerator - создает скрипт. Но он должен получать откуда то данные к этому скрипту. Для этого мы создали библиотеку TestDataGenerator.Data. В ней мы и разместим класс, предоставляющий данные нашему потребителю. Принято классы, которые работают с данными называть репозитариями. Но так как мы на стадии проектирования, то начинаем не с класса, а с интерфейса. Добавляем в библиотеку интерфейс IRepository.cs и делаем интерфейс открытым (public). 31. Возвращаемся к файлам, входящим в наше приложение. Они и являются опосредованным источником данных. Почему опосредованным? Из файла EnglishWord.txt мы не напрямую берем слова, а убираем номер строк, транскрипцию, толкование, а берем лишь вычлененное слово (слова). В какой то степени обработка коснется и остальных файлов. Т.е. наш класс-репозитарий длолжен обратится к этим файлам и предоставить потребителю информацию из них в удобном для потребителя формате. 32. Перечень этих данных четко виден в примере конечного скрипта. Помним, что почта = уникальный(!) логин + случайный ящик (ящик не запрашивается у файлов). Т.е. мы запрашиваем всего 4 сущности у репозитария - Имя, Отчество, Фамилию и логин. Все остальное - генерируем. Формируем методы для получения случайных данных из репозитария GetRandom...(); для всех 4-ех сущностей. Таким образом генератор скрипта будет абстрагирован от способа получения данных. 33. GetRandomUniqLogin() имеет одну тонкость: как определять границы сессии в течении которой формируются уникальные логины? Принимаем, что логины уникальны в течении генерации одного скрипта. Далее механизм учета уникальности сбрасывается и другой скрипт может однажды принять логин, который использовался, скажем, предыдущим скриптом. Для отработки этого механизма вводим метод инициализации репозитария void Init(); 34. Ну что? Пишем unit-test-ы на репозитарий? Нет!!! Unit-test покрывает не весь код. Даже вредно покрывать весь код! Юнит тестами покрывается основная часть кода - "Слой Бизнесс-Логики", т.е. библеотека .BL . Остальные слои не покрываем тестами исходя из идеологии unit-test-ирования. Unit-test-ами покрываются только независимые методы, которые ни к чему не привязаны. "Слой Призентации" привязана либо к файловой системе (наш случай), либо к UI, либо к приему пользовательских запросов, т.е. привязан к "Внешней Среде", которую мы не можем контролировать в unit-test-ах. Нижний слой - "Слой Доступа к данным" тоже зависит, но уже от "Источника[Хранилище] Данных" (папка Files). Это может быть и БД и т.д. Именно по этому интерфейс IRepository останется не покрытым unit-test-ированием. 35. Теперь подходим к реализации. Создаем открытый класс Repositary. 36. Наследоваться этот класс должен от IRepositary. Resharper на автомате реализует все поведение с реализацией throw new NotImplementedException(); Это очень хорошое исключение. Всегда стоит применять это исключение у нереализованых методов. Ни каких null - это приведет к серьезным ошибкам! Итак, все методы исполняют throw new NotImplementedException(); На данном этапе нас такая реализация устраивает. 37. Возвращаемся к интерфейсу IScriptGenerator и для него делаем все тоже самое, что и на предыдущих двух шагах для IRepositary. Т.е. создаем наследуемый от IScriptGenerator класс ScriptGenerator и просим Resharper сгенерировать все интерфейсные методы с заглушкой - throw new NotImplementedException(); 38. Псевдореализация интерфейсных методов (а других и нет) класса ScriptGenerator готова. Теперь в тестах мы можем заглушку объектов из null преобразовать в реальные объекты: public void Init() public void Init() { { _generator = null; -> _generator = new ScriptGenerator(); } } 39. Запускаем тестирование и убеждаемся в том, что все тесты упадут (что хорошо). 40. Возвращаемся в ScriptGenerator и приступаем к реализации: - public UserEntity GenerateUser() Код тривиальный, вся логика метода в этой сроке: entity.Email = string.Format("{0}@{1}", entity.Login, randomEmailDomain); 41. Пробуем запустить тесты и получаем сообщение о не реализации репозитария. Здесь есть тонкий момент, который важно понимать: - мы тестируем не класс репозитария, - мы тестируем ScriptGenerator, т.е. логику. - нам совершенно не важно как себя ведет класс репозитария. Но как мы можем абстрогироваться от класса репозитария если мы в нашем методе постоянно к нему обращаемся??? В 99% случаев методы одного класса будут зависеть от методов другого класса, но идеология unit-tseting заключается в том, что тестируется только код одного метода. Без зависимости от другого (третьего) метода. В этом случае разработчики прибегают к приему, которая называемся иньекция зависимости (Dependency Injection). В чем он заключается (практически)? Возвращаемся в метод GenerateUser(), конкретно его первую строку: IRepository repository = new Repositary(); - это очень "нехорошая" строка кода, т.к. она гвоздями прибивает наш метод к классу репозитария, в частности к его реализации {new Repository}. Если мы захотим заменить, то мы будем должны найти в классе ScriptGenerator все методы, в которых используется репозитарий и там его заменить на какую-то другую переменную. Это очень не удобно! 42. В таких то случаях и делают инъекцию зависимостей, которая к тому же явно показывает от каких именно классов зависит наш класс. Инъекция может быть проброшена в класс многими способами, но мы рассмотрим самый очевидный - Инъекцию Через Конструктор: a) Создаем закрытое поле для чтения типа IRepositary - private readonly IRepository _repository; б) Создаем конструктор нашего класса в котором инициируем созданое поле передаваемым в конструктор параметром. в) Заменяем все ссылки на репозитарий на ссылку на вновь созданное поле. г) Коментируем (убираем) строку создания старого экземпляра репозитария. 43. Что мы получили? Наш класс полностью избавился от зависимости от репозитария. Он по прежнему обращается к объекту репозитария, но теперь зависимость от объекта репозитария поступает от конструктора класса. Т.е управление этими зависимостями возлагается на иной класс. А именно на управляющий класс по отношению к ScriptGenerator (инстанцирующий ScriptGenerator). Для изменения зависимости ему хватит поменять параметр в конструкторе. А поскольку в качестве типа параметра мы указываем не конкретный класс, а интерфейс, то мы можем сюда подставить любой класс который реализует интерфейс параметра конструктора. А таких классов может быть уже достаточно много. Теперь можно переходить к тестовому классу!
@_kul879
@_kul879 2 жыл бұрын
Ве-ли-ко-ле-п-но! Хочу также про интеграционны тесты!
@user-nc7zt9rj9e
@user-nc7zt9rj9e 2 жыл бұрын
Очень хороший урок👍 Сегодня провалился на Внедрении зависимостей на собеседовании. А теперь смотрю оказывается я им пользовался довольно таки часто не зная ему названия😄. Только опять таки что то не оговаривается. Или я не понимаю. Зачем нам поменять класс Repository если другой класс тоже все равно обязан реализовать тот же интерфейс и те же методы? И следовательно зачем депенденси инжекшн в таком случае?
@BoxaShu
@BoxaShu 8 жыл бұрын
Спасибо. жду продолжения.
@anatoliymedinets241
@anatoliymedinets241 6 жыл бұрын
Однозначно лайк!
@jestemzbiaorusi8379
@jestemzbiaorusi8379 4 жыл бұрын
Мне кажется до меня дошло... :)
@NikitaReznikow
@NikitaReznikow 8 жыл бұрын
Спасибо за уроки, давно хотел учить тесты, сильно помогли! Такой ворос: у меня Password_Required проходит, я так понимаю что это связано с тем что, проверяет на Empty а не на Null, ибо когда меняю проверку на null тест не проходит, хотя полностью повторил ваш код?
@WorldCount
@WorldCount 8 жыл бұрын
Вот и я это заметил. Причем если в Mock изменить возвращаемое значение для имени на null, то начинает проходить тест и для имени. Походу везде надо проверять именно на null.
@WorldCount
@WorldCount 8 жыл бұрын
Вообще не пойму, в коде у автора везде на Empty проверка и у него не проходит.
@sanyasa2092
@sanyasa2092 8 жыл бұрын
Неплохо бы уроки для Windows (UWP) . Мне например уже заказывают для девайсов на разбери.
@Milording
@Milording 8 жыл бұрын
+sanya sa я попробую сделать уроки, Игорь посмотрит. Если подойдут, то ожидайте! :)
@svLimones
@svLimones 8 жыл бұрын
А будет ли показаны другие типы тестов? Авто-тесты, функциональные тесты?
@Defazze
@Defazze 8 жыл бұрын
+Arthur “svLimones” Ishmatov В рамках этого курса - скорее всего нет
@sergepikovsky3385
@sergepikovsky3385 8 жыл бұрын
Прошу прощения если сделал не правильно, просто конспект всегда пишу, чтобы помнил не только мозг, но и 10 пальцев, да и вспоминать легче... может пригодиться кому.
@dimabogdan1380
@dimabogdan1380 8 жыл бұрын
+Serge Pikovsky так же делаю, отлично помогает, только конспектировать правильно нужно)
@sergepikovsky3385
@sergepikovsky3385 8 жыл бұрын
+Dima Bogdan Интересно, что по вашему правильно? У меня особых правил нет. Ну, не совсем как акын, конечно, пишу, что слышу... стараюсь придать какую то структуру записям и если решил писать не выборочно, то стараюсь не пропускать смысловых блоков лекции/урока. Есть правила Димы Богдана? :-)
@sergepikovsky3385
@sergepikovsky3385 8 жыл бұрын
+Dima Bogdan А, еще... когда я здесь написал "правильно", я имел ввиду без разрешения читающего лекцию.
@denyszorin8675
@denyszorin8675 8 жыл бұрын
Здравствуйте, у меня есть вопрос Как правильно нужно приплюсовывать стринги ?? на собеседовании мне сказали что вот так делать нежелательно - "some string" + " new string"
@Defazze
@Defazze 8 жыл бұрын
+Денис Зорин через string.format или (в C# 6) через интерполяцию строк
@denyszorin8675
@denyszorin8675 8 жыл бұрын
+Программирование - это просто , нашел ответ на свой вопрос в вашем следующем уроке. Как вариант еще это при помощи стринг билдера ) спасибо за ответ )
@qwertyq2570
@qwertyq2570 8 жыл бұрын
+Денис Зорин Странно, что в этом такого ? Надо им Рихтера дать почитать. ) "Чтобы объединить несколько строк в одну строку, используйте оператор + языка C#: String s = "Hi" + " " + "there."; // Конкатенация трех литеральных строк образует одну литеральную строку Поскольку все строки в этом коде литеральные, компилятор выполняет их конкатенацию на этапе компиляции, в результате в метаданных модуля оказывается лишь строка "Hi there.". Конкатенация нелитеральных строк с помощью оператора + происходит на этапе выполнения. Для конкатенации нескольких строк на этапе выполнения оператор + применять нежелательно, так как он создает в куче несколько строковых объектов. Вместо него рекомендуется использовать тип System.Text.StringBuilder"
@arturbo3134
@arturbo3134 Жыл бұрын
репазитАрии :D
Уроки WPF. Таблицы и списки
15:45
Программирование - это просто
Рет қаралды 50 М.
What will he say ? 😱 #smarthome #cleaning #homecleaning #gadgets
01:00
王子原来是假正经#艾莎
00:39
在逃的公主
Рет қаралды 14 МЛН
ISSEI & yellow girl 💛
00:33
ISSEI / いっせい
Рет қаралды 25 МЛН
这三姐弟太会藏了!#小丑#天使#路飞#家庭#搞笑
00:24
家庭搞笑日记
Рет қаралды 87 МЛН
Примеры C#. DataGenerator. Тесты и рефакторинг
22:09
Программирование - это просто
Рет қаралды 12 М.
Dependency Injection | Внедрение зависимостей в C# и ASP.NET Core
50:38
Путь к Dependency Injection
52:48
Valery Leontyev
Рет қаралды 17 М.
Dependency Injection, The Best Pattern
13:16
CodeAesthetic
Рет қаралды 802 М.
Dependency Injection in .NET Core (.NET 6)
1:00:32
IAmTimCorey
Рет қаралды 188 М.
Dependency Injection простыми словами
18:17
devschacht
Рет қаралды 85 М.
What will he say ? 😱 #smarthome #cleaning #homecleaning #gadgets
01:00