Плюсы и минусы Go, отвергающие неиспользуемые зависимости - PullRequest
11 голосов
/ 01 декабря 2009

Новый язык Google Go пытается упростить управление зависимостями, явно требуя, чтобы все зависимости, перечисленные в модуле, фактически использовались . Компилятор отклонит модуль, который объявляет зависимость от модуля, не используя ничего из этого модуля.

Запрещается импортировать пакет самостоятельно или импортировать пакет без ссылки на какой-либо из его экспортированных идентификаторов.

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

У вас есть опыт работы с другими языками? Каковы плюсы и минусы этого подхода?

Ответы [ 3 ]

5 голосов
/ 01 декабря 2009

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

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

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

1 голос
/ 01 декабря 2009

Я предполагаю, что самая большая мотивация для этого и самый большой результат, это улучшение во время компиляции. Предварительный видеоролик о технических новостях продемонстрировал их способность компилировать большие объемы кода за короткие промежутки времени (их пример - 200 000 строк кода за 8 секунд на MacBook - без каких-либо технических характеристик машины).

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

Вот пример того, как что-то будет работать в текущей системе C / C ++:

Класс A определен в заголовочном файле C_H и реализован в C_CPP. Класс B наследуется от C и реализован в файлах B_H и B_CPP. Класс A является производным от B и реализован в файлах A_H и A_CPP.

Из-за цепочек деривации A_CPP включает в себя A_H, B_H и C_H. B_CPP включает в себя B_H и C_H. C_CPP включает в себя C_H. Из-за природы препроцессора C, который по существу превращает #include в операцию вырезания и вставки, содержимое C_H запускается через компилятор 3 раза, а B_H - дважды.

Кроме того, все содержимое A_CPP, B_CPP и C_CPP находится в своих собственных объектных файлах. Следовательно, когда компоновщик отправляется для разрешения A.o, он вынужден загружать и обрабатывать как B.o, так и C.o. Кроме того, когда он разрешает B.o, он должен снова обработать C.o.

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

Го подходит к вещам по-другому. В словах прямо из PDF из их технической беседы :

"Компилятор Go тянет переходный информация о типе зависимости от объекта файл - но только то, что ему нужно. Если А.го зависит от B.go зависит от C.go: - составить C.go, B.go, затем A.go. - для компиляции A.go, компилятор читает B.o, а не C.o. В масштабе это может быть огромным ускорив. "

ОК, небольшая касательная выполнена. Почему это актуально? Ответ также есть в Go Tech Talk PDF:

"Модель пакета: явные зависимости чтобы ускорить сборку. "

Я предполагаю, что разработчики Go придерживались той позиции, что когда время компиляции измеряется в секундах, даже для очень больших проектов, для разработчиков более продуктивно сохранять время компиляции таким коротким. Скажем, мне нужно 8 секунд, чтобы скомпилировать 200 000 строк кода и обнаружить, что у меня есть посторонний импорт пакетов, 5-10 секунд (с хорошей IDE или хорошим знакомством с вашей средой разработки), чтобы найти и исправить это, и еще 8 секунд для перекомпиляции. Назовите это всего 30 секунд - и теперь все мои будущие компиляции остаются в диапазоне 10 секунд. Или мы можем позволить нашему модулю расти за счет включения ненужных зависимостей и наблюдать, как время компиляции увеличивается с 8 до 10, 12 или 15 секунд. Это не так много, потому что мы все привыкли компилировать время порядка минут - но когда вы начинаете понимать, что это снижение производительности на 25%, вы останавливаетесь и думаете об этом минуту.

Время компиляции Go уже молниеносно. Также учтите, что скорости процессора все еще увеличиваются (если не так сильно, как в прошлом) и что число доступных ядер также увеличивается (а компиляция больших объемов кода хорошо подходит для многопоточности). 200 000 строк кода за 8 секунд сегодня означают, что не исключено, что 200 000 строк кода будут компилироваться практически мгновенно за 10 лет. Я думаю, что команда Go приняла здесь осознанное решение сделать время компиляции делом прошлого, и хотя проблема, о которой вы говорите, является лишь малой ее частью, она является все еще частью этой проблемы. .

В заключение отметим, что команда Go также, похоже, разработала философию языкового дизайна, которая стимулирует некоторые хорошие практики программирования. К их чести, они приложили усилия, чтобы добиться этого без серьезных потерь производительности, и в основном добились успеха. [В сторону: единственные две вещи, которые я могу придумать, что на самом деле влияет на производительность, это сборка мусора и принудительно инициализированные переменные - и последнее довольно тривиально в наше время.] Это будет по-королевски раздражать некоторых программистов, а других радовать , Это старый, старый аргумент в мире программирования, и совершенно ясно, на какую сторону пошёл Go, нравится вам это или нет.

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

0 голосов
/ 01 декабря 2009

Как упомянул yuku, если у вас есть IDE, которая находится на одном уровне с тем, что Netbeans и Eclipse могут сделать для Java, вам не нужно беспокоиться об этом.

Щелкните правой кнопкой мыши на маленькой лампочке на полях и выберите «Удалить все неиспользуемые зависимости».

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

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

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

...