Pull to refresh

Comments 29

Иными словами, предлагается не использовать возможности языка TypeScript, т.к. автор изначальной статьи не очень верит в first-class поддержку инструментами этого языка.

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

Как мы не отказываемся от циклов for/foreach в серверных языках по причине лишь того, что в ассемблер или в IL они не транслируются "как есть", а выражаются через goto, так же и нет смысла отказываться от идиоматичных средств языка из-за особенностей трансляции в нижележащий "технический" язык исполнения.

Не только автор
twitter.com/youyuxi/status/1488039446167490561

и не оглядываться на JS,

А почему не оглядываться на JS? Бандлы по 2 мегабайта, это нормально? Это же ужасно фигачить на js как на java а потом удивляться размеру бандла.

Как мы не отказываемся от циклов for/foreach в серверных языках по причине лишь того

потому что у циклов for/foreach «удобство vs перформанс» имеет значительный перевес в сторону удобства и совсем незначительную просадку в производительности, если она вообще есть.
А тут вы предлагаете закрыть глаза на то, что js в принципе не типизируется. И хрен бы с ним с объемом выходного кода.

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

Мне кажется, на размер бандла прежде всего влияют зависимости в большом количестве. А не enum.

Сколько будет в среднем проекте этих enum? 10? 20?

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

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

С декораторами я бы ещё привёл в пример Angular как фреймворк, активнейшими образом их использующий.

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

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

Та же фигня с CLI-тулзами (не только ангуляр, в том же реакте то же самое) - есть шаблон типового поведения - нет понимания, не говорю уже о контроле, что там происходит. Не то, что я хочу поныть в стиле "раньше на курсах вождения карбюратор на время собирали, а сейчас видосик 5 минут смотрят где какая педаль, и всё". Это, скорее, профессиональный перекос, потому что меня постоянно зовут то ng-eject делать, то просто руками новый бандлер написать, когда задача перерастает возможности стандартного тулчейна.

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

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

Сорри за офтопик, просто как раз сижу разгребаю один проект-переросток на ангуляре.

Думаете много людей понимают как работают / устроены хуки?

Магия это неотъемлемая часть высокоуровневых фреймворков.

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

Впрочем, зависит от проекта и людей, наверное. Ко мне на собеседование приходили "ангуляр-разработчики", которые не знали чистого JS вообще (но и "реактовский" такой был тоже, для справделивости).

"Я пять проектов написал на ангуляре, зачем мне ваш жаваскрипт знать?"

(я, если что, не спрашивал сложение массивов с объектами - банальные this, замыкания, шедулер в общих чертах, передача по ссылке... народ претендовал на сеньоров/стронг мидлов).

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

UFO just landed and posted this here

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

В NestJs они тоже очень активно используются.

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

Ах этот замечательный испанский стыд, когда автор оригинальной статьи рекламирует свои курсы по typescript, но при этом const enum осилить не смог:)

const enum не может быть странспилирован пофайлово. А непофайловая транспиляция сильно бьёт по скорости ребилда.

Прямо подборка вредных советов. Какое кому дело, во что там компилируется typescript?

Особенно с js-овским #private, об использовании которого надо миллион раз подумать, поскольку сериализовать такой объект с сохранением его внутреннего состояния просто невозможно.

А декораторы с reflect-metadata уже много лет как стандарт индустрии.

Особенно с js-овским #private, об использовании которого надо миллион раз подумать, поскольку сериализовать такой объект с сохранением его внутреннего состояния просто невозможно.

Это вполне нормально, что вопрос о возможности сериализации того или иного объекта должен решаться с участием этого объекта. А не то, что внешние силы чего-то там сериализуют как им удобно.

Смотря с какой целью. Если задача в том, чтобы сохранить состояние программы между (пере)запусками или выгружать-загружать из оперативки на диск по мере нужды (будь то персистенция Aggregate Root с помощью DataMapper в парадигме DDD, или что-то наподобие PhantomOS), объекту как раз ни к чему об этом знать: это ведь просто инфраструктурная деталь (ограниченность объема и неустойчивость к сбоям питания оперативной памяти), а не бизнес-логика.

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

объекту как раз ни к чему об этом знать

В этом случае объекту всего лишь достаточно удовлетворять определенному интерфейсу. Т.е. в яве быть Serializable, а в терминах нашего разговора — не иметь приватных полей, или не хранить там ничего относящегося к состоянию.
И это опять же выбор объекта, быть ли ему таким или эдаким, вы не можете просто так проигнорировать все слои абстракции под объектом, заявив, что вы хотите сделать что-то такое, что "всего лишь инфраструктурная деталь". Объекту лучше знать, можно ли над ним совершить такое действие, или таки нет. Игнорируя абстракции и их неизбежные протечки, вы так завтра начнете писать /dev/urandom в БД до исчерпания потока, да еще и будете возмущаться, что у вас с этой деятельностью что-то пошло не так.


