19/03/2021

Размышления (2): о C++, Java и областях применения их

В прошлой статье (Размышления (1): о C, C++, связи между ними, почему ООП переоценен и последствия этого) я рассмотрел историю развития двух основных парадигм программирования, уместность и неуместность применения их в современных условиях. В этой статье я поднимусь чуть выше, и опишу своё видение применения самих языков, основываясь на технических особенностях их реализаций и обоснованности применения их в областях.

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

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

Из этого вытекают определённые последствия:
C++ хорошо применять для решения двух задач: разработки высоконагруженных приложений и приложений, работающих в условиях ограниченных ресурсов (что, на самом деле есть одно и то же, только с разных сторон). Как правило, оба вида этих приложений пишутся для узкого круга платформ. Высоконагруженные иногда вовсе для одного сервера или супер-компьютера компании. А работающие в ограниченных условиях — для какого нибудь одного процессора/контроллера. То есть кросс-платформенность в таких ситуациях бывает не нужна. Иногда даже возможность переноса на уровне кода (сборка под другие платформы, портирование) бывает не востребована. А возможности оптимизации, как через сам код C++, так и через применение ассемблерных вставок, безграничны. То есть, исходя из особенностей технической реализации языка C++, использовать его целесообразно для разработки высокоточных с точки зрения вычислительных ресурсов приложений (после C и ассемблера, разумеется) и высоконагруженные сервисы. Без сомнения вам было бы приятно, если бы мой блог (как и другие сайты) загрузился бы и работал в несколько раз быстрее.
Java же разрабатывалась для быстрой разработки кросс-платформенных приложений с относительно низкими порогами вхождения в разработку. На этом языке есть очень мало возможностей что-то оптимизировать (всё это делается путём косвенного воздействия на JVM через свой код). Работают приложения на Java относительно небыстро. А если это «относительно» небыстро умножить на тысячу, миллион запросов/операций/вызовов, получится ощутимо медленно. Зато можно быстро и легко разработать пользовательское (end-user) приложение любой сложности и оно будет работать на всех популярных платформах без переноса (пересборки, перекомпиляции и даже без переконфигурации!).

И что мы видим на практике? В подавляющем большинстве Java используется для разработки enterprise-платформ и web-backend, то есть достаточно критических с точки зрения вычислительных ресурсов систем. А для разработки пользовательских приложений используется C++. Ответом на эту потребность стала кросс-платформенная Qt для разработки пользовательских приложений, в том числе и с GUI, на C++. Да, работает быстро, так как это C++, но писать на C++/Qt несколько сложнее — пороги входа значительно выше, чем на Java и переносимость всё равно обеспечивается только через пересборку. А возможность создавать кроссплатформенные приложения, которой обладает Java из коробки остаётся не востребована вовсе — крупные enterprise-приложения, которые разрабатываются на ней, редко куда-то портируются и бывает так что такой продукт всю свою жизнь работает на одном сервере.

Разработку Enterprise и Web на Java можно понять с финансовой точки зрения — воспользоваться Java для ускорения разработки ПО и повышения безопасности (а на Enterprise и Web она очень важна), заплатив больше за серверные мощности, дешевле чем вкладывать в оптимизацию разрабатываемого ПО и, следовательно, тратить больше времени, разрабатывая их на языке более низкого уровня — C++. А вот разработку end-user-приложений на C++ я понять не могу.

Мне кажется, в сложившейся ситуации, логичнее было бы использовать для разработки пользовательских приложений Java, оставить её на Enterprise и Web, а C++ «вытолкнуть» (скорее оставить, ибо она и так там) на встраиваемую технику и на низкий уровень. В «идеальном» варианте лучше C++ использовать и на Enterprise с Web'ом, но это уже наверное маловероятный сценарий.

Но всё есть так как есть — молодые специалисты тяжело работают, решая несложные задачи на C++ (помним о высоких порогах входа), где часто меньше нужна скорость и больше пригодилась бы кроссплатформенность, а имидж Java опошлен, её область применения искусственно заужена, а уровень оплаты труда так же искусственно завышен.

Что это? Сложившиеся традиции? Как и когда они сложились? Когда и почему всё повернуло в эту сторону?

P.S.
Смоделировать ситуацию, в которой разработка высокоответственных продуктов ведётся на C++, а простых — на Java (что так же снижает барьеры использования пользователями разных платформ), я оставляю вам.

P.P.S
Здесь я сравнивал только применение Java и C++ потому что я имею опыт и (конечно личное) видение проблемы некорректного использования только этих языков. Это не означает, что я не понимаю что конфликты PHP vs Python, Python vs Java, Python vs C++ и пр. так же существуют (а, может, какие-то из этих конфликтов и не существуют). Я не писал о них только потому что не имею достаточного опыта участия в таких проектах или хотя бы наблюдения их.