Обновить
16
0.4

Пользователь

Отправить сообщение

Главная задача программиста - борьба со сложностью.

Надеюсь в резюме у себя Вы такое не указываете

А как только начинаем смотреть МКД, нифига ж себе, оказываются есть архитектурные нормы и требования. 

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

А если у вас более сложная архитектура?

Например стандартная библиотека какого-нибудь популярного языка программирования. Где в среднем нарушение SOLID во всех позах поставлено на поток. Интересно почему? Вроде бы не глупые люди должны таким заниматься.

Классный ответ, правда и ошибки С++, это тоже "проблемы разработчика, а не языка".

Проблема Rust в том, что он в принципе не может реализовать некоторые алгоритмы без вставок unsafe кода.

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

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

И таких людей не переубедишь. Приводи им примеры или нет - свой опыт им не передашь. Да и слушать у нас как-то стало не модно".

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

Поэтому я решил попробовать доказать вам, что принципы разработки (почти как законы физики)

А если ли у этих принципов явные и понятные всем а главное однозначные формулировки? Ну например что такое ответственность а как ее рассчитать для конкретного случая? Есть ли доказательства эффективности применимости данных принципов отличные от субъективного восприятия? Или основной показатель эффективности - это "я считаю оно работает у меня а значит работает у всех"?

Для дрели: кнопка под указательным пальцем должна управлять только оборотами. Нельзя на неё вешать переключение на перфорацию.

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

L - Liskov Substitution Principle (Принцип подстановки Барбары Лисков). Классы-наследники не должны противоречить базовому классу.

Советую изучать лучше данный принцип. Там нет ничего про классы.

А теперь вопрос - сколько ещё будут держаться эти принципы? Через сколько лет вы захотите чтобы производители дрелей перестали этого придерживаться?

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

Яркий пример из Второй мировой - зенитная артиллерия. Эта та которая по самолетам стреляет. Вместо того чтобы всякие единственные ответственности соблюдать, инженеры сделали орудие которое может стрелять и по земле а более того были сделаны противотанковые снаряды. И более того, впоследствии оказалось что зенитное орудие едва ли не лучшее противотанковое средство. После чего в Германии и СССР стали ставить слегка модифицированные зенитные орудия на танки. А вот если бы знали про SOLID не страдали бы видиом фигней и делали зенитные орудия которые могут стрелять только по самолетам.

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

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

кстати, эту же идею Вы можете обнаружить в книге "Чистый Код" от Роберта Мартина

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

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

  1. Единственный публичный метод. Вся работа с сервисом ведётся через метод call. Избавляемся от проблемы когда разработчики начинают придумывать run-ы, execute-ы, process-ы и т.д.

Спасибо за комментарий! Возможно, тут возникло недопонимание - в классе может быть несколько методов, просто публичный - только один - и это метод call.

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

Объект - это история про некое состояние, про применение методов к этому состоянию для его изменения или создания новых. У Вас, класс(объект) - это просто банка с одной функцией. Если Вы вытащите функцию из банки - ничего не поменяется но станет чуть чуть проще так как останеться разделение на простые функции и простые данные. Подход - в функцию передается и возвращается DTO сильно проще чем Ваш, не нужно объяснять кому-то что это вроде бы сервис но на самом деле команда с состоянием, а еще там может быть только одна функция и она должна быть такой то, не нужно объяснять не нужно следить за таким стилем чтобы никто не начал еще функции публичные писать, не нужно никого учить и объяснять почему класс должен имитировать функцию. Будьте проще - просто используйте функции и не нужно будет ничего объяснять и проверять.

  1. Единая ответственность. Каждый сервис реализует законченный кусок бизнес-логики — от простого создания объекта до комплексных операций с вызовами других сервисов или внешних API.

  2. Единственный публичный метод. Вся работа с сервисом ведётся через метод call. Избавляемся от проблемы когда разработчики начинают придумывать run-ы, execute-ы, process-ы и т.д.

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

Runtime async

Наверное, вы уже слышали о runtime async, даже есть отличная статья на Хабре. Если коротко, это позволит создавать легковесные асинхронные задачи, как горутины в Go, управление которыми ляжет на рантайм, без нагрузки на потоки ОС.

Боюсь Вы не до конца поняли как статью так и механику.

В указанной Вами статье:

Для реализации Async2 были рассмотрены два подхода: размотка стека (tasklets, stack unwindind) и JIT-сгенерированные машины состояний (continuations, JIT State Machine). Подход на основе JIT оказался предпочтительным благодаря лучшей совместимости с текущей инфраструктурой .NET, меньшим накладным расходам и более высокой производительности в большинстве сценариев. Размотка стека, хотя и поддерживает сложные конструкции, такие как byref и span, оказалась менее практичной из-за увеличения времени пауз сборки мусора и сложности реализации.

указано что как раз был выбран путь не как в Go. Если сильно упростить - останеться та жа стейт-машина но создаваться и поддерживаться она будет на уровне рантайма.

Без преувеличения, самая ожидаемая фича, которая позволит C# выбить главный козырь из рукава Go.

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

К примеру для виртуальных потоков Java главная задача была - это безболезненно мигрировать огромное количество проектов. Для Go - создать шайтан машину которое позволит разработчикам вообще не грузить голову по поводу управления задачами в среднем по больнице. Для C# - это - наглядность и управляемость.

