
- •Основи програмної інженерії Тема 1. Поняття програмної інженерії. Вступ
- •Процес створення програмного забезпечення
- •Моделі технологічного процесу створення пз
- •Моделі процесу розробки по
- •Характеристики якісного пз
- •Тема 2. Види моделей систем. Поняття і класифікація вимог до програмної системи.
- •Способи запису специфікацій вимог.
- •Види моделей систем.
- •Мова моделювання uml.
- •Об'єктні моделі
- •Інструментальні case-засоби.
- •Тема 3. Поняття архітектурного проектування. Архітектурні моделі.
- •Архітектурний шаблон mvc.
- •Особливості шаблону mvc.
- •Модель проблемної сфери.
- •Тема 4. Важливі функціональні засоби мови c#. Автоматично реалізовані властивості.
- •Ініціалізатори об'єктів та колекцій.
- •Автоматичне виведення типу.
- •Анонімні типи.
- •Використання методів розширення Методи розширення
- •Застосування методів розширення до інтерфейсу
- •Створення фільтруючих методів розширення
- •Тема 5. Лямбда-вирази. Мова linq. Лямбда-вирази.
- •Мова linq.
- •Методи розширення linq.
- •Відкладені запити linq.
- •Тема 6. Створення слабо зв'язаних компонентів. Впровадження залежності.
- •Контейнери впровадження залежності.
- •Бібліотека Ninject.
- •Порядок роботи з Ninject.
- •Тема 7. Засоби доступу до даних. Технологія ado.Net.
- •Реалізація доступу до даних.
- •Робота з даними.
- •Тема 8. Тестування пз. Розробка через тестування. Автоматизоване тестування пз та його види.
- •Розробка через тестування. Робочий потік "червоний-зелений-рефакторинг".
- •Модель "організація.Дія.Твердження".
- •Використання бібліотеки Moq
- •Тема 9. Проектування інтерфейсу користувача. Інтерфейс користувача.
- •Переваги графічного інтерфейсу.
- •Процес проектування графічного інтерфейсу.
- •Принципи проектування інтерфейсів користувача.
- •Шаблони.
- •Тема 10. Основи інженерії вимог. Розробка вимог.
- •Формування і аналіз вимог.
- •Опорні точки зору.
- •Сценарії.
- •Атестація вимог.
- •Тема 11. Прототипування програмних систем. Поняття прототипування.
- •Переваги прототипування.
- •Види прототипування.
- •Технології швидкого прототипування.
- •Тема 12. Покомпонентна розробка. Компоненти і класи об'єктів.
- •Компоненти як постачальники послуг.
- •Рівні абстракції компонентів.
- •Вимоги до компонентів.
- •Тема 13. Шаблони проектування. Структурні шаблони.
- •Поняття шаблону проектування.
- •Основні елементи шаблону.
- •Механізми повторного використання.
- •Структурні шаблони проектування.
Тема 6. Створення слабо зв'язаних компонентів. Впровадження залежності.
Як вже було сказано, одна з найбільш важливих особливостей моделі MVC полягає в тому, що вона робить можливим поділ відповідальності. Нам потрібно, щоб компоненти в нашому додатку були максимально незалежними один від одного і мали лише таку кількість взаємозалежностей, яким ми зможемо управляти.
У ідеалі кожен компонент нічого НЕ знає про будь-якому іншому компоненті І взаємодіє з іншими областями програми лише за допомогою абстрактних інтерфейсів. Така взаємозалежність називається слабким зв'язком, і вона спрощує тестування і модифікування застосування.
Простий приклад допоможе розумінню цього підходу. Якби ми створювали компонент MyEmailSender, призначений для відправки повідомлень електронної пошти, ми б реалізували інтерфейс, що визначає всі загальнодоступні функції, необхідні для відправки електронної пошти, який можна було б назвати IEmailSender.
Тоді будь-який інший компонент нашого застосування, якому потрібно надіслати повідомлення електронної пошти – наприклад, допоміжний метод скидання пароля PasswordResetHelper – може відправити повідомлення, звертаючись тільки до методів, певним всередині інтерфейсу. Як видно з рисунку 1, ніякої прямої залежності між PasswordResetHelper і MyEmailSender не існує.
Рис. 1 - Використання інтерфейсів для роз'єднання компонентів
Вводячи інтерфейс IEmailSender, ми гарантуємо відсутність будь-якої прямої залежності між PasswordResetHelper і MyEmailSender. Компонент MyEmailSender можна було б замінити іншим постачальником електронної пошти або навіть виконувати фіктивну реалізацію з метою тестування.
На замітку! Не всі відношення обов'язково розривати за допомогою інтерфейсу. У дійсності рішення залежить від ступеня складності застосування, виду необхідного тестування і і простому додатку ASP.NET MVC можна було б відмовитися від розриву зв'язку між контролерами і моделлю предметної області .
Інтерфейси допомагають роз'єднати компоненти, але ми як і раніше стикаємося з проблемою – C# не надає вбудованого способу простого створення об'єктів, які реалізують інтерфейси. Єдине, що ми можемо зробити – це створити екземпляр конкретного компонента. У результаті ми отримуємо код, наведений у лістингу 1.
Лістинг 1. Створення примірників конкретних класів для отримання реалізації інтерфейсу
public class PasswordResetHelper {
public void ResetFasswordO {
IEmailSender mySender = new MyEmailSender () ;
// ... call interface methods to configure e-mail details.
mySender . SendEmail ();
}
}
Ми знаходимося лише на середині шляху до створення слабко зв'язаних компонентів. Клас PasswordResetHelper конфігурує і відправляє повідомлення електронної пошти за допомогою інтерфейсу IEmailSender, але щоб створити об’єкт, який реалізує цей інтерфейс, йому потрібно створити екземпляр MyEmailSender.
Ми посилили ситуацію. Тепер PasswordResetHelper залежить і від IEmailSender, і від MyEmailSender. як показано на рисунку 2.
Рис. 2 - У кінцевому рахунку , компоненти виявляються тісно пов'язаними
Нам потрібно спосіб отримання об'єктів, які реалізують даний інтерфейс без необхідності безпосереднього створення реалізує об'єкта. Вирішення цієї проблеми називають впровадженням залежності (dependency injection - DI) або оберненням (інверсією) управління (inversion of control - IoC).
DI – це модель розробки, яка доповнює слабкий зв'язок, який ми почали створювати з додавання інтерфейсу IEmailSender у наш простий приклад. Вона є центральною концепцією для ефективної розробки додатків MVC.
Модель DI складається з двох частин. Для початку зі свого компонента – у даному випадку PasswordResetHelper – ми видаляємо будь-які залежності від конкретних класів. Це виконується за рахунок передачі реалізації необхідних інтерфейсів конструктору класу, як показано в лістингу 2.
Лістинг 2. Видалення залежностей із класу PasswordResetHelper
public class PasswordResetHelper
{
private IEmailSender emailSender;
public PasswordResetHelper (IEmailSender emailSenderParam)
{
emailSender = emailSenderParam;
}
public void ResetPasswordO
{
emailSender.SendEmail () ;
}
}
Ми розірвали залежність між PasswordResetHelper і MyEmailSender.
Конструктор PasswordResetHelper вимагає об'єкт, який реалізує інтерфейс IEmailSender, але не знає і не турбується про те, що собою являє цей об'єкт, і більше не відповідає за його створення.
Залежності впроваджуються в PasswordResetHelper під час виконання. Тобто примірник якогось класу, який реалізує інтерфейс IEmailSender, буде створений і переданий конструктору PasswordResetHelper під час створення екземпляра. Більше не існує ніякої залежності часу компіляції між PasswordResetHelper і будь-яким класом, які реалізують інтерфейси, від яких він залежить.
Підхід, за якого залежності класу впроваджуються за допомогою його конструктора називають впровадженням за допомогою конструктора.
Підхід, за якого залежності класу впроваджуються за допомогою загальнодоступної властивості називають впровадженням за допомогою установника .
Оскільки з залежностями доводиться мати справу під час виконання, то під час запуску програми можна вирішити, які реалізації інтерфейсів повинні використовуватися. Можна вибирати між різними постачальниками електронної пошти або впровадити фіктивну реалізацію для тестування. Ми домоглися відносин залежності, до яких прагнули.