• Чем бизнесу и пользователям грозит борьба РКН и Telegram? Мнения экспертов
    +1

    Например то, что у меня на конкретной машине не было локального кеша и я минут 5 соображал почему у меня Rider пакеты не обновляет

  • О декораторах, сквозной функциональности, CQRS и слоеной архитектуре
    0
    Думаю, доменные события для такого логирования подойдут лучше декораторов.
  • О декораторах, сквозной функциональности, CQRS и слоеной архитектуре
    0

    Добавьте дополнительное логирование в необходимых ветках. Можно явно с помощью императивного кода или с помощью декораторов для декораторов. Это как удобнее. Цель статьи — показать как можно очистить доменную логику от инфраструктурного кода. Взаимодействие инфраструктуры с инфраструктурой — другой вопрос.

  • О декораторах, сквозной функциональности, CQRS и слоеной архитектуре
    0

    Спасибо большое за комментарий. Вы поняли все верно. Я теперь знаю, что донёс идею внятно:)

  • О декораторах, сквозной функциональности, CQRS и слоеной архитектуре
    0
  • Паттерны внедрения зависимостей. Часть 1
    0
    Как гарантировать, что вызов DoSomething из вашего примера произойдет после того как Dependency будет установлен?
  • Паттерны внедрения зависимостей. Часть 1
    0
    «Необязательные зависимости» довольно часто свидетельствуют о нарушении SRP и приводят к NRE. Так что лучше без них.
  • REST API Best Practices
    0

    Или 422, например если валидация не прошла.

  • Почему не работают Уставы и Планы управления проектом?
    0
    Де-факто все это разбивается о нашу судебную систему. Довольно часто дороже судиться, чем расстаться с клиентом. Кроме того, не всегда судебное решение легко исполнить.
  • Опыт разработки некоммерческого проекта силами джуниоров
    0

    Может потому что этих людей за деньги не спешат брать и они хотят набраться опыта, чтобы брали?

  • Если у вас нет собаки…
    +2
    А писали бы на .NET взяли бы готовый SpecFlow :)
  • Карго-культ вокруг и внутри нас: IT HR и маркетинг
    0
    Тут: cargo-cult.club? Видео трансляции появится вместо регистрации?
  • Карго-культ вокруг и внутри нас: IT HR и маркетинг
    0
    А трансляция будет?
  • Вопросы для собеседования бэкенд-разработчика
    +1

    Я на большинство вопросов «хотите обсудить эту тему» ответил «нет»:) Видимо, меня не возьмут.

  • Кто такой программист?
    –1

    Вы не один такой. Мне 29, я тоже окончил физ-мат школу и виду как снижается качество образования. Готовят в основном «обслуживающий персонал». Может это и неплохо, но все чаще ощущаю себя героем романа Олдоса Хаксли.

  • CQRS. Факты и заблуждения
    0
    Кстати, не хотите подлелиться опытом в DDD в комментариях здесь? Я как раз затронул тему «прикладного» DDD в рамках ООП-парадигмы.
  • Domain Driven Design на практике
    0
    cartCalculator.Calculate(cart), кэп!:) Калькулятор считает ценую корзины, потому что скидки могут применять как позиции заказа, так и заказу в целом. Бывает «3 по цене 2», «купи на 3000 рублей и получи в подарок шнурки для галошь» и просто накопительные скидки для постоянных клиентов.
  • CQRS. Факты и заблуждения
    +1
    F# в вопросе типов сильнее C#. Например, union'а часто не хватает для моделирования, приходится multiple dispatch городить. Опять же какое ООП имеется в виду? То, что в C++ или в SmallTalk?
  • Domain Driven Design на практике
    0
    На одном из проектов есть такая задача. У нас отдельно Product.BasePrice и есть CartCalculator. Внутри калькулятора — еще другие зависимости, которые расчитывают цену в зависимости от лицензии, роялти, накопительной скидки и других бизнес-правил.
  • Domain Driven Design на практике
    0
    Можете раскрыть свой вопрос более подробно?
  • Domain Driven Design на практике
    0
    Спасибо за вопросы.
    Обоснуйте пожалуйста, почему метод Accept принадлежит сущности Company. Ведь аккредитация выдается Ведомством. А то получается что компания сама себя куда хочешь может аккредетировать… Ну или как минимум в этот метод должен передаваться Policy ведомства или экземпляр объекта Аккредитация, с данными кто выдал и почему.

    Именно в данном приложении ведомство было одно, а аккредитация проходила автоматическом режиме при закрытии квартала при соблюдении определенных условий. Сущность в проекте называется по другому и там довольно увесистый агрегат. Возможно более естественно смотрелись бы названия методов BecomeAccepted и BecomeDeclined, чтобы субъект и объект действия не путались.

    Почему метод DangerouslyChangeInnAndKpp вообще содержит в себе эту приставку? Если предметной области это нормальное явление — это бессмысленно. Может стоило тогда ввести другую сущность?

    Смена ИНН и КПП — это перерегистрация. Т.е. в реальном мире нельзя просто так взять и сменить. Однако, предполагалось, что в подаваемых сведениях могут быть ошибки и к системе были предъявлены требования дать возможность эти ошибки исправлять.
    Название DangerouslyChangeInnAndKpp навеяно React'ом. Видимо, зря я удалил аннотации, в которых эта логика объяснялась.

    Я не знаком с .Net вообще, но вы упоминаете «луковую» и «чистую» архитектуры, а потом в домене используете public class Specs. Разве это не кусок вашего фреймворка только что просочился в домен? Т.о. вы нарушаете направление связей.

    В .NET на уровне платформы встроены «деревья выражений» (Expression Trees). Например:
    Expression<Func<Company, bool>> acceptedSpec = 
         x => x.State = CompanyState.Accepted;
    

    Expression<Func<Company, bool>> — довольно многословная конструкция. Spec<T> — более читаемая и сразу специализирована для сигнатуры T -> bool. Плюс добавлена перегрузка операторов && и ||. Спецификация по определению представляет правила бизнес-логики, т.е. является частью домена.

    Необязательно создавать спецификации внутри класса сущности, можно положить их рядом. Мне просто удобно использовать такой синтаксис: Company.Specs.Accepted. Все бизнес-правила фильтрации агрегата Company под рукой и intellisense поможет их найти. Можно использовать и другие правила, например отдельный статический класс. Тогда будет так: CompanySpecs.Accepted.
  • Domain Driven Design на практике
    0
    Промахнулся и ответил вам ниже отдельным комментарием.
  • Domain Driven Design на практике
    0
    Непонятно только только, почему при использовании DDD нельзя описывать бизнес логику в сервисах

    Почему же нельзя? Сервисам посвящен целый параграф. Другой вопрос, что есть смысл хранить не всю логику. Обратите внимание на метод Decline. Он четко показывает: чтобы отклонить заявку необходимо добавить непустой комментарий с пояснением, почему компания не может быть аккредитована. Представьте, у нас в домене три бизнес-сценария, где мы должны отклонять аккредитацию. Где гарантия, что все три метода будет реализовывать один разработчик? Даже если так, он может забыть правило про обязательный комментарий. В варианте с отдельным методом это невозможно.

    Кроме того в реальном приложении при отклонении необходимо было хранить историю заявок, в том числе с указанием менеджера, работающего с юр.лицом. При переходе из одного статуса в другое необходимо было менять 2-3 разных поля по определенным правилам. Объектная модель с поведением здорово помогает с пониманием «что здесь происходит и почему».

    Более подробно этот вопрос раскрывает Дино Эспозито. Ближе к концу доклада он приводит следующий пример. Допустим, в поддержку приходит баг. Пользователь объясняет, что он совершил некоторое действие, но ему не были начислены бонусные балы (или типа того). Если в коде программист видит «репозитории» и изменение каких-то свойств ему потребуется приложить дополнительные усилия, чтобы интерпретировать слова пользователя и сопоставить с кодом. А если он видит в коде нечто вроде:
    if(user.IsVip)
    {
       user.AddBonus(100);
    }
    

    Он может сразу уточнить статус пользователя. Может быть, про бонусные баллы он услышал от друга, а про VIP-статус позабыл. Может быть у нас баг и пользователю не был присвоен VIP-статус, хотя должен был. В любом случае, диалог получится куда более предметным.
  • Domain Driven Design на практике
    0
    Спасибо за комментарий. Ошибся при редактировании кода. ToList там вообще не скомпилируется, потому что ByInnAndKpp выполняет FirstOrDefault. Добавил пример метода ByInn и отредактировал статью.
  • CQRS. Факты и заблуждения
    0
    Тогда я не понимаю, чего вы хотите. Все возможные варианты не устраивают:)
  • CQRS. Факты и заблуждения
    0
    Но сути это не меняет. Нужно бросить исключение чтоб прекратить выполнение и поднять сообщение(я) об ошибке наверх в контроллер. Я не в восторге от такого подхода.

    В моем примере используется возвращаемый тип Result, а не исключения. Подробно подход описан здесь.
  • CQRS. Факты и заблуждения
    0
    А ссылочкой не поделитесь?
  • CQRS. Факты и заблуждения
    0
    А этот вариант вам не подходит? При необходимости валидацию расширяете просто доменными правилами.
  • CQRS. Факты и заблуждения
    0
    Дописал. Все сходятся, что это неудобно. Мы пробовали компоновать QueryHandler'ы. Получается нечитаемо и многословно.
  • CQRS. Факты и заблуждения
    0
    На основании, что предметная модель не предоставляет естественного Id. Guid гарантирует уникальность за счет математики (хотя и подвержен коллизиям), Id — за счет СУБД. У Эванса, на сколько я помню, про выбор Id написано четко: если есть Id в домене — берите из домена. Нет — положитесь на технические срадства.

    кто гарантирует, что со следующим обновлением БД-движка или его заменой останутся те же самые идентификаторы?

    Приведите реальный пример обновления СУБД, чтобы слетели первичные ключи?

    Guid'ы совсем не бесплатные. Если есть возможность использовать автоинкремент в БД зачем усложнять себе жизнь?
  • CQRS. Факты и заблуждения
    0
    Один интерфейс решает проблему с двумя декораторами, которую я решил с помощью кастинга к делегатам. Это плюс.

    Субъективно кажется, что имея IRequestHandler<SomeCommand> и IRequestHandler<SomeQuery> проще запутаться и случайно добавить мутацию в IRequestHandler<SomeQuery>, чем в случае двух интерфейсов: IRequestHandler<SomeQuery>, а в IQueryHandler<SomeQuery>. Это минус.

    Библиотека выглядит приятно. Если у вас нет проблем с соблюдением нейминага и код-ревью не в web-морде, а в IDE (чтобы можно было по файлам пробежаться, посмотреть, проверить наличие мутаций), решение вполне имеет право на жизнь.
  • CQRS. Факты и заблуждения
    0
    Я имел в виду, что доменная модель смоделирована так: сначала есть «корзина», а в момент оформления появляется «заказ». Заказ создает наша система и сообщает его Id клиенту. Вы знаете альтернативу автогенерируемым БД Id и Guid для сущностей, для которых нет естественных Id (типа ИНН, КПП, паспортных данных и т.д.)?
  • CQRS. Факты и заблуждения
    0
    Все сделали на IRequest без сервисного слоя?
  • CQRS. Факты и заблуждения
    0
    Допустимо, но тогда это не CQRS так как доступ к данным организован через один и тот же объект для двух разных типов операций.

    Мы довольно долго так думали, пока не нашли QueryableExtension'ы. Кейсы, где нужно возвращать сущности как-то после этого кончились.
  • CQRS. Факты и заблуждения
    +1
    Сейчас я в обработчиках использую EF контекст напрямую и при тестировании подменяю хранение на InMemoryStorage (у нас ef core) и вроде всё хорошо, но как-то не по себе.

    А что вас не устраивает в таком подходе? DbContext уже реализует репозиторий, зачем городить абстракцию поверх. Можно отвязаться от EF и инжектировать IQueryable<T> через фабрику: dbContext.Set<T>(), но тогда EF не будет кешировать обращения по Id (по-умолчанию кешируются только вызовы метода Find). Это тоже можно исправить, но работа с контекстом — это вообще тема отдельной статьи.

    На практике абстракция от ORM создает больше проблем. Если можно говорить о какой-то заменяемости между EF и NHibernate, то остальные, даже если поддерживают LINQ требуют значительного переписывания кода для замены. Так что первая ложь — ORM абстрагирует вас от БД и вы сможете через 5 лет разработки переехать с Оракла на Постргес. Вторая — IQueryable абстрагирует вас от деталей реализации.

  • CQRS. Факты и заблуждения
    0
    И второй вопрос — что скажете на счёт MediatR в качестве инфраструктуры для CQRS. Там правда всего один интерфейс, но проблема деления на команды и запросы решается нэймингом.

    MediatR реализует идею separation of concerns, только вместо декораторов использует Behaviors. Даже используется «фишка» с пустым дженерик-интерфейсом, чтобы указать возвращаемый тип:

    public class Ping : IRequest<string> { }

    В данном контексте я не вижу разницы: использовать SimpleInjector с декораторами или MediatR. Есть смысл проверить производительность и выбрать, что работает быстрее. SimpleInjector компилирует деревья выражений, а MediatR использует механизм фабрик.
  • CQRS. Факты и заблуждения
    0
    Вы имеете в виду дорого писать маппинги для Select? Если да, посмотрите в сторону Mapster Queryable Extensions. Вы же в любом случае в JSON сериализуете не сущность, а какие-то агрегированные данные. Зачем тащить из базы ненужные поля, если можно выбрать только то, что нужно?
  • CQRS. Факты и заблуждения
    0
    Единственное, что мне до сей поры очень плохо ясно, это куда во всей этой схеме пихать валидацию?

    Посмотрите еще раз абзац с декораторами. Там пример, как работать с валидацией. Middleware тоже подойдет со следующими ограничениями:

    1. некоторые сущности могут быть вычитана по два раза
    2. транзакционностью придется управлять за границей CQRS-стека

    Тут был поднят вопрос без ответа на него: что делать с автосгенерированными БД ID? Я полагаю, тут истинно верного решения нет?

    Если у вас синхронный CQRS без шины — возвращайте Id из команды / хендлера и не мучайтесь. Если с шиной, то у вас либо должен быть механизм доставки доменного события «заказ создан» до пользователя, например web sockets. Либо отказ от автогенерируемых Id — создаем Guid'ы на клиенте.
  • CQRS. Факты и заблуждения
    0
    А если на начальном этапе разработки в качестве хранилища взять тот же EF Core, и оперировать его контекстом, как в командах, так и в запросах. А потом, по мере роста нагрузок и усложнения логики — проводить постепенный рефакторинг, устраняя узкие места (с использованием того же Dapper или вообще ADO).

    Я в абзаце «Возвращать из QueryHandler сущности или DTO» примерно это и предлагаю. Что вас смутило?:)
  • Java с ассемблерными вставками
    0
    .NET реализация сможет это делать только на win-платформе с запуском от администратора?