С# я не планирую вводить на канал ближайшим временем) Но примеры из соседних языков программирования в плейлист паттернов могут попадать чисто для наглядности :)
DTO - это разве не для обмена данными между сервисами или бэк фронт? Локальный DTO это скорее антипаттерн т.к. возникнет необходимость маппить данные, что локально вообще не к чему. На Nest-е DTO-шки вообще сила, документация OpenAPI(swagger) и валидация через Entity в 2 клика настраивается. п.с. на 9:35 вместо тернарника можно написать this.loop = props.loop ?? true; :)
Тернарник не подошёл бы, так как нужно было привести к типу DTO обмен данными между слоями (сервисами), все верно, бэкэнд фронтенд это частный случай. В Nest JS вокруг DTO ещё куча настроек, также в C# через атрибуты много чего настраивается. Но документация достигается декораторами, а не самим DTO, DTO там не сложнее чем я его описал) Класс с набором свойств и типизацией на тайпскрипт, если бы за сваггер и валидацию отвечало ДТО, то невозможно было бы добавлять новый функционал, а так это наслоение конфигурации которая не конфликтует друг с другом и можно ещё десяток возможностей додумать под цели проекта)
У меня на проекте бек онли джаваскрип. По архитектуре: контролеры, юзкейсы и репозиторий. Вот так типизируем в DTO поля "email = type .string().min(3).required() .email();" + на выход тоже есть реалтайм проверка - "const mapUsers = usersFromUseCase.map((user) => new userDTO(user))". И как то без ТС норм. линтер настроен ts проверку можно сделать глобальной + задавать значения по умолчанию.
Тут еще декларация правил валидации идет как я понимаю DTO - не всегда речь о контроллере и получении данных из реквеста Я бы сказал что в Вашем случае DTO это результат работы маппера и валидатора В тайпскрипт это достигается за счет декораторов (та же логика) @Required() @Min(3) @Email() @Type('string') email Ну или в другой лакончиной форме Из описанного не понятно в какой момент применяется цепочка настроек, хотелось бы больше контекста
Материалы все лучше и лучшее 👍 По поводу значение по умолчанию в TS, да ещё и в интерфейсе, такого сделать нельзя. Как выход из ситуации - это сделать потом Object.assign в объект, у которого уже будут значения по умолчанию. На этом строится много разных полезных техник. А вот в C# это делается легко.
В TS нужно было описать класс для моего случая, и использовать его как интерфейс. TypeScript позволяет такие манипуляции использовать литерал объекта и выдавать его как будто это некоторый инстанс класса. P.S. мой кейс - абстрактный класс Допустил классическую ошибку непонимания Interface vs Abstract Class (собес бы не прошел )😆
материал актуальный, но много ляпов, к примеру с заданием дефотных значений в интерфесе или в 9 примере у тебя много ошибок, в C# нету типа Number и типа Bool, ты видимо попутал с TS, и ты забыл про прелести полиморфизма, мы можем принимать число или строку в высоте и длине, если сделаем параметризированный дженерик или как вариант перегрузить конструктор, либо задать тип object на эти свойства, но это плохая практика, так как будет происходить постоянный Boxing/Unboxing при типе int, либо вообще вариант с базовой моделью и двумя дочерними с разными типами, вариантов много public class CarouselDTO { public T Width { get;set; } public T Height { get;set; } public int ViewItems { get; set; } = 2; public Boolean Loop { get; set; } = true; } создаавать ДТОшки соответсввенно var firstCarousel = new CarouselDTO { Width = "100px", Height = "100px" }; var secondCarousel = new CarouselDTO { Width = 100, Height = 100 }; а похорошему у тебя должен быть маппер который будет выполнять грязную работу по мапингу DBModel или любой другой(другого слоя) в DTO и обратно, так называемый реверс Ну и немного обидно за слова по поводу C#, он более низкоуровневый язык, плюс со статической типизацией, поэтому парог вхождения в него выше, чем во многие динамические языки типа JS, питона, PHP, Ruby и т.п., если тебе это не нравится, это не делает его хуже этих языков.
Спасибо за замечания Нужно было мне проверить код в Visual Studio, а не в VS Code...ибо небыло подсветки и поспешил с классом Object === any, вариант не очень Вложенный объект тоже вариант не упрощающий жизнь Дженерик вариант хороший, но это только 2 свойства...и уже 4ре комбинации на простейших int / string C Bool постоянно путаю, в php bool/boolean это алиасы, а по C# пока пишу не так много C Number тут вообще мне прощения нет) Но не в этом суть примера был Вернемся к дженерикам, что делать если у меня коллекция DTO и там неоднородные данные, то придется прибегнуть к object... И тут опять получаем boxing / unboxing Я не говорю что C# плохой язык) я на него перешел после 5 лет работы в php. И я говорил что в php дела похуже. Я просто утверждаю, что TypeScript решает задачу типизации идеально для веба. C# очень мощный язык программирования, через чур мощный для веба. 5 лет работы с PHP и несколько лет работы с JavaScript дают свой субъективный вклад при изучении C#
@@grommaks что ты имеешь ввиду под коллекцией DTO? просто коллекция в C# - это List(список), тебе никто не мешает создать параметризированную коллекцию var listExample = new List(); суть C# как раз в том, что ты должен работать с неразнородными данными, а задание типа помогает выделять заранее строго определенное кол-во памяти для твоих сущностей в момент когда к ним обращаются, отсюда и эффективная работа с ней, в отличие от языков с динамической типизацией, если у тебя возможно несколько типов в одной переменной, то значит ты где-то свернул не туда, ведь суть в том чтобы получить что-то из БД(у одной сущности один тип данных) на уровне дата аксес, повзаимодействовать на уровне бизнес логики и отдать на вьюху, и DTOшка твоя используется только в промежутке для каких-либо расчётов или преобразований, и вьюмодель не равна DTO, даже если у тебя все свойства совпадают, ты всё равно должен сматить на вью модель пускай и стакими же свойствами, я просто не понимаю в чём суть вопроса, ты видимо просто заморочился на том, что писал всё время на языках с динамической типизацией и писал скорее всего 90% на фронте, поэтому не привык к строгости, зачем с бэка отдавать два возможных варианта типов?) ведь это даже архитектурно неправильно, всегда отдавай число, а на фронте уже преобразуй и мапь во что и как хочешь) либо создай разные ендпоинты котоыре будут отдавать разные модели, в одних случаях число, в другом строку, в C# можно работать с разнородными данными, но тогда его суть, как строго типизированного языка пропадает
@@grommaks для инта выделяется 4 байта, а для стринги в зависимости от ее длины, т.к. стринга это массив чаров то с точки зрения памяти лучше использовать инт, так как, к примеру, 100 или 100500 - 4 байта, а для “100px” - 10 байта и в базе надо хранить в типах, которые меньше весят, и трафика, чем меньше гоняешь, тем лучше, все просто.
Именно так делают большинство фреймворков старого образца Но есть ряд минусов 1) нет подсветки (Laravel style) 2) над сеттерами часто используют аннотации или в PHP 8 аттрибуты для дополнения логикой (например валидация или связь с колонками в БД) но это уже не DTO (Simfony style) 3) нет возможности разбирать с помощью рефлексии (Magento style) Но чем хорош PHP по сравнению с C# или JS, то что можно автоматически генерировать DTO (из конфига, yaml например) в специальную папочку и автолоадер будет генерировать класс заново, если удалить старый класс. По принципу генерации работает Magento, чем безумно ускоряет разработку в Java стиле в PHP
@@i.am.rossalex описанные проблемы могут быть актуальны и не во фреймворке. Любой паттерн работает в связке с остальной архитектурой, а значит мы можем использовать магический метод сет для облегчения установки данных, но пожертвуем другой частью приложения. И не понятно чем это будет отличаться от ассоциативного массива :)
Хорошее замечание, нужно было class использовать для моего примера Чуток поторопился, надеюсь это мне принесет много комментов под видео и возможно дизлайков :) Спасибо за внимательность
Глядя на предыдущие видео на этом канале у меня нет сомнений, что автор - трушный профессионал. А ошибиться может каждый. Плох не тот разраб, который ошибается, а тот, который не признаёт ошибку и не делает выводов. Макс же наоборот - и признал и сделал выводы и исправился, хоть и в комментах уже. Так что от меня, Максим, - респект и уважуха
Есть впечатление что DTO появилось из за рефакторинга если в функции или методе более 2 параметров и если они логически связаны например user то их можно вынести в interface и использовать вместо 3 и более параметров
Да, это часть логики которую берет на себя DTO...даже в строгих языках или в языках где это сделать гораздо сложнее чем в JavaScript (PHP например) то использование DTO сильно упрощало поддержку, хоть и требовало дополнительных усилий по созданию DTO Но не стоит забывать о втором важном назначении - разделении слоев) особенно когда есть эти самые слои в приложении) В последнее время я перестал верить, что о создании слоистой архитектры много кто заморачивается, если это не продукт монолит
DTO это не ValueObject, с конструктором есть свои нюансы. Но если подход с конструктором вписывается в архитектуру фреймворка или системы, то почему нет) но с трудом представляю Х полей в конструкторе, и при любом запросе добавить новые поля будут добавляться в конец списка параметров
@@alexzhaliazouski5924 DTO это объект в котором что-то хранится, это что-то может быть массивом объектов или массивом примитивов. Или как сказано выше, коллекцией. Но как указать коллекцией чего? Generic ещё не завезли в PHP. В php типизация ещё не полноценная, чтобы покрыть все потребности этого паттерна, но есть обходной путь через аннотации и рефлексию комментариев над свойствами или в более новой версии это атрибуты
Добрый день! Пример не совсем корректный, как по мне. Больше все таки относится к фронтенду. Также не совсем понял, почему у с# "похуже" типизация?) Да и зачем вообще типизировать и строкой и числом? Бред полный, пришедший из фронденда как раз, имхо) Даже если и есть такая необходимость, то что делать потом с этой dto, если ее параметр, который может быть и числом и строкой, должен передаваться в какую нибудь другую функцию, которая принимает например только число? Будем городить проверки и приведения. Такое себе, имхо. А таких функций может быть много. Поэтому не лучше типизировать строго одним и при инициализации dto один раз привести к чему-то одному?
Такая жизнь) приходится городить что-то потом по необходимости. Гибкость динамического языка программирования с типизацией раскрыты в TypeScript который не ограничен способом хранения данных, а лишь предоставляет механизм декларирования типов. TypeScript мощнее чем возможности типизации в C#, потому что в C# это прежде всего задача хранения свойств и оптимизации используемой памяти...а в TypeScript это облечение написания логики проекта Как дела обстоят с Enum со строковыми значениями в C#? Насколько мне известно, то сложно
по моему это заморочь ... а если передается параметр которого нет, как он обработается? ошибки возможны, и подобный подход не панацея ... имхо и в дто по классике логики быть не должно. Подобный финт используется в яве, это обуславливается особенностями языка, как я считаю
Подписывался ради ангуляра, походу теперь ещё и ради C# буду смотреть, круто)
С# я не планирую вводить на канал ближайшим временем)
Но примеры из соседних языков программирования в плейлист паттернов могут попадать чисто для наглядности :)
Автор, поясни плз. ссылка на гист ведет на пару файликов где один console.log и всё. а типа проект из видео есть?
DTO - это разве не для обмена данными между сервисами или бэк фронт? Локальный DTO это скорее антипаттерн т.к. возникнет необходимость маппить данные, что локально вообще не к чему. На Nest-е DTO-шки вообще сила, документация OpenAPI(swagger) и валидация через Entity в 2 клика настраивается.
п.с. на 9:35 вместо тернарника можно написать this.loop = props.loop ?? true; :)
Тернарник не подошёл бы, так как нужно было привести к типу
DTO обмен данными между слоями (сервисами), все верно, бэкэнд фронтенд это частный случай.
В Nest JS вокруг DTO ещё куча настроек, также в C# через атрибуты много чего настраивается. Но документация достигается декораторами, а не самим DTO, DTO там не сложнее чем я его описал)
Класс с набором свойств и типизацией на тайпскрипт, если бы за сваггер и валидацию отвечало ДТО, то невозможно было бы добавлять новый функционал, а так это наслоение конфигурации которая не конфликтует друг с другом и можно ещё десяток возможностей додумать под цели проекта)
Спасибо! (Data Transfer Object)
У меня на проекте бек онли джаваскрип. По архитектуре: контролеры, юзкейсы и репозиторий. Вот так типизируем в DTO поля "email = type
.string().min(3).required() .email();" + на выход тоже есть реалтайм проверка - "const mapUsers = usersFromUseCase.map((user) => new userDTO(user))". И как то без ТС норм. линтер настроен ts проверку можно сделать глобальной + задавать значения по умолчанию.
Тут еще декларация правил валидации идет как я понимаю
DTO - не всегда речь о контроллере и получении данных из реквеста
Я бы сказал что в Вашем случае DTO это результат работы маппера и валидатора
В тайпскрипт это достигается за счет декораторов (та же логика)
@Required()
@Min(3)
@Email()
@Type('string')
email
Ну или в другой лакончиной форме
Из описанного не понятно в какой момент применяется цепочка настроек, хотелось бы больше контекста
Материалы все лучше и лучшее 👍 По поводу значение по умолчанию в TS, да ещё и в интерфейсе, такого сделать нельзя. Как выход из ситуации - это сделать потом Object.assign в объект, у которого уже будут значения по умолчанию. На этом строится много разных полезных техник. А вот в C# это делается легко.
Спасибо коллега 😎
В TS нужно было описать класс для моего случая, и использовать его как интерфейс. TypeScript позволяет такие манипуляции использовать литерал объекта и выдавать его как будто это некоторый инстанс класса.
P.S. мой кейс - абстрактный класс
Допустил классическую ошибку непонимания Interface vs Abstract Class (собес бы не прошел )😆
материал актуальный, но много ляпов, к примеру с заданием дефотных значений в интерфесе или в 9 примере у тебя много ошибок, в C# нету типа Number и типа Bool, ты видимо попутал с TS, и ты забыл про прелести полиморфизма, мы можем принимать число или строку в высоте и длине, если сделаем параметризированный дженерик или как вариант перегрузить конструктор, либо задать тип object на эти свойства, но это плохая практика, так как будет происходить постоянный Boxing/Unboxing при типе int, либо вообще вариант с базовой моделью и двумя дочерними с разными типами, вариантов много
public class CarouselDTO
{
public T Width { get;set; }
public T Height { get;set; }
public int ViewItems { get; set; } = 2;
public Boolean Loop { get; set; } = true;
}
создаавать ДТОшки соответсввенно
var firstCarousel = new CarouselDTO { Width = "100px", Height = "100px" };
var secondCarousel = new CarouselDTO { Width = 100, Height = 100 };
а похорошему у тебя должен быть маппер который будет выполнять грязную работу по мапингу DBModel или любой другой(другого слоя) в DTO и обратно, так называемый реверс
Ну и немного обидно за слова по поводу C#, он более низкоуровневый язык, плюс со статической типизацией, поэтому парог вхождения в него выше, чем во многие динамические языки типа JS, питона, PHP, Ruby и т.п., если тебе это не нравится, это не делает его хуже этих языков.
Спасибо за замечания
Нужно было мне проверить код в Visual Studio, а не в VS Code...ибо небыло подсветки и поспешил с классом
Object === any, вариант не очень
Вложенный объект тоже вариант не упрощающий жизнь
Дженерик вариант хороший, но это только 2 свойства...и уже 4ре комбинации на простейших int / string
C Bool постоянно путаю, в php bool/boolean это алиасы, а по C# пока пишу не так много
C Number тут вообще мне прощения нет) Но не в этом суть примера был
Вернемся к дженерикам, что делать если у меня коллекция DTO и там неоднородные данные, то придется прибегнуть к object...
И тут опять получаем boxing / unboxing
Я не говорю что C# плохой язык) я на него перешел после 5 лет работы в php. И я говорил что в php дела похуже.
Я просто утверждаю, что TypeScript решает задачу типизации идеально для веба. C# очень мощный язык программирования, через чур мощный для веба.
5 лет работы с PHP и несколько лет работы с JavaScript дают свой субъективный вклад при изучении C#
@@grommaks что ты имеешь ввиду под коллекцией DTO? просто коллекция в C# - это List(список), тебе никто не мешает создать параметризированную коллекцию
var listExample = new List();
суть C# как раз в том, что ты должен работать с неразнородными данными, а задание типа помогает выделять заранее строго определенное кол-во памяти для твоих сущностей в момент когда к ним обращаются, отсюда и эффективная работа с ней, в отличие от языков с динамической типизацией, если у тебя возможно несколько типов в одной переменной, то значит ты где-то свернул не туда, ведь суть в том чтобы получить что-то из БД(у одной сущности один тип данных) на уровне дата аксес, повзаимодействовать на уровне бизнес логики и отдать на вьюху, и DTOшка твоя используется только в промежутке для каких-либо расчётов или преобразований, и вьюмодель не равна DTO, даже если у тебя все свойства совпадают, ты всё равно должен сматить на вью модель пускай и стакими же свойствами, я просто не понимаю в чём суть вопроса, ты видимо просто заморочился на том, что писал всё время на языках с динамической типизацией и писал скорее всего 90% на фронте, поэтому не привык к строгости, зачем с бэка отдавать два возможных варианта типов?) ведь это даже архитектурно неправильно, всегда отдавай число, а на фронте уже преобразуй и мапь во что и как хочешь) либо создай разные ендпоинты котоыре будут отдавать разные модели, в одних случаях число, в другом строку, в C# можно работать с разнородными данными, но тогда его суть, как строго типизированного языка пропадает
@@levapveeskela4327 подходы отличаются, согласен) пример в видео был не удачен с точки зрения манипуляции с данными, я бы манипулировал лишь строками
@@grommaks для инта выделяется 4 байта, а для стринги в зависимости от ее длины, т.к. стринга это массив чаров то с точки зрения памяти лучше использовать инт, так как, к примеру, 100 или 100500 - 4 байта, а для “100px” - 10 байта и в базе надо хранить в типах, которые меньше весят, и трафика, чем меньше гоняешь, тем лучше, все просто.
В PHP, почему не использовать __set вместо огромного набора setter'ов?
Именно так делают большинство фреймворков старого образца
Но есть ряд минусов
1) нет подсветки (Laravel style)
2) над сеттерами часто используют аннотации или в PHP 8 аттрибуты для дополнения логикой (например валидация или связь с колонками в БД) но это уже не DTO (Simfony style)
3) нет возможности разбирать с помощью рефлексии (Magento style)
Но чем хорош PHP по сравнению с C# или JS, то что можно автоматически генерировать DTO (из конфига, yaml например) в специальную папочку и автолоадер будет генерировать класс заново, если удалить старый класс.
По принципу генерации работает Magento, чем безумно ускоряет разработку в Java стиле в PHP
@@grommaks, прости, не сторонник фреймворков.
@@i.am.rossalex описанные проблемы могут быть актуальны и не во фреймворке. Любой паттерн работает в связке с остальной архитектурой, а значит мы можем использовать магический метод сет для облегчения установки данных, но пожертвуем другой частью приложения. И не понятно чем это будет отличаться от ассоциативного массива :)
@@grommaks согласен
Отличный контент!
7:57 слова про ДЕФОЛТНОЕ ЗНАЧЕНИЕ в ФИЛДЕ ИНТЕРФЕЙСА, заставляют усомниться в профессионализме автора канала.
Хорошее замечание, нужно было class использовать для моего примера
Чуток поторопился, надеюсь это мне принесет много комментов под видео и возможно дизлайков :) Спасибо за внимательность
Глядя на предыдущие видео на этом канале у меня нет сомнений, что автор - трушный профессионал. А ошибиться может каждый. Плох не тот разраб, который ошибается, а тот, который не признаёт ошибку и не делает выводов. Макс же наоборот - и признал и сделал выводы и исправился, хоть и в комментах уже. Так что от меня, Максим, - респект и уважуха
Есть впечатление что DTO появилось из за рефакторинга если в функции или методе более 2 параметров и если они логически связаны например user то их можно вынести в interface и использовать вместо 3 и более параметров
Да, это часть логики которую берет на себя DTO...даже в строгих языках или в языках где это сделать гораздо сложнее чем в JavaScript (PHP например) то использование DTO сильно упрощало поддержку, хоть и требовало дополнительных усилий по созданию DTO
Но не стоит забывать о втором важном назначении - разделении слоев) особенно когда есть эти самые слои в приложении)
В последнее время я перестал верить, что о создании слоистой архитектры много кто заморачивается, если это не продукт монолит
В PHP обязательные поля через конструктор передать можно было
DTO это не ValueObject, с конструктором есть свои нюансы. Но если подход с конструктором вписывается в архитектуру фреймворка или системы, то почему нет) но с трудом представляю Х полей в конструкторе, и при любом запросе добавить новые поля будут добавляться в конец списка параметров
После 6го примера уже потерялся что там происходит ) typescript лучший, ну и C#
у тебя в php в dto нет типизации? ты хоть в курсе что она появилась хрен когда, лет 5 назад?
А напомните как описать массив строк, в какой версии появилась такая возможность? Год назад это делалось через php docs
@@grommaks через коллекции. Речь правда не о том, а про дто, где вообще нет массивов
@@alexzhaliazouski5924 DTO это объект в котором что-то хранится, это что-то может быть массивом объектов или массивом примитивов. Или как сказано выше, коллекцией. Но как указать коллекцией чего? Generic ещё не завезли в PHP. В php типизация ещё не полноценная, чтобы покрыть все потребности этого паттерна, но есть обходной путь через аннотации и рефлексию комментариев над свойствами или в более новой версии это атрибуты
Добрый день! Пример не совсем корректный, как по мне. Больше все таки относится к фронтенду. Также не совсем понял, почему у с# "похуже" типизация?) Да и зачем вообще типизировать и строкой и числом? Бред полный, пришедший из фронденда как раз, имхо) Даже если и есть такая необходимость, то что делать потом с этой dto, если ее параметр, который может быть и числом и строкой, должен передаваться в какую нибудь другую функцию, которая принимает например только число? Будем городить проверки и приведения. Такое себе, имхо. А таких функций может быть много. Поэтому не лучше типизировать строго одним и при инициализации dto один раз привести к чему-то одному?
Такая жизнь) приходится городить что-то потом по необходимости.
Гибкость динамического языка программирования с типизацией раскрыты в TypeScript который не ограничен способом хранения данных, а лишь предоставляет механизм декларирования типов.
TypeScript мощнее чем возможности типизации в C#, потому что в C# это прежде всего задача хранения свойств и оптимизации используемой памяти...а в TypeScript это облечение написания логики проекта
Как дела обстоят с Enum со строковыми значениями в C#? Насколько мне известно, то сложно
НА props.loop === false ? false : true; ЗАКРЫЛ ВИДЕО!
по моему это заморочь ... а если передается параметр которого нет, как он обработается? ошибки возможны, и подобный подход не панацея ... имхо и в дто по классике логики быть не должно. Подобный финт используется в яве, это обуславливается особенностями языка, как я считаю
+
Не самая лучшая реализация DTO у вас в PHP...