Pull to refresh
-2
0
Send message

Интересный эксперимент, но я бы вежливо посомневался на предмет практической пользы от Ext JS на сервере как вообще, так и в данной конкретной реализации:


  • Классовая система имеет смысл в браузерах, которые ничего кроме ванильного ES5 не знают; Node умеет в ES8, которое хоть и не так наворочено, но вполне работоспособно.
  • Загрузчик и отслеживание зависимостей заточено на Cmd и вне своих рамок выпьет крови по полной программе. То, что вы грузите ext-all-debug.js уже как бы намекает; при этом загружается весь фреймворк, а используется может быть 1% от его возможностей. Понятно, что 30-40 мб памяти для сервера ни о чём, но сам факт.
  • Система конфигов гибка и приятна, но платить за неё придётся производительностью, и платить дорого. А отказываться от неё больно.
  • Система событий абсолютно полностью заточена под браузеры. Я не до конца понимаю, как вам вообще удалось завести всю эту дребедень под Нодой, но есть все шансы, что выстрел в ногу из ядерной пушки на каком-то этапе случится. А если нет, то и толку от неё мало: событийная система в Ext синхронна по определению, что для браузера ещё как-то в общем ничего, но для Ноды смерти подобно.
  • Абсолютно не очевидный при разработке нюанс, который впоследствии практически гарантированно поставит колом систему в боевой среде: Ext JS полностью завязан на глобальные объекты. Ваша память ещё не течёт, как дырявое решето? Будет. Опять же для браузеров терпимо, а вот для сервера каюк.

И т.д., и т.п. Реализация серверной логики на Ext.app.Controller улыбнула, сделали приятно старому шарлатану. :) А что касается приёма и отправки сообщений, то всё уже украдено до нас. Ext Direct вам в помощь.


В общем, не нужно оно на сервере, совсем. Это я вам как доктор говорю.

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

С этим никто не спорит. Вопрос в том, какого типа тесты надо писать.

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


Ну вы ведь понимаете, что упёрлись рогом в красную селёдку?


Когда я пишу на хаскеле, я не пишу юнит-тесты. Вообще. Совсем. Они мне не нужны.

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


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

Я не знаю специфики вашего проекта, но то, что вы описываете, может быть либо юнит-, либо интеграционными тестами.


Собственно, да, такие тесты и есть спека на всю систему целиком.

Если ваша система предназначена к использованию как единое целое, без разбивки на отдельные части, то это как раз и будут юнит-тесты. См. определение.

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

Вот тут вы как раз и задели большую и интересную тему. Если вкратце и упрощённо: а зачем это гарантировать? Нет, погодите возмущаться, подумайте. От кода нужно, чтобы он делал что-то полезное: проценты какие-нибудь считал, или DOM элемент создал, или ещё что-нибудь. В подавляющем большинстве случаев конечный результат работы это строка. Если смотреть с этой стороны, то типы данных это не более чем внутренняя абстракция программы, инструмент для достижения каких-то целей. Почему этому инструменту придаётся такое большое значение?


Тесты, проверяющие логику работы — нужны, конечно.

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


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

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


По-этому можно, конечно, использовать, но надеяться на то, что они отработают правильно — нельзя.

Вот тут, мне кажется, вы переводите вопрос в эмоциональную плоскость. Если отойти от эмоций и уверенности/обеспокоенности, то можно заметить, что динамический анализатор это такой же инструмент, как и все остальные: статическая проверка типов, тесты, и т.д. Динамические анализаторы не могут решить 100% проблем, равно как и остальные инструменты. Мы используем эти инструменты для уменьшения количества дефектов в программах, но добиться полной победы невозможно, поэтому надеяться на это тоже бессмысленно.


А с другой стороны, как всегда, вопрос стоимости того или иного инструмента. Стоимость внедрения, стоимость поддержки, ограничения — вот это всё. Плюсы против минусов.


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

Я очень часто слышу эту мантру: вот встретишь, мол, по-настоящему большой проект, тогда поймёшь. Давайте определимся, о каком размере речь-то идёт? Я уже приводил пример проекта на 1.5 млн строк в JavaScript. Написанных очень, очень опытными и профессиональными людьми, и весьма плотно. Это web framework, на котором построены высоконагруженные проекты, соответственно и требования к качеству кода намного выше, чем у обычного LoB приложения.


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


Основной контроль качества на этом проекте осуществляется через тестирование. Динамический анализ только-только начал внедряться недавно (это сложная тема). Проблемы при внедрении анализатора были выявлены в основном в старом и плохо протестированном коде. Исправление этих проблем заняло день или два.


Насколько же большой проект мне нужно глубоко изучить, чтобы всё-таки дойти до точки невозврата и броситься в тёплые объятия type safety? :)


Тесты обычно на порядок медленнее компиляции.

