Читая о языке Go, вы часто слышите слово «простота».
Но разные люди интерпретируют это слово по-разному, особенно в контексте разработки программного обеспечения, и многие зачастую даже не осознают, почему оно вообще используется как характеристика языка.
В этой статье мы попытаемся концептуально подойти к вопросу «сложности» и «простоты» в разработке программного обеспечения и посмотрим, почему и как язык Go сделал простоту краеугольным камнем своего дизайна.
О сложности.
Простота является противоположностью сложности.
Сложность разработки программного обеспечения – тема, давно волнующая умы инженеров и ученых, а один из наиболее концептуальных подходов к вопросу был сформулирован автором знаменитой книги «Мифический человеко-месяц».
Фредерик Брукс , в виде отдельного произведения - «Серебряной пули не существует» ( «Нет серебряной пули» ).
Эта работа была написана в 1987 году, но концептуальный взгляд на тему делает ее актуальной и 30 лет спустя.
В частности, Брукс делает важное разделение сложности на «врожденный» ( существенный ) И "принес в" (или «случайный» — случайный ).
Внутренняя сложность - это сложность, которая исходит из самой области проблемы, из ее природы.
Скажем, если вам нужно реализовать протокол FTP, неважно, какой язык или инструментарий вы для этого выберете, у вас все равно есть набор команд, действий, кодов возврата и логики, которые придется реализовать.
Невозможно упростить задачу до однострочной реализации.
Сложность вам дана как задана (в данном случае из спецификации протокола), и в целом у вас нет возможности повлиять на эту составляющую.
Введенная сложность — наоборот, сложность исходит из инструментов, которые мы используем.
Это сложность, которую мы сами себе создаем.
Мы можем повлиять на него и уменьшить его.
История развития индустрии разработки программного обеспечения сводится к сокращению именно этого, случайный , сложности.
Почему сложность — это плохо?
Все должно быть сделано максимально просто.Ответ на вопрос «хорошо» или «плохо»? — лежит исключительно в области признания или непризнания хороших и плохих практик.Но это не проще.
Альберт Эйнштейн
Не существует формального способа доказать, что, скажем, «глобальные переменные» хороши или плохи.
Рассматривая отдельные примеры, сторонники каждой стороны найдут для вас сотню убедительных аргументов как за, так и против.
Но собрав, хотя бы частично, опыт многих и многих разработчиков программного обеспечения, работающих с самыми разными программистами и языками, вы так или иначе услышите высказывания о «хороших практиках» или «плохих практиках».
Только благодаря коллективному эмпирическому опыту многих тысяч инженеров и программистов, изложивших свои мысли на бумаге, становится ясно, что «сложности» следует избегать, насколько это возможно.
Сложность приводит к целой лавине не сразу очевидных эффектов, которые к тому же часто сложно доказать формально и которые измеряются вероятностями — большая вероятность ошибок, больше времени на понимание кода, больше времени и усилий, необходимых для изменения дизайна программного обеспечения.
при необходимости (рефакторинг), что, в свою очередь, создает стимул не вносить эти изменения, что, в свою очередь, приводит к тому, что разработчики начинают искать обходные пути и так далее.
В конце концов, код — это всего лишь инструмент решения задач, и в конце концов, главным критерием, отделяющим «хорошее» от «плохого», является продуктивность — скорость и качество решения этих самых задач.
Сложность убивает производительность, поэтому вся индустрия разработки движется в сторону снижения сложности.
При чем здесь языки программирования?
Управление сложностью — это квинтэссенция программирования.Выбор языка программирования — очень хороший, если не лучший, пример «внедренной сложности» в мире разработки программного обеспечения.Брайан Керниган
Сами языки программирования также являются инструментами снижения сложности разработки.
И каждый раунд их разработки так или иначе решает один из аспектов сложности разработки ПО, но тем самым привносит новые элементы сложности.
Вся история их развития – это история поиска более простого инструмента для реалий того времени.
Теория языков программирования — такая же развивающаяся наука, как, скажем, нейробиология, и единого канонического знания о том, каким должен быть язык программирования, не существует. Это случайный процесс, заложенный законами рынка, удачными решениями, хорошей поддержкой в виде крупной компании (почти за всеми популярными языками стояла крупная компания) и массой других факторов.
И этот процесс не стоит на месте, новые концепции порождают новые проблемы и новые уровни абстракций, растут коллективный опыт и понимание, в то же время экосистема аппаратного и программного обеспечения развивается и быстро меняется, меняются приоритеты в вопросах.
компромиссов и экономии ресурсов, и все это плотно завязано на инерции человеческого мозга и образовательных систем.
Другими словами, это очень сложная махина.
Простого решения здесь нет и не может быть.
Но что можно сказать наверняка, так это то, что некоторые языки добавляют больше сложности в общий пул сложности, а другие — меньше.
Некоторые практики и шаблоны («шаблоны — это отчет об ошибках на вашем языке»), навязанные языками, увеличивают общую сложность разработки, а другие уменьшают ее.
И мы, как инженеры, должны в конечном итоге стремиться избежать этой «внесенной сложности».
Сложность в Го
Go родился как ответ на возросшую сложность существующих языков.По крайней мере, в той предметной области, которая волновала Google — разработка системного, сетевого и серверного ПО.
Его главной целью изначально было уменьшить эту сложность любой ценой.
Это было главным приоритетом с самого начала.
Немалую роль здесь сыграл огромный практический опыт авторов Go — Пайка, Томпсона и компании — людей, которые стояли у истоков Unix, языка C и UTF-8, а сейчас работают над ключевыми продуктами Google. Так или иначе, Go был своего рода радикальным языком, который качнул маятник сложности в другую сторону, пытаясь выровнять существующий ландшафт мира разработки программного обеспечения.
И это именно то, что подразумевается под термином «простота» в контексте Go. Уменьшение сложности.
Сокращение времени, необходимого среднестатистическому программисту для понимания среднестатистического проекта, написанного другими людьми.
Снижение риска ошибок.
Сокращение времени и затрат на «передовую практику».
Уменьшение шансов написать плохой и некрасивый код. Сокращение времени на освоение языка.
И так далее и тому подобное.
Числа
Но хватит слов, давайте попробуем оценить сложность, которую приносят языки.В комментариях к предыдущим статьям отсутствие «формальных доказательств» стало причиной жарких споров.
Скажу сразу, что понимаю сложность этой задачи.
Реальная оценка лежит в плоскости субъективного практического опыта и трудноизмеримых вероятностей.
Не существует простого способа свести все к одному числу и сказать: «сложность языка А больше, чем сложность языка Б».
Но тем не менее, если вы хорошо знаете два и более языков, вы легко сможете решить для себя, какой язык вам проще.
Ваш мозг каким-то образом знает, как оценить и решить, какой язык сложнее.
Поэтому, за неимением лучшего варианта, попробую воспользоваться несколькими методами и посмотреть, какую картину они рисуют. У каждой методики есть серьезные недостатки, но если их результаты не сильно различаются, ее можно считать чем-то большим, чем случайное назначение.
При этом я буду анализировать языки, которые достаточно универсальны для решения широкого круга задач, имеют достаточно большое сообщество и доступную информацию о них.
Мы не рассматриваем такие экзотические вещи, как Brainfuck.
Способ 1.
Один из таких простейших методов — подсчет ключевых слов языка.На самом деле точнее было бы оценить понятия, которые вводит язык – но это сложнее подсчитать, и в то же время коррелирует с количеством ключевых слов.
Оценка будет очень грубой, но вполне показательной и логичной.
Логично, потому что меньше знаний означает меньшую когнитивную нагрузку на мозг.
Вот что у нас есть:
Питон 2.7 | 31 | docs.python.org/2.7/reference/lexical_anaанализ.
html |
Питон 3 | 33 | docs.python.org/3.4/reference/lexical_anaанализ.
html |
Луа | 21 | www.lua.org/manual/5.1/manual.html |
С (С99) | 32 | en.wikipedia.org/wiki/C_syntax#Reserved_keywords |
С (С11) | 37 | en.wikipedia.org/wiki/C_syntax#Reserved_keywords |
С++11 | 85 | en.cppreference.com/w/cpp/keyword |
Идти | 25 | golang.org/ref/spec |
JS (ECMAScript 5.1) | 41 | www.ecma-international.org/ecma-262/5.1/#sec-7.6.1 |
Хаскелл | 55 | www.haskell.org/haskellwiki/Keywords |
Джава | 50 | en.wikipedia.org/wiki/List_of_Java_keywords |
С# | 79 | msdn.microsoft.com/en-us/library/x53a06bb.aspx |
PHP | 58 | www.php.net/manual/en/reserved.keywords.php |
Рубин 1.9 | 42 | Ruby-doc.org/docs/keywords/1.9 |
Скала | 41 | www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html |
Эрланг | 27? | erlang.org/doc/reference_manual/introduction.html |
Способ 2
Вы можете попробовать оценить грамматики языка, многие из которых описываются с помощью Формы Бэкуса-Наура .Грамматики в этом формате (BNF/EBNF) есть не для всех языков, но в Интернете довольно много разных грамматик, составленных полуавтоматически.
Например, я взял несколько грамматик отсюда: slps.github.io/zoo/index.html .
Я оценю количество правил, используя простые однострочники.
Например, для Go очень легко извлечь правила ENBF прямо со страницы спецификации официального языка:
Хотя в других спецификациях подсчитать количество правил иногда не очень просто.$ curl -s http://golang.org/ref/spec | grep pre.*ebnf | wc -l
На всякий случай я приведу с собой команду, которой, как я думал, я являюсь.
Язык | Количество правил |
---|---|
С | 65 |
Идти | 58 |
Питон | 83 |
Хаскелл | 78 |
JS (ECMAScript 5.1) | 128 |
Руби (для 1.4) | 37 |
Java (JRE 1.9) | 216 |
С++ (2008 г.
) |
159 |
С# 4.0 | 314 |
Луа 5.1 | 25 |
PHP | 146 |
Ржавчина | 115 |
Эрланг | 219 |
Скала | 143 |
*::'| тр -д ' ' | сортировка -у | туалет -л Руби (для 1.4) локон -s docs.huihoo.com/ruby/ruby-man-1.4/yacc.html | греп ": " | туалет -л Java (JRE 1.9) локон -s docs.oracle.com/javase/specs/jls/se8/html/jls-19.html | греп '' | туалет -л С++ (2008 г.
) локон -s slps.github.io/zoo/cpp/iso-n2723.bnf | egrep ":$" | туалет -л С# 4.0 локон -s slps.github.io/zoo/cs/csharp-msft-ls-4.0.bnf | egrep ":$" | туалет -л Луа 5.1 локон -s wiki.luajit.org/Extended-BNF | греп "::=" | туалет -л PHP локон -s slps.github.io/zoo/php/cordy.bnf | egrep ":$" | туалет -л Ржавчина локон -s doc.rust-lang.org/grammar.html | grep "[a-z_]* :" | туалет -л Эрланг локон -s raw.githubusercontent.com/ignatov/intellij-erlang/master/grammars/erlang.bnf | греп "::=" | туалет -л Скала локон -s www.scala-lang.org/files/archive/spec/2.11/13-syntax-summary.html | греп "::=" | туалет -л
В виде графика:
Опять же, эти методы не дают объективной картины и цифр, но дают приблизительную оценку одного из факторов сложности языка.
Способ 3.
Третий метод оценки практической сложности языка будет основан на статистических данных — количестве вопросов на StackOverflow с учетом коэффициента популярности языка.Предвижу критику, что методика спорная, но на самом деле она имеет смысл, и ребята из RedMonk уже некоторое время даже ведут такую статистику: redmonk.com/sogrady/2015/01/14/language-rankings-1-15 StackOverflow хорош тем, что благодаря модерации теги по языкам расставлены довольно аккуратно, и это, как ни крути, теперь место, куда многие люди ходят с вопросами даже раньше, чем на официальный сайт - там даже придумали термин - SODD, Разработка, управляемая переполнением стека.
Поэтому логично предположить, что чем больше вопросов, тем непонятнее, тем сложнее (хотя факторов, влияющих, конечно, еще очень много).
StackOverflow удобно предоставляет количество вопросов по тегам здесь: stackoverflow.com/tagsЭpage=2&tab=popular В этом случае, конечно, нужно учитывать абсолютное количество людей, пишущих на том или ином языке, и для этого я возьму рейтинг репозиториев GitHub за последний квартал 2014 года, доступный в чудесном виде здесь: githut.info и я буду рассматривать количество активных репозиториев как коррелирующий показатель количества людей, активно использующих язык.
А дальше схема проста — количество вопросов на StackOverflow делим на количество активных репозиториев на Github. Чем выше число, тем сложнее язык.
Вот что происходит:
Язык | Репозитории на GitHub | Вопросы по СО | Соотношение |
---|---|---|---|
Идти | 22264 | 10272 | 0,46 |
Рубин | 132848 | 136920 | 1,03 |
Луа | 8123 | 8502 | 1,04 |
Ржавчина | 4383 | 2478 | 1,76 |
С | 73075 | 184984 | 2,53 |
Хаскелл | 8789 | 22930 | 2,60 |
Питон 2.7 | 164852 | 439994 | 2,66 |
JS | 323938 | 880188 | 2,71 |
Джава | 222852 | 879064 | 3,94 |
С++ | 86505 | 377834 | 4,36 |
PHP | 138771 | 768018 | 5,53 |
С# | 56062 | 811952 | 14,48 |
Эрланг | 2961 | 5571 | 1,88 |
Скала | 10853 | 38302 | 3,52 |
выводы
Предвосхищая комментарии, напишу еще раз, что прекрасно понимаю плюсы и минусы всех описанных выше методов оценки, но именно поэтому их несколько, чтобы иметь возможность сформировать сводную картину, минимизируя влияние недостатки всех этих подходов.Ошибка здесь может быть очень большой (например, грамматика Ruby здесь проще, чем грамматика Go, но этот однострочный скрипт считает только количество правил, но не их сложность — и весь синтаксический сахар Ruby, который добавляет довольно небольшая сложность, здесь не учитывается).
Если у кого-то есть еще идеи, как объективно оценить сложность языков программирования, пишите, буду рад услышать и обсудить.
В целом на этих графиках видно, что данные вполне согласуются и сильных расхождений нет — четко видны группы «сложных», «простых» и «средних» языков.
Меня немного удивил результат Rust на последнем графике — ведь Rust отнюдь не простой язык: скорее всего этот результат связан с молодостью языка (версия 1.0 вышла пару месяцев назад) , и, как следствие, высокая средняя квалификация разработчиков ржавчины — отсюда и низкая относительная активность на Stack Overflow. В целом эти цифры подтверждаются моими личными наблюдениями, по крайней мере, на тех языках, которые знаю лично я.
А тех, кого я не знаю, я оцениваю достаточно внимательно.
Предвижу критику вышеизложенных методов и заявления об их неадекватности.
Поэтому сразу задаю два вопроса, ответы на которые можно оставлять прямо в комментариях с критикой: а) какой метод оценки сложности языка является лучшим (в терминологии сложности данной статьи)? б) как объяснить достаточно очевидную корреляцию результатов всех трех методов, если они несостоятельны и их результаты являются результатом случайного распределения? И наконец, сложность языка — лишь один из факторов успеха.
Хоть статья и посвящена простоте Go, это далеко не единственная причина его успеха, хотя и одна из важных.
Если бы Go был таким простым, но без богатой стандартной библиотеки и отличного инструментария, его путь, скорее всего, был бы совершенно другим.
Заключение
Описав важность простоты инструментов разработки и попытавшись формально доказать простоту Go по сравнению с другими популярными языками, важно напомнить, что это не случайность, а намеренное решение авторов языка.Это было задумано вопреки распространенному мнению – «чем сложнее, тем лучше» – и принесло ожидаемый эффект. Число людей и проектов, подхвативших Go, растёт быстрыми темпами (сегодня нет графиков, ссор)), и многие делают упор на это «освежающее» качество Go — его простоту.
В конце концов, простота позволяет людям сосредоточиться на логике программы, а не на управлении памятью, борьбе с компилятором и расшифровке запутанного синтаксиса языка.
И это снова делает программирование интересным и увлекательным, таким, каким оно было, пожалуй, при первом знакомстве с программированием вообще.
Возможно, вы все еще помните то веселье, когда писали свои первые программы.
Большинство отзывов от людей, которые начали писать на Go, заканчиваются словами: «Go снова делает программирование увлекательным».
Но при этом вы пишете не Hello, World, а качественный современный софт, быстрый, кроссплатформенный, многопоточный и безопасный.
У каждого языка есть своя ниша, свои компромиссы, свои плюсы и минусы.
Но если ваши задачи пересекаются с областями, в которых Go уже зарекомендовал себя, вы, вероятно, получите большую выгоду от простоты Go и его влияния на производительность и качество.
Ссылки
Нет серебряной пули - факультет.salisbury.edu/~xswang/Research/Papers/SERelated/no-silver-bullet.pdf Меньше значит экспоненциально больше — Commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html Меньше - больше - лямбда-the-ultimate.org/node/4852 Теги: #Go #complexity #complexity #brooks #complexity #Разработка сайтов #программирование #Системное программирование #Go-
2Гис Показал Что-То Новое
19 Oct, 24 -
Игры Для Zx-Spectrum
19 Oct, 24 -
Клиент Для Google Translate
19 Oct, 24 -
Список Профессий Для Иммиграции В Канаду
19 Oct, 24