Реальные жизненные преимущества динамических языков?

Я изучаю несколько возможностей для разработки новой системы (веб-приложения).

Я "старомодный" любопытный парень, объектно ориентированный в природе (преобразованный из процедур много лет назад). Я играл с Python и изучал немного Ruby, но, откровенно говоря, меня привлекают инструменты Microsoft (С#, ASP.NET MVC). Вся эта типизация во время выполнения, отсутствие ошибок компилятора в базовых материалах и т.д. Просто усложняет жизнь, когда дело доходит до построения сложных сложных приложений.

Я постоянно слышу, как люди говорят о великих вещах, которые вы можете делать с динамическими языками, но, за исключением примеров с собаками, кошками и как быстро вы можете прописать классный способ подсчета вещей, "промышленная сила" Visual Studio просто кажется чтобы устранить эти аккуратные мелочи, предлагаемые динамическими языками, особенно теперь, когда у вас есть бесплатные экспресс-версии VS и полные версии, доступные бесплатно для начинающих.

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

Ответ 1

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

Преимущества динамических языков.

  • Нет компиляции, нет сборки. Просто код и тест, а затем развертывание в производство.

  • Немедленное удовлетворение. Не тратя время на то, чтобы вырвать мои руки над тем, что может вызвать API. Просто введите его интерактивно в подсказке Python → > и посмотрите, что он на самом деле делает.

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

  • Меньше кода. Динамическая языковая интроспекция уменьшает объем источника. Я не пишу это в своих приложениях; Я полагаюсь на рамки, чтобы сделать это для меня. Но код на основе структуры часто очень короткий; нет дублирующих объявлений, которые так распространены в Java, где вам нужно повторять что-то в конфигурации XML.

  • Никаких тайн. Как мы говорим в сообществе Python: "Используйте источник, Люк". Там нет двусмысленности в том, что делает каркас или что API действительно означает.

  • Абсолютная гибкость. По мере изменения наших требований нам не нужно бороться с разрушительными изменениями, которые разрушают всю архитектуру. Мы можем - тривиально - внести изменения в несколько классов, потому что Python Duck Typing устраняет необходимость переопределять недостающие определения интерфейсов, где мы не думали, что они понадобятся. Они просто не нужны; код, который мы не писали, - это код, который нам не нужно исправлять или поддерживать.

  • Упругость

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

  • Поскольку источником является приложение, источником может быть собственный файл конфигурации. У нас нет файлов конфигурации XML или INI в некоторых внешних синтаксисах. У нас есть файлы конфигурации в Python. Рамка Django делает это, и мы следуем их примеру. У нас очень сложные издевательства над декларациями данных для демонстрации продаж и модульного тестирования. Суперкомплексные данные на самом деле представляют собой набор объектов Python, которые были бы получены из базы данных - кроме - мы пропустили загрузку базы данных. Проще просто настроить конструктор объекта Python вместо загрузки базы данных SQL.

[КСТАТИ. После 30 лет разработки программного обеспечения в Cobol, Fortran, PL/I, Java, C, С++, я просто устал от относительно низкоуровневой оптимизации рук, которую требуют большинство компилируемых языков. Несколько лет назад я прочитал комментарий о неэффективности большинства компиляторов: он заставляет нас создавать сложные системы сборки, чтобы обойти ограничения компилятора. Нам нужен только make, потому что cc настолько медленный.]


Edit

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

Если вы хотите написать много кода на основе неправильно понятого API, то может помочь динамический язык. Вы можете написать много кода, который сбой и ожоги на языке: С#, VB, С++, Java или Python. Вы всегда можете написать код, который не будет работать.

Компилятор дает вам предварительное предупреждение о том, что код не будет работать. Обычно компиляция - это большой намек. Тем не менее, вы все равно можете написать много кода, который компилирует и не выполняет все модульные тесты. Компилятор проверяет синтаксис, а не семантику.

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

Ответ 2

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

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

Для этого подходит общая система типов Lisp. Все объекты данных знают свой тип, и вы можете явно указать этот тип, если хотите.

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

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

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

Ответ 3

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

С помощью интерактивного языка, как правило, легко модифицировать небольшую часть, а затем сразу же тестировать результаты. Если ваш тест все еще занимает время лома, вы этого не выиграли, но обычно можете тестировать на более мелкие случаи. Это способствует быстрому развитию. Как только вы реализуете известную правильную реализацию, это также помогает оптимизировать, так как вы можете быстро и быстро разрабатывать и тестировать свои новые улучшенные функции и экспериментировать с различными представлениями или алгоритмами.

Ответ 4

Вот часть моего ответа на предыдущий аналогичный вопрос (Я знаю С#. Буду ли я быть более продуктивным с Python):

Я сам из С#/.NET. Началось программирование в .NET в abt. 2001, и примерно в то же время был представлен Python. В 2001 году мое время, проведенное в С# против Python, составляло около 90% С#/10% Python. Теперь отношение составляет 5% С#/95% Python. В моей компании мы все еще поддерживаем линейку продуктов на основе .NET. Но все новые вещи основаны на Python.

Мы создали нетривиальные приложения в Python.

В моем опыте, что делает меня более продуктивным в Python против С#, есть:

  • Это динамический язык. Использование динамического языка часто позволяет удалять целые архитектурные слои из вашего приложения. Динамическая природа Pythons позволяет создавать многоразовые абстракции высокого уровня более естественным и гибким (синтаксическим) способом, чем вы можете на С#.
  • Библиотеки. Стандартные библиотеки и множество библиотек с открытым исходным кодом, предоставляемых сообществом, имеют высокое качество. Диапазон приложений, используемых Python, означает, что диапазон библиотек широк.
  • Более быстрый цикл разработки. Без шага компиляции я могу быстрее протестировать изменения. Например, при разработке веб-приложения сервер-разработчик обнаруживает изменения и перезагружает приложение, когда файлы сохраняются. Запуск unit test из моего редактора - это просто нажатие клавиши и выполняется мгновенно.
  • "Легкий доступ" к часто используемым функциям: списки, списки, генераторы, кортежи и т.д.
  • Менее подробный синтаксис. Вы можете создать веб-инфраструктуру Python на основе WSGI в меньшем количестве строк кода, чем ваш типичный файл .NET web.config: -)
  • Хорошая документация. Хорошие книги.

Ответ 5

Интерактивные оболочки! Это огромный прирост производительности. Просто запустите irb/python, чтобы сидеть перед интерактивной оболочкой (для рубина и питона соответственно). Затем вы можете интерактивно тестировать свои классы, функции, экспериментировать с выражением (отлично подходит для регулярных выражений), различный синтаксис и алгоритмы. Это настоящая игровая площадка для программистов и отличный инструмент для отладки.

Только мне два цента об ошибках:

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

Ошибки обнаружения компилятора - это те ошибки, которые вы обнаружите при выполнении различных автоматических тестов (единицу, функциональность и т.д.) и тех, которые вы должны писать в любом случае. Вероятно, Линус Торвальдс может сказать: "Регрессионное тестирование"? Что это? Если он компилируется, это хорошо, если он загружается, он идеален, но у него тысячи тестировщиков, которые будут выполнять работу по его. Ah и используя интерактивные оболочки, вы получаете автоматическую обратную связь о своем синтаксисе, например, при компиляции приложения, но код выполняется на месте.

Ответ 6

Мне тоже нравится статическая печать. Но я не нахожу, что очень скучаю по этому поводу, когда пишу Python (пока классы, которые я использую, хорошо документированы), и я бы сказал, что никакая языковая функция никогда не спасет нас от плохой документации), Я также не пропущу большинство динамических функций Python при написании С++ (lambdas, я пропустил: включил С++ 0x, даже если синтаксис ужасен и содержит список).