Смотря где, могут быть и на два порядка. :) Но их всё равно гонять надо, а при грамотном подходе можно и 500,000 тестов прогнать на дюжине браузеров за 15 минут.

Честно сказать, я не совсем понял ваш посыл про Питон. В нём типизирование строгое/динамическое, но совершенно не опциональное.


Понятия действительно смешаны, mea culpa. Прочитал ваше сообщение по диагонали и увидел то, что хотел увидеть, вместо написанного. Прошу пардона. :)


Если применить мою логику к вашему изначальному сообщению, то получается, что речь идёт об опциональной статической типизации (и не обязательно строгой). А это как раз, скажем, JavaScript + Flow. Надо попробовать.


А полезные для себя мысли я всё же вынес, так что спасибо за беседу.

Мне обычно 2-х недель хватает, чтобы начать и еще 2-х чтобы прочувствовать язык.

Ну вот считайте, что я такой слоупок, мне не интересно галопом по Европам. А для глубокого понимания, анализа отличий, и, самое главное, осознания преимуществ тех или иных решений нужно не просто почитать документацию и покодить демки на уровне todo list, а ещё и шишек набить на реальных взрослых проектах. Которых на Java/F#/Kotlin у меня нет, а у вас вроде есть, поэтому я и спросил.


Те, кому это интересно изучают (инвестируют) не потому что нужно, а потому что интересно. И там есть, что изучать.

С чего вы решили, что мне нечего изучать? :) Список того, что мне хотелось бы попробовать и поковырять, гораздо длиннее списка того, что я уже знаю. Но вот ни Java, ни F#, ни Kotlin в этот список не входят, как и многие другие языки со строгим типизированием, хотя скорее вне зависимости от оного. Просто не интересны.


Кроме того, проблемы понимания это не решит: в Java нельзя обойтись без строгого типизирования, и сравнивать не с чем.


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


Ой, забыл спросить, как у человека пишущего на JsvaScript 8 лет: Как там вас бомбит от пропоузалов по private fields?

Да вообще не бомбит, точно так же, как и от TypeScript и многих других вещей. Кому-то надо, они пилят. Меня это не обязывает все эти фичи использовать. :)


Не приходит мысль о том, что в других языках такой проблемы нет и не было никогда? Почему бы это? Как вы думаете?

В каких именно других языках? Их много разных. Вот, скажем, в очень модно-популярно-строго-типизированном Python их тоже нет. Точнее, даже хуже: private fields как бы есть, но в виде уродливого хака в компиляторе.


Плохой язык, получается? Или просто культура/подход/методология другая? Почему бы это, как вы думаете?

Естественно, теперь везде на call site должна быть добавлена проверка на null'ы — вы меняете возвращаемый тип с X на X | null и теперь код не скомпилируется, если где-то есть непроверенные места.

Спасибо, это убедительный пример. Зерно сомнений продолжает расти.


Вы врете.

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


А с типами никакого покрытия тестами не надо.

Это очень распространённое мнение, но, на мой взгляд, весьма ошибочное. Смысл тестирования вовсе не в том, чтобы заменить строгую типизацию. Правильно написанные тесты выполняют как минимум три основные задачи:


а) Документирование ожиданий
б) Проверка правильности исполнения в нужном контексте (для front end, в конкретных браузерах)
в) Защиту от регрессий


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


Очевидно, за тем, чтобы не писать

Это тоже очень распространённое мнение, и, на мой взгляд, настолько же ошибочное. Смотрите:


  • Рефакторинг становится не только возможным, но и вполне лёгким, когда вы можете менять любой код в системе, зная что тесты будут падать, если что-то не так. И даже в тех случаях, когда компилятор пропустит.
  • Наличие работающего набора тестов позволяет легко решить проблему с устранением дефектов: пишем тест, который падает без фикса, и проходит с фиксом. Со временем такие тесты становятся просто незаменимыми для учёта различных пограничных случаев при рефакторинге.
  • На базе набора тестов с достаточным покрытием можно внедрить разные продвинутые механизмы динамического QA, статическим анализаторам и компиляторам просто неподвластные.

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


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


(и потом не выполнять регулярно)

А вот это уже мелочи, извините. Вам не всё равно, что именно выполнять, компиляцию или тесты?

У меня нет особо задачи вас убеждать.

Да я в общем-то и не просил меня убеждать. Я попросил привести пример и пояснил, зачем спрашиваю.


Программируйте больше на современных языках (не на Java) и сами всё поймете. F# возьмите или Kotlin хотя бы.

С Java я не работаю, равно как и с F# или Kotlin. Нет практических задач на них по основной специальности, а инвестировать 5 лет вечеров в изучение ненужных мне языков просто для того, чтобы может быть понять прелести строгой типизации, это как-то странно было бы. У меня столько времени нет.


То, что вы спрашиваете — довольно очевидные вещи для тех, кто писал на разных языках. Не очень интересно на спичках объяснять азы про всякие про рефакторинги вроде change method signature.

