Языки программирования: нельзя просто написать «1 + 2»

Программист с опытом разработки почти всего – от Java-приложений для телефонов до утилит и веб-сайтов – Дмитрий делится своим мнением о языках программирования.

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

Все мы знаем, что у компьютера есть оперативная память. Если мы пишем программу на языке низкого уровня – таком, как C, например, - то там мы выделяем и удаляем память вручную. Для этого есть специальный оператор. Точнее, в C это функции, которые выделяют и освобождают память. Эти операции приходится делать вручную, и, если мы выделяем память, а потом забываем ее удалить (еще раз повторюсь, это два вызова функций, которые нужно сделать в нужных местах), то возникают так называемые утечки памяти, memory leaks. Как правило, это происходит в достаточно сложных программах, где трудно держать в голове все случаи выделения памяти.

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

 

Шаблоны проектирования (GoF). Редакция для Java

м. Сокол, Октябрьское поле


В курсе рассматриваются базовые 23 паттерна, изложенные в книге "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.

 

Работа с Java веб-сервисами

м. Сокол, Октябрьское поле


В рамках курса слушатели получат практические навыки разработки XML based web services на базе платформы Java SE 7.

 

Разработка бизнес-компонентов с использованием технологии EJB, Java EE 6

м. Нагатинская


Курс уделяет внимание главным образом особенностям Enterprise JavaBeans и дает необходимые представление об управлении.

Тут, конечно, возникает вопрос: если высокоуровневые языки такие удобные, почему бы не программировать только на них? Потому что, как правило, удобство влечет за собой дополнительные накладки. Высокоуровневый язык многие вещи пытается делать автоматически, и из-за этого он может быть менее эффективен, чем низкоуровневый. Нередко для программ, написанных на Java или Python, пишутся расширения (extensions) на низкоуровневых языках. Если нужно выполнить какие-нибудь сложные вычисления или провести обработку данных с выделением памяти, то достаточно часто для этих целей пишутся расширения на C. Объясню на примере.

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

Современные высокоуровневые языки ограничивают тебя в хорошем смысле. Имеется в виду не ограничение возможностей, а ограничение количества способов решения одной и той же задачи. Это касается многих аспектов начиная от синтаксических, заканчивая архитектурными. Например, в том же C++ ты можешь использовать ООП (объектно-ориентированное программирование), или использовать только процедуры, ты можешь вручную работать с памятью, или использовать «умные» указатели. В Java или C# ты вынужден работать только с ООП и автоматическим управлением памятью. И это, на самом деле, хорошо, потому что не только снижает риск ошибок, но и сокращает время изучения языка, при условии, что вы ставите себе задачу изучить возможности языка целиком и полностью.

Поэтому начинающему программисту я бы все-таки рекомендовал изучать какой-нибудь современный язык, который сейчас наиболее востребован. Целостное понимание программирования, как профессии, особенно не пострадает, если начать изучать сразу высокоуровневый язык. На самом деле, изучение низкоуровневого языка просто обогащает тебя как специалиста, потому что оно зачастую делает более понятными те процессы, которые в высокоуровневом языке от тебя скрыты. То, что происходит «behind the scenes», как часто любят писать в документации.

Вот самый низкоуровневый язык после машинного кода – Assembler. Там все делается на очень низком уровне: чтобы сложить два числа, ты не можешь просто написать «1+2». Ты должен единицу записать в один регистр, двойку в другой, а в третий записать результат операции сложения. Изучая эти вещи, я просто стал лучше понимать компьютерную архитектуру. Но если учить сразу высокоуровневый язык, об этом не узнаешь. Зачем нужны эти знания? Для тех редких случаев, когда ты в процессе разработки сталкиваешься со сложной и непонятной проблемой, с какой-то ошибкой, которую тебе знания только лишь высокоуровневого языка не позволяют интерпретировать, ты не можешь понять, как решить проблему. Вот тут знания о более низкоуровневой архитектуре могут пригодиться.

Не все высокоуровневые языки – современные: некоторые появились больше 20 лет назад. Например, C++. Он считается высокоуровневым языком, в нем есть множество удобных инструментов, которые отсутствуют в его предшественнике, языке С, один из главных - это конечно поддержка ООП. Однако управление памятью там, по сути, ручное, хотя «умные» указатели значительно облегчают эту задачу . C++ дает очень много свободы для интересного кода. Но в нем может быть разный подход к программированию, и это обстоятельство порой приводит к ошибкам. То есть, один программист выполнил свою часть задачи, а другой потом с этим же кодом работает, и ему не комфортно, так как он просто привык «кодить» по-другому.

