All streams
Search
Write a publication
Pull to refresh
36
1.2
Send message

Специфика ORM в том, что он сам по себе накидывает сложности проекту. И это оправдано там, где сложность проекта стала проблемой. Собственно, об этом и статья.

Я уже однажды приводил пример:

Orders.Where(o => o.IsCompleted && o.CreatedDate.Year > 2020).OrderBy(o.ID)

Трансформируется в:

SELECT * FROM db.Orders a WHERE a.IsCompleted = 1 AND YEAR(a.CreatedDate) > 2020 ORDER BY a.ID

Разница невелика на первый взгляд. Просто чистый sql ещё предстоит отправить через коннекшен, получить результат и распихать по полям объектов. ORM сам всё делает, строка самодостаточна.

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

Мы просто не знаем, зачем добавили прямоугольник в приложение. Это область детектирования номерных знаков автомобиля? Это баундбокс текстовой строки? Это примитив рисования?

Наследование квадрата от прямоугольника может быть правильным. Как и наследования прямоугольника от квадрата. Смотря чего хотите.

С одной стороны соглашусь. Команда должна быть сильная, чтобы понимать, что она делает и зачем. Конечно, без базовых знаний SQL заниматься разработкой приложения с ORM прямо противопоказано. Архитектурой тем более должен заниматься сильный программист, а внедрение ORM - это архитектура приложения.

С другой стороны, ORM умеет генерить селекты c where и некоторые умеют в left join. У EF правда есть linq to entities, где можно совращать гусей, но тут синтаксис максимально близок к sql. Если честно, совсем не понимаю, что в этих запросах может быть сложного.

Простите, а когда это "потом" начнётся? Один проект у меня уже 13 лет на ORM, пока всё хорошо. Или имеется в виду, что падает скорость разработки? Тогда тем более непонятно. ORM как раз нужен, чтобы снизив сложность, её повысить. И это работает.

Потому, что интерфейсом пользуются. Если им не пользуются, то "you ain't gonna need it". Тебе не нужен интерфейс без реализации, потому что им пользоваться не будут.

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

Если бы не одно но. Нет и не должно быть таких рекомендаций по использованию интерфейсов везде. Не надо, правда. Я насмотрелся на код, где каждый чих делается через интерфейс. Это НЕ удобно. Это НЕ правильно. Это НЕ даёт никакого выигрыша.

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

В случае с тестами оказывается, что мок класс - тоже класс. Внезапное такое откровение. И он станет второй реализацией.

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

  1. Single responsibility. В вашем примере нарушается инкапсуляция класса непонятно за какими целями. Вообще вполне нормально может быть, что робот может и move и speak. Вполне возможно, что у него эти методы завязаны на одних и тех же данных внутри класса. Если слепо следовать S, то у класса вылезают кишки наружу, логика переносится в другие классы, плодятся контроллеры, сервисы и прочие странные мутанты. Я уж не говорю про DDD, где класс соответствует термину предметной области - тут прямой конфликт с принципом единственной ответственности.

  2. Вы приводите в качестве примера простое использование наследования. Никакого отношения к OCP это не имеет. OCP - это когда часть класс спроектирован так, что можно без труда поменять логику в унаследованном классе, не трогая базовый класс.

  3. LSP. А что, если подставить экземпляр студента вместо персоны, он не будет работать? Пример нарушения - это как раз когда наследуют прямоугольник от квадрата и удивляются, почему при задании одного размера его не видно. Конечно, квадрат - это частный случай прямоугольника.

  4. ISP. Интерфейс вообще-то строится для клиентского кода. Соответственно, интерфейс может дробиться только до уровня требований этого кода. Если он требует объект, который должен и говорить и двигаться, то разделять эти интерфейсы не нужно. В вашем примере вы рассматриваете неправильную проектировку самого класса, а не интерфейсов. Ну на этапе создания Robot уже должно дойти, что он не умеет летать, верно?

  5. Интерфейс ради интерфейса? Вот зачем? Внедрять лишнюю сущность, когда нет ещё уверенности, что будет другая база данных - это раздувание кода ради культа карго.

Велосипед можно бросить в одно мгновение, чтобы отпрыгнуть в нужную сторону. Если, конечно, на нём не едешь.

У меня эта статья вызвала флешбеки )

Если мы получаем от словаря ссылку на структуру и потом работаем по ссылке, то чем, собственно говоря, это отличается от класса?

Да, есть небольшой выигрыш за счёт того, что ссылки не считаются и ансейф во все поля. Но этот выигрыш чувствителен только для сценария с большим количеством поисков и не пополняющимся словарём. Для такого сценария существуют контейнеры получше, вроде FrozenDictionary. А то и бинарное дерево.

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

И ещё. Не нашёл в коде объявления GetHash и Equals. Может у вас хэш коллизит и поиск деградировал до линейного.

чтобы такие ручки для разных модулей

Что за "ручки" такие? Вы тащите в статью какой-то ваш внутренний сленг?

По статье:

Нормализация. Делать нормализацию только потому, что "так учили" - сомнительно. Бывает приходится сознательно денормализовывать данные.

Отдельные схемы для разных модулей. Крайне сомнительно. Особенно, если данные используются далеко не одним модулем.

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

<данные удалены>

В этой статье мы разъясним довольно тонкий семантический вопрос, который часто остаётся за кадром при изучении программирования на императивных языках.

А где сформулированный вопрос?

Анекдот

Однажды Базарбаев пришёл в гости к Мыркымбаеву. Мыркымбаев угостил Базарбаева чаем с баурсаками, а сам вышел из комнаты. Через какое-то время Базарбаев пошёл в соседнюю комнату и увидел, что в ней сидит Мыркымбаев и ест целую тарелку дымящегося мяса. Базарбаев тогда сказал: — Как тебе не стыдно, ведь я гость, и ты должен был меня угостить мясом. На что Мыркымбаев ему ответил: — Ты стыдишь меня? Посуди сам: я угостил тебя чаем с баурсаками, и ты был доволен. Ты был доволен до тех пор, пока не вышел из комнаты и не увидел, что я ем мясо. Разве не ты сам виноват в том, что вышел из комнаты? И разве же я виноват в том, что не оправдал твоих ожиданий? Так кто же виноват в твоём недовольстве? Разве не ты сам? На что Базарбаев сказал: — Ты мозги не еби, мясо давай.

Semaphore использует Monitor.WaitHandle.

Lock использует Monitor.WaitHandle.

AutoResetEvent использует Monitor.WaitHandle.

И всё это использует объекты ядра операционки - mutex.

SemaphoreSlim тоже использует мьютексы, когда не может обойтись атомарками (interlocked). Вообще, худые семафоры - это попытка сэкономить на использовании мьютексов за счёт атомарных операций. Очень удачная, надо сказать.

Статья - безграмотная чушь.

Интересно, а что мешает на текущей орбите просто затормозить МКС кораблём-толкателем? Получаем резкое и контролируемое снижение орбитальной скорости, затем совершенно предсказуемое падение горизонтально вниз.

Или слишком много энергии надо?

Я где-то говорил, что не вижу разницы? Я где-то говорил, что времена те же самые остались?

xkcd_extrapolation.jpg

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

Information

Rating
1,497-th
Registered
Activity