Сила утиной типизации

от автора

За жизнь я программировал на разных языках программирования, включая Ассемблер, Си, Java и JavaScript. И в этой цепочке явно замечается, на сколько удобнее и быстрее идёт разработка на каждом следующем языке по сравнению с предыдущим. В этой статье я хочу поговорить о свойствах последнего из них, а точнее об одном свойстве – неявной (утиной) типизации, и развить мысль дальше. Вы не вынесете из этой статьи ничего полезного для повседневной работы. Скорее это послание к создателям языков и размышление на тему того, каким должен быть современный язык программирования. Если у вас есть свободные 10 минут – прошу под кат.

image


Многие ещё помнят, когда-то в базах данных нужно было задавать размеры текстовых полей, программистам приходилось думать, а хватит 20 символов для имени пользователя или не жадничать и дать 255. Сейчас у нас есть NoSQL базы, в которых можно не думать не только о размере полей, но и о структуре таблиц, добавляя поля в каждую запись индивидуально. Конечно иногда приходится проводить оптимизации, использовать старые, но эффективные инструменты, прописывать длину полей, индексы и т.п… Но здесь есть принципиальный момент – эта работа делается только по необходимости. Это экономит самый важный ресурс – наше время.

К чему это отступление? Сейчас у архитекторов языков наметился интересный тренд, на типизацию JavaScript, давно существует CoffeeScript со встроенными классами, EcmaScript 6 объявил для них нативную реализацию, TypeScript ввёл типизацию в название. Не удивительно, ведь не типизованный язык сложнее компилировать, сложнее проводить его статический анализ и искать ошибки. И безусловно классы – это то, чего в JavaScript давно не хватало. Сейчас меня закидают тапками, но какова же обратная сторона? Эта ситуация напоминает переход от NoSQL баз данных назад к структуре. Это понятнее, производительнее, но медленнее в разработке. И хорошо, если язык разрешает расширение объявленных экземпляров класса и использование нетипизованных хешей, в TypeScript, например, с этим наблюдались проблемы. Ждём, что покажет ES6.

Почему я об этом так беспокоюсь? Я решал проблему нетипизованности JavaScript в большом финансовом проекте, где нужна была абсолютная стабильность. Многие знают как, используя JSDocs. Вы просто пишите типы в специальных комментариях, объявляете классы, наследование, добавляете описание функций, классов и модулей. Немного неудобно, кажется, что делаешь двойную работу, зато можно писать хоть ERP-систему. На этот раз я решил покрыть весь код, чтобы не осталось ни одного неоттипированного кусочка. Проблему начались когда я начал спускаться на уровни глубже модулей и классов, к функциям, их аргументам, их преобразованиям. Сущности начали плодиться как грибы, на 15 строчек JavaScript кода приходилось по 3 класса и 2 сущности обработчика, и по 30 строчек JSDocs комментариев. Некоторые участки были более плодовитыми, некоторые менее, но тренд явно прослеживался. Одно время назад знакомый джавист жаловался, что на то, что он может собрать на HTML за 2 недели на Java ему приходится тратить 2 месяца. И сейчас я понял почему. Это не проблема Java – это проблема всего типизованного подхода. Многие объекты создаются всего один раз, зачем создавать для них класс? Существует огромное количество мелких объектов из двух-трёх свойств, если создавать класс для каждого из них – мы закопаемся в этом зоопарке. В JavaScript распространён паттерн параметра-конфигурации, когда мы посылаем в функцию хеш из свойств, а функция уже сама реагирует на какие их этих свойств реагировать. Кроме того существуют сквозные обработчики таких свойств, которые принимают хеш и перенаправляют кому-то, даже не зная что внутри. Отсутствие типизации – это замечательное свойство языка, которое кардинально экономит время программисту.

Чего бы хотелось? Хотелось бы типизации по запросу. Знаете в чём основная причина возникновения ООП? Я сам был удивлён, когда узнал. Можно отлично писать программы и в процедурном стиле, они получатся не менее эффективными, компиляторы прекрасно их съедят, а функционал они смогут выполнять полностью тот же самый. Основная причина – когда мы группируем свойства и методы в одну сущность с говорящим названием – нам проще это понимать. Вот это Лисица, она наследуется от Животного, она имеет метод «съесть», который принимает экземпляр класса Заяц. Это проще запоминается, вот и всё. Всё это сделано для нас, чтобы экономить наши мыслительные усилия. Есть и другие причины, чтобы избежать конфликтов имён и, чтобы обращаться к свойствам внутри класса по короткому имени, но они могут быть решены гораздо более простыми способами. Я работал в проекте, писавшем в процедурном стиле, и там модуль с 2000 функций, конфликта имён не возникало, а обращаться к ним без префикса названий классов было даже быстрее. Единственная настоящая причина существования классов – они делают программу проще для понимания. Поэтому, следуя этой логике, должны применяться на объектах, которые действительно представляют из себя законченные сущности, которые мы хотим выделить и дать им название. Но нужно оставить возможность использовать и нетипизованные хеши, принимающие свойствами примитивы, функции, как объекты первого рода, или другие хеши. Это огромный шаг вперёд и не нужно от него отказываться.

image
Даже больше того, нам нужно больше таких фич. Пускай observable будет встроен во все объекты нативно и будет вызываться по требованию (кажется над этим уже работают). Пускай компилятор сам определяет границы функций и служебных блоков (а что, думаете невозможно?). Пускай callback-hell и клёвые, но громоздкие promises, решаются средствами языка в одну строчку. Ветвления логики сейчас разруливаются или через if, или через наследование или агрегацию, если заранее подумать. А как бы сделать так, чтобы заранее не думать и совместить плюсы обоих подходов? Хотим больше синтаксического сахара, хотим [a, b] = [2, 3] (уже делается). Хотим кроме иерархического ещё и лексический this (видимо под другим именем). Хотим передавать текущий скоуп (и доступ ко всем замыканиям) как аргументы в другую функцию. Понимаю, что сложно. Много работы по оптимизации, сложный инженерный вызов. Но отцы же наши подарили нам утиную типизацию, должно и наше поколение внести свой вклад.

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

P.S.: Прошу строго не судить, если не согласны с какими-то тезисами статьи. Для того и публикую на geektimes, что статья скорее не техническая, а метательская. А мечтать каждый из нас волен в любом направлении. Однажды из таких мечтаний и вырастает будущее.

P.P.S: Мы сейчас живём в такое время, что либо ты сам создаёшь себе мечту, либо мечты тебе создаёт реклама. Предлагаю всем желающим заняться первым.

ссылка на оригинал статьи http://geektimes.ru/post/248978/


Комментарии

Добавить комментарий

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