как, скажем, позволяет сделать, пусть с определенными неудобствами и оговорками, Reflection в Java

Рефлексия никогда не является вычислительно бесплатной, и если она мне не нужна — я предпочту её не иметь вообще, чем иметь всегда, и не пользоваться (ява, да).


PS: Да и вообще говоря, дело не в приватности — ваш пример про сериализацию уже требует от объекта намного более детального и конкретного контракта, чем просто "не пользуйтесь #" (тут и по чтению полей будет много соображений, и по записи — еще больше). Так что вы сильно лукавите, когда ставите этот случай в упрек яваскриптовым приватным полям.

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

Универсальное решение для персистенции вообще всего, очевидно, невозможно. За исключением случаев, когда необходимые для этого механизмы не будут обеспечены внешним миром (т.е. средой выполнения, например). Во всех остальных случаях — вам придётся таки договариваться о том, что у вас там будут за объекты. Даже если таковые договоренности достаточно простые.


PS: даже и в яве с её безусловной рефлексией нельзя персистировать что угодно.

Паттерн Data Mapper напрямую подразумевает разделение самого объекта и описания механизма персистенции. В этом суть паттерна. Никакой магии, конечно, не произойдет (кроме элементарных случаев), маппинг придется описывать. Но объекту про само наличие этого маппинга знать не надо ровным счётом ничего.


Дизайн языка, который не позволяет применить один из самых распространенных (а в рамках парадигмы DDD по сути обязательных) паттернов проектирования — прямо скажем, спорное решение.

Я совсем не понимаю, с чем вы всё еще пытаетесь спорить.


Но объекту про само наличие этого маппинга знать не надо ровным счётом ничего.

Объекту всегда (включая эти ваши хибернейты) нужно удовлетворять критериям пригодности к использованию в маппере.
"Знать" не нужно, нет. Иметь совместимый с маппером интерфейс — да.

И какой же "интерфейс" нужно иметь POJO для "совместимости"?

А сфигали в хибернейте POJO? Откуда тогда взялось дополнительное требование к no-arguments constructor? Или тут POJO, тут не POJO, тут рыбу заворачивали?


Все эти дополнительные требования — это и есть описание интерфейса.

В Hibernate (в отличие от JPA) нет требования no-arguments constructor. Да, без дополнительных плясок, связанных со спецификой Class.newInstance() (что, на самом деле, ужасно неудобное ограничение Java, и часто приходится извращаться через платформоспецифичные методы типа Unsafe.allocateInstance), не обойтись — но прежде всего для того, чтобы не было требования no-arguments constructor, в Hibernate и существуют интерцепторы.

На самом деле это советы разного уровня полезности.
Самый полезный — enum. Потому что рефакторинг енумов, действительно, очень легко может превратиться в рантайм-ошибки — а вообще-то главным образом TS используется именно для того, чтоб как можно меньше проблем с типизацией протекало в рантайм.
Только это происходит не тем путем, что описан в статье, конечно (там транспиляция не пройдет, всё ок), а при изменении, например, правой части строковых енумов: было someEnum.A = 'A', отрефакторили по любой причине в someEnum.A = 'a' — и удачи найти все места в коде, которые теперь могут отработать неправильно.
На этом фоне изменения в union type, которые точно не пройдут транспиляцию — это просто рай, пусть даже и придется сделать больше правок в коде при рефакторинге. А учитывая, что в текущем TS union type спокойно создаются из константных списков — разница с енумом осталась довольно маленькой, и строго не в пользу енума.


Совет про namespace скорее вредный, аргумент "ой это нельзя просто взять и удалить из TS-кода, получив корректный JS-код" не выдерживает никакой критики. Ну нельзя, и что?


Совет про декораторы — "средненький". Используя декораторы, очень желательно понимать, как конкретно они работают в целом, и как конкретно — вот этот, который вы используете. Тогда хотя бы если что-то начнет ломаться по причине очередного сдвига стандартов и их черновиков — вы будете иметь представление о том, что же именно могло сломаться. Декораторы в прошлом пару раз уже (потенциально) ломались.


Совет про # — приемлемый. Если у вас тулинг это всё поддерживает, то действительно, пишите # вместо private, почему нет. Но это не повод прям агрессивно избегать private, рефакторить имеющийся код, и совершать подобные резкие движения.

Ну делать enum типа `Get = 'GET'` действительно довольно бесссысленно и этого стоит избегать:) Алгебраический тип тут справится гораздо лучше.

А вот вещи типа `green = '#00ff00'` ложатся на перечисления куда лучше. Это ведь типизированный маппинг, так сказать.

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

Я ещё больше задумываюсь о том, насколько страшно веб программирование, что базовые вещи любой другой сферы под запретом

Тайпскрипт вообще не нужно использовать!

И переходить уже от ООП болота е нормальному программированию.

Sign up to leave a comment.

Articles