Референсная архитектураприложения на ASP.NET MVC        Андрей Майоров            BYTE-force        twitter.com/xorets
MVC
Model-View-Controller• Разделяет данные и представление• Модель: активная или пассивная                  Controller       ...
Holy war• Где держать бизнес-логику?• Можно брать доменные объекты в модель?
Модификации: MVP• Model-View-Presenter                  Presenter           View               Model
Модификации: MVVM• Model-View-ViewModel      View        ViewModel   Model
ASP.NET
Олдскульный .ASPX• <% … %>• Code behind• Web controls• Раздутый HTML на выходе
Олдскульный .ASPX// Hello World in C#class HelloWorld{       static void Main()       {              System.Console.WriteL...
ASP.NET MVC
Контроллерpublic class HomeController : Controller{       public ActionResult Index()       {              var model = …  ...
Маршрутыroutes.MapRoute(      name: "Default",      url: "{controller}/{action}/{id}",      defaults: new {              c...
Передача параметровpublic ActionResult Index( int id, string x ){ …}routes.MapRoute(      url: "{controller}/{action}/{id}...
View• «Представление», «вьюха»• Модель → HTML• Отделено от контроллера
Реализация вьюхи• Файл /view/home/index.*• Расширения файлов:  • ASPX → Web Forms Engine  • CHTML → Razor  • ... → Что душ...
DemoШаблонный проект
Проблема: 1 метод на 1 URL•   Огромные контроллеры•   Нечеткие критерии группировки методов•   Мало базовых классов•   Сер...
Решение:Только один action в   контроллере
Один action на контроллер• Execute()• Исключение из правил – NextPage ()
Single responsibility principleKаждый объект должен иметь однуобязанность и эта обязанность должнабыть полностью инкапсули...
Сложности с именами view/View        /Home              /Execute.chtml        /News              /Execute.chtml        /Pr...
Свой ViewEngine/View        /Home.xslt        /News.xslt        /Products.xslt        /Products_NextPage.xslt        /Prod...
Преимущества•   Один контроллер – одно действие•   Контроллеры маленькие•   Общий функционал → в базовый класс•   Создаем ...
ControllerBase                  +Model                  +FillCommonData()IndexController                       ListControl...
Правила1. Один контроллер – одно действие
Модель
Модель• Данные для View• НЕ интерфейс получения/записи данных** — холивар варнинг
ViewModel      vs.Domain Objects
Типизированная модель         vs.    Динамическая
Typed vs. Dynamicpublic ActionResult Execute(){       var model = new Model();       …       return View(model);}      dyn...
Модель – член класса
Правила1. Один контроллер – одно действие2. Модель – член класса
Декларация маршрутов
Явная декларация маршрутаroutes.MapRoute( name: "Home", url: "home",      new { controller = "Home", action = "Execute" })...
Правила1. Один контроллер – одно действие2. Модель – член класса3. Задавайте маршруты явно
DemoSingle action controllers
Domain Specific Language
Domain Specific Languagepublic ActionResult Execute(){       CheckAccessRights( “index” );       Model.news = SelectObject...
ControllerBase                  +Model                  +FillCommonData()                  +CheckAccessRights()           ...
Сервисные классы                                  ControllerBase                                +Model                    ...
DemoDSL and helpers
Правила1.   Один контроллер – одно действие2.   Модель – член класса3.   Задавайте маршруты явно4.   Делайте собственные DSL
Dependency Injection
Dependency inversion principleМодули верхних уровней не должнызависеть от модулей нижних уровней.Модули должны зависеть от...
Dependency Inversion <<interface>> INewsService +GetNews() NewsServiceImpl   IndexController +GetNews()        +Execute()
Dependency Injection<<interface>>INewsService+GetNews() NewsServiceImpl               IndexController +GetNews()          ...
Указание зависимостей• Параметры конструктора• Свойства с атрибутами• Правила именования полей и аргументов
Указание зависимостейpublic class HomeController : Controller{       [Dependency]       public INewsService NewsService { ...
Настройка DI-контейнера • Связь между интерфейсом и реализацией* • Контроль за жизнью объекта<register type="INewsService"...
DemoDependency Injection
DI delivers• Уменьшает связность приложения• Помогает писать модульные тесты• Заставляет правильно мыслить
Правила1.   Один контроллер – одно действие2.   Модель – член класса3.   Задавайте маршруты явно4.   Делайте собственные D...
Редактирование    данных
Обычный процесс1.   Браузер запрашивает URL2.   Сервер формирует HTML, шлет на клиент3.   Браузер показывает HTML4.   Поль...
Проблемы обычного подхода• Сериализация-десериализация состояния• Постоянные перезагрузки• Трафик
Ajax-редактирование1.   Браузер запрашивает URL2.   Сервер формирует HTML, шлет на клиент3.   Браузер показывает HTML4.   ...
JSON// Браузер шлет серверу{      id: 245,      price: 19.95}// Сервер отвечает{ success: true }
Ajax delivers• Не надо сериализовать всю страницу• При ошибке можно повторить• Трафик меньше на порядки
Правила1.   Один контроллер – одно действие2.   Модель – член класса3.   Задавайте маршруты явно4.   Делайте собственные D...
AngularJS - MVVM// Model$scope.id = 245;$scope.title = “Red button”;$scope.price = 19.95;<!-- View -->Price for {{title}}:...
Спасибо за внимание   Андрей Майоров       BYTE-force  xor@byte-force.com   twitter.com/xorets
Референсная архитектура приложения на ASP.NET MVC
Референсная архитектура приложения на ASP.NET MVC
Upcoming SlideShare
Loading in …5
×

Референсная архитектура приложения на ASP.NET MVC

328 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
328
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Референсная архитектура приложения на ASP.NET MVC

  1. 1. Референсная архитектураприложения на ASP.NET MVC Андрей Майоров BYTE-force twitter.com/xorets
  2. 2. MVC
  3. 3. Model-View-Controller• Разделяет данные и представление• Модель: активная или пассивная Controller View Model
  4. 4. Holy war• Где держать бизнес-логику?• Можно брать доменные объекты в модель?
  5. 5. Модификации: MVP• Model-View-Presenter Presenter View Model
  6. 6. Модификации: MVVM• Model-View-ViewModel View ViewModel Model
  7. 7. ASP.NET
  8. 8. Олдскульный .ASPX• <% … %>• Code behind• Web controls• Раздутый HTML на выходе
  9. 9. Олдскульный .ASPX// Hello World in C#class HelloWorld{ static void Main() { System.Console.WriteLine("Hello, World!"); }}
  10. 10. ASP.NET MVC
  11. 11. Контроллерpublic class HomeController : Controller{ public ActionResult Index() { var model = … return View(model); // of type ViewResult }}
  12. 12. Маршрутыroutes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );/home/index
  13. 13. Передача параметровpublic ActionResult Index( int id, string x ){ …}routes.MapRoute( url: "{controller}/{action}/{id}", …/home/index/123?x=red
  14. 14. View• «Представление», «вьюха»• Модель → HTML• Отделено от контроллера
  15. 15. Реализация вьюхи• Файл /view/home/index.*• Расширения файлов: • ASPX → Web Forms Engine • CHTML → Razor • ... → Что душа пожелает
  16. 16. DemoШаблонный проект
  17. 17. Проблема: 1 метод на 1 URL• Огромные контроллеры• Нечеткие критерии группировки методов• Мало базовых классов• Сервисные методы раздувают контроллеры
  18. 18. Решение:Только один action в контроллере
  19. 19. Один action на контроллер• Execute()• Исключение из правил – NextPage ()
  20. 20. Single responsibility principleKаждый объект должен иметь однуобязанность и эта обязанность должнабыть полностью инкапсулирована в класс.SOLID
  21. 21. Сложности с именами view/View /Home /Execute.chtml /News /Execute.chtml /Products /Execute.chtml /NextPage.chtml /Product /Execute.chtml
  22. 22. Свой ViewEngine/View /Home.xslt /News.xslt /Products.xslt /Products_NextPage.xslt /Product.xslt
  23. 23. Преимущества• Один контроллер – одно действие• Контроллеры маленькие• Общий функционал → в базовый класс• Создаем DSL*• Дружит с Dependency Injection*
  24. 24. ControllerBase +Model +FillCommonData()IndexController ListControllerBase+Execute() NewsController ProductsController +Execute() +Execute()
  25. 25. Правила1. Один контроллер – одно действие
  26. 26. Модель
  27. 27. Модель• Данные для View• НЕ интерфейс получения/записи данных** — холивар варнинг
  28. 28. ViewModel vs.Domain Objects
  29. 29. Типизированная модель vs. Динамическая
  30. 30. Typed vs. Dynamicpublic ActionResult Execute(){ var model = new Model(); … return View(model);} dynamic model = new ExpandoObject();
  31. 31. Модель – член класса
  32. 32. Правила1. Один контроллер – одно действие2. Модель – член класса
  33. 33. Декларация маршрутов
  34. 34. Явная декларация маршрутаroutes.MapRoute( name: "Home", url: "home", new { controller = "Home", action = "Execute" });routes.MapRoute( name: "News", url: "news", new { controller = "News", action = "Execute" });Url.RouteUrl( home ) // Returns “/home”
  35. 35. Правила1. Один контроллер – одно действие2. Модель – член класса3. Задавайте маршруты явно
  36. 36. DemoSingle action controllers
  37. 37. Domain Specific Language
  38. 38. Domain Specific Languagepublic ActionResult Execute(){ CheckAccessRights( “index” ); Model.news = SelectObjects() .OfType( “article” ) .FilterPublished() .Execute(); return View(Model);}
  39. 39. ControllerBase +Model +FillCommonData() +CheckAccessRights() +SelectObjects()IndexController ListControllerBase+Execute() +PreparePagingData() NewsController ProductsController +Execute() +Execute()
  40. 40. Сервисные классы ControllerBase +Model +FillCommonData() +CheckAccessRights() +SelectObjects() IndexController ListControllerBase +Execute() +PreparePagingData()NewsService+GetNews() NewsController ProductsController +Execute() +Execute()
  41. 41. DemoDSL and helpers
  42. 42. Правила1. Один контроллер – одно действие2. Модель – член класса3. Задавайте маршруты явно4. Делайте собственные DSL
  43. 43. Dependency Injection
  44. 44. Dependency inversion principleМодули верхних уровней не должнызависеть от модулей нижних уровней.Модули должны зависеть от абстракций.Абстракции не должны зависеть отдеталей. Детали должны зависеть отабстракций.SOLID
  45. 45. Dependency Inversion <<interface>> INewsService +GetNews() NewsServiceImpl IndexController +GetNews() +Execute()
  46. 46. Dependency Injection<<interface>>INewsService+GetNews() NewsServiceImpl IndexController +GetNews() +Execute() Assembler +Resolve()
  47. 47. Указание зависимостей• Параметры конструктора• Свойства с атрибутами• Правила именования полей и аргументов
  48. 48. Указание зависимостейpublic class HomeController : Controller{ [Dependency] public INewsService NewsService { get; set; } public HomeController( IDatabase database ) { … } …}
  49. 49. Настройка DI-контейнера • Связь между интерфейсом и реализацией* • Контроль за жизнью объекта<register type="INewsService" mapTo="NewsService"> <lifetime type="singleton"/></register> * Не обязательно
  50. 50. DemoDependency Injection
  51. 51. DI delivers• Уменьшает связность приложения• Помогает писать модульные тесты• Заставляет правильно мыслить
  52. 52. Правила1. Один контроллер – одно действие2. Модель – член класса3. Задавайте маршруты явно4. Делайте собственные DSL5. Используйте DI
  53. 53. Редактирование данных
  54. 54. Обычный процесс1. Браузер запрашивает URL2. Сервер формирует HTML, шлет на клиент3. Браузер показывает HTML4. Пользователь редактирует данные. Submit5. Браузер шлет данные в POST-запросе6. Сервер обновляет базу, goto 2
  55. 55. Проблемы обычного подхода• Сериализация-десериализация состояния• Постоянные перезагрузки• Трафик
  56. 56. Ajax-редактирование1. Браузер запрашивает URL2. Сервер формирует HTML, шлет на клиент3. Браузер показывает HTML4. Пользователь редактирует данные. Submit5. Браузер шлет данные в POST-запросе6. Сервер обновляет базу7. goto 4
  57. 57. JSON// Браузер шлет серверу{ id: 245, price: 19.95}// Сервер отвечает{ success: true }
  58. 58. Ajax delivers• Не надо сериализовать всю страницу• При ошибке можно повторить• Трафик меньше на порядки
  59. 59. Правила1. Один контроллер – одно действие2. Модель – член класса3. Задавайте маршруты явно4. Делайте собственные DSL5. Используйте DI6. Используйте Ajax для редактирования
  60. 60. AngularJS - MVVM// Model$scope.id = 245;$scope.title = “Red button”;$scope.price = 19.95;<!-- View -->Price for {{title}}: <input type=“text” ng-model=“price” />
  61. 61. Спасибо за внимание Андрей Майоров BYTE-force xor@byte-force.com twitter.com/xorets

×