На самом деле, о языках неправильно говорить в отрыве от области применения. Я могу сказать, что мне больше нравятся языки высокоуровневые и интерпретируемые. JavaScript и Python к этому типу относятся. Но если мы говорим о написании драйверов для оборудования или о написании ядра операционной системы, то тут лучше всего подойдет язык C, которому уже очень много лет, и он последние десятилетия особо не меняется. Если речь идет о веб-разработке, то я отдаю предпочтение JavaScript, но использую его по большей части на клиентской стороне – для написания скриптов, которые работают в браузере. До появления популярного сегодня фреймворка NodeJS, JavaScript никак нельзя было использовать для серверной разработки, и она производилась чаще всего на PHP. В определенной области, скорее всего, будет достаточно одного языка, что бы это ни было. Я знаю несколько, просто потому что мне было интересно поработать в разных областях.

Я достаточно долго работал в области веба, и в начале имел дело с PHP и JavaScript: один для серверной стороны, другой – для клиентской. Объясню на двух примерах, что значат эти термины.

 

Разработка web-приложений с использованием Servlets 2.5

м. Сокол, Октябрьское поле


В процессе обучения слушатели получат знания и практические навыки использования Java Servlets для разработки Web-приложений на платформе Java EE.

 

Введение в Apache Maven

м. Сокол, Октябрьское поле


В курсе освещается применение сборщика приложений Apache Maven, в том числе управление зависимостями, структура POM-файла, жизненный цикл проекта, создание плагинов и архетипов.

 

Разработка и продвижение Web-проектов

м. Киевская


Курс «Разработка и продвижение Web-проектов» разработан специально для тех, кто хочет научиться этому с нуля

В случае с вебом, браузер – это клиент. Он запущен у нас на компьютере, и он что-то отображает. Когда мы заходим на сайт, то, что будет отображено, определяется сервером (код которого может быть написан, в том числе, на PHP). Сервер выдает браузеру ответ в виде текстовых данных, а браузер их формирует в какую-то картинку для нас: в частности, он форматирует текст согласно структуре HTML и CSS-стилям. А вот если еще что-то интерактивное предполагается на странице, какая-то реакция на действия пользователя (лайт-боксы с фотографиями, анимированные надписи и пр.), это программируется на JavaScript.

Если говорить об играх (возьмем, например, Counter-Strike), то в этом случае клиентом будет компьютер игрока, а конкретно - сама запущенная на этом компьютере игра. Она посылает на сервер сообщение о том, что игрок выстрелил, а сервер производит сложные вычисления и отвечает клиенту, попал тот в другого игрока или нет. В клиенте, в первую очередь, выполняется визуализация графики, воспроизведение звуков и пр. А серверу не нужно ничего рисовать, ему нужно просчитывать.

В веб-разработке (для клиентской стороны), так уж исторически сложилось, популярен JavaScript. А для серверной части много вариантов – Java, C#, Perl, Python, даже на C и C++ пишут. В моей практике веб-разработки самый популярный серверный язык – PHP. И, как я уже сказал, на JavaScript теперь можно делать и то, и другое.

В разработке игр довольно долгое время прочные позиции удерживал C++, но последние лет пять его постепенно вытесняют другие языки, например, C#, который используется в Unity (можно сказать, №1 движок для разработки игр на данный момент). В Unity, впрочем, существует возможность использовать и JavaScript, но там используется особая редакция с более строгой типизацией, чем в обычном JS.

В десктопном программировании – например, в банковской сфере,– скорее всего, будут Java или C#, потому что разработчики этих языков предоставляют, что называется «out of the box» библиотеки для удобной разработки оконных приложений, работы с базами данных, с сетью, взаимодействия с ОС. Если же мы хотим написать новую ОС (хотя сейчас за такую задачу разработчик-одиночка или даже небольшой коллектив в здравом уме не возьмется, но для примера), то на высокоуровневом языке это будет сложно, потому что он не заточен под низкоуровневые задачи. Придется, скорее всего, возвращаться на C и местами даже на Assembler. Это касается также драйверов оборудования, они тоже, насколько я знаю, пишутся чаще всего на C, потому что нужен уровень, максимально приближенный к «железу».

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

Резюмируя все вышесказанное. Если человек говорит: «хочу заняться программированием», то нужно у него спросить, какая область ему интересна. И, исходя из его ответов, дать ему рекомендации. И чем уже область, тем более точными будут рекомендации. А так, на самом деле, это такое иерархическое дерево, по которому человек, желающий заниматься разработкой, должен пройти, и остановится на одной из его ветвей, где будет понятно, какой язык или набор языков ему подходит.