All streams
Search
Write a publication
Pull to refresh
0
0
Send message

SRP

Радостно видеть, что автор понимает, что SRP - это принцип про людей (не только изначально, но и сейчас). То что этот принцип коверкают - это не проблема принципа. Если у автора есть аргументы против оригинальной версии SRP, было бы интересно их услышать.

OCP

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

LSP

Вот тут очень плохой пример получился. API чтения файлов должно отдавать поток байтов и ему должно быть по барабану зашифрованы они или нет. Логика дешифрования пишется как обертка для потока байтов, которая на выходе тоже отдает поток байт. Это позволяет а) очень легко тестировать каждую часть по отдельности б) добавлять обертки для сжатия/разжатия данных и других манипуляций в) использовать в качестве исходного источника потока байт не только файлы.

ISP

То же что OCP - не следуем фанатично, но и совсем о нем забывать нельзя.

DIP

Грустно наблюдать, что этот принцип понимают как "всегда используйте интерфейсы". Этот принцип на мой взгяд очень плохо себя проявляет в рамках одного проекта т.к. обычно процесс сборки проекта означает выпуск нового билда, который должен так или иначе пройти все этапы тестирования. Другое дело - разные библиотеки. Если у нас есть библиотеки, которые образуют цепь зависимостей A->B->C->D->E->F, и что-то меняется в F, то нам придется проводить тестирование и пересобирать библиотеки E, D, C, B, A. Если же мы введем промежуточную API библиотеку G, то сможем разорвать цепь зависимостей:
A->B->C-->G<--D->E->F

и изменения в F уже затронут только две библиотеки - E и D.

Вот некоторые примеры такой инверсии из мира java:
slf4j-api - фасад для подсистемы логирования

opentelemetry-api - API для записи метрик и трейсинга

jjwt-api - API для работы с jwt токенами

  1. У вас база реализует бизнес логику?

  2. Принцип имеет смысл и на одном уровне. Что выше в вашей системе мер - БД или система логирования?

  3. Модулю нижнего уровня важны детали высокого уровня? Если нет, то в чем смысл деления здесь?

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

D: принцип инверсии зависимостей

Высокоуровневые модули не должны зависеть от низкоуровневых

Нету в контексте это принципа понятий "высокий модуль" и "низкий модуль". Пример в статье для этого принципа с едой больше относится к OCP.

Принцип о том что не нужно делать большие цепочки зависимостей между модулями. Если не следовать принципу, то можно реализовать зависимые друг от друга модули A->B->C->D->E->F и при любом изменении в модуле F все остальные модули в нашей цепочке нужно перетестировать и пересобирать. Если же добавить тут один абстрактный модуль G, то можем разбить нашу цепь на три:

A->B->C->G

D->G

D->E->F

И изменения в F уже влияют не на 5 модулей, а на 2. Где именно и как часто ломать цепи зависимостей используя DI - это уже может варьироваться от проекта к проекту.

JSON с быстрым сжатием на lz4 покажет похожие цифры скорости и объема трафика. Плюс есть и бинарные форматы для сериализации json'а (но мои эксперименты с ними показали те же цифры что и обычный JSON с сжатием).

А пользователь тут при чем?

При том, что вам неудобно, когда язык заставляет принимать решения (nullability), которые в последствии помогут избежать багов. Т.е. ваше удобство важнее чем правильно работающая программа.

Наследование то костыль?) Сходите в дурку, пожалуйста, на обследование

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

Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four, GoF)

Favor object composition over class inheritance.

Effective Java (Joshua Bloch)

Favor composition over inheritance

---

Я сказал, что это неудобно, а не плохо

Вы сравнили новый синтаксис с запахом канализации. Если для вас запах канализации не является плохим, то не имею вопросов.

Так вы сами и подтверждаете по сути еще один парадокс, когда в языке ждя краткости сделано не кратко.

Kotlin - это не язык для краткости. Это язык для людей. Он упрощает то что можно упростить и не упрощает то что после упрощения может стать хуже.

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

Без примера все же сложно понять о чем речь.

Лучше или нет - совсем другой вопрос. Я говорил об удобстве для себя, потому что я программирую не ради идеальной программы, а ради удовольствия.

Что ж, ваше право. Соболезную людям, которые пользуются софтом, к которому вы приложили руку. Тестирование тоже считаете бесполезной тратой времени?

Откройте для себя композицию

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

Наследование полезно в единичных случаях, а не на постоянке. Вообще наследование как один большой костыль выглядит.

Лично для меня - неудобное определение переменных.

Привыкнуть и не замечать можно и запах канализации в подъезде, привычка не доказывает ничего.

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

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

Если вы печатаете одной рукой, то я могу вас понять. Иначе - звучит как придирка из воздуха. Программист - это не мартышка, которая ценится за максимальное количество нажатий клавиш в единицу времени.

Это всё создает огромную путаницу, особенно в контексте нескольких языков. 

Путаницу как раз ввела java в свое время сделав оператор == практически бесполезным в большинстве случаев. В kotlin исправили эту проблему и большое им спасибо за это. Если сравнение ссылок кому-то действительно нужно, то это обычно продвинутые разработчики, которые в состоянии выбрать подходящий оператор в нужном месте.

MyClass::class.java