Остается надеяться что самая темная ночь перед рассветом

лучше решает нестандартные задачи -> выше IQ ->

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

Если нет, зачем вообще проводить собеседование, можно же просто отбирать призеров олимпиад и турниров, не тратя время на собесы?

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

Если ужать все в одно предложение - мы создали копию Idea чтобы занять место JetBrains.

Единственный плюс - не зависеть от прихоти негодяев из JB. Это да. В остальном.

OpenIDE, напротив, полностью локален. Мы не передаём исходный код за границу и не отправляем телеметрию в сторонние облачные сервисы. Для компаний, особенно крупных, это вопрос доверия и информационной безопасности.

Где гарантии что завтра вы сами не станете это делать как только наберете достаточную базу пользователей?

OpenIDE Pro будет коммерческим продуктом. Это ответ на запросы рынка, которых получили немало, и закономерное решение: корпоративная поддержка требует реальных ресурсов — инженеров, времени на тестирование, инфраструктуры и процессов по SLA.

Предположу что вы изначально делали проект не из альтруизма но оно и понятно.

Проблема в другом. Что нового вы привнесете с этим продуктом помимо независимости от редисок из JB?

Да это не на Ваш комментарий ответ а на то что выше, а ответил Вам скорей в контексте эликсира. Специально написал "Это я в контексте прошлого комментария." Признаю, сформулировать получилось неудачно.

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

Я не понимаю претензий вида Rust не совершенен - я в нем разочаровался, и это еще на фоне таких "совершенных" языков как C++.
Есть один инструмент который одной делает хорошо а другое - плохо и другой который имеет обратные характеристики. Мы все ждем идеальный инструментов, но что-то пока не завезли. Когда завезут то что во всем будет лучше и решать большинство проблем, мне вот честно нафиг тогда не нужно будет копятся во временах жизни. Но это когда-то и возможно. А пока что есть то есть.

Я (внимание! лично я! это частное мнение! не претендующее на объективность!) не вижу архитектурных проблем в эликсире.

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

Мы имеем либо:
- просто и безопасно но не быстро(GC языки)
- просто и быстро но не безопасно(C/C++, все остальные виды C с бантиками)
- быстро и безопасно но не просто(Rust)

Я не знаю сейчас более менее живых языков, которые решают одновременно три эти проблемы. В этом контексте я не понимаю претензии к Rust. Разработчики сделали ставку на скорость и безопасность решая конкретную проблему - сделать быстрый язык без отстрела себе ног, это имело свои последствия в виде сложности. За все нужно платить. Можно было лучше? Наверное. Но где те идеальные инструменты где все и быстро и надежно и просто? Очевидно нигде. Когда появиться такое то уже будет интересно сравнить или действительно прийти к выводу что Rust не торт. А сравнивать с самострелами в контексте простоты наглухо закрывая глаза на отстреленные конечности такое себе.

Это я в контексте прошлого комментария.

По поводу Эликсира, в данном контексте его проблемой была бы производительность.

Я бросил раньше, видя глобальные проблемы. Правда я начал уже "зная брод".

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

- я ранее наткнулся и переводил статью Александреску касательно Раста

Почитал. Целых две и обе невероятно объективные.

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

Вторая - "Чуждый синтаксис. Это раздражает людей, пришедших из языков семейства Algol’а". Ну это по мне стыд и позор такие претензии предъявлять, что-то на уровне, язык плохой потому что у него маскот - краб.

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

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

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

  • не заморачиваться с инкапсуляцией и сделать все функции публичными. Думаю комментировать не нужно.

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

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

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

почему ссылки &foo — не поведение по умолчанию?!

Потому что не все типы ссылочные, есть еще и типы значений(i32, bool, структуры с копированием, перечисления и т.д.).В подавляющем большинстве языков дефолт - это передача по значению. Передавать все по ссылке а значения передавать специальным синтаксисом - это разрыв мозга.

Метапрограммирование

Это ад. Всё, кроме этого — вкусовщина и вопрос привычки, но если в языке в 2025 году заявлено метапрограммирование — оно не может быть настолько убогим.

Тут вообще не поспорить.

комментарии — это ад; 2025 год на дворе, но я не могу просто прочитать документацию перед функцией, нет — передо мной выстроен частокол //!. Ну как так-то?

Пока Вы не написали, если честно даже не замечал. А сейчас сходил посмотрел, точно.

какие тесты я кладу рядом с кодом, какие в папку test?

Рядом с кодом - модульные. И получаете доступ ко всем приватным функциям модуля, что очень полезно. В различные test интеграционные и прочие тесты.

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

Ну справедливости ради, такой велосипед не только в Rust но и в Python, Kotlin, C#, Scala, Swift и будет в Java. Думаю подход выбран для единообразия синтаксиса. В Rust нет перегрузок функций и делать исключения в виде особого синтаксиса именно для PM видимо было нецелесообразно. По карайне мере мне так кажеться.

Мне вот понадобился недавно язык с goto. Искал-искал

C# язык в котором есть практически все, в том числе goto

1
23 ...

Информация

В рейтинге
2 217-й
Откуда
Санкт-Петербург и область, Россия
Зарегистрирован
Активность

Специализация

Бэкенд разработчик
Ведущий
C#
Java
Rust
Golang
Многопоточность
C
Системное программирование
Разработка игр
Unity3d
Алгоритмы и структуры данных