Здравый смысл есть, но все же идёт подмена понятий. Если замолкать вызовы то это юнит тест. Если вместо соков уже какая то реализация, то это не юнит. Есть ещё компонентные тесты, но тут сложно провести границу, где начнутся инновационные. Так что если вместо большого pgsql вы поставите SQLite, то юнит тестом это вы никак не можете назвать
Вот опять запихали репозиторий. Вот зачем? Ну когда возникает необходимость изменить ORM? Даже если такое потребуется, то все равно придется менять репозиторий, к гадалке не ходи. А так над EF, который и так реализует UoW+Repository ещё один «обвес». Опять же, все объяснения репозитория работают только с этими «лабораторными» приложениями (ToDo, People и т.п.). Когда появляются множественные связи, все рушиться, как карточный домик
Давно есть стандартная кросплатформеная либа для работы с изображениями на .Net Core devblogs.microsoft.com/dotnet/net-core-image-processing
Да, тот же ImageSharp обладает готовыми методами и хэлперами. Но в любом случае это готовое решение. В своем проекте я именно его использовал для резайза. Более чем доволен результатом
Что-то подобное уже читал, кажется на medium.
Вот как это часто бывает, все на пример Hello World. Все вокруг похлопали и забыли, потому что нет описания реального применения.
Неудобство флага fake в том, что классы сервисов становятся слишком большими и содержат логику к ним не относящуюся. Более правильно сделать абстрактный класс сервиса и два наследника: реализация сервиса и фейковый. В случае фейк-режима, фабрика будет инжектировать фейк-сервис. Но и это порождает много дополнительного кода, ведь для каждого сервиса, работающего в фейк-режиме, необходимо иметь фабрику для инжектирования, а также базовый абстрактный класс. Поэтому в таком случае, лучше всего использовать HttpInterceptor, выдающий определенные ответы. Тогда и код фейковых запросов будет строго изолирован, и сервисы не потребуют дополнительного кода. Более того, сервисы даже знать не будут, что работают с фейковыми данными
Ещё один паникер. Один раз раскупили к некоторых магазинах макароны, так форумы тут же взорвались.
От себя: да, народу мало, многие в масках или их «заменителях». Но никаких пустых полок в магазинах нет. Разве что много раскуплено в онлайн-магазинах. Причины: кто-то боится выходить на улицу, кто без масок после новостей о том, что не будут пускать без них просто сидит дома, кто-то просто «закупился по максимуму».
Согласен с автором на счет тестирования БД. Да, это будут уже совсем не unit-тесты, а интеграционные. Но, как правильно было замечено, попытка замокать приводит к копипасту кода EF. Кстати, нельзя просто так замокать DbContext или DbSet. Отсюда вытекают фразы «так есть же шаблон UnitOfWork + Repository». Опять начинаются «танцы с бубном», чтобы обернуть EF в шаблон репозиторий, в то время как сам EF уже реализует UnitOfWork+Repo.
Второе. Когда ж, закончиться этот ужас с #if DEBUG. Ну специально для этого в .Net Core при работе с файлами конфигураций добавили поддержка имени окружения. Не зря же пустом проекте можно найти appsettings.json и appsettings.development.json
Почему не рассматривается вариант с проектом интеграционных тестов в Core? В своей практике я всегда его использовал для работы unit-тестов, связанных с БД. Нужна минимальная «обвязка». К тому же, в некоторых случаях необходимо работать с in-memory database. В случае статического метода, класс контекста начинает «обрастать» новыми метода, в зависимости от сценариев использования, что никак не добавляет читабельности коду. Даже class helpers проблему не решат, а только спрячут ее
Вот как раз 0 или 1.. Их заголовки это тоже данные, не имеющие отношение к данным. Но не будем спорить в этом русле, потому как и ваш вариант также укладывается в MVC. Я говорю немного о другом. Если заголовки enum относить к представлению, то получается, что одни и те же данные и бизнес платила для них будут находится на нескольких уровнях. И это главная проблема. Да, тут можно поспорить, "что есть представление", не отрицаю, тут ваши аргументы весомы. Но для чего обычно используется enum (точнее когда я его использую). Когда необходимо описать набор значений, от которых может зависеть бизнес-логика, когда это крайне неудобно представлять в виде отдельной таблицы в БД. Например, при описании набора состояний, особенной когда по условиям задачи, варианты состояний не меняются. Если это реализовать в виде таблицы, то в коде будет неявная свять, в виде "если Id=0, то вызываем какую то функцию". Поэтому и удобнее использовать enum. Это позволяет определить набор состояний, которые можно хранить в базе и которые однозначно определяются в коде. Но это пять же мое мнение.
Не совсем соглашусь с вами. То, что 0 соответствует строке «Any», а 1 — «Open» это никак не слой представления, это данные. 0 и 1 это идентификаторы. Строки — значения, им соответствующие.
Но наша идея интересная и имеет место быть.
Enum используется в проекте «исторически» и задача по стоит поддерживать чтение из существующей базы.
В конкретно взятом случае — да. Но если это веб-сервис, или вам нужно получить список сущностей с фильтрацией и сортировкой, то маппинг плохая идея. Тут нужно проекцией пользоваться
В статье как раз есть такой хелпер EnumHelper.GetShortname
Но идея то не в этом, а в том, как эту операцию "отправить" в sql-запрос, чтобы не вытягивать из базы все записи, а потом маппить из поля
Согласен. Но это уже будет не будет «не то». В таком случае, используя Automapper, в запрос будут добавлены `JOIN`.
Я говорил о том, что не получиться создать индекс для проекции, создаваемой «на лету». Если бы это был `VIEW, тогда да. Для вьюшек в MSSQL можно создать индексы. Но не для одного запроса
Если вы уже получили корректный IQueryable, т.е. когда как минимум можно получить данные через ToArray/ToList, значит запрос корректно транслируется в sql-запрос.
В данном случае, нужно помнить что тип данных результирующей колонки будет STRING. Поэтому при применении сортировки и фильтрации к этому полю, операции будут применяться к строковому результату, а не к исходному числовому enum.
Поддержу. Ничего принципиально нового не рассказали. Изначальные примеры взяты с презентации DevCon. Была попытка рассказать про тонкости работы. Но рассказано было так плохо, что понять это можно только если ты сам полностью понимаешь эти тонкости. Если объективно — вебинар требует хорошей доработки и отметки сложности 101 (для новичков)
М — полнофункциональная модель предметной области. Не имеет связи ни с контроллером, ни с представлением.
Не очень понятно, что такое «полнофункциональная», но да, она не должна иметь ничего общего с другими компонентами
V — средство отображения, кроме шаблонов обладающее собственной логикой
View может обладать своей логикой, но реализовывать ее. Строго говоря, в нем и логики нет, ее реализует средство управления отображением.
C — набор действий — конечных точек маршрутизации.
Нет! базовый класс Controller в ASP.NET MVC — таковым является, потому как определяем какие данные принять и какой view вернуть. Но Контроллер в MVC не является средством маршрутизации.
Вообще, в статье, на мой взгляд, поднято несколько проблем, заслуживающих внимания и пояснения. Но вот пояснения в некоторых случаях только больше путают.
На Хабре было две замечательные статьи по мотивам публикаций Реенскауга, где рассказывается, что именно «прородитель MVC» имел в виду код каждым компонентом системы. Один Два
Здравый смысл есть, но все же идёт подмена понятий. Если замолкать вызовы то это юнит тест. Если вместо соков уже какая то реализация, то это не юнит. Есть ещё компонентные тесты, но тут сложно провести границу, где начнутся инновационные. Так что если вместо большого pgsql вы поставите SQLite, то юнит тестом это вы никак не можете назвать
devblogs.microsoft.com/dotnet/net-core-image-processing
Да, тот же ImageSharp обладает готовыми методами и хэлперами. Но в любом случае это готовое решение. В своем проекте я именно его использовал для резайза. Более чем доволен результатом
Вот как это часто бывает, все на пример Hello World. Все вокруг похлопали и забыли, потому что нет описания реального применения.
От себя: да, народу мало, многие в масках или их «заменителях». Но никаких пустых полок в магазинах нет. Разве что много раскуплено в онлайн-магазинах. Причины: кто-то боится выходить на улицу, кто без масок после новостей о том, что не будут пускать без них просто сидит дома, кто-то просто «закупился по максимуму».
Вот и будет у вас окружение
Второе. Когда ж, закончиться этот ужас с #if DEBUG. Ну специально для этого в .Net Core при работе с файлами конфигураций добавили поддержка имени окружения. Не зря же пустом проекте можно найти appsettings.json и appsettings.development.json
Почему не рассматривается вариант с проектом интеграционных тестов в Core? В своей практике я всегда его использовал для работы unit-тестов, связанных с БД. Нужна минимальная «обвязка». К тому же, в некоторых случаях необходимо работать с in-memory database. В случае статического метода, класс контекста начинает «обрастать» новыми метода, в зависимости от сценариев использования, что никак не добавляет читабельности коду. Даже class helpers проблему не решат, а только спрячут ее
Вот как раз 0 или 1.. Их заголовки это тоже данные, не имеющие отношение к данным. Но не будем спорить в этом русле, потому как и ваш вариант также укладывается в MVC. Я говорю немного о другом. Если заголовки enum относить к представлению, то получается, что одни и те же данные и бизнес платила для них будут находится на нескольких уровнях. И это главная проблема. Да, тут можно поспорить, "что есть представление", не отрицаю, тут ваши аргументы весомы. Но для чего обычно используется enum (точнее когда я его использую). Когда необходимо описать набор значений, от которых может зависеть бизнес-логика, когда это крайне неудобно представлять в виде отдельной таблицы в БД. Например, при описании набора состояний, особенной когда по условиям задачи, варианты состояний не меняются. Если это реализовать в виде таблицы, то в коде будет неявная свять, в виде "если Id=0, то вызываем какую то функцию". Поэтому и удобнее использовать enum. Это позволяет определить набор состояний, которые можно хранить в базе и которые однозначно определяются в коде. Но это пять же мое мнение.
Но наша идея интересная и имеет место быть.
Enum используется в проекте «исторически» и задача по стоит поддерживать чтение из существующей базы.
В конкретно взятом случае — да. Но если это веб-сервис, или вам нужно получить список сущностей с фильтрацией и сортировкой, то маппинг плохая идея. Тут нужно проекцией пользоваться
В статье как раз есть такой хелпер
EnumHelper.GetShortname
Но идея то не в этом, а в том, как эту операцию "отправить" в sql-запрос, чтобы не вытягивать из базы все записи, а потом маппить из поля
В любом случае, мы явно отдалились от изначального вопроса.
Я говорил о том, что не получиться создать индекс для проекции, создаваемой «на лету». Если бы это был `VIEW, тогда да. Для вьюшек в MSSQL можно создать индексы. Но не для одного запроса
Индексация над проекцией в принципе невозможна.
Например, есть таблица USERS с ID, NAME, SURNAME.
Какой тут индекс?
Если вы уже получили корректный
IQueryable
, т.е. когда как минимум можно получить данные черезToArray/ToList
, значит запрос корректно транслируется в sql-запрос.В данном случае, нужно помнить что тип данных результирующей колонки будет
STRING
. Поэтому при применении сортировки и фильтрации к этому полю, операции будут применяться к строковому результату, а не к исходному числовому enum.Не очень понятно, что такое «полнофункциональная», но да, она не должна иметь ничего общего с другими компонентами
View может обладать своей логикой, но реализовывать ее. Строго говоря, в нем и логики нет, ее реализует средство управления отображением.
Нет! базовый класс Controller в ASP.NET MVC — таковым является, потому как определяем какие данные принять и какой view вернуть. Но Контроллер в MVC не является средством маршрутизации.
Вообще, в статье, на мой взгляд, поднято несколько проблем, заслуживающих внимания и пояснения. Но вот пояснения в некоторых случаях только больше путают.
На Хабре было две замечательные статьи по мотивам публикаций Реенскауга, где рассказывается, что именно «прородитель MVC» имел в виду код каждым компонентом системы.
Один
Два