Save 37% off PRO during our Black Friday Sale! »

Эмиль Янгиров "Скаффолдинг — когда делать надо, но лень"

Ceecdee9ee77b63d81100be62b7e1090?s=47 DotNetRu
March 16, 2020

Эмиль Янгиров "Скаффолдинг — когда делать надо, но лень"

Ceecdee9ee77b63d81100be62b7e1090?s=128

DotNetRu

March 16, 2020
Tweet

Transcript

  1. Скаффолдинг История одной лени yangirov emil_yangirov 1

  2. Дисклеймер 2

  3. Мотивация 3

  4. 4

  5. Ребята, мы пишем CRUD 5

  6. Ребята, мы пишем CRUD • У кого-то проще 6

  7. Ребята, мы пишем CRUD • У кого-то проще • У

    кого-то сложнее 7
  8. Ребята, мы пишем CRUD • У кого-то проще • У

    кого-то сложнее • Но суть одна 8
  9. Ребята, мы пишем CRUD • У кого-то проще • У

    кого-то сложнее • Но суть одна • Мы выполняем много однотипных действий 9
  10. 10

  11. 11 Динамика трудоспособности

  12. Монотония 12 Динамика трудоспособности

  13. 13

  14. Готовые решения? Как облегчить такой труд? 14

  15. 15 Скаффолдинг Скаффолдинг — это метод метапрограммирования для создания веб-

    приложений, взаимодействующих с базой данных. Разработчик в них задает спецификации, по которым в дальнейшем генерируется программный код для операций создания определенных записей в базе данных, их чтения, обновления и удаления.
  16. 16

  17. 17 Скаффолдинг Скаффолдинг — инициализация проекта. Обычно это развертывание файловой

    структуры проекта и генерация некоторого количества кода. Скаффолдер — инструмент реализации скаффолдинга.
  18. 18

  19. Хорошие примеры других ребят 19

  20. Ruby on Rails > rails generate scaffold Book body:text shark:references

    На выходе: • модель • миграция БД • контроллер • полный набор представлений для управления стандартными операциями CRUD • шаблоны для партиалов, хелперов и тестов 20
  21. Что-то напоминает? 21

  22. CMS • Orchard CMS • Awesome CMS Core • Cofoundry

    • Lynicon • Squidex https://github.com/thangchung/awesome-dotnet-core#cms 22
  23. CMS Огромный выбор Добавление своих моделей, готовые круды Связаны по

    рукам в рамках архитектуры 23
  24. Фреймворки / бойлерплейты 24

  25. ASP.NET Boilerplate Из коробки Client Applications Presentation Distributed Service Application

    Domain Infrastructure 25
  26. ASP.NET Boilerplate Понятная DDD-like архитектура Поддержка современных фронтенд-фреймворков Production-ready Нет

    никакой генерации 26
  27. ABP FRAMEWORK > dotnet tool install -g Volo.Abp.Cli > abp

    new <solution-name> [options] > abp add-module Volo.Blogging Модули из коробки • Account • Audit Logging • Background Jobs • Blogging • Docs • Feature Management • Identity • Permission Management • Setting Management • Tenant Management • Users 27
  28. ABP FRAMEWORK Актуальная документация Понятная архитектура Свои шаблоны для модулей

    Пока не production-ready 28
  29. steeltoe Actuators, Circuit Breakers, Cloud Foundry, Discovery, DynamicLogger, OAuthConnector, Config

    Server, Placeholder Configuration Source, RandomValue Configuration Source 29
  30. Когда использовать? Если нужен быстрый старт и вы готовы принять

    определенную архитектурную парадигму. 30
  31. Инструменты 31

  32. 32 ASP.NET Dynamic Data

  33. 33 ASP.NET Dynamic Data Вся связь между слоями основана на

    информации о типах из схемы модели данных Настройка метаданных, шаблонов полей, валидации Технология морально устарела Нет интеграции с новомодными фреймворками
  34. Scaffold in Visual Studio 34

  35. 35

  36. 36

  37. А что мы хотим? • модель для БД • набор

    DTO • маппер • репозиторий • сервис • контроллер • тесты (необязательно) 37
  38. А что мы хотим? • модель для БД => /DataAccess/Models/ModelName.cs

    • набор DTO => /Contracts/Models/ModelNameDto.cs • маппер => /BusinessLogic/Mappers/ModelNameProfile.cs • репозиторий => /DataAccess/Repositories/ModelNameRepository.cs • сервис => /BusinessLogic/Services/ServiceName.cs • контроллер => /Api/Controllers/ModelNameController.cs • тесты (необязательно) => /Api.Tests/ModelNameTest.cs 38
  39. 39 Models ModelName.cs Repositories ModelNameRepository.cs Models ModelNameDto.cs Mappers ModelNameProfile.cs Services

    ModelNameService ModelNameTests.cs Controllers ModelNameController.cs
  40. Must have dotnet new Yeoman 40

  41. dotnet new Cоздает проект/решение/etc на основе указанного шаблона. > dotnet

    new <TEMPLATE> [--dry-run] [--force] [-i|--install] [-lang|--language] [-n|--name] [--nuget-source] [-o|--output] [-u|--uninstall] [--update-apply] [--update-check] [Template options] > dotnet new <TEMPLATE> [-l|--list] [--type] 41
  42. dotnet new — свой шаблон # Создаем простое web-приложение >

    dotnet new web > cd src # Создаем простой шаблон > mkdir template/.template.config > cd template/.template.config > nano template.json https://github.com/dotnet/aspnetcore/tree/master/src/ProjectTemplates https://github.com/dotnet/templating/wiki/Available-templates-for-dotnet-new 42
  43. dotnet new — свой шаблон src template .template.config template.json 43

  44. dotnet new — файл шаблона { "$schema": "http://json.schemastore.org/template", "author": "Emil

    Yangirov", "classifications": [ "Common", "Code" ], "identity": "UfaDotNet", "name": "UfaDotNet Model", "shortName": "model", "tags": { ... }, "symbols": { ... }, "sources": { ... }, "postActions": { ... } } 44
  45. dotnet new — переменные "symbols": { "ModelName": { "type": "parameter",

    "replaces": "{ModelName}", "FileRename": "ModelName" }, "DbTableName": { "type": "parameter", "replaces": "{DbTableName}" }, "WithTest": { "type": "parameter", "datatype": "bool", "description": "Генерация тестов" , "defaultValue" : "false" } } 45
  46. dotnet new — переменные namespace DataAccess.Models ModelName.cs { public class

    {ModelName} : IBaseEntity<int> { public int Id { get; set; } public int Identifier => Id; } } namespace Contracts.Models ModelNameDto.cs { public class {ModelName}Dto : IDto<int> { public int Id { get; set; } } } 46
  47. 47 dotnet new — структура

  48. dotnet new — условия "sources": [ { "modifiers": [ {

    "condition": "(!WithTest)", "exclude": [ "Api.Tests/ModelNameTest.cs" ] } ] } ] 48
  49. dotnet new — post-actions "postActions": [ { "condition": "true", "description":

    "Ending", "manualInstructions": [ { "text": "Ура! Вы дошли до конца." } ], "actionId": "30C66942-E0B6-4F7C-9008-378DCD16E600", "continueOnError": true } ] 49
  50. dotnet new — how to use > dotnet new -i

    .\ Templates Short Name Language Tags ------------------------------------ ----------------------------- UfaDotNet Model model [C#] Common/Code > dotnet new model --ModelName=Book --DbTableName=Books --ServiceName=BookService --WithTest=true The template "UfaDotNet Model" was created successfully. Processing post-creation actions... Description: Ending Manual instructions: Ура! Вы дошли до конца. 50
  51. 51

  52. 52 dotnet new Официально поддерживается Много дефолтных шаблонов Слабая документация

    (!) Сложная система условий и выбора
  53. 53 dotnet new [ROADMAP] • Создание официальной документации • Интерактивный

    режим (как в yo aspnet) • Интеграция с Visual Studio • Интеграция с yo aspnet • Обновления шаблонов (как обязательные, так и необязательные) https://github.com/dotnet/templating/#roadmap
  54. А что мы хотим? • модель для БД • набор

    DTO • маппер • репозиторий • сервис • контроллер • тесты (необязательно) 54
  55. А что мы хотим? • модель для БД => /DataAccess/Models/ModelName.cs

    • набор DTO => /Contracts/Models/ModelNameDto.cs • маппер => /BusinessLogic/Mappers/ModelNameProfile.cs • репозиторий => /DataAccess/Repositories/ModelNameRepository.cs • сервис => /BusinessLogic/Services/ServiceName.cs • контроллер => /Api/Controllers/ModelNameController.cs • тесты (необязательно) => /Api.Tests/ModelNameTest.cs 55
  56. 56 Models ModelName.cs Repositories ModelNameRepository.cs Models ModelNameDto.cs Mappers ModelNameProfile.cs Services

    ModelNameService ModelNameTests.cs Controllers ModelNameController.cs
  57. Yeoman > sudo npm i -g yo > yo generator-name

    Универсальный скаффолдер, позволяющий создавать любые приложения. Предоставляет так называемые «генераторы», которые можно вызывать с помощью команды yo, чтобы сгенерировать структуру приложения. 57
  58. Yeoman Генератор — это npm-пакет с инструкциями и шаблонами для

    Yo, которые описывают инициализацию проекта: какие директории создать, какие файлы и куда копировать, каким образом обрабатывать шаблоны и куда их разместить после обработки. 58
  59. generator-aspnet [deprecated] > npm i -g generator-aspnet > dev yo

    aspnet > yo aspnet:Class Book https://github.com/OmniSharp/generator-aspnet https://github.com/jhipster/jhipster-dotnetcore 59
  60. 60 Yeoman — свой генератор { package.json "name": "generator-ufadotnet", "version":

    "0.1.0", "description": "UfaDotNet simple scaffold" , "files": [ "generators" ], "main": "generators/app/index.js" , "keywords": ["yeoman-generator"], "dependencies": { "yeoman-generator": "^1.0.0" } }
  61. Yeoman — структура package.json generators app templates index.js prompts.js writing.js

    61
  62. Yeoman — структура app templates ModelName.js .... index.js prompts.js writing.js

    62
  63. Yeoman — свой генератор var Generator = require('yeoman-generator'); index.js var

    prompts = require('./prompts'); var writeFiles = require('./writing'); module.exports = class extends Generator { prompting() { return this.prompt(prompts).then((props) => { this.props = props; }); } writing() { writeFiles.call(this); } } 63
  64. Yeoman — параметры module.exports = [ prompts.js { type: 'input',

    name: 'modelName', message: 'Название модели', default: 'Model' }, ... { type: 'confirm', name: 'withTests', message: 'Генерировать тесты?', default: true } ] 64
  65. module.exports = function () { writing.js let {modelName, withTests} =

    this.props; this.fs.copyTpl( this.templatePath('ModelName.cs'), this.destinationPath(`DataAccess/Models/${modelName}.cs`), { ModelName: modelName } ); if (withTests) { this.fs.copyTpl( this.templatePath('ModelNameTest.cs'), this.destinationPath(`Api.Tests/${modelName}Test.cs`), { ModelName: modelName } ); } }; 65
  66. Yeoman — переменные namespace DataAccess.Models ModelName.js { public class <%=ModelName%>

    : IBaseEntity<int> { public int Id { get; set; } public int Identifier => Id; } } namespace Contracts.Models ModelNameDto.js { public class <%=ModelName%>Dto : IDto<int> { public int Id { get; set; } } } 66
  67. Yeoman — свой генератор var Generator = require('yeoman-generator'); index.js var

    prompts = require('./prompts'); var writeFiles = require('./writing'); module.exports = class extends Generator { prompting() { return this.prompt(prompts).then((props) => { this.props = props; }); }, writing() { writeFiles.call(this); } } 67
  68. 68

  69. 69 Yeoman Удобная разбивка на модули Передача переменных, условий Возможность

    создавать вопросы Много кода на JavaScript Неудобный плейсмент файлов
  70. github.com/yangirov/scaffold 70

  71. Вердикт Я стал немножко счастливее В большинстве случаев я бы

    выбрал dotnet new вместо Yeoman 71
  72. Что почитать? 72 https:/ /vk.cc/aroJxk

  73. Вопросы? yangirov emil_yangirov 73