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

Обсуждая эволюцию компьютерных языков, Алан Кей говорит, что самым важным атрибутом его Smalltalk является поздняя привязка; это придает языку гибкость и расширяемость, а также позволяет с течением времени подвергать рефакторингу неподходящую связь. Ты согласен? Есть ли компенсирующие преимущества для раннего связывания, которые объясняют, почему он кажется доминирующим из двух парадигм для доменов, где любой из них может быть использован?

Мой личный опыт (который не является достаточно широким или глубоким, чтобы быть авторитетным), основанный на реализации веб-приложений с использованием javascript, jQuery, jsext, actionscript, php, java, RoR и asp.net, по-видимому, указывает на положительную корреляцию между поздним связыванием и раздуванием снижение. Раннее связывание, я уверен, помогает обнаруживать и предотвращать некоторые ошибки безопасности типов, но так же, как и автозаполнение, и хорошая IDE, и хорошие практики программирования в целом. Так что я склонен ловить себя на том, что болею за сторону позднего связывания, прежде чем моя сторона избегания риска восстановит мою рациональную перспективу.

Но я действительно не знаю, как сбалансировать компромиссы.

6 ответов

Решение

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

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

Там было два основных преимущества раннего связывания. Первый:

  • Производительность во время выполнения

Это общепринято, но, как правило, не имеет значения, потому что в большинстве случаев возможно бросить оборудование на проблему, которая дешевле. Есть, конечно, исключения (например, если у вас нет оборудования, на котором вы работаете).

Второе преимущество раннего связывания:

  • Легкость развития

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

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

Поздние выпуски позволяют работающей системе расширяться. Например, система запускается, зная о волках. Когда время проходит метод evolveDomesticate(), в Wolf(?) Запускается новый класс с именем Dog и создается его экземпляр, и теперь у нас есть Dogs. Smalltalk сохранит весь образ SYSTEM, поэтому, если вы выключите его и перезапустите, Dogs все равно будут существовать после перезапуска. Как только вы эволюционируете в объекты, работающие на определенном оборудовании и подключенные в ячеистой сети, не произойдет реального отключения всей экосистемы (только до тех пор, пока не взорвется Sun). Я думаю, что это то, о чем Алан Кей говорил о преимуществе позднего связывания, стать Богом.

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

В то время как некоторые языки на основе виртуальных машин, такие как Java, являются ранним связыванием, машинный код на самом деле может напрямую выполнять раннее связывание. Чтобы выполнить позднее связывание, он должен выполнить тот же тип поиска хеша, что и динамический интерпретатор языка. Позднее связывание требует выполнения фрагмента кода для получения адреса (так работает автоматизация OLE). Это не может быть сделано непосредственно процессором - код должен быть выполнен.

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

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

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

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

Но мне нравится "простая в использовании" независимость версии от позднего связывания
Просто используйте

var excel = CreateObject("Excel.Application");

и Позднее связывание выяснит, что это за Excel.Application и где его взять...

Привязка времени компиляции, при которой связывание выполняется во время компиляции, называется ранним связыванием

динамическое связывание, при котором связывание функции, выполняемой во время выполнения при вызове функции, называется поздним связыванием

Другие вопросы по тегам