Спасибо, мне не надо объяснять азы. Я их вполне неплохо знаю. :) А вещи, о которых я спрашиваю, как раз не очевидны, иначе я бы не спрашивал.


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

Это ни о чём не говорит, кроме того, что большому количеству людей очень неуютно без тёплого лампового type safety.


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

Хм. Давненько меня в хипстеры не записывали. :)


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


Спасибо за беседу.

А современная тенденция заключается в переиспользовании существующего DOM-а.

Да я в курсе, просто позанудствовал. :)

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

Блин, ну вы банально пишите где-то: myobj.myMethod.

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


С тем, что хорошее покрытие тестами спасает от таких проблем, я спорить не собирался. Я вообще с вами не спорю, а пытаюсь (в очередной раз) узреть свет истины в строгой типизации. Пока не очень получается, т.к. все приводят банальные примеры в стиле: ну вот мне надо поле в объекте поменять, типизация меня спасёт. Чего-то более убедительного я пока не видел, а когда начинаешь копать, всё сводится к тёплому ламповому ощущению безопасности (Type safety? Отличный маркетинг).


В то же время строгая типизация ооочень сильно продвинулась за последние годы

Это всё хорошо и замечательно, но не показывает, зачем всё это нужно.

Понятно, спасибо. Далее вопросов не имею. :)

Формальные тесты проверяют корректность API: принимают ли методы/функции задекларированные типы аргументов, что возвращают, что получается если передать "неправильный" тип данных, и т.д.


Функциональные тесты проверяют что код делает. Нажали на кнопку, получили результат. Тот результат или не тот? И т.д.

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

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


Можете привести примеры, когда статическая типизация помогла вам провести логический рефакторинг когда без наличия существенного тестового покрытия? Честно не флейма ради, мне правда интересно.

Это ваше личное мнение, или можете привести результаты исследований? :)

Ну и есть огромная разница между innerHTML= и производительной работой с DOM.

Не флейма ради, а объективности для: разница есть, в разы. В IE (включая 11) и Edge* innerHTML = ... гораздо быстрее appendChild. В WebKit с точностью до наоборот.


Всплакнём, господа гусары...


* По данным на год или около того назад, с тех пор не проверял.

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


Пользуюсь таким столом уже несколько лет, удобнее не встречал нигде и ничего. Ссылок приводить не буду, но производитель называется Herman Miller, а модель — Envelop.

Загрузку данных можно делать по-разному, в каких-то случаях имеет смысл загрузить весь набор данных, в каких-то нет. Фреймворк умеет работать с разрозненными данными и подгружать страницы по необходимости. Поиск и сортировка тоже могу происходить либо на клиентской стороне, либо запросом на сервер. Один из наших клиентов использует Ext JS для визуализации/поиска по базе данных размером около 7 млрд записей. Это самый большой пример, который я видел, могут быть и другие.


Документации у нас много и она довольно подробная: quick start guide.

Ext JS, очень большой фреймворк. Около 1.5 млн строк JavaScript + SASS.

Почему вы решили, что компиляторы были разные? Наоборот, у меня были все основания предположить, что для всех продуктов Microsoft используется компилятор производства Microsoft же. Какой смысл использовать что-то ещё? К 1999, когда выпустили IE 5.5, MSVC был уже матёрым и обкатанным компилятором, в который вряд ли будут вносить радикальные изменения. Обе версии IE были 32-битными, что тоже помогло.


А дальше всё (относительно) просто: есть пример с минимальной HTML/CSS/JavaScript разметкой, стабильно воспроизводящей баг. Проблема где-то в mshtml.dll, это видно из сообщения об ошибке. Ставим MS Visual Studio, оно добавляет системный обработчик ошибок с возможностью открыть программу на шаге, вызвавшем исключение. Вокруг этого шага есть дизассемблированная каша и немного ключевых слов: названия методов и т.д.


Я не помню, удалось ли мне найти и поставить отладочные символы для IE; скорее всего нет, иначе не потребовались бы пляски с бубнами вокруг исходников Win 2000. Но проблема была где-то в коде mshtml.dll, который, как я предположил, между IE 5.5 и IE 7.0 менялся несущественно. Мне ещё зверски повезло, что в "слитом" коде были исходники mshtml.dll, там вообще не так, чтобы очень много интересного было. Вовсе не "полные исходники Windows 2000", как об этом в своё время жужжали на всех углах. :)


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


Это я сейчас по памяти рассказываю, возможно что-то и не совсем так шло. Почти 6 лет назад дело было, да и баг был хоть и заковыристый, но далеко не самый важный/сложный, так что обращать на него много внимания не было смысла. Так, страшилка "из былого", чтобы было о чём с коллегами языками почесать за пивом. :))

Information

Rating
Does not participate
Registered
Activity