Upload
nikita-filippov
View
2.375
Download
2
Embed Size (px)
DESCRIPTION
http://agiledays.ru
Citation preview
DDD + TDD + MVP + GoF + PoEAA= Love!
Евгений СорокинАнтон Бевзюк
9 декабря 2009
IT.intel.com
Содержание
1. Intro2. DDD3. MVP/MVVM4. TDD5. DSL6. GoF/PoEAA…Profit!
IT.intel.com
Intro
IT.intel.com
Кто мы такие?
• Программируем• Руководимразработкой
• Обучаемстудентовсотрудников
IT.intel.com
Портфолио отдела
•Бизнес-приложения•7 лет в Agile•20 человек
–.NET–SAP–Business Intelligence
IT.intel.com
Самый большой agile-проект
32 проекта140 000 строк кода5000+ юнит тестов
IT.intel.com
DDDDomain-Driven Design
IT.intel.com
Почему DDD
Сложный бизнес процесс
IT.intel.com
DDD
•Общий язык•Выделенный домен
IT.intel.com
Стандартный DDD
UI
Application
Domain
Infrastructure
IT.intel.com
Зависит от технологии Не зависит от технологии
Presentation
Domain
UI
Infrastructure
Application
IT.intel.com
Дизайн
КлиентСервер
UI
Application Presentation
Infrastructure
WebService
Application
Infrastructure
Domain
DB
IT.intel.com
Что дает DDD
• «Чистый» домен• Инкапсуляция доменной логики• И еще кое-что...
IT.intel.com
IT.intel.com
MVP /MVVM
Model-View-Presenter / Model-View-ViewModel
IT.intel.com
Тестирование GUI
•GUI есть везде•Важная часть приложения
IT.intel.com
Методы тестирования GUI
•Ручное•Автоматическое –LoadRunner–TestComplete
•Юнит-тестирование
IT.intel.com
Passive View
View
Presenter
Model
IT.intel.com
Пример
IT.intel.com
IManagerView
public interface IManagerView { List<Manager> Managers { set; } Manager SelectedManager { get; set; } List<Employee> Employees { set; } Notification Add { set; } Notification Edit { set; } Notification Delete { set; } Notification Save { set; }}
IT.intel.com
ManagerPresenterTests
[TestMethod]public void CanAddEmployee() {var view = new ManagerViewFake();
var presenter = new ManagerPresenter(view); var manager = Persist.Manager(); view.SelectedManager = manager; view.Add();
Assert.AreEqual(1, view.Employees.Count);}
IT.intel.com
ManagerPresenterprivate void IManagerView view;…public void OnAdd() { SelectedManager.Employees.Add(new Employee());
Rebind();}…private void Rebind() { view.Managers = Managers; view.SelectedManager = SelectedManager; view.Employees = SelectedManager.Employees;}
IT.intel.com
ManagerView
public class ManagerView : IManagerView { public List<Employee> Employees { set { employeesListView.DataSource =
value; } } … public Notification Add { get; set; } … private void addButton_click(…) { Add(); }}
IT.intel.com
Model-View-ViewModel
View
ViewModel
Model
Binding
IT.intel.com
ManagerViewModelTests
[TestMethod]public void AddEmployee() {var viewModel = new ManagerViewModel();
var manager = Create.Manager(); viewModel.Managers = new [] {manager}; viewModel.SelectedManager = manager; viewModel.Add();
Assert.AreEqual(1,viewModel.Employees.Count);
}
IT.intel.com
ManagerViewModel
public class ManagerViewModel { List<Manager> Managers { get; private set; } Manager SelectedManager { get; set; } List<Employee> Employees { get { return SeelctedManager.Employees; } }… Notification Add { get; private set; }… private void OnAdd() { SelectedManager.Employees.Add(new Employee()); }}
IT.intel.com
ManagerView
IT.intel.com
Что дает MVP/MVVM
• Тестирование Presentation
IT.intel.com
TDDTest-Driven Development
IT.intel.com
Мифы о TDD
• Юнит тесты == TDD• TDD == объем работы * 2• TDD == 100% тестовое
покрытие• TDD == серебряная пуля
IT.intel.com
RED/GREEN/REFACTOR
Подумай.Напиши тест
Начало
Скомпилируй
Напиши код
Запусти все тесты и убедись, что они прошли
Исправь ошибки
Запусти все тесты и убедись, что они упали
Рефакторинг
5 мин
IT.intel.com
Тестируем все
•Код•Конфигурацию•Хранимые процедуры•GUI binding
IT.intel.com
Тестируем код[TestMethod]public void CanConvertMoney() {var service = new ExchangeRatesServiceFake()
.UsdCosts(1, "USD")
.UsdCosts(29M, "RUR");
var money = new Money(5, "RUR");
Assert.AreEqual(new Money(5/29M, "USD"), money.Convert("USD", service));
}
IT.intel.com
Тестируем конфигурацию
IT.intel.com
Тестируем конфигурацию
[TestMethod]public void CorrectConnectionString() {var dataContext = new DataContext();
StringAssert.Contains( “Correct connection string”, dataContext.Connection.ConnectionString,
“Please change connection string in DataContext to ConnectionString.");
}
IT.intel.com
Тестируем хранимые процедуры[TestMethod]public void GetYearSales() {DataContextUtils.Insert(new order { order_date = "2009-01-01", order_items = {
new order_item {amount = 5, price = 10.00M},new order_item {amount = 2, price = 20.00M},
});
var sales = DataContext.pr_get_year_sales(2009).Single();
Assert.AreEqual(7, sales.total_amount);Assert.AreEqual(5*10M + 2*20M, sales.total_sum);
}
IT.intel.com
Тестируем GUI binding
IT.intel.com
Тестируем GUI bindingpublic void EmployeeViewBindingsAreOk() {
var expected = new[] {new BindingData("managers", "DataMember", "Managers", typeof
(EmployeeViewModel)),new BindingData(“managers", "SelectedItem", "SelectedManager",
typeof (EmployeeViewModel)),new BindingData("employees", "DataMember", "Employees", typeof
(EmployeeViewModel)),new BindingData("add", "Action", "CreateEmployee", typeof
(EmployeeViewModel)),new BindingData("edit", "Action", "EditEmployee", typeof
(EmployeeViewModel)),new BindingData("delete", "Action", "DeleteEmployee", typeof
(EmployeeViewModel)),new BindingData("save", "Action", "Save", typeof
(EmployeeViewModel)),};
var view = new EmployeeView();
BindingAssert.Matches(expected, view);}
IT.intel.com
Имена тестов
[TestClass]EmployeePresenterTests { [TestMethod]CanSelectEmployee(){…}
[TestMethod]ItWorksTest(){…}
}
IT.intel.com
Имена тестов
[TestClass]WhenAddEmployee { [TestMethod] AddedEmployeeSelectedByDefault(){…}
}
IT.intel.com
Что дает TDD
•Простота•Гибкость•Поддерживаемость•Тестируемость•5000+ тестов за 1 минуту
IT.intel.com
DSLDomain Specific Language
IT.intel.com
DSL
new DateTime(2009, 11, 12)
12.11.of2009();
public static DateTime of2009(this double ddMM) {
var day = (int) Math.Round(ddMM, 0); var month = (int) Math.Round(ddMM*100, 0)
- day * 100;
return new DateTime(2009, month, day);}
IT.intel.com
DSL
var month = new CalendarMonth(2009, 10);
var month = Oct.of2009();
internal static class Oct { public static CalendarMonth of2009 { get { return new CalendarMonth(2009, 10);
} }}
IT.intel.com
DSLvar customer = new Customer();customer.Name = “Vasya Pupkin”;var order = new Order();order.Customer = customer;order.Date = new DateTime(2009, 10, 11);var orderItem = new orderItem(); orderItem.Product = new Product(“Chips”);orderItem.Amount = 3;orderItem.Price = 45.30;order.Items.Add(orderItem);orderItem.Product = new Product(“Beer”);orderItem.Amount = 3;orderItam.Price = 20.50;order.Items.Add(orderItem);
IT.intel.com
DSLvar order = new OrderBuilder().WithCustomer(“Vasya Pupkin”).WithDate(11.10.of2009()).WithLineItem()
.WithProduct(“Chips”)
.WithAmount(3)
.WithPrice(45.30).WithLineItem()
.WithProduct(“Beer”)
.WithAmount(3)
.WithPrice(20.50).GetResult();
IT.intel.com
GoF / PoEAA
Gang of Four / Patterns of Enterprise Application Architecture
IT.intel.com
Зачем паттерны?
IT.intel.com
Спецификация
• Динамические фильтры InfrastructureFacade.Get<T>( Specification<T> specification)
• Дублирование условий
IT.intel.com
Спецификация
// if order is criticalif (order.Amount >= 1000000) { …}
IT.intel.com
Спецификация
public class CriticalOrder { public bool IsSatisfiedBy(Order order) { return order.Amount >= 1000000; }}
IT.intel.com
Спецификацияpublic class CriticalOrder { private readonly int minimalAmount;
public CriticalOrder(int minimalAmount) {
this.minimalAmount = minimalAmount; }
public bool IsSatisfiedBy(Order order) { return order.Customer.Type == CustomerType.KeyCustomer && order.Amount >= minimalAmount; }}
IT.intel.com
Композитные спецификации
var specification = new CriticalOrder( CustomerType.KeyCustomer, 200000) & new SoldTo(new Country("Russia")) & new AsOf(2009);
IT.intel.com
Что дают шаблоны
•Повторное использование•Расширяемость•Гибкость•SOLID
IT.intel.com
Profit!
IT.intel.com
Результаты для разработчиков
•Хорошая оценка Microsoft•Тестируемость•Поддерживаемость•Гибкость дизайна•Концептуальная целостность
•Повторное использование
IT.intel.com
Результаты для бизнеса
•Нет регрессионных багов•Гибкость требований•Быстрая разработка•Легкость при обсуждении требований
IT.intel.com
Резюме
1. DDD2. MVP/MVVM3. TDD4. DSL5. GoF/PoEAA…Profit!
IT.intel.com
?
IT.intel.com
Антон Бевзюк[email protected]
Евгений Сорокин[email protected]
Для журналистов:[email protected]
IT.intel.com
IT.intel.com
Backup
IT.intel.com
Не все гладко
•Передача другой команде•Производительность•Безопасность•Тяжелый solution
IT.intel.com
MSBuild
• Deploy– Сборка приложения– Прогон тестов– Деплой файлов– Запуск SQL Script– Разные конфигурации для DEV/CONS/PROD
• Nightly Build – Метрики
• CheckIn– Рассылка результатов
IT.intel.com
Continuous Integration
•MSBuild•Частый деплой•Разные environments•Безопасность
IT.intel.com
ClickOnce
IT.intel.com
ReSharper
IT.intel.com
Комментарии
Их нет!
IT.intel.com
Самый большой agile-проект
•2 года• •Разработчики