Для обнаружения ошибок большинство ошибок "неправильного типа" и "неправильный метод" не являются тонкими, поэтому основное отличие заключается в том, что исключения заменяют ошибки компилятора. Вы должны убедиться, что вы действительно выполняете каждый путь кода и все важные пути передачи данных, но, конечно же, вы делаете это в любом случае для серьезных проектов. Я подозреваю, что редко бывает трудно проверить все классы, которые могут быть назначены данной переменной. Основная проблема заключается в том, что люди, привыкшие к С++, научились опираться на компилятор, и не старайтесь избегать больших классов ошибок, которые компилятор поймает. В Python у вас есть возможность подумать об этом, когда вы код, или до тех пор, пока тесты не начнут узнавать об этом. Аналогично, операция "автоматического рефакторинга" на С++ "изменять параметры и видеть, что не удается скомпилировать" нуждается в некоторой модификации в Python, если вы хотите найти все сайты вызовов.

Поэтому вам нужно убедиться, что вы используете правильное подмножество тестов, поскольку полный запуск unit test большого приложения Python займет гораздо больше времени, чем это приемлемо на этапе "компиляции" вашего текущего кода на С++/компиляция/код/​​компиляция/код/​​компиляция/цикл тестирования. Но это точно та же проблема, что и нежелание перестраивать все на С++.

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

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

Ответ 7

Мой опыт

Я работал с обоими, возможно, примерно с десятилетием с каждым профессиональным образом.

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

Исследования

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

Тоталитарные

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

Системы статического типа могут заставить вас задуматься о полезных вещах. Это особенно актуально на языке, таком как Haskell с Type Classes и Monads (который, я признаю, я до сих пор не получил). Это хорошо, но я чувствую, что тоталитарно полагать, что это всегда хорошо. Вы должны подумать об этом, когда это необходимо. Язык не должен заставлять вас думать об этом или знать об этом с самого начала развития.

Оба слишком ограничены и недостаточно ограничены

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

Вместо этого, почему бы вам не использовать базовый динамический язык для описания типов и типов систем, если вы хотите? Как библиотека. Это более выразительно; более мощный (при желании); более гибкий; и означает меньший базовый язык.

Boilerplate

Статически типизированные языки, похоже, стимулируют формирование шаблонов или кода. Я не уверен, что это присуще. Возможно, достаточно мощная макросистема преодолела бы ее. Я сравниваю состояние mocks для тестирования в Swift с объективом c.

Монолитные

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

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

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

Скорость

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

Долгосрочный

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

Ответ 8

Рассмотрим случай, когда у вас есть подпрограмма, которая принимает один аргумент:

sub calculate( Int $x ){ ... }

Теперь ваши требования меняются, и вам приходится иметь дело с несколькими аргументами:

multi sub calculate( Int $x ){ ... }
multi sub calculate( Int @x ){
  my @ret;
  for @x -> $x {
    push @ret, calculate( $x );
  }
  return @ret;
}

Обратите внимание, что между различными версиями было очень мало изменений.

Теперь, если вы узнали, что действительно должны были использовать числа с плавающей запятой:

multi sub calculate( Num $x ){ ... }
multi sub calculate( Num @x ){
  my @ret;
  for @x -> $x {
    push @ret, calculate( $x );
  }
  return @ret;
}

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

Эти примеры были написаны в Perl6

Ответ 9

Я знаю, что это было какое-то время, но принятые ответы отображают свойства, которые не ограничены динамически типизированными языками. Например, # 4 (меньше кода) также относится к Scala (если я правильно помню). Это определенно верно для Groovy (который построен поверх Java, поэтому технически Groovy является как статическим, так и динамическим). Единственное, с чем я согласен, это № 7 (устойчивость)

Из википедии

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

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

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

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