• Обзор самых интересных докладов DotNext 2018: версия EastBanc Technologies
    0
    Какую книгу читать сначала: “синюю” или “красную”?

    Ну так какую?

  • Не уважаю инкапсуляцию, или использование таблицы методов другого типа для быстрого вызова приватных методов
    0
    Фух, я уж думал, я опозорился начав писать коменты, не прочитав статью.
  • Не уважаю инкапсуляцию, или использование таблицы методов другого типа для быстрого вызова приватных методов
    0

    Хм, если честно у меня более прозаическая догадка.
    Игрался с таким кодом


    Заголовок спойлера
    public class CustomClass
    {
        public override string ToString()
        {
            return "CUSTOM";
        }
    
        public virtual object SomeVirtualMethod()
        {
            return "SomeVirtualMethod";
        }
    
        public object SomeMethod()
        {
            return "SomeMethod";
        }
    }
    
    [StructLayout(LayoutKind.Explicit)]
    public class CustomStructWithLayout
    {
        [FieldOffset(0)]
        public string Str;
    
        [FieldOffset(0)]
        public CustomClass SomeInstance;
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            CustomStructWithLayout instance = new CustomStructWithLayout();
            instance.SomeInstance = new CustomClass();
            instance.Str = "4564";
            Console.WriteLine(instance.SomeInstance.GetType()); //System.String
            Console.WriteLine(instance.SomeInstance.ToString()); //4564     
    
            Console.WriteLine(instance.SomeInstance.SomeMethod()); // SomeMethod
            Console.WriteLine(instance.SomeInstance.SomeVirtualMethod()); // null       
        }
    }

    И как мне кажется, для виртуального метода CLR генерит метод-заглушку, возвращающий дефолтное значение.


    Поскольку, насколько я понимаю, для вызова виртуального метода CLR необходимо действительно найти этот метод в иерархии типа, и так как метода SomeVirtualMethod нет в иерархии типа string, то и возвращается эта заглушка.

  • Не уважаю инкапсуляцию, или использование таблицы методов другого типа для быстрого вызова приватных методов
    0
    Разрядка для мозгов: Что будет выведено при вызове виртуального свойства CustomClass?

    А можно для не просвящённых почему так?
    Я понимаю, какой был бы результат, если бы свойство было не виртуальным, но почему возвращается null для виртуального я не догоняю.


    Мне бы хотелось получить что-нибудь вроде MethodNotFoundException.

  • Модификация ajax js для ajax Asp .net mvc
    +2
    Вы же понимаете, что multipart это стандарт и никак не привязан к технологии?
  • Модификация ajax js для ajax Asp .net mvc
    0
    Не использовать Ajax.BeginForm, использовать FormData, сделать php обработчик и еще тучи советов по увеличению программного кода.

    Думаю, стоило прислушаться к совету и не использовать Ajax.BeginForm.
    Кода получилось бы меньше, да и получился бы он более поддерживаемым. А с учётом кучи JS библиотек, задачу вы решили бы быстрее.


    Да и логику вашего обработчика/хелпера я так и не понял.

  • PWA — это просто
    0

    Не так давно я мониторил место на диске и обнаружил 4гб папку в профиле хрома — indexeddb от my.mail.ru. При этом я даж хз когда я туда заходил.

  • Redux против React Context API
    +1

    юзайте сагу наконец

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

    Ну, в общем-то, в статье. Под заголовками "Код без cross-cutting concern" и "Код с cross-cutting concern"

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

    Всё просто, на самом деле. Смотрите здесь https://github.com/jbogard/MediatR/wiki/Behaviors


    Очень удобная штука. Вынесли валидацию и транзакции


    DataAnnotation валидация
        public class DataAnnotationsValidationPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
        {
            public Task Process([NotNull] TRequest request, CancellationToken cancellationToken)
            {
                var context = new ValidationContext(request);
                var results = new List<ValidationResult>();
    
                if (Validator.TryValidateObject(request, context, results))
                {
                    return Task.CompletedTask;
                }
    
                var errors = results.Select(x => new ValidationFailure(x.MemberNames.First(), x.ErrorMessage));
                throw new ValidationException(errors);
            }
        }
    
  • Смена основного стека с .NET на Java
    0

    rider нынче позволяте дебажить чужие исходники

  • Вредный Кейворд «Interface»
    +1

    Не то, чтобы это прям решение для всех, но в решарпере есть возможность делегировать реализацию в один клик.

  • Вредный Кейворд «Interface»
    +7
    "Не пользуйтесь ООП в ООП"? Ну круто, теперь заживём.

    ООП это не только наследование. Я не призываю отказываться от наследования совсем, но мой подход чем реже, тем лучше.


    А если писать код как попало, то это "частенько" ведёт к нарушению всего SOLID. Это не причина.

    Серебряной пули и правда нет. Но есть best practices и они появились не с пустого места. А насчёт аббревиатур — это удобный способ донести мысль другому человеку по-быстрому.


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

    Везде свои компромиссы. Хотите хорошую систему, с которой приятно работать и удобно вносить изменения — делегируйте; проект небольшой — колбасьте код как угодно.
    Да и про какие сотни строк вы говорите? Если у вас есть класс, который реализует так много интерфейсов, то проблема возникла раньше. Опять же из-за не следования хорошим практикам.


    Жить вообще опасно. Просто если хочешь унаследоваться вместо композиции — подумай 10 раз, унаследоваться глубоко — 100, унаследоваться множественно — 1000.

    Об этом и речь — зачем усложнять и думать 10-100-1000 раз, если можно сделать просто?


    Интерфейсы ни от чего не спасают. Это ужасная сущность с точки зрения развития системы, потому что их изменять вообще невозможно. Любое изменение — всё, система сломана.

    Интерфейсы это ваш контракт. Это ваш api, если хотите. И если контракт меняется, значит на то была причина — изменилось требуемое поведение.


    Чем это лучше классов, где что-то в предках изменилось, и вдруг поломался потомок? Ну, хотя бы есть ненулевой шанс, что оно будет работать. Изменение интерфейса ломает систему всегда.

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


    Рассуждение выше про интерфейсы немного устаревает с введением костыля под названием "default interface implementation" — интерфейсы теперь становятся недо-классами.

    Согласен, default interface implementation неоднозначная фича. Пока что, я вижу ей применение для добавление утилитарного поведения, вроде того же observer'a.


    Кстати, насчёт глубокой цепочки наследования в GUI — тот же реакт построен на High Order Components и там этот подход весьма органичен.

  • Вредный Кейворд «Interface»
    +29

    Лениться делегировать — это экономия на спичках. Больше огребётесь от огромного количества наследников.


    Наследование это не способ писать меньше кода. Это способ выразить отношение is-a (ну и ещё способ сделать discriminated union, в языках где его нет). Более того, я считаю что наследование как раз более вредно — чем чаще вы наследуете, тем более костной становится ваша система.
    Примеры:


    1. У вас есть базовый класс, который часто наследуется в вашей системе. Затем, только некоторому числу наследников понадобилось новое поведение — вы меняете базовый класс, но вместе с этим вы также меняете и контракт тех классов, которым это поведение не нужно. Как итог, вам нужно протестировать те компоненты, которые даже не менялись — нарушение OCP. А ещё частенько ведёт и к нарушению LSP.


    2. В укор первому примеру, вы можете сказать — "да я щас наделаю много мелких классов (например, VisibleAndSolid, VisibleAndMovable, VisibleAndSolidAndMovable) с точечным поведением и буду множественно наследовать от них". Ок, но чего вы этим сэкономите? Количество LOC будет примерно сравнимым при композиции. Только в этот раз вы усложнили систему, наделав в ней кучу ненужных сущностей.


    3. Имея некоторый базовый класс, вы делаете вид, что знаете как он будет использоваться. Нарушение инкапсуляции здесь ещё грубее — каждый разработчик должен знать детали реализации в базовом классе (иначе опять можно нарушить LSP).


    4. Ещё более опасна длинная цепочка наследования. Например, есть у вас некоторая иерархия с некоторым поведением в самом верхнем родителе. Затем, одному или нескольким наследникам нужно отличное поведение. Как итог порождается ещё одна иерархия классов, что в конечном итоге ведёт к сложности системе.

    Да и вообще сто раз это исписанно.


    ps. В java (и скоро в c#) ведь есть partial interface implementation — пользуйтесь.

  • Исследуем минорные возможности C# 7
    0

    "Бойлерплейтить" — это добавить один метод MainAsync и дождаться его завершения в Main?

  • А вы знаете где можно применить expression's в вашем проекте или оптимизация создания тестов
    +1

    AutoMoq AutoFixture


    А вообще, мне кажется, проблемы у вас поглубже

  • Анатомия .NET Core: как мы настроили NTLM под Linux
    0

    Не пробовали в CoreFx закомитить переключалку способа аутентификации?

  • Управляем состоянием приложения без шаблонного кода и магии
    0
  • О чем не пишут в документации, или тонкости рефакторинга на .Net Core
    +1

    Не пробовали https://habrahabr.ru/post/319996/ ?

  • CQRS. Факты и заблуждения
    +1

    https://martinfowler.com/bliki/ContextualValidation.html
    https://lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world/


    Главный посыл таков — "Instead of answering the question, “is this object valid”, try and answer the question, “Can this operation be performed?”.


    Например, мы можем сохранить некоторый заказ без адреса в базу, но выполнить операцию отправки нет.

  • CQRS. Факты и заблуждения
    0

    Есть такой подход в ddd, как ContextValidation. Думаю, его лучше юзать

  • CQRS. Факты и заблуждения
    +3

    С guid'ами проще, например, мержить две таблицы в одну либо данные с двух разных бд. Был реальный кейс объединения двух клиентских баз

  • CQRS. Факты и заблуждения
    0

    BTW у автомаппера также есть возможность не писать явный маппинг

  • CQRS. Факты и заблуждения
    +1

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

  • CQRS. Факты и заблуждения
    0

    Есть несколько сервисов типа LdapServise/AuthService, но всякие бизнес и crud операции напрямую в обработчике.


    Вот кстати еще вопрос — а кошерно ли использовать CommandHandler'ы внутри CommandHandler'ов?


    Джимми Боггард пишет, что нет и лучше юзать композицию/реализовывать несколько commandHandler'ов в одном классе

  • CQRS. Факты и заблуждения
    +1

    По поводу только одного интерфейса- достаточно завести свой собственный интерфейс и унаследовать от IRequest
    Что-то вроде
    interface IQuery: IRequestКовариацию не забудьте только, мне с телефона неудобно редактировать

  • CQRS. Факты и заблуждения
    +1

    У медиатра ваш прием с ResultHandler'ом не пройдет, поскольку вы меняете тип возвращаемого значения.
    Но всякие валидации, транзакции и прочие шаблоны очень здорово залетают в pipeline behavior

  • CQRS. Факты и заблуждения
    0

    Mediatr очень хорошо подойдет. Сделали на нем уже два проекта.
    Посмотрите мои ссылки выше и ниже, там статьи от создателя медиатра с хорошей теорией и практикой.

  • CQRS. Факты и заблуждения
    +1

    Спасибо за статью!
    У меня нубский вопрос — а как быть с загрузкой данных во write части? Городить ещё репозиториев для CommandHandler'ов?


    Сейчас я в обработчиках использую EF контекст напрямую и при тестировании подменяю хранение на InMemoryStorage (у нас ef core) и вроде всё хорошо, но как-то не по себе.
    В общем-то, пример можно посмотреть здесь у Jimmy Bogard'a

  • CQRS. Факты и заблуждения
  • Не вебпаком единым
    +1

    Поддержка async/await в браузерах уже давненько нативная, поэтому при разработке не имеет смысла их транспайлить в es5 => нет проблем с отладкой

  • Как искать IT вакансии в ЕС
    0

    По моему опыту, компанию посредник открывал сразу же.
    Так же хороший посредник может за вас договориться о зарплате и выбить вам какие-нибудь бонусы.

  • DI для полностью переиспользуемых JSX-компонентов
    0

    Я имею ввиду посмотреть саму идею расширяемости wpf; понятно, что это не перетащишь в веб просто так (хотя попытки были http://bridge.net/ http://www.cshtml5.com )
    У меня просто стойкое ощущение, что всё это было там уже довольно давно.

  • DI для полностью переиспользуемых JSX-компонентов
    0

    Посмотрите WPF с его точками расширения/слотами/темплейтами и DataContext'ами.
    Вот там можно переопределить всё и даже довольно удобно.

  • Lazy Loading в Entity Framework
    –1

    Для устранения протечки абстракции

  • Lazy Loading в Entity Framework
    –3

    Не использовать lazy loading, абстагироваться от персистенса и может даже перейти на dapper.

  • Два года с Dart: о том, как мы пишем на языке, который ежегодно «хоронят» (часть 2)
    0

    У вас, видимо, неправильный ООП

  • Junior, который в первый день работы удалил базу данных с production
    0

    Не, вот тут


    Далее, как понимаю, тесты добавили ненастоящие данные и очистили существующие, то есть между запусками тестов все данные из БД в production были удалены
  • Junior, который в первый день работы удалил базу данных с production
    0

    В тестах, написано же

  • Redux: попытка избавиться от потребности думать во время запросов к API
    0

    А по-моему, это как раз про то.
    Имея middleware и единую шину, мы можем контролировать и реагировать на любое действие централизованно, а не позволять произвол на местах (в контейнерах).
    Взять ту же обработку ошибок/логгирование/телеметрию.


    +без redux надо shouldComponentUpdate писать самому