Главная » Хабрахабр » Приверженцы статической и динамической типизаций никогда не поймут друг друга. И TypeScript им не поможет

Приверженцы статической и динамической типизаций никогда не поймут друг друга. И TypeScript им не поможет

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

Закончили школу, отучились в универах, отслужили в армии, устроились на работы. Я начал учить плюсы и C#, он — JavaScript. Нас потаскало промышленной разработкой там и тут, и когда мы оба от нее подустали, вспомнили с чего начинали.

Так как друг был чистый фронт, а я фулстек, очевидной платформой для нас стал браузер. Собравшись уже матерыми разрабами, мы решили, наконец, сделать свой проект — двумерную видеоигру. Возьмем его и все пройдет гладко. Раньше я разрабатывал фронт только на TypeScript, и мы подумали, никаких проблем, TS — всего-лишь надмножество JavaScript. Когда мы начали обсуждать работу, столкнулись с невероятной бездной непонимания друг друга.
Вот я увидел задачу сделать игру. Как бы не так. Я примерно представляю, как они работают вместе, описываю их, собираю проект и все работает. Я такой — ага, у нас есть тип «игра», тип «инвентарь», тип «вещь», тип «карта», тип «локация». Дальше я начинаю писать код, который использует эти типы. Компилятор меня проверил, я все сделал правильно. IDE мне подсказывает и проверяет на ошибки. Из-за того, что они есть, мне намного проще. Я потратил силы на описания типов, и это принесло пользу. Если проект собирается — скорее всего он и работает. Вот мой подход.

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

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

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

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

У статической и динамической типизации есть принципиальная непримиримая разница

Мой код отвечает на вопрос «Как с этим работать», а как код разрабов, привыкших к динамической типизации — «Как это работает». Оба подхода имеют право на жизнь, и есть инструменты для обоих, но только один может стоять во главе угла.

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

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

. Все обучение программированию на Java — это обучение проектированию и использованию типов. Cтатическая типизация лежит в центре дизайна объектно-ориентированного программирования (привет, классы из JS, я решил, что вы не нужны). NET CLR — рантайм C# — построен на типах и для типов. Канонические реализации большинства ООП паттернов пестрят кейвордом Interface, который совершенно бессмысленнен в динамически типизированном языке.

А билдер? Сами паттерны — штука кросс-языковая, но кто-нибудь может мне сказать, зачем нужен паттерн «состояние» в динамически типизированном языке? Типы и ООП связаны неразрывно. Эти паттерны не про разработку, они про типы.

Именно поэтому есть фронтендеры, которые покрывают свой код невообразимым количеством юнит тестов, которые как раз и проверяют кодовую базу на отсутствие type errors.
Мы все отлично знаем, что защищенность через покрытие — иллюзия. Нельзя строить свою бизнес логику, основываясь на типах, но при этом ничего о них не знать в процессе разработки. Тесты пишут руками, они по определению менее надежны, чем встроенная в язык система проверки типов.

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

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

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

Поэтому я критикую только тех из них, кто суется в мой definitely-typed проект, и наводит там свои any порядки. Эти ребята по неведомой причине просто не готовы жить в мире, где их видение содержит серьезные пробелы.

Мы бы так и жили в своих мирках, но TypeScript нас столкнул

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

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

Но на практике ты не можешь не рассматривать Тайпскрипт, как самостоятельный язык, даже если ты чертов король фронтендеров. Самый разрушительный аргумент — TypeScript лишь надмножество JS. Потому что тут нужен другой подход — статический, а не динамический.

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

Никакой он не компромисс, его система типов просто особенная. Многим кажется, что TypeScript — это компромисс систем типов между JS и Java.

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

Самый вопиющий кейс в нем — паттерн Ice factory. JavaScript, как мне видится, очень хороший инструмент, чтобы написать код, который решает проблему, не выделяя при этом лишние абстракции. Если я обработаю этой фабрикой свой объект, она отдаст мне такой же, но при попытке изменить значение одного из свойств, я получу исключение. Этой штуке можно скармливать свои инстансы, и она обмазывает их рантайм-иммутабельностью. Просто, WAT?!?

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

Бери F#, Haskell, OCaml, Кложу, ReasonML — там мутации запрещены из коробки. С другой стороны, и это не нужно, потому что есть чистое функциональное программирование. Но я боюсь, что если дать фронтендеру функциональный язык, он тут же начнет модернизировать его и сделает поведение похожим на JS.

Все компромиссные решения дают только иллюзию компромисса. Потому что выбор типизации — путь без возврата. Не знаю, как бы все сложилось, начни я учить C# и JavaScript одновременно и параллельно друг другу. Ты либо ставишь во главе угла типы, либо нет. Они есть, но вне поля моего зрения, и все что мне остается — закрывать на них глаза, как на любые чуждые мне проявления мира, с которыми приходится жить. Но сейчас я так крепко прибит к своему мышлению, что не вижу и не хочу видеть плюсов динамической типизации. Понимаю, что не прав, но работать мне надо здесь и сейчас, и метаться между полюсами бюджета нет.

Если только начинаете изучать разработку, начинайте со статической типизации. Поэтому я не хочу искать компромиссов, а говорю прямо.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Векторные представления товаров, или еще одно применение модели Word2Vec

Когда видов товаров тоже много, решить задачу помогает модель Word2Vec. Каждый день полтора миллиона людей ищут на Ozon самые разные товары, и к каждому из них сервис должен подбирать похожие (если пылесос все-таки нужен помощней) или сопутствующие (если к поющему ...

[Перевод] Внутренняя и внешняя линковка в C++

Всем добрый день! Надеемся, что она будет полезна и интересна для вас, как и нашим слушателям. Представляем вам перевод интересной статьи, который подготовили для вас рамках курса «Разработчик C++». Поехали. Хотите узнать, для чего используется ключевое слово extern, или как ...