Информация
- В рейтинге
- 2 984-й
- Откуда
- Санкт-Петербург и область, Россия
- Зарегистрирован
- Активность
Специализация
Бэкенд разработчик
Ведущий
C#
Java
Rust
Golang
Многопоточность
C
Системное программирование
Разработка игр
Unity3d
Алгоритмы и структуры данных
Другими словами: "докажите что не нужно". Но ведь Ваше же утверждение можно применить и в обратную сторону - "докажите что нужно".
Многие говорят, что это всё нужно, но ни разу не видел крупный (практически production-ready) проект, написанный таким образом и который бы:
не становился мага тяжелым, сложным и запутанным за счет огромного числа абстракций на всякий случай
не имел протекающие абстракции на каждом шагу
не имел огромного числа костылей, потому что реальная жизнь не натягивается на чистые архитектуры
Более того, в подавляющем числе статей и книг нельзя посмотреть как реализуются на практике советы по сложным архитектурам.
Найти и предоставить хороший простой проект с простой архитектурой не проще чем найти такой же хороший со сложной.
Огромное заблуждение считать что есть какая-то архитектурная чистота и каноничность. Все эти чистые архитектуры и DDD это не более чем завирусившиеся авторские методики отдельных скучающих писателей. Будучи объективным нужно сказать что нет никаких хотя бы околонаучных доказательств что вся эта многослойность, вся эта эмуляция реального мира, вся эта чисто-архитектурность дает пользы больше чем вреда. Да по папочкам разложено, да уложено приложено, все реализации поменять можно, вот только там где в нормальном проекте для доработки хватить пары строк, в книжных архитектурах все будет когнитивно переусложнено, раскидано по десяткам классов и будут уходить часы, дни и недели на обсуждения архитектурной частоты согласно книжке и будет написаны тысячи строк кода которые решают проблемы которая такая архитектура и создала и не имеют никакой практической ценности для практической задачи.
Это я к чему. Наверное не стоит делать такие противопоставления. Делать из перехайпленых книжных подходов какой то эталон. Под задачу выбираем инструменты а не под инструменты подгоняем задачу.
Вообще, это забавно и печально одновременно - как в одно идиотское политическое решение cделать .Net только под Windows, до сих пор не дает, технически куда более зрелому и совершенному .Net(C#) обойти Java(JVM) исключительно по политическим причинам. Один раз упустили, а потом все по привычке будут делать все только на Java.
Второй забавный момент - изначально именно Java/JVM делалась как инструмент под все платформы-задачи а сейчас все наоборот, C#/CLR - хороший инструмент для решения практически любой задачи, в то время как Java/JVM в подавляющей доле это инструмент написания корпоративного backend и практически ничего более.
Хвост начинает вилять собакой
Просто иронизирую на тему компенсации профессиональных качеств красивыми названиями
Кто бы тогда мог подумать что сейчас это будет +1 к цветовой дифференциации штанов
Зачем называть вещи своими именами если можно заменить слово "программист" на "инженер" и все вдруг станет загадочнее, элитарнее, понтовее и круче. И пофиг что чем дальше тем средний программист тупее в техническом плане с каждым годом, главное что теперь он гордо зовется "инженер" и занимается они не никчемным программированием а целой инженерией!
Толку от переноса такой локальной логики - мало. Если проверка подписания - это проверка сущности и проверка в БД то мне ни горячо ни холодно от того что какой то кусок логики лежит в сущности. Мне все-равно нужно искать способы шарить логику связанную с походами в БД. А потом когда я зашарю логику usecase мне нужно дружить с отдельно зашареной логикой из сущности. Вопрос зачем мне все это если я просто могу написать метод который в себе будет содержать вообще все что для этого нужно?
Логика в сущности - это бесполезная полу-мера. Никакого толку от метода is_signed в сущности нет, потому что по итогу она мне не отвечает на вопрос - подписано ли что-то или нет, мне нужно еще искать другую половинку логики. Проще все концентрировать в одном месте где таких ограничений нет.
PS. Потом будет еще веселей, когда захотите реагировать на события. Будете городить городьбу внутри сущности, возвращать из нее события, пришивать эти события к юзкейсам и прочий мрак. Знаем проходили.
Не получаем. Все бизнес-операции сущности живут в сервисе сущности и больше нигде.
Как я уже написал - логика не будет в нескольких сервисах.
В Вашем примере данная логика работает ровно до той поры пока там нет работы ввода вывода. Если логика проверки подписи требует сходить в другую систему, или хотя бы в БД, то метод сущности превращается в тыкву и все нужно переделывать и решать вопрос с перед-использованием. Вариант с управляющим сервисом такой проблемы лишен.
Ну смотрите, давайте от обратного - зачем нам вообще какие-либо бизнес -правила описывать в модели? Вполне разумные преимущества:
1.концентрируем логику в одном месте - из какого бы участка кода мы не вызвали сущность, нельзя привести ее в неправильное состояние
2.вместо изменения отдельных полей мы делаем осмысленные операции с валидацией состояний и прочим
Звучит здорово, но ломается в то что это полумера. Сущность неполноценна. Ну допустим, мы зашили в ней правила касаемо ее полей. А какой в этом толк?
Вот есть операция - подписать. В ней мы меняем поля signature, signer, signed_at, предварительно проверил состояние подписываемого объекта. красиво. А потом в проверку приходиться вставлять запрос и толк от этой схемы стремиться к нулю, потому что из любого места в коде можно сделать подпись и сохранить а внешние проверки застряли в юзкейсе. При этом мы разнесли логику по разным классам, ходи потом бегай и собирай по кускам как делаться подпись. Решительных преимуществ не получили а вот недостатки в полной мере.
Теперь сравните с классической схемой когда все это будет написано в сервисе. В сервисе будет представлена вся логика работы с доменом от и до и без ограничений. Вы нажимаете метод sign и в нем вся бизнес логика, все инварианты и проверки, все походы в БД и во все интеграции. Все сконцентрировано в одном месте. Если сущность будет глупой но Вы просто запретите менять ее поля в любом месте кроме ее сервиса то получите концентрацию логики в одном месте без всех этих проблем и костылей.
Что мы хотим?
Что мы для этого делаем?
2/5 технических встреч, остальные это гуманитарное балабольство на тему ценностей, тердностей, самых сложных задач, философии принятия решений и видимо вопросов в духе - кем Вы себя видите через 5 лет?
Не очень понимаю к чему все эти заявления про инженерное мышление, если описание собеседования - это просто классический пример современного, модного, бессмысленного и беспощадного подхода как у всех.
Немного покритикую что хорошо а что нет.
Раз, и между двумя предложениями рождается противотечение. Это фундаментальная проблема ООП подхода на бэке. Мы не можем оперировать всей доменной логикой без инфраструктуры. Как только появиться необходимость валидировать на существование других данных в БД или что еще хуже, менять их - этот подход сразу превратиться в тыкву.
У нас получилась модель которая не самодостаточна даже для соблюдения своих собственных инвариантов а значит толку от нее ноль, она все равно нормально не работает и намного удобнее сконцентрировать всю доменную логику в одном месте - в сервисе.
Дальше:
Окей. Зачем нам этот класс? Вы по сути написали очень странную и неуклюжую функцию. Просто передайте storage и uow в параметры и выкинете никому не нужный класс.
Во-вторых, у вас в этом классе, как я и писал раньше, торчат инварианты инварианты, которые размазаны между несколькими классами.
В-третих, что будете делать, когда появиться общая логика между usecases? Дублировать? Или выносить в еще одну костыль-абстракцию?
Сервис намного проще как решение. Ну или просто оставить это функциями.
Ну тут вопрос то от обратного - зачем AI вся эта ерунда? Для него нет никакой проблемы разобраться и распутать или вообще переписать и как раз наоборот, лучше отдать предпочтение очень простому коду, который AI может зарефачить там где раньше это была боль. Для человека простой минималистичный код куда проще и для понимания и для валидации AI чем ломать мозг от валидации тонны кода при добавлении одного флага.
Мне кажеться Вы сами запутались.
Асинхронность - это свойство частей исполняемого кода работать не последовательно. Например, у нас есть задача A, для ее вычисления нам нужно еще вычислить задачи B и C. Если мы вычисляем их последовательно: A1->B->C->A2 то получаем синхронно выполненный набор задач. Если же мы ломаем последовательность вычислений, продолжая вычислять работу которая должна быть после B и C еще не имея результатов тех самых B и C , то получаем непоследовательно, ну или не синхронно ну или асинхронно выполненную последовательность.
Причем здесь IO bound задачи в определении асинхронности? Я с тем же успехом могу асинхронно считать алгоритмы в разных потоках выполняя работу параллельно или не параллельно в одном, и так и так работа будет асинхронной.
Как выполнять работу: на той же машине или на другой, с одном потоке или нескольких, на корутинах или потоках ОС, блокировать или не блокировать дополнительный поток - это все уже детали. Единственно важное свойство - это возможность текущему потоку управления не блокироваться в ожидании другой задачи в определенных точках. Это и есть асинхронное выполнение.
На самом деле проблема намного глубже и шире. Сводиться она к трем состовляющим: лени, жадности и тупости.
На уровне рынка: бизнес всеми силами создает условия чтобы у среднего разработчика было все меньше мотивации расти. Зарплата перестала коррелировать с знаниями и опытом и все больше стала зависеть от связей, умения себя нахваливать и врать.
На уровне компании: с ростом числа проектов - нужно и больше менеджеров, которых нет. Приходят слабые менеджеры, основное желание которых - скинуть с себя все обязанности на остальных. Отсюда мы получаем новый формат команд, человеко-оркестров, где каждый сам себе и аналитик и руководитель и скрам мастер. Естественно, такие руководители будут нанимать не, опытных а максимально удобных и приятных для себя людей.
Далее, повышать зп будут не самых технически грамотным а самым удобным и приятным софт-скилистам. Как результат - отрицательный отбор, хардскиловые специалисты вымываются, а софтскиловые, понимающие что здесь мягко и тепло а за бортом не очень остаются.
На уровне проекта: слабые менеджеры не могут продавать заказчика, в результате, не самого высокого технического уровня ответственные софт-скилисты, начинаю в спешке писать еще более отвратительное говно не пытаясь спорить с руководством.
Вот отсюда по итогу и беруться Иваны из статьи, которые своими действиями по сути делают возвраточку бизнесу который для всего этого создал условия.
Через две недели и тысячи коммитов, ИИ радостно сообщит что у него лапки и нужен кожаный. Кожаный констатирует что за две недели было выполнено 100500 задач каждая их которых крутилась в цикле сансары и все ее коммиты перемерджены с тысячами коммитов других чудо задач. Оператор управления ИИ приходит к выводу что проще проект сжечь чем что-то откатывать или чинить.
Предлагаю на такие случаи выводить на экран довольную морду Бориса Черни.
Я и не писал что они не могу это сделать технически я писал что не могут - фактически.
Нет. Это попытка сделать в духе C# со своей спецификой - добавить возможность иметь в рантайме типы значения и позволить использовать специализацию в дженериках вместо боксинга. Это исключительно задача для изменения JVM. нынешняя JVM ничего про дженерики не знает точно также как не может инлайнить данные друг в друга.
Сто лет в обед у них там все хорошо сделано изначально и работает. Ничего не понял что там внезапно выяснилось?
Если попадется - обязательно скину.
История от колбэков NodeJs, горутин Go, корутин C# до виртуальных потоков Java это история - как удобно управлять асинхронностью.
Асинхронная операция - это операция которая может быть прервана и выполнена позднее. В контексте Web это в основном сетевые запросы. Смысл виртуальных потоков - сделать эти операции неблокирующими из коробки вот и все. Какой то там философской дикой разницы нет, немного разный инструмент. Что корутины что горутины это удобный инструмент управления асинхронными задачами, не важно параллельно мы выполняем задачу на нашем процессоре или на другом сервере. Виртуальные потоки это просто оптимизация этого процесса. В старой Java для этого использовался отдельный поток и это было не эффективно а в новой доросли до возможностей не блокировать ОС поток. По сути очень близко к тому что в Go но менее удобно.
Возможность не равно данность. Если я открываю голую Java то написанный код близок к байткоду если я открываю голый Kotlin, без всякого аnnotation processing и фреймворков это с порога не так.
А мне как пользователю Kotlin какое дело? В Java я с таким не сталкиваюсь а в Kotlin сталкиваюсь - это единственное что важно.
Какое мне дело до F#? Я пишу про Kotlin и Java. Если будем говорить про F# и C# то буду критиковать F#.
Верите нет но большинству пользователей вообще фиолетово на это. Важно только тем у кого ограничения. Вот у KoltinJS, ну в теории то он есть и кто-то может писать на нем но вот на практике он практически никому не нужен как платформа.
Большинство пользователей заинтересовано работать на последней версии JVM и разработчики Kotlin вынуждены с этим считаться. Разработчики вынуждены считаться с всеми фичами новых JVM для того чтобы Kotlin работал оптимально. Можно сколько угодно рассказывать про теоретическую слабую связь с Java экосистемой но на практике эта связь сильная и вынуждает Kotlin следовать в этом мейнстриме как бы Вам не хотелось убедить себя в обратном.
Не нужно перехваливать. С Гораздо лучшей: Haskell, Scala, TypeScript, Rust. А Kotlin с чуть лучшей.
Звучит как "Так то я тебе наваляю но просто не хочу". Если не сделали, значит в силу разных обстоятельств не могут. Никого не волнует что бы они в теории могли или не могли, волнует только то что есть и чего нет в языке.
Львиная доля потребности в специализации - это иметь нормальные, не тормозные коллекции и другие контейнеры. Именно этого все хотят и именно поэтому в Java их делают уже 12 лет. Если бы reified type parameters закрывали львиную долю потребностей в Java бы их ввели давно но на деле как раз менее важные потребности.
Был хороший доклад от Андрея Бреслав, лень искать, где он ответил на вопрос почему не сделали pattern matching. Ответ был такой: это очень муторная и сложная фича пользы от которой не так много, тем более в Java уже делают, мы дождемся пока они сделают, проанализируем и может быть сделаем.
Spring и Hibernate требуют пустого публичного конструктора,что несовместимо с Kotlin без костылей в виде плагинов.
Mockito из коробки нормально работать не будет.
Jackson / Gson из коробки тоже нормально не работают.
Могу ошибаться, но вроде бы с MyBatis были какие то проблемы в свое время.
Таких либ достаточно которые без оберток-костылей не будет работать.
Нет, они про одно и тоже, про работу с асинхронными операциями. И главная проблема не в прикручивании чего-то к чему-то а в мейнстриме. В Java он в том чтобы ничего лишнего не писать и оно само под капотом будет работать, большинство библиотек будут поддерживать Java подход и будет идти вразрез с Kotlin.
Компилятор Kotlin генерирует байткод который не поддерживается JVM но она его по старой дружбе всеравно выполняет?
Spring и Lombok входят в спецификацию Java?
Вот я напишу Вам Int а вы скажите, это примитивный тип или ссылочный?
Я захожу в исходники через инструмент который написала компания который этот язык и сделала и часто вижу или месиво нечитаемое или вообще отсутствие реализации как будто бы я в C. Можно ли запариваться, использовать специальные инструменты? Можно. Но вот почему то в Java у меня таких проблем нет и в C# тоже а в Kotlin есть.
Рискую тоже открыть тайну - мало кому интересен язык который будет крутиться на устаревшей платформе, поддержка которой через какое-то то время закончиться.
В теории да, на практике - очень нужно. Никто в здравом уме при нормальных обстоятельствах не выберет между последней версией Java и свежим JDK и Kotlin на старой 1.8 в пользу последнего.
Да, все так. Чудовищной ошибкой Microsoft было делать C# только под Windows. Жадность покоя не давала. Только в 2016 одумались и сделали кроссплатформу. Хоть доля C# на рынке большая до Java естественно не дотягивает. Но как язык и платформа C#/.net это прям пример как нужно делать.
ps. Занимательный забавный факт.
Java опередила C# за счет кроссплатформенности в свое время. Но если посмотреть сейчас, то почти все что пишут на Java это корпоративный бэкенды. Ну и мобилки (Kotlin). В то время как на C# пишут и бэкенды и фронтенды и десктопы и игры и CLI утилиты и чего только не пишут.
В теории то оно понятно, там и Scala в JS умеет. На практике в реальной жизни это либо андроид либо backend т.е. один к одному с джавой.
Тогда лучше не пробовать C#. Можно словить разочарование от осознания - насколько на самом деле все нормально и удобно можно было сделать.