Специфика ORM в том, что он сам по себе накидывает сложности проекту. И это оправдано там, где сложность проекта стала проблемой. Собственно, об этом и статья.
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. Я бы вообще не рекомендовал фанатично следовать этим принципам, фанатичное следование любым принципам никогда к хорошим результатам не приводит.
Single responsibility. В вашем примере нарушается инкапсуляция класса непонятно за какими целями. Вообще вполне нормально может быть, что робот может и move и speak. Вполне возможно, что у него эти методы завязаны на одних и тех же данных внутри класса. Если слепо следовать S, то у класса вылезают кишки наружу, логика переносится в другие классы, плодятся контроллеры, сервисы и прочие странные мутанты. Я уж не говорю про DDD, где класс соответствует термину предметной области - тут прямой конфликт с принципом единственной ответственности.
Вы приводите в качестве примера простое использование наследования. Никакого отношения к OCP это не имеет. OCP - это когда часть класс спроектирован так, что можно без труда поменять логику в унаследованном классе, не трогая базовый класс.
LSP. А что, если подставить экземпляр студента вместо персоны, он не будет работать? Пример нарушения - это как раз когда наследуют прямоугольник от квадрата и удивляются, почему при задании одного размера его не видно. Конечно, квадрат - это частный случай прямоугольника.
ISP. Интерфейс вообще-то строится для клиентского кода. Соответственно, интерфейс может дробиться только до уровня требований этого кода. Если он требует объект, который должен и говорить и двигаться, то разделять эти интерфейсы не нужно. В вашем примере вы рассматриваете неправильную проектировку самого класса, а не интерфейсов. Ну на этапе создания Robot уже должно дойти, что он не умеет летать, верно?
Интерфейс ради интерфейса? Вот зачем? Внедрять лишнюю сущность, когда нет ещё уверенности, что будет другая база данных - это раздувание кода ради культа карго.
Если мы получаем от словаря ссылку на структуру и потом работаем по ссылке, то чем, собственно говоря, это отличается от класса?
Да, есть небольшой выигрыш за счёт того, что ссылки не считаются и ансейф во все поля. Но этот выигрыш чувствителен только для сценария с большим количеством поисков и не пополняющимся словарём. Для такого сценария существуют контейнеры получше, вроде FrozenDictionary. А то и бинарное дерево.
И сравнение считаю некорректным. Структуры у вас с ружьём, направленным в ногу, а классы используют стандартный сейф механизм.
И ещё. Не нашёл в коде объявления GetHash и Equals. Может у вас хэш коллизит и поиск деградировал до линейного.
Холодильник на лоджии - это же очень неудобно! Не понимаю, как можно заморачиваться с умным домом, не решив базовых проблем планировки. Вроде на кухне достаточно места.
В этой статье мы разъясним довольно тонкий семантический вопрос, который часто остаётся за кадром при изучении программирования на императивных языках.
Однажды Базарбаев пришёл в гости к Мыркымбаеву. Мыркымбаев угостил Базарбаева чаем с баурсаками, а сам вышел из комнаты. Через какое-то время Базарбаев пошёл в соседнюю комнату и увидел, что в ней сидит Мыркымбаев и ест целую тарелку дымящегося мяса. Базарбаев тогда сказал: — Как тебе не стыдно, ведь я гость, и ты должен был меня угостить мясом. На что Мыркымбаев ему ответил: — Ты стыдишь меня? Посуди сам: я угостил тебя чаем с баурсаками, и ты был доволен. Ты был доволен до тех пор, пока не вышел из комнаты и не увидел, что я ем мясо. Разве не ты сам виноват в том, что вышел из комнаты? И разве же я виноват в том, что не оправдал твоих ожиданий? Так кто же виноват в твоём недовольстве? Разве не ты сам? На что Базарбаев сказал: — Ты мозги не еби, мясо давай.
И всё это использует объекты ядра операционки - mutex.
SemaphoreSlim тоже использует мьютексы, когда не может обойтись атомарками (interlocked). Вообще, худые семафоры - это попытка сэкономить на использовании мьютексов за счёт атомарных операций. Очень удачная, надо сказать.
Интересно, а что мешает на текущей орбите просто затормозить МКС кораблём-толкателем? Получаем резкое и контролируемое снижение орбитальной скорости, затем совершенно предсказуемое падение горизонтально вниз.
Специфика ORM в том, что он сам по себе накидывает сложности проекту. И это оправдано там, где сложность проекта стала проблемой. Собственно, об этом и статья.
Я уже однажды приводил пример:
Трансформируется в:
Разница невелика на первый взгляд. Просто чистый 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. Я бы вообще не рекомендовал фанатично следовать этим принципам, фанатичное следование любым принципам никогда к хорошим результатам не приводит.
Single responsibility. В вашем примере нарушается инкапсуляция класса непонятно за какими целями. Вообще вполне нормально может быть, что робот может и move и speak. Вполне возможно, что у него эти методы завязаны на одних и тех же данных внутри класса. Если слепо следовать S, то у класса вылезают кишки наружу, логика переносится в другие классы, плодятся контроллеры, сервисы и прочие странные мутанты. Я уж не говорю про DDD, где класс соответствует термину предметной области - тут прямой конфликт с принципом единственной ответственности.
Вы приводите в качестве примера простое использование наследования. Никакого отношения к OCP это не имеет. OCP - это когда часть класс спроектирован так, что можно без труда поменять логику в унаследованном классе, не трогая базовый класс.
LSP. А что, если подставить экземпляр студента вместо персоны, он не будет работать? Пример нарушения - это как раз когда наследуют прямоугольник от квадрата и удивляются, почему при задании одного размера его не видно. Конечно, квадрат - это частный случай прямоугольника.
ISP. Интерфейс вообще-то строится для клиентского кода. Соответственно, интерфейс может дробиться только до уровня требований этого кода. Если он требует объект, который должен и говорить и двигаться, то разделять эти интерфейсы не нужно. В вашем примере вы рассматриваете неправильную проектировку самого класса, а не интерфейсов. Ну на этапе создания Robot уже должно дойти, что он не умеет летать, верно?
Интерфейс ради интерфейса? Вот зачем? Внедрять лишнюю сущность, когда нет ещё уверенности, что будет другая база данных - это раздувание кода ради культа карго.
Велосипед можно бросить в одно мгновение, чтобы отпрыгнуть в нужную сторону. Если, конечно, на нём не едешь.
У меня эта статья вызвала флешбеки )
Если мы получаем от словаря ссылку на структуру и потом работаем по ссылке, то чем, собственно говоря, это отличается от класса?
Да, есть небольшой выигрыш за счёт того, что ссылки не считаются и ансейф во все поля. Но этот выигрыш чувствителен только для сценария с большим количеством поисков и не пополняющимся словарём. Для такого сценария существуют контейнеры получше, вроде FrozenDictionary. А то и бинарное дерево.
И сравнение считаю некорректным. Структуры у вас с ружьём, направленным в ногу, а классы используют стандартный сейф механизм.
И ещё. Не нашёл в коде объявления GetHash и Equals. Может у вас хэш коллизит и поиск деградировал до линейного.
Какое кошмарное выравнивание на КДПВ...
Что за "ручки" такие? Вы тащите в статью какой-то ваш внутренний сленг?
По статье:
Нормализация. Делать нормализацию только потому, что "так учили" - сомнительно. Бывает приходится сознательно денормализовывать данные.
Отдельные схемы для разных модулей. Крайне сомнительно. Особенно, если данные используются далеко не одним модулем.
Холодильник на лоджии - это же очень неудобно! Не понимаю, как можно заморачиваться с умным домом, не решив базовых проблем планировки. Вроде на кухне достаточно места.
<данные удалены>
А где сформулированный вопрос?
Анекдот
Однажды Базарбаев пришёл в гости к Мыркымбаеву. Мыркымбаев угостил Базарбаева чаем с баурсаками, а сам вышел из комнаты. Через какое-то время Базарбаев пошёл в соседнюю комнату и увидел, что в ней сидит Мыркымбаев и ест целую тарелку дымящегося мяса. Базарбаев тогда сказал: — Как тебе не стыдно, ведь я гость, и ты должен был меня угостить мясом. На что Мыркымбаев ему ответил: — Ты стыдишь меня? Посуди сам: я угостил тебя чаем с баурсаками, и ты был доволен. Ты был доволен до тех пор, пока не вышел из комнаты и не увидел, что я ем мясо. Разве не ты сам виноват в том, что вышел из комнаты? И разве же я виноват в том, что не оправдал твоих ожиданий? Так кто же виноват в твоём недовольстве? Разве не ты сам? На что Базарбаев сказал: — Ты мозги не еби, мясо давай.
Эскобар про меньшее из зол
Semaphore использует Monitor.WaitHandle.
Lock использует Monitor.WaitHandle.
AutoResetEvent использует Monitor.WaitHandle.
И всё это использует объекты ядра операционки - mutex.
SemaphoreSlim тоже использует мьютексы, когда не может обойтись атомарками (interlocked). Вообще, худые семафоры - это попытка сэкономить на использовании мьютексов за счёт атомарных операций. Очень удачная, надо сказать.
Статья - безграмотная чушь.
Интересно, а что мешает на текущей орбите просто затормозить МКС кораблём-толкателем? Получаем резкое и контролируемое снижение орбитальной скорости, затем совершенно предсказуемое падение горизонтально вниз.
Или слишком много энергии надо?
Я где-то говорил, что не вижу разницы? Я где-то говорил, что времена те же самые остались?
xkcd_extrapolation.jpg
Может это говорит больше о текучке в вакансиях на веб, чем о востребованности десктопа?