Если здесь проблема в количестве символов, то странно слышать такие аргументы при сравнении с java, которая не славится краткостью. Если вы копнете глубже в рефлексию и возможности, которые предоставляют Kotlin типы и классы, то поймете почему они решили сделать свои варианты классов.

Множество кода превращается в кашу, выдавая слишком много информации на одну строку.

Наговнокодить можно и в java. В чем здесь вина kotlin?

Null-safety нужно не всем.

Null References очень часто называют The Billion Dollar Mistake. Kotlin помогает свести шанс этих ошибок к минимуму. Почему это плохо? Да, это заставляет разрабочика каждый раз задумываться "а может ли тут быть null? И если да, то что это значит?" и это может быть неприятно на первых порах (мозг по своей природе думать вообще не любит), но по итогу что лучше - чуть меньшее время разработчика (что спорно т.к. куда больше время тратится потом на отлов и фикс багов) или безошибочная работа программы?

Закрытые для расширения классы тормозят процесс. Расширяемость в Java - преимущество, а не проблема.

Откройте для себя композицию и мир заиграет новыми красками.

Лично для меня - неудобное определение переменных.

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

Каша со сравнением классов: в Джаве четкое и понятное разделение на == и equals, что очень удобно.

Потому что вы так привыкли. В том же C# '==' вызывает equals под капотом как и в Kotlin. В 95% сравнение ссылок никому не нужно и заставлять всех каждый раз писать equals, вызов которого может еще и привести к NullPointerException - это тот еще цирк с конями. Есть конечно Objects.equals, но это уже какие-то костыли для решения проблемы, которой изначально быть не должно.

Неудобства с классами

А в каких сценариях это неудобство проявляется?

Я не считаю kotlin идеальным языком, но все его недостатки обычно достаточно мелкие, а плюсы ооочень весомые. Используем его для enterprise без всяких мобилок и живем отлично.

Почему Вы считаете, что нейросети - это про случайности? У нейросетей бывают галлюцинации, но это временный недостаток, который с каждым днем все меньше и меньше влияет на итоговый результат.

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

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

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

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

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

Я бы с радостью посмотрел на компанию, которая дает новичкам добавлять расширения в базу и разрешает им писать рекурсивные запросы на чистом SQL.

А зачем вообще hibernate отправляет заведомо бесполезный запрос в бд в этом случае?

Скратч для детей вроде неплохо подходит, но близко с ним не знакомился. Мне кажется для обучения новичков лучше всего подходит современный язык с наименьшим количеством магии (сахара). Java тут подходит идеально и в будущем будет опция перейти на продвинутый уровень (Kotlin).

Закопайте уже дедушку пожалуйста. Он давно умер и не дает для новичков никакого особенного опыта, который нельзя получить с другими современными языками.

Здравствуй, путешественник из прошлого. У нас тут 2024 год и java уже давно оптимизирована настолько, что говорить о большой разнице между нативным кодом и jvm не приходится.

Не хочу чтобы дискуссию ушла ещё в сторону JIT или AOT, я очень неплохо разбираюсь и в этом.

За последние ~10-15 лет очень многое изменилось. Советую разобраться заново.

У нас в kotlin/java продукте много библиотек используется и проблемы поднимаемые в статье раньше тоже часто встречались. В итоге пришли к такому решению:


1. Во всех библиотеках зависимости от остальных библиотек выставлены как provided (т.е. транзитивно не тянутся).

2. Каждая библиотека заливает в maven repo не только себя и исходники, но и тесты отдельной jar'кой

3. Все библиотеки с указанием нужных версий подключены в общем проекте, который билдит родительские pom'ники для всех конечных приложений. Этот общий проект при выполнении тестов так же прогоняет все тесты из подключаемых библиотек. Это позволяет довольно легко отлавливать проблемы с совместимостью ABI.

По технологиям - используем Spring Boot с Kotlin/Java

  1. Используют статический метод TxnContext.doInTxn {/*действия в рамках транзакции*/}. Есть разные вариации этого метода с флагом readOnly и указанием нужно или не нужно принудительно создавать новую транзакцию, но это уже детали. Есть еще реализация адаптера для транзакционного менеджера спринга и с ней можно использовать штатную аннотацию @Transactional на любом методе. С т.з. разработчиков работа с распределенными транзакциями идет так же как и с локальными. Работа 2PC полностью скрыта в реализации транзакционного менеджера + API либе, которая занимается регистрацией внешних приложений в качестве XA ресурсов для менеджера.

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

  3. Нагрузка пока не сильно большая. Порядка 300-400 одновременных пользователей, которые работают с ~десятком миллионов записей в БД.

Из интересного еще - основная потребность в 2PC возникла из-за работы BPMN движка Camunda с документами, которые находятся в других базах и приложениях. В результате реализации 2PC теперь сценарии завершили_задачу -> поменяли_документ -> что-то_пошло_не_так работают на ура.

Обычно же как раз не советуют использовать 2PC.

В некоторых системах мб и это и зло (как минимум там где транзакции выполняются очень значимое кол-во времени), но для нас это оказалось лучшим решением из тех что были изобретены в распределенном мире. Какого рода подробности интересуют? Если описывать все подробно, то наверное это уже формат статьи получится.

Information

Rating
Does not participate
Registered
Activity

Specialization

Specialist
Lead
Java
Java Spring Framework
